]> git.pld-linux.org Git - packages/iptables.git/blob - iptables-netfilter.patch
- require llh 2.6.7.0-3 (previous versions had broken ip{,6}t API)
[packages/iptables.git] / iptables-netfilter.patch
1 diff -Nur iptables.org/extensions/.policy-test iptables/extensions/.policy-test
2 --- iptables.org/extensions/.policy-test        1970-01-01 01:00:00.000000000 +0100
3 +++ iptables/extensions/.policy-test    2004-06-29 12:35:40.000000000 +0200
4 @@ -0,0 +1,3 @@
5 +#!/bin/sh
6 +#
7 +[ -f $KERNEL_DIR/include/linux/netfilter_ipv4/ipt_policy.h ] && echo policy
8 diff -Nur iptables.org/extensions/.policy-test6 iptables/extensions/.policy-test6
9 --- iptables.org/extensions/.policy-test6       1970-01-01 01:00:00.000000000 +0100
10 +++ iptables/extensions/.policy-test6   2004-06-29 12:35:40.000000000 +0200
11 @@ -0,0 +1,3 @@
12 +#!/bin/sh
13 +#
14 +[ -f $KERNEL_DIR/include/linux/netfilter_ipv6/ip6t_policy.h ] && echo policy
15 diff -Nur iptables.org/extensions/libip6t_policy.c iptables/extensions/libip6t_policy.c
16 --- iptables.org/extensions/libip6t_policy.c    1970-01-01 01:00:00.000000000 +0100
17 +++ iptables/extensions/libip6t_policy.c        2004-06-29 12:35:40.000000000 +0200
18 @@ -0,0 +1,471 @@
19 +/* Shared library add-on to iptables to add policy support. */
20 +
21 +#include <stdio.h>
22 +#include <netdb.h>
23 +#include <string.h>
24 +#include <stdlib.h>
25 +#include <syslog.h>
26 +#include <getopt.h>
27 +#include <netdb.h>
28 +#include <errno.h>
29 +#include <sys/socket.h>
30 +#include <netinet/in.h>
31 +#include <arpa/inet.h>
32 +#include <ip6tables.h>
33 +
34 +#include <linux/netfilter_ipv6/ip6_tables.h>
35 +#include <linux/netfilter_ipv6/ip6t_policy.h>
36 +
37 +/*
38 + * HACK: global pointer to current matchinfo for making
39 + * final checks and adjustments in final_check.
40 + */
41 +static struct ip6t_policy_info *policy_info;
42 +
43 +static void help(void)
44 +{
45 +       printf(
46 +"policy v%s options:\n"
47 +"  --dir in|out                        match policy applied during decapsulation/\n"
48 +"                              policy to be applied during encapsulation\n"
49 +"  --pol none|ipsec            match policy\n"
50 +"  --strict                    match entire policy instead of single element\n"
51 +"                              at any position\n"
52 +"[!] --reqid reqid             match reqid\n"
53 +"[!] --spi spi                 match SPI\n"
54 +"[!] --proto proto             match protocol (ah/esp/ipcomp)\n"
55 +"[!] --mode mode               match mode (transport/tunnel)\n"
56 +"[!] --tunnel-src addr/masklen match tunnel source\n"
57 +"[!] --tunnel-dst addr/masklen match tunnel destination\n"
58 +"  --next                      begin next element in policy\n",
59 +       IPTABLES_VERSION);
60 +}
61 +
62 +static struct option opts[] =
63 +{
64 +       {
65 +               .name           = "dir",
66 +               .has_arg        = 1,
67 +               .val            = '1',
68 +       },
69 +       {
70 +               .name           = "pol",
71 +               .has_arg        = 1,
72 +               .val            = '2',
73 +       },
74 +       {
75 +               .name           = "strict",
76 +               .val            = '3'
77 +       },
78 +       {
79 +               .name           = "reqid",
80 +               .has_arg        = 1,
81 +               .val            = '4',
82 +       },
83 +       {
84 +               .name           = "spi",
85 +               .has_arg        = 1,
86 +               .val            = '5'
87 +       },
88 +       {
89 +               .name           = "tunnel-src",
90 +               .has_arg        = 1,
91 +               .val            = '6'
92 +       },
93 +       {
94 +               .name           = "tunnel-dst",
95 +               .has_arg        = 1,
96 +               .val            = '7'
97 +       },
98 +       {
99 +               .name           = "proto",
100 +               .has_arg        = 1,
101 +               .val            = '8'
102 +       },
103 +       {
104 +               .name           = "mode",
105 +               .has_arg        = 1,
106 +               .val            = '9'
107 +       },
108 +       {
109 +               .name           = "next",
110 +               .val            = 'a'
111 +       },
112 +       { }
113 +};
114 +
115 +/* FIXME - Duplicated code from ip6tables.c */
116 +/* Duplicated to stop too many changes in other files .... */
117 +static void
118 +in6addrcpy(struct in6_addr *dst, struct in6_addr *src)
119 +{
120 +        memcpy(dst, src, sizeof(struct in6_addr));
121 +        /* dst->s6_addr = src->s6_addr; */
122 +}
123 +
124 +static char *
125 +addr_to_numeric(const struct in6_addr *addrp)
126 +{
127 +        /* 0000:0000:0000:0000:0000:000.000.000.000
128 +        * 0000:0000:0000:0000:0000:0000:0000:0000 */
129 +        static char buf[50+1];
130 +        return (char *)inet_ntop(AF_INET6, addrp, buf, sizeof(buf));
131 +}
132 +
133 +static char *
134 +mask_to_numeric(const struct in6_addr *addrp)
135 +{
136 +        static char buf[50+2];
137 +        int l = ipv6_prefix_length(addrp);
138 +        if (l == -1) {
139 +               strcpy(buf, "/");
140 +               strcat(buf, addr_to_numeric(addrp));
141 +               return buf;
142 +       }
143 +       sprintf(buf, "/%d", l);
144 +       return buf;
145 +}
146 +
147 +/* These should be in include/ip6tables.h... */
148 +extern u_int16_t parse_protocol(const char *s);
149 +extern void parse_hostnetworkmask(const char *name, struct in6_addr **addrpp,
150 +               struct in6_addr *maskp, unsigned int *naddrs);
151 +
152 +/* End duplicated code from ip6tables.c */
153 +
154 +static void init(struct ip6t_entry_match *m, unsigned int *nfcache)
155 +{
156 +       *nfcache |= NFC_UNKNOWN;
157 +}
158 +
159 +static int parse_direction(char *s)
160 +{
161 +       if (strcmp(s, "in") == 0)
162 +               return POLICY_MATCH_IN;
163 +       if (strcmp(s, "out") == 0)
164 +               return POLICY_MATCH_OUT;
165 +       exit_error(PARAMETER_PROBLEM, "policy_match: invalid dir `%s'", s);
166 +}
167 +
168 +static int parse_policy(char *s)
169 +{
170 +       if (strcmp(s, "none") == 0)
171 +               return POLICY_MATCH_NONE;
172 +       if (strcmp(s, "ipsec") == 0)
173 +               return 0;
174 +       exit_error(PARAMETER_PROBLEM, "policy match: invalid policy `%s'", s);
175 +}
176 +
177 +static int parse_mode(char *s)
178 +{
179 +       if (strcmp(s, "transport") == 0)
180 +               return POLICY_MODE_TRANSPORT;
181 +       if (strcmp(s, "tunnel") == 0)
182 +               return POLICY_MODE_TUNNEL;
183 +       exit_error(PARAMETER_PROBLEM, "policy match: invalid mode `%s'", s);
184 +}
185 +
186 +static int parse(int c, char **argv, int invert, unsigned int *flags,
187 +                 const struct ip6t_entry *entry,
188 +                 unsigned int *nfcache,
189 +                 struct ip6t_entry_match **match)
190 +{
191 +       struct ip6t_policy_info *info = (void *)(*match)->data;
192 +       struct ip6t_policy_elem *e = &info->pol[info->len];
193 +       struct in6_addr *addr = NULL, mask;
194 +       unsigned int naddr = 0;
195 +       int mode;
196 +
197 +       check_inverse(optarg, &invert, &optind, 0);
198 +
199 +       switch (c) {
200 +       case '1':
201 +               if (info->flags & (POLICY_MATCH_IN|POLICY_MATCH_OUT))
202 +                       exit_error(PARAMETER_PROBLEM,
203 +                                  "policy match: double --dir option");
204 +               if (invert)
205 +                       exit_error(PARAMETER_PROBLEM,
206 +                                  "policy match: can't invert --dir option");
207 +
208 +               info->flags |= parse_direction(argv[optind-1]);
209 +               break;
210 +       case '2':
211 +               if (invert)
212 +                       exit_error(PARAMETER_PROBLEM,
213 +                                  "policy match: can't invert --policy option");
214 +
215 +               info->flags |= parse_policy(argv[optind-1]);
216 +               break;
217 +       case '3':
218 +               if (info->flags & POLICY_MATCH_STRICT)
219 +                       exit_error(PARAMETER_PROBLEM,
220 +                                  "policy match: double --strict option");
221 +
222 +               if (invert)
223 +                       exit_error(PARAMETER_PROBLEM,
224 +                                  "policy match: can't invert --strict option");
225 +
226 +               info->flags |= POLICY_MATCH_STRICT;
227 +               break;
228 +       case '4':
229 +               if (e->match.reqid)
230 +                       exit_error(PARAMETER_PROBLEM,
231 +                                  "policy match: double --reqid option");
232 +
233 +               e->match.reqid = 1;
234 +               e->invert.reqid = invert;
235 +               e->reqid = strtol(argv[optind-1], NULL, 10);
236 +               break;
237 +       case '5':
238 +               if (e->match.spi)
239 +                       exit_error(PARAMETER_PROBLEM,
240 +                                  "policy match: double --spi option");
241 +               
242 +               e->match.spi = 1;
243 +               e->invert.spi = invert;
244 +               e->spi = strtol(argv[optind-1], NULL, 0x10);
245 +               break;
246 +       case '6':
247 +               if (e->match.saddr)
248 +                       exit_error(PARAMETER_PROBLEM,
249 +                                  "policy match: double --tunnel-src option");
250 +
251 +               parse_hostnetworkmask(argv[optind-1], &addr, &mask, &naddr);
252 +               if (naddr > 1)
253 +                       exit_error(PARAMETER_PROBLEM,
254 +                                  "policy match: name resolves to multiple IPs");
255 +
256 +               e->match.saddr = 1;
257 +               e->invert.saddr = invert;
258 +               in6addrcpy(&e->daddr, addr);
259 +               in6addrcpy(&e->dmask, &mask);
260 +                break;
261 +       case '7':
262 +               if (e->match.daddr)
263 +                       exit_error(PARAMETER_PROBLEM,
264 +                                  "policy match: double --tunnel-dst option");
265 +
266 +               parse_hostnetworkmask(argv[optind-1], &addr, &mask, &naddr);
267 +               if (naddr > 1)
268 +                       exit_error(PARAMETER_PROBLEM,
269 +                                  "policy match: name resolves to multiple IPs");
270 +
271 +               e->match.daddr = 1;
272 +               e->invert.daddr = invert;
273 +               in6addrcpy(&e->daddr, addr);
274 +               in6addrcpy(&e->dmask, &mask);
275 +               break;
276 +       case '8':
277 +               if (e->match.proto)
278 +                       exit_error(PARAMETER_PROBLEM,
279 +                                  "policy match: double --proto option");
280 +
281 +               e->proto = parse_protocol(argv[optind-1]);
282 +               if (e->proto != IPPROTO_AH && e->proto != IPPROTO_ESP &&
283 +                   e->proto != IPPROTO_COMP)
284 +                       exit_error(PARAMETER_PROBLEM,
285 +                                  "policy match: protocol must ah/esp/ipcomp");
286 +               e->match.proto = 1;
287 +               e->invert.proto = invert;
288 +               break;
289 +       case '9':
290 +               if (e->match.mode)
291 +                       exit_error(PARAMETER_PROBLEM,
292 +                                  "policy match: double --mode option");
293 +               
294 +               mode = parse_mode(argv[optind-1]);
295 +               e->match.mode = 1;
296 +               e->invert.mode = invert;
297 +               e->mode = mode;
298 +               break;
299 +       case 'a':
300 +               if (invert)
301 +                       exit_error(PARAMETER_PROBLEM,
302 +                                  "policy match: can't invert --next option");
303 +
304 +               if (++info->len == POLICY_MAX_ELEM)
305 +                       exit_error(PARAMETER_PROBLEM,
306 +                                  "policy match: maximum policy depth reached");
307 +               break;
308 +       default:
309 +               return 0;
310 +       }
311 +
312 +       policy_info = info;
313 +       return 1;
314 +}
315 +
316 +static void final_check(unsigned int flags)
317 +{
318 +       struct ip6t_policy_info *info = policy_info;
319 +       struct ip6t_policy_elem *e;
320 +       int i;
321 +
322 +       if (info == NULL)
323 +               exit_error(PARAMETER_PROBLEM,
324 +                          "policy match: no parameters given");
325 +
326 +       if (!(info->flags & (POLICY_MATCH_IN|POLICY_MATCH_OUT)))
327 +               exit_error(PARAMETER_PROBLEM,
328 +                          "policy match: neither --in nor --out specified");
329 +
330 +       if (info->flags & POLICY_MATCH_NONE) {
331 +               if (info->flags & POLICY_MATCH_STRICT)
332 +                       exit_error(PARAMETER_PROBLEM,
333 +                                  "policy match: policy none but --strict given");
334 +
335 +               if (info->len != 0)
336 +                       exit_error(PARAMETER_PROBLEM,
337 +                                  "policy match: policy none but policy given");
338 +       } else
339 +               info->len++;    /* increase len by 1, no --next after last element */
340 +
341 +       if (!(info->flags & POLICY_MATCH_STRICT) && info->len > 1)
342 +               exit_error(PARAMETER_PROBLEM,
343 +                          "policy match: multiple elements but no --strict");
344 +
345 +       for (i = 0; i < info->len; i++) {
346 +               e = &info->pol[i];
347 +               if ((e->match.saddr || e->match.daddr)
348 +                   && ((e->mode == POLICY_MODE_TUNNEL && e->invert.mode) ||
349 +                       (e->mode == POLICY_MODE_TRANSPORT && !e->invert.mode)))
350 +                       exit_error(PARAMETER_PROBLEM,
351 +                                  "policy match: --tunnel-src/--tunnel-dst "
352 +                                  "is only valid in tunnel mode");
353 +       }
354 +}
355 +
356 +static void print_mode(char *prefix, u_int8_t mode, int numeric)
357 +{
358 +       printf("%smode ", prefix);
359 +
360 +       switch (mode) {
361 +       case POLICY_MODE_TRANSPORT:
362 +               printf("transport ");
363 +               break;
364 +       case POLICY_MODE_TUNNEL:
365 +               printf("tunnel ");
366 +               break;
367 +       default:
368 +               printf("??? ");
369 +               break;
370 +       }
371 +}
372 +
373 +static void print_proto(char *prefix, u_int8_t proto, int numeric)
374 +{
375 +       struct protoent *p = NULL;
376 +
377 +       printf("%sproto ", prefix);
378 +       if (!numeric)
379 +               p = getprotobynumber(proto);
380 +       if (p != NULL)
381 +               printf("%s ", p->p_name);
382 +       else
383 +               printf("%u ", proto);
384 +}
385 +
386 +#define PRINT_INVERT(x)                \
387 +do {                           \
388 +       if (x)                  \
389 +               printf("! ");   \
390 +} while(0)
391 +
392 +static void print_entry(char *prefix, const struct ip6t_policy_elem *e,
393 +                        int numeric)
394 +{
395 +       if (e->match.reqid) {
396 +               PRINT_INVERT(e->invert.reqid);
397 +               printf("%sreqid %u ", prefix, e->reqid);
398 +       }
399 +       if (e->match.spi) {
400 +               PRINT_INVERT(e->invert.spi);
401 +               printf("%sspi 0x%x ", prefix, e->spi);
402 +       }
403 +       if (e->match.proto) {
404 +               PRINT_INVERT(e->invert.proto);
405 +               print_proto(prefix, e->proto, numeric);
406 +       }
407 +       if (e->match.mode) {
408 +               PRINT_INVERT(e->invert.mode);
409 +               print_mode(prefix, e->mode, numeric);
410 +       }
411 +       if (e->match.daddr) {
412 +               PRINT_INVERT(e->invert.daddr);
413 +               printf("%stunnel-dst %s%s ", prefix,
414 +                      addr_to_numeric((struct in6_addr *)&e->daddr),
415 +                      mask_to_numeric((struct in6_addr *)&e->dmask));
416 +       }
417 +       if (e->match.saddr) {
418 +               PRINT_INVERT(e->invert.saddr);
419 +               printf("%stunnel-src %s%s ", prefix,
420 +                      addr_to_numeric((struct in6_addr *)&e->saddr),
421 +                      mask_to_numeric((struct in6_addr *)&e->smask));
422 +       }
423 +}
424 +
425 +static void print_flags(char *prefix, const struct ip6t_policy_info *info)
426 +{
427 +       if (info->flags & POLICY_MATCH_IN)
428 +               printf("%sdir in ", prefix);
429 +       else
430 +               printf("%sdir out ", prefix);
431 +
432 +       if (info->flags & POLICY_MATCH_NONE)
433 +               printf("%spol none ", prefix);
434 +       else
435 +               printf("%spol ipsec ", prefix);
436 +
437 +       if (info->flags & POLICY_MATCH_STRICT)
438 +               printf("%sstrict ", prefix);
439 +}
440 +
441 +static void print(const struct ip6t_ip6 *ip,
442 +                  const struct ip6t_entry_match *match,
443 +                 int numeric)
444 +{
445 +       const struct ip6t_policy_info *info = (void *)match->data;
446 +       unsigned int i;
447 +
448 +       printf("policy match ");
449 +       print_flags("", info);
450 +       for (i = 0; i < info->len; i++) {
451 +               if (info->len > 1)
452 +                       printf("[%u] ", i);
453 +               print_entry("", &info->pol[i], numeric);
454 +       }
455 +
456 +       printf("\n");
457 +}
458 +
459 +static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
460 +{
461 +       const struct ip6t_policy_info *info = (void *)match->data;
462 +       unsigned int i;
463 +
464 +       print_flags("--", info);
465 +       for (i = 0; i < info->len; i++) {
466 +               print_entry("--", &info->pol[i], 0);
467 +               if (i + 1 < info->len)
468 +                       printf("--next ");
469 +       }
470 +}
471 +
472 +struct ip6tables_match policy = {
473 +       .name           = "policy",
474 +       .version        = IPTABLES_VERSION,
475 +       .size           = IP6T_ALIGN(sizeof(struct ip6t_policy_info)),
476 +       .userspacesize  = IP6T_ALIGN(sizeof(struct ip6t_policy_info)),
477 +       .help           = help,
478 +       .init           = init,
479 +       .parse          = parse,
480 +       .final_check    = final_check,
481 +       .print          = print,
482 +       .save           = save,
483 +       .extra_opts     = opts
484 +};
485 +
486 +void _init(void)
487 +{
488 +       register_match6(&policy);
489 +}
490 diff -Nur iptables.org/extensions/libipt_policy.c iptables/extensions/libipt_policy.c
491 --- iptables.org/extensions/libipt_policy.c     1970-01-01 01:00:00.000000000 +0100
492 +++ iptables/extensions/libipt_policy.c 2004-06-29 12:35:40.000000000 +0200
493 @@ -0,0 +1,431 @@
494 +/* Shared library add-on to iptables to add policy support. */
495 +#include <stdio.h>
496 +#include <netdb.h>
497 +#include <string.h>
498 +#include <stdlib.h>
499 +#include <syslog.h>
500 +#include <getopt.h>
501 +#include <netdb.h>
502 +#include <errno.h>
503 +#include <sys/socket.h>
504 +#include <netinet/in.h>
505 +#include <arpa/inet.h>
506 +#include <iptables.h>
507 +
508 +#include <linux/netfilter_ipv4/ip_tables.h>
509 +#include <linux/netfilter_ipv4/ipt_policy.h>
510 +
511 +/*
512 + * HACK: global pointer to current matchinfo for making
513 + * final checks and adjustments in final_check.
514 + */
515 +static struct ipt_policy_info *policy_info;
516 +
517 +static void help(void)
518 +{
519 +       printf(
520 +"policy v%s options:\n"
521 +"  --dir in|out                        match policy applied during decapsulation/\n"
522 +"                              policy to be applied during encapsulation\n"
523 +"  --pol none|ipsec            match policy\n"
524 +"  --strict                    match entire policy instead of single element\n"
525 +"                              at any position\n"
526 +"[!] --reqid reqid             match reqid\n"
527 +"[!] --spi spi                 match SPI\n"
528 +"[!] --proto proto             match protocol (ah/esp/ipcomp)\n"
529 +"[!] --mode mode               match mode (transport/tunnel)\n"
530 +"[!] --tunnel-src addr/mask    match tunnel source\n"
531 +"[!] --tunnel-dst addr/mask    match tunnel destination\n"
532 +"  --next                      begin next element in policy\n",
533 +       IPTABLES_VERSION);
534 +}
535 +
536 +static struct option opts[] =
537 +{
538 +       {
539 +               .name           = "dir",
540 +               .has_arg        = 1,
541 +               .val            = '1',
542 +       },
543 +       {
544 +               .name           = "pol",
545 +               .has_arg        = 1,
546 +               .val            = '2',
547 +       },
548 +       {
549 +               .name           = "strict",
550 +               .val            = '3'
551 +       },
552 +       {
553 +               .name           = "reqid",
554 +               .has_arg        = 1,
555 +               .val            = '4',
556 +       },
557 +       {
558 +               .name           = "spi",
559 +               .has_arg        = 1,
560 +               .val            = '5'
561 +       },
562 +       {
563 +               .name           = "tunnel-src",
564 +               .has_arg        = 1,
565 +               .val            = '6'
566 +       },
567 +       {
568 +               .name           = "tunnel-dst",
569 +               .has_arg        = 1,
570 +               .val            = '7'
571 +       },
572 +       {
573 +               .name           = "proto",
574 +               .has_arg        = 1,
575 +               .val            = '8'
576 +       },
577 +       {
578 +               .name           = "mode",
579 +               .has_arg        = 1,
580 +               .val            = '9'
581 +       },
582 +       {
583 +               .name           = "next",
584 +               .val            = 'a'
585 +       },
586 +       { }
587 +};
588 +
589 +static void init(struct ipt_entry_match *m, unsigned int *nfcache)
590 +{
591 +       *nfcache |= NFC_UNKNOWN;
592 +}
593 +
594 +static int parse_direction(char *s)
595 +{
596 +       if (strcmp(s, "in") == 0)
597 +               return POLICY_MATCH_IN;
598 +       if (strcmp(s, "out") == 0)
599 +               return POLICY_MATCH_OUT;
600 +       exit_error(PARAMETER_PROBLEM, "policy_match: invalid dir `%s'", s);
601 +}
602 +
603 +static int parse_policy(char *s)
604 +{
605 +       if (strcmp(s, "none") == 0)
606 +               return POLICY_MATCH_NONE;
607 +       if (strcmp(s, "ipsec") == 0)
608 +               return 0;
609 +       exit_error(PARAMETER_PROBLEM, "policy match: invalid policy `%s'", s);
610 +}
611 +
612 +static int parse_mode(char *s)
613 +{
614 +       if (strcmp(s, "transport") == 0)
615 +               return POLICY_MODE_TRANSPORT;
616 +       if (strcmp(s, "tunnel") == 0)
617 +               return POLICY_MODE_TUNNEL;
618 +       exit_error(PARAMETER_PROBLEM, "policy match: invalid mode `%s'", s);
619 +}
620 +
621 +static int parse(int c, char **argv, int invert, unsigned int *flags,
622 +                 const struct ipt_entry *entry,
623 +                 unsigned int *nfcache,
624 +                 struct ipt_entry_match **match)
625 +{
626 +       struct ipt_policy_info *info = (void *)(*match)->data;
627 +       struct ipt_policy_elem *e = &info->pol[info->len];
628 +       struct in_addr *addr = NULL, mask;
629 +       unsigned int naddr = 0;
630 +       int mode;
631 +
632 +       check_inverse(optarg, &invert, &optind, 0);
633 +
634 +       switch (c) {
635 +       case '1':
636 +               if (info->flags & (POLICY_MATCH_IN|POLICY_MATCH_OUT))
637 +                       exit_error(PARAMETER_PROBLEM,
638 +                                  "policy match: double --dir option");
639 +               if (invert)
640 +                       exit_error(PARAMETER_PROBLEM,
641 +                                  "policy match: can't invert --dir option");
642 +
643 +               info->flags |= parse_direction(argv[optind-1]);
644 +               break;
645 +       case '2':
646 +               if (invert)
647 +                       exit_error(PARAMETER_PROBLEM,
648 +                                  "policy match: can't invert --policy option");
649 +
650 +               info->flags |= parse_policy(argv[optind-1]);
651 +               break;
652 +       case '3':
653 +               if (info->flags & POLICY_MATCH_STRICT)
654 +                       exit_error(PARAMETER_PROBLEM,
655 +                                  "policy match: double --strict option");
656 +
657 +               if (invert)
658 +                       exit_error(PARAMETER_PROBLEM,
659 +                                  "policy match: can't invert --strict option");
660 +
661 +               info->flags |= POLICY_MATCH_STRICT;
662 +               break;
663 +       case '4':
664 +               if (e->match.reqid)
665 +                       exit_error(PARAMETER_PROBLEM,
666 +                                  "policy match: double --reqid option");
667 +
668 +               e->match.reqid = 1;
669 +               e->invert.reqid = invert;
670 +               e->reqid = strtol(argv[optind-1], NULL, 10);
671 +               break;
672 +       case '5':
673 +               if (e->match.spi)
674 +                       exit_error(PARAMETER_PROBLEM,
675 +                                  "policy match: double --spi option");
676 +               
677 +               e->match.spi = 1;
678 +               e->invert.spi = invert;
679 +               e->spi = strtol(argv[optind-1], NULL, 0x10);
680 +               break;
681 +       case '6':
682 +               if (e->match.saddr)
683 +                       exit_error(PARAMETER_PROBLEM,
684 +                                  "policy match: double --tunnel-src option");
685 +
686 +               parse_hostnetworkmask(argv[optind-1], &addr, &mask, &naddr);
687 +               if (naddr > 1)
688 +                       exit_error(PARAMETER_PROBLEM,
689 +                                  "policy match: name resolves to multiple IPs");
690 +
691 +               e->match.saddr = 1;
692 +               e->invert.saddr = invert;
693 +               e->saddr = addr[0].s_addr;
694 +               e->smask = mask.s_addr;
695 +                break;
696 +       case '7':
697 +               if (e->match.daddr)
698 +                       exit_error(PARAMETER_PROBLEM,
699 +                                  "policy match: double --tunnel-dst option");
700 +
701 +               parse_hostnetworkmask(argv[optind-1], &addr, &mask, &naddr);
702 +               if (naddr > 1)
703 +                       exit_error(PARAMETER_PROBLEM,
704 +                                  "policy match: name resolves to multiple IPs");
705 +
706 +               e->match.daddr = 1;
707 +               e->invert.daddr = invert;
708 +               e->daddr = addr[0].s_addr;
709 +               e->dmask = mask.s_addr;
710 +               break;
711 +       case '8':
712 +               if (e->match.proto)
713 +                       exit_error(PARAMETER_PROBLEM,
714 +                                  "policy match: double --proto option");
715 +
716 +               e->proto = parse_protocol(argv[optind-1]);
717 +               if (e->proto != IPPROTO_AH && e->proto != IPPROTO_ESP &&
718 +                   e->proto != IPPROTO_COMP)
719 +                       exit_error(PARAMETER_PROBLEM,
720 +                                  "policy match: protocol must ah/esp/ipcomp");
721 +               e->match.proto = 1;
722 +               e->invert.proto = invert;
723 +               break;
724 +       case '9':
725 +               if (e->match.mode)
726 +                       exit_error(PARAMETER_PROBLEM,
727 +                                  "policy match: double --mode option");
728 +               
729 +               mode = parse_mode(argv[optind-1]);
730 +               e->match.mode = 1;
731 +               e->invert.mode = invert;
732 +               e->mode = mode;
733 +               break;
734 +       case 'a':
735 +               if (invert)
736 +                       exit_error(PARAMETER_PROBLEM,
737 +                                  "policy match: can't invert --next option");
738 +
739 +               if (++info->len == POLICY_MAX_ELEM)
740 +                       exit_error(PARAMETER_PROBLEM,
741 +                                  "policy match: maximum policy depth reached");
742 +               break;
743 +       default:
744 +               return 0;
745 +       }
746 +
747 +       policy_info = info;
748 +       return 1;
749 +}
750 +
751 +static void final_check(unsigned int flags)
752 +{
753 +       struct ipt_policy_info *info = policy_info;
754 +       struct ipt_policy_elem *e;
755 +       int i;
756 +
757 +       if (info == NULL)
758 +               exit_error(PARAMETER_PROBLEM,
759 +                          "policy match: no parameters given");
760 +
761 +       if (!(info->flags & (POLICY_MATCH_IN|POLICY_MATCH_OUT)))
762 +               exit_error(PARAMETER_PROBLEM,
763 +                          "policy match: neither --in nor --out specified");
764 +
765 +       if (info->flags & POLICY_MATCH_NONE) {
766 +               if (info->flags & POLICY_MATCH_STRICT)
767 +                       exit_error(PARAMETER_PROBLEM,
768 +                                  "policy match: policy none but --strict given");
769 +
770 +               if (info->len != 0)
771 +                       exit_error(PARAMETER_PROBLEM,
772 +                                  "policy match: policy none but policy given");
773 +       } else
774 +               info->len++;    /* increase len by 1, no --next after last element */
775 +
776 +       if (!(info->flags & POLICY_MATCH_STRICT) && info->len > 1)
777 +               exit_error(PARAMETER_PROBLEM,
778 +                          "policy match: multiple elements but no --strict");
779 +
780 +       for (i = 0; i < info->len; i++) {
781 +               e = &info->pol[i];
782 +               if ((e->match.saddr || e->match.daddr)
783 +                   && ((e->mode == POLICY_MODE_TUNNEL && e->invert.mode) ||
784 +                       (e->mode == POLICY_MODE_TRANSPORT && !e->invert.mode)))
785 +                       exit_error(PARAMETER_PROBLEM,
786 +                                  "policy match: --tunnel-src/--tunnel-dst "
787 +                                  "is only valid in tunnel mode");
788 +       }
789 +}
790 +
791 +static void print_mode(char *prefix, u_int8_t mode, int numeric)
792 +{
793 +       printf("%smode ", prefix);
794 +
795 +       switch (mode) {
796 +       case POLICY_MODE_TRANSPORT:
797 +               printf("transport ");
798 +               break;
799 +       case POLICY_MODE_TUNNEL:
800 +               printf("tunnel ");
801 +               break;
802 +       default:
803 +               printf("??? ");
804 +               break;
805 +       }
806 +}
807 +
808 +static void print_proto(char *prefix, u_int8_t proto, int numeric)
809 +{
810 +       struct protoent *p = NULL;
811 +
812 +       printf("%sproto ", prefix);
813 +       if (!numeric)
814 +               p = getprotobynumber(proto);
815 +       if (p != NULL)
816 +               printf("%s ", p->p_name);
817 +       else
818 +               printf("%u ", proto);
819 +}
820 +
821 +#define PRINT_INVERT(x)                \
822 +do {                           \
823 +       if (x)                  \
824 +               printf("! ");   \
825 +} while(0)
826 +
827 +static void print_entry(char *prefix, const struct ipt_policy_elem *e,
828 +                        int numeric)
829 +{
830 +       if (e->match.reqid) {
831 +               PRINT_INVERT(e->invert.reqid);
832 +               printf("%sreqid %u ", prefix, e->reqid);
833 +       }
834 +       if (e->match.spi) {
835 +               PRINT_INVERT(e->invert.spi);
836 +               printf("%sspi 0x%x ", prefix, e->spi);
837 +       }
838 +       if (e->match.proto) {
839 +               PRINT_INVERT(e->invert.proto);
840 +               print_proto(prefix, e->proto, numeric);
841 +       }
842 +       if (e->match.mode) {
843 +               PRINT_INVERT(e->invert.mode);
844 +               print_mode(prefix, e->mode, numeric);
845 +       }
846 +       if (e->match.daddr) {
847 +               PRINT_INVERT(e->invert.daddr);
848 +               printf("%stunnel-dst %s%s ", prefix,
849 +                      addr_to_dotted((struct in_addr *)&e->daddr),
850 +                      mask_to_dotted((struct in_addr *)&e->dmask));
851 +       }
852 +       if (e->match.saddr) {
853 +               PRINT_INVERT(e->invert.saddr);
854 +               printf("%stunnel-src %s%s ", prefix,
855 +                      addr_to_dotted((struct in_addr *)&e->saddr),
856 +                      mask_to_dotted((struct in_addr *)&e->smask));
857 +       }
858 +}
859 +
860 +static void print_flags(char *prefix, const struct ipt_policy_info *info)
861 +{
862 +       if (info->flags & POLICY_MATCH_IN)
863 +               printf("%sdir in ", prefix);
864 +       else
865 +               printf("%sdir out ", prefix);
866 +
867 +       if (info->flags & POLICY_MATCH_NONE)
868 +               printf("%spol none ", prefix);
869 +       else
870 +               printf("%spol ipsec ", prefix);
871 +
872 +       if (info->flags & POLICY_MATCH_STRICT)
873 +               printf("%sstrict ", prefix);
874 +}
875 +
876 +static void print(const struct ipt_ip *ip,
877 +                  const struct ipt_entry_match *match,
878 +                 int numeric)
879 +{
880 +       const struct ipt_policy_info *info = (void *)match->data;
881 +       unsigned int i;
882 +
883 +       printf("policy match ");
884 +       print_flags("", info);
885 +       for (i = 0; i < info->len; i++) {
886 +               if (info->len > 1)
887 +                       printf("[%u] ", i);
888 +               print_entry("", &info->pol[i], numeric);
889 +       }
890 +}
891 +
892 +static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
893 +{
894 +       const struct ipt_policy_info *info = (void *)match->data;
895 +       unsigned int i;
896 +
897 +       print_flags("--", info);
898 +       for (i = 0; i < info->len; i++) {
899 +               print_entry("--", &info->pol[i], 0);
900 +               if (i + 1 < info->len)
901 +                       printf("--next ");
902 +       }
903 +
904 +       printf("\n");
905 +}
906 +
907 +struct iptables_match policy = {
908 +       .name           = "policy",
909 +       .version        = IPTABLES_VERSION,
910 +       .size           = IPT_ALIGN(sizeof(struct ipt_policy_info)),
911 +       .userspacesize  = IPT_ALIGN(sizeof(struct ipt_policy_info)),
912 +       .help           = help,
913 +       .init           = init,
914 +       .parse          = parse,
915 +       .final_check    = final_check,
916 +       .print          = print,
917 +       .save           = save,
918 +       .extra_opts     = opts
919 +};
920 +
921 +void _init(void)
922 +{
923 +       register_match(&policy);
924 +}
925 diff -Nur iptables.org/extensions/libipt_policy.man iptables/extensions/libipt_policy.man
926 --- iptables.org/extensions/libipt_policy.man   1970-01-01 01:00:00.000000000 +0100
927 +++ iptables/extensions/libipt_policy.man       2004-06-29 12:35:40.000000000 +0200
928 @@ -0,0 +1,46 @@
929 +This modules matches the policy used by IPsec for handling a packet.
930 +.TP
931 +.BI "--dir " "in|out"
932 +Used to select whether to match the policy used for decapsulation or the
933 +policy that will be used for encapsulation.
934 +.B in
935 +is valid in the
936 +.B PREROUTING, INPUT and FORWARD
937 +chains,
938 +.B out
939 +is valid in the
940 +.B POSTROUTING, OUTPUT and FORWARD
941 +chains.
942 +.TP
943 +.BI "--pol " "none|ipsec"
944 +Matches if the packet is subject to IPsec processing.
945 +.TP
946 +.BI "--strict"
947 +Selects whether to match the exact policy or match if any rule of
948 +the policy matches the given policy.
949 +.TP
950 +.BI "--reqid " "id"
951 +Matches the reqid of the policy rule. The reqid can be specified with
952 +.B setkey(8)
953 +using
954 +.B unique:id
955 +as level.
956 +.TP
957 +.BI "--spi " "spi"
958 +Matches the SPI of the SA.
959 +.TP
960 +.BI "--proto " "ah|esp|ipcomp"
961 +Matches the encapsulation protocol.
962 +.TP
963 +.BI "--mode " "tunnel|transport"
964 +Matches the encapsulation mode.
965 +.TP
966 +.BI "--tunnel-src " "addr[/mask]"
967 +Matches the source address of a tunnel. Only valid with --mode tunnel.
968 +.TP
969 +.BI "--tunnel-dst " "addr[/mask]"
970 +Matches the destination address of a tunnel. Only valid with --mode tunnel.
971 +.TP
972 +.BI "--next"
973 +Start the next element in the policy specification. Can only be used with
974 +--strict
975 diff -Nur iptables.org/include/libipq/libipq.h iptables/include/libipq/libipq.h
976 --- iptables.org/include/libipq/libipq.h        2003-09-07 12:09:22.000000000 +0200
977 +++ iptables/include/libipq/libipq.h    2004-06-29 12:35:08.000000000 +0200
978 @@ -79,6 +79,13 @@
979                      size_t data_len,
980                      unsigned char *buf);
981  
982 +int ipq_set_vwmark(const struct ipq_handle *h,
983 +                    ipq_id_t id,
984 +                    unsigned int verdict,
985 +                    unsigned long nfmark,
986 +                    size_t data_len,
987 +                    unsigned char *buf);
988 +
989  int ipq_ctl(const struct ipq_handle *h, int request, ...);
990  
991  char *ipq_errstr(void);
992 diff -Nur iptables.org/libipq/libipq.c iptables/libipq/libipq.c
993 --- iptables.org/libipq/libipq.c        2003-11-14 20:17:45.000000000 +0100
994 +++ iptables/libipq/libipq.c    2004-06-29 12:35:08.000000000 +0200
995 @@ -352,6 +352,54 @@
996         return ipq_netlink_sendmsg(h, &msg, 0);
997  }
998  
999 +int ipq_set_vwmark(const struct ipq_handle *h,
1000 +                    ipq_id_t id,
1001 +                    unsigned int verdict,
1002 +                    unsigned long nfmark,
1003 +                    size_t data_len,
1004 +                    unsigned char *buf)
1005 +{
1006 +       unsigned char nvecs;
1007 +       size_t tlen;
1008 +       struct nlmsghdr nlh;
1009 +       ipq_peer_msg_t pm;
1010 +       struct iovec iov[3];
1011 +       struct msghdr msg;
1012 +
1013 +       memset(&nlh, 0, sizeof(nlh));
1014 +       nlh.nlmsg_flags = NLM_F_REQUEST;
1015 +       nlh.nlmsg_type = IPQM_VWMARK;
1016 +       nlh.nlmsg_pid = h->local.nl_pid;
1017 +       memset(&pm, 0, sizeof(pm));
1018 +       pm.msg.vwmark.value = verdict;
1019 +       pm.msg.vwmark.id = id;
1020 +       pm.msg.vwmark.data_len = data_len;
1021 +       pm.msg.vwmark.nfmark = nfmark;
1022 +       iov[0].iov_base = &nlh;
1023 +       iov[0].iov_len = sizeof(nlh);
1024 +       iov[1].iov_base = &pm;
1025 +       iov[1].iov_len = sizeof(pm);
1026 +       tlen = sizeof(nlh) + sizeof(pm);
1027 +       nvecs = 2;
1028 +       if (data_len && buf) {
1029 +               iov[2].iov_base = buf;
1030 +               iov[2].iov_len = data_len;
1031 +               tlen += data_len;
1032 +               nvecs++;
1033 +       }
1034 +       msg.msg_name = (void *)&h->peer;
1035 +       msg.msg_namelen = sizeof(h->peer);
1036 +       msg.msg_iov = iov;
1037 +       msg.msg_iovlen = nvecs;
1038 +       msg.msg_control = NULL;
1039 +       msg.msg_controllen = 0;
1040 +       msg.msg_flags = 0;
1041 +       nlh.nlmsg_len = tlen;
1042 +       return ipq_netlink_sendmsg(h, &msg, 0);
1043 +}
1044 +
1045 +
1046 +
1047  /* Not implemented yet */
1048  int ipq_ctl(const struct ipq_handle *h, int request, ...)
1049  {
1050 diff -Nur iptables.org/libipq/libipq.c.orig iptables/libipq/libipq.c.orig
1051 --- iptables.org/libipq/libipq.c.orig   1970-01-01 01:00:00.000000000 +0100
1052 +++ iptables/libipq/libipq.c.orig       2003-11-14 20:17:45.000000000 +0100
1053 @@ -0,0 +1,377 @@
1054 +/*
1055 + * libipq.c
1056 + *
1057 + * IPQ userspace library.
1058 + *
1059 + * Please note that this library is still developmental, and there may
1060 + * be some API changes.
1061 + *
1062 + * Author: James Morris <jmorris@intercode.com.au>
1063 + *
1064 + * 07-11-2001 Modified by Fernando Anton to add support for IPv6.
1065 + *
1066 + * Copyright (c) 2000-2001 Netfilter Core Team
1067 + *
1068 + * This program is free software; you can redistribute it and/or modify
1069 + * it under the terms of the GNU General Public License as published by
1070 + * the Free Software Foundation; either version 2 of the License, or
1071 + * (at your option) any later version.
1072 + *
1073 + * This program is distributed in the hope that it will be useful,
1074 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1075 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1076 + * GNU General Public License for more details.
1077 + *
1078 + */
1079 +
1080 +#include <stdlib.h>
1081 +#include <stdio.h>
1082 +#include <string.h>
1083 +#include <unistd.h>
1084 +#include <sys/time.h>
1085 +#include <sys/types.h>
1086 +
1087 +#include <libipq/libipq.h>
1088 +
1089 +/****************************************************************************
1090 + *
1091 + * Private interface
1092 + *
1093 + ****************************************************************************/
1094 +
1095 +enum {
1096 +       IPQ_ERR_NONE = 0,
1097 +       IPQ_ERR_IMPL,
1098 +       IPQ_ERR_HANDLE,
1099 +       IPQ_ERR_SOCKET,
1100 +       IPQ_ERR_BIND,
1101 +       IPQ_ERR_BUFFER,
1102 +       IPQ_ERR_RECV,
1103 +       IPQ_ERR_NLEOF,
1104 +       IPQ_ERR_ADDRLEN,
1105 +       IPQ_ERR_STRUNC,
1106 +       IPQ_ERR_RTRUNC,
1107 +       IPQ_ERR_NLRECV,
1108 +       IPQ_ERR_SEND,
1109 +       IPQ_ERR_SUPP,
1110 +       IPQ_ERR_RECVBUF,
1111 +       IPQ_ERR_TIMEOUT,
1112 +        IPQ_ERR_PROTOCOL
1113 +};
1114 +#define IPQ_MAXERR IPQ_ERR_PROTOCOL
1115 +
1116 +struct ipq_errmap_t {
1117 +       int errcode;
1118 +       char *message;
1119 +} ipq_errmap[] = {
1120 +       { IPQ_ERR_NONE, "Unknown error" },
1121 +       { IPQ_ERR_IMPL, "Implementation error" },
1122 +       { IPQ_ERR_HANDLE, "Unable to create netlink handle" },
1123 +       { IPQ_ERR_SOCKET, "Unable to create netlink socket" },
1124 +       { IPQ_ERR_BIND, "Unable to bind netlink socket" },
1125 +       { IPQ_ERR_BUFFER, "Unable to allocate buffer" },
1126 +       { IPQ_ERR_RECV, "Failed to receive netlink message" },
1127 +       { IPQ_ERR_NLEOF, "Received EOF on netlink socket" },
1128 +       { IPQ_ERR_ADDRLEN, "Invalid peer address length" },
1129 +       { IPQ_ERR_STRUNC, "Sent message truncated" },
1130 +       { IPQ_ERR_RTRUNC, "Received message truncated" },
1131 +       { IPQ_ERR_NLRECV, "Received error from netlink" },
1132 +       { IPQ_ERR_SEND, "Failed to send netlink message" },
1133 +       { IPQ_ERR_SUPP, "Operation not supported" },
1134 +       { IPQ_ERR_RECVBUF, "Receive buffer size invalid" },
1135 +       { IPQ_ERR_TIMEOUT, "Timeout"},
1136 +       { IPQ_ERR_PROTOCOL, "Invalid protocol specified" }
1137 +};
1138 +
1139 +static int ipq_errno = IPQ_ERR_NONE;
1140 +
1141 +static ssize_t ipq_netlink_sendto(const struct ipq_handle *h,
1142 +                                  const void *msg, size_t len);
1143 +
1144 +static ssize_t ipq_netlink_recvfrom(const struct ipq_handle *h,
1145 +                                    unsigned char *buf, size_t len,
1146 +                                    int timeout);
1147 +
1148 +static ssize_t ipq_netlink_sendmsg(const struct ipq_handle *h,
1149 +                                   const struct msghdr *msg,
1150 +                                   unsigned int flags);
1151 +
1152 +static char *ipq_strerror(int errcode);
1153 +
1154 +static ssize_t ipq_netlink_sendto(const struct ipq_handle *h,
1155 +                                  const void *msg, size_t len)
1156 +{
1157 +       int status = sendto(h->fd, msg, len, 0,
1158 +                           (struct sockaddr *)&h->peer, sizeof(h->peer));
1159 +       if (status < 0)
1160 +               ipq_errno = IPQ_ERR_SEND;
1161 +       return status;
1162 +}
1163 +
1164 +static ssize_t ipq_netlink_sendmsg(const struct ipq_handle *h,
1165 +                                   const struct msghdr *msg,
1166 +                                   unsigned int flags)
1167 +{
1168 +       int status = sendmsg(h->fd, msg, flags);
1169 +       if (status < 0)
1170 +               ipq_errno = IPQ_ERR_SEND;
1171 +       return status;
1172 +}
1173 +
1174 +static ssize_t ipq_netlink_recvfrom(const struct ipq_handle *h,
1175 +                                    unsigned char *buf, size_t len,
1176 +                                    int timeout)
1177 +{
1178 +       int addrlen, status;
1179 +       struct nlmsghdr *nlh;
1180 +
1181 +       if (len < sizeof(struct nlmsgerr)) {
1182 +               ipq_errno = IPQ_ERR_RECVBUF;
1183 +               return -1;
1184 +       }
1185 +       addrlen = sizeof(h->peer);
1186 +
1187 +       if (timeout != 0) {
1188 +               int ret;
1189 +               struct timeval tv;
1190 +               fd_set read_fds;
1191 +               
1192 +               if (timeout < 0) {
1193 +                       /* non-block non-timeout */
1194 +                       tv.tv_sec = 0;
1195 +                       tv.tv_usec = 0;
1196 +               } else {
1197 +                       tv.tv_sec = timeout / 1000000;
1198 +                       tv.tv_usec = timeout % 1000000;
1199 +               }
1200 +
1201 +               FD_ZERO(&read_fds);
1202 +               FD_SET(h->fd, &read_fds);
1203 +               ret = select(h->fd+1, &read_fds, NULL, NULL, &tv);
1204 +               if (ret < 0) {
1205 +                       if (errno == EINTR) {
1206 +                               return 0;
1207 +                       } else {
1208 +                               ipq_errno = IPQ_ERR_RECV;
1209 +                               return -1;
1210 +                       }
1211 +               }
1212 +               if (!FD_ISSET(h->fd, &read_fds)) {
1213 +                       ipq_errno = IPQ_ERR_TIMEOUT;
1214 +                       return 0;
1215 +               }
1216 +       }
1217 +       status = recvfrom(h->fd, buf, len, 0,
1218 +                             (struct sockaddr *)&h->peer, &addrlen);
1219 +       if (status < 0) {
1220 +               ipq_errno = IPQ_ERR_RECV;
1221 +               return status;
1222 +       }
1223 +       if (addrlen != sizeof(h->peer)) {
1224 +               ipq_errno = IPQ_ERR_RECV;
1225 +               return -1;
1226 +       }
1227 +       if (h->peer.nl_pid != 0) {
1228 +               ipq_errno = IPQ_ERR_RECV;
1229 +               return -1;
1230 +       }
1231 +       if (status == 0) {
1232 +               ipq_errno = IPQ_ERR_NLEOF;
1233 +               return -1;
1234 +       }
1235 +       nlh = (struct nlmsghdr *)buf;
1236 +       if (nlh->nlmsg_flags & MSG_TRUNC || nlh->nlmsg_len > status) {
1237 +               ipq_errno = IPQ_ERR_RTRUNC;
1238 +               return -1;
1239 +       }
1240 +       return status;
1241 +}
1242 +
1243 +static char *ipq_strerror(int errcode)
1244 +{
1245 +       if (errcode < 0 || errcode > IPQ_MAXERR)
1246 +               errcode = IPQ_ERR_IMPL;
1247 +       return ipq_errmap[errcode].message;
1248 +}
1249 +
1250 +/****************************************************************************
1251 + *
1252 + * Public interface
1253 + *
1254 + ****************************************************************************/
1255 +
1256 +/*
1257 + * Create and initialise an ipq handle.
1258 + */
1259 +struct ipq_handle *ipq_create_handle(u_int32_t flags, u_int32_t protocol)
1260 +{
1261 +       int status;
1262 +       struct ipq_handle *h;
1263 +
1264 +       h = (struct ipq_handle *)malloc(sizeof(struct ipq_handle));
1265 +       if (h == NULL) {
1266 +               ipq_errno = IPQ_ERR_HANDLE;
1267 +               return NULL;
1268 +       }
1269 +       
1270 +       memset(h, 0, sizeof(struct ipq_handle));
1271 +       
1272 +        if (protocol == PF_INET)
1273 +                h->fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_FIREWALL);
1274 +        else if (protocol == PF_INET6)
1275 +                h->fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_IP6_FW);
1276 +        else {
1277 +               ipq_errno = IPQ_ERR_PROTOCOL;
1278 +               free(h);
1279 +               return NULL;
1280 +        }
1281 +        
1282 +       if (h->fd == -1) {
1283 +               ipq_errno = IPQ_ERR_SOCKET;
1284 +               close(h->fd);
1285 +               free(h);
1286 +               return NULL;
1287 +       }
1288 +       memset(&h->local, 0, sizeof(struct sockaddr_nl));
1289 +       h->local.nl_family = AF_NETLINK;
1290 +       h->local.nl_pid = getpid();
1291 +       h->local.nl_groups = 0;
1292 +       status = bind(h->fd, (struct sockaddr *)&h->local, sizeof(h->local));
1293 +       if (status == -1) {
1294 +               ipq_errno = IPQ_ERR_BIND;
1295 +               close(h->fd);
1296 +               free(h);
1297 +               return NULL;
1298 +       }
1299 +       memset(&h->peer, 0, sizeof(struct sockaddr_nl));
1300 +       h->peer.nl_family = AF_NETLINK;
1301 +       h->peer.nl_pid = 0;
1302 +       h->peer.nl_groups = 0;
1303 +       return h;
1304 +}
1305 +
1306 +/*
1307 + * No error condition is checked here at this stage, but it may happen
1308 + * if/when reliable messaging is implemented.
1309 + */
1310 +int ipq_destroy_handle(struct ipq_handle *h)
1311 +{
1312 +       if (h) {
1313 +               close(h->fd);
1314 +               free(h);
1315 +       }
1316 +       return 0;
1317 +}
1318 +
1319 +int ipq_set_mode(const struct ipq_handle *h,
1320 +                 u_int8_t mode, size_t range)
1321 +{
1322 +       struct {
1323 +               struct nlmsghdr nlh;
1324 +               ipq_peer_msg_t pm;
1325 +       } req;
1326 +
1327 +       memset(&req, 0, sizeof(req));
1328 +       req.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(req));
1329 +       req.nlh.nlmsg_flags = NLM_F_REQUEST;
1330 +       req.nlh.nlmsg_type = IPQM_MODE;
1331 +       req.nlh.nlmsg_pid = h->local.nl_pid;
1332 +       req.pm.msg.mode.value = mode;
1333 +       req.pm.msg.mode.range = range;
1334 +       return ipq_netlink_sendto(h, (void *)&req, req.nlh.nlmsg_len);
1335 +}
1336 +
1337 +/*
1338 + * timeout is in microseconds (1 second is 1000000 (1 million) microseconds)
1339 + *
1340 + */
1341 +ssize_t ipq_read(const struct ipq_handle *h,
1342 +                 unsigned char *buf, size_t len, int timeout)
1343 +{
1344 +       return ipq_netlink_recvfrom(h, buf, len, timeout);
1345 +}
1346 +
1347 +int ipq_message_type(const unsigned char *buf)
1348 +{
1349 +       return ((struct nlmsghdr*)buf)->nlmsg_type;
1350 +}
1351 +
1352 +int ipq_get_msgerr(const unsigned char *buf)
1353 +{
1354 +       struct nlmsghdr *h = (struct nlmsghdr *)buf;
1355 +       struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h);
1356 +       return -err->error;
1357 +}
1358 +
1359 +ipq_packet_msg_t *ipq_get_packet(const unsigned char *buf)
1360 +{
1361 +       return NLMSG_DATA((struct nlmsghdr *)(buf));
1362 +}
1363 +
1364 +int ipq_set_verdict(const struct ipq_handle *h,
1365 +                    ipq_id_t id,
1366 +                    unsigned int verdict,
1367 +                    size_t data_len,
1368 +                    unsigned char *buf)
1369 +{
1370 +       unsigned char nvecs;
1371 +       size_t tlen;
1372 +       struct nlmsghdr nlh;
1373 +       ipq_peer_msg_t pm;
1374 +       struct iovec iov[3];
1375 +       struct msghdr msg;
1376 +
1377 +       memset(&nlh, 0, sizeof(nlh));
1378 +       nlh.nlmsg_flags = NLM_F_REQUEST;
1379 +       nlh.nlmsg_type = IPQM_VERDICT;
1380 +       nlh.nlmsg_pid = h->local.nl_pid;
1381 +       memset(&pm, 0, sizeof(pm));
1382 +       pm.msg.verdict.value = verdict;
1383 +       pm.msg.verdict.id = id;
1384 +       pm.msg.verdict.data_len = data_len;
1385 +       iov[0].iov_base = &nlh;
1386 +       iov[0].iov_len = sizeof(nlh);
1387 +       iov[1].iov_base = &pm;
1388 +       iov[1].iov_len = sizeof(pm);
1389 +       tlen = sizeof(nlh) + sizeof(pm);
1390 +       nvecs = 2;
1391 +       if (data_len && buf) {
1392 +               iov[2].iov_base = buf;
1393 +               iov[2].iov_len = data_len;
1394 +               tlen += data_len;
1395 +               nvecs++;
1396 +       }
1397 +       msg.msg_name = (void *)&h->peer;
1398 +       msg.msg_namelen = sizeof(h->peer);
1399 +       msg.msg_iov = iov;
1400 +       msg.msg_iovlen = nvecs;
1401 +       msg.msg_control = NULL;
1402 +       msg.msg_controllen = 0;
1403 +       msg.msg_flags = 0;
1404 +       nlh.nlmsg_len = tlen;
1405 +       return ipq_netlink_sendmsg(h, &msg, 0);
1406 +}
1407 +
1408 +/* Not implemented yet */
1409 +int ipq_ctl(const struct ipq_handle *h, int request, ...)
1410 +{
1411 +       return 1;
1412 +}
1413 +
1414 +char *ipq_errstr(void)
1415 +{
1416 +       return ipq_strerror(ipq_errno);
1417 +}
1418 +
1419 +void ipq_perror(const char *s)
1420 +{
1421 +       if (s)
1422 +               fputs(s, stderr);
1423 +       else
1424 +               fputs("ERROR", stderr);
1425 +       if (ipq_errno)
1426 +               fprintf(stderr, ": %s", ipq_errstr());
1427 +       if (errno)
1428 +               fprintf(stderr, ": %s", strerror(errno));
1429 +       fputc('\n', stderr);
1430 +}
This page took 1.173447 seconds and 3 git commands to generate.