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-05-18 12:39:55.000000000 +0200
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-05-18 12:39:55.000000000 +0200
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-05-18 12:39:55.000000000 +0200
19 +/* Shared library add-on to iptables to add policy support. */
29 +#include <sys/socket.h>
30 +#include <netinet/in.h>
31 +#include <arpa/inet.h>
32 +#include <ip6tables.h>
34 +#include <linux/netfilter_ipv6/ip6_tables.h>
35 +#include <linux/netfilter_ipv6/ip6t_policy.h>
38 + * HACK: global pointer to current matchinfo for making
39 + * final checks and adjustments in final_check.
41 +static struct ip6t_policy_info *policy_info;
43 +static void help(void)
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"
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",
62 +static struct option opts[] =
89 + .name = "tunnel-src",
94 + .name = "tunnel-dst",
115 +/* FIXME - Duplicated code from ip6tables.c */
116 +/* Duplicated to stop too many changes in other files .... */
118 +in6addrcpy(struct in6_addr *dst, struct in6_addr *src)
120 + memcpy(dst, src, sizeof(struct in6_addr));
121 + /* dst->s6_addr = src->s6_addr; */
125 +addr_to_numeric(const struct in6_addr *addrp)
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));
134 +mask_to_numeric(const struct in6_addr *addrp)
136 + static char buf[50+2];
137 + int l = ipv6_prefix_length(addrp);
140 + strcat(buf, addr_to_numeric(addrp));
143 + sprintf(buf, "/%d", l);
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);
152 +/* End duplicated code from ip6tables.c */
154 +static void init(struct ip6t_entry_match *m, unsigned int *nfcache)
156 + *nfcache |= NFC_UNKNOWN;
159 +static int parse_direction(char *s)
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);
168 +static int parse_policy(char *s)
170 + if (strcmp(s, "none") == 0)
171 + return POLICY_MATCH_NONE;
172 + if (strcmp(s, "ipsec") == 0)
174 + exit_error(PARAMETER_PROBLEM, "policy match: invalid policy `%s'", s);
177 +static int parse_mode(char *s)
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);
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)
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;
197 + check_inverse(optarg, &invert, &optind, 0);
201 + if (info->flags & (POLICY_MATCH_IN|POLICY_MATCH_OUT))
202 + exit_error(PARAMETER_PROBLEM,
203 + "policy match: double --dir option");
205 + exit_error(PARAMETER_PROBLEM,
206 + "policy match: can't invert --dir option");
208 + info->flags |= parse_direction(argv[optind-1]);
212 + exit_error(PARAMETER_PROBLEM,
213 + "policy match: can't invert --policy option");
215 + info->flags |= parse_policy(argv[optind-1]);
218 + if (info->flags & POLICY_MATCH_STRICT)
219 + exit_error(PARAMETER_PROBLEM,
220 + "policy match: double --strict option");
223 + exit_error(PARAMETER_PROBLEM,
224 + "policy match: can't invert --strict option");
226 + info->flags |= POLICY_MATCH_STRICT;
229 + if (e->match.reqid)
230 + exit_error(PARAMETER_PROBLEM,
231 + "policy match: double --reqid option");
233 + e->match.reqid = 1;
234 + e->invert.reqid = invert;
235 + e->reqid = strtol(argv[optind-1], NULL, 10);
239 + exit_error(PARAMETER_PROBLEM,
240 + "policy match: double --spi option");
243 + e->invert.spi = invert;
244 + e->spi = strtol(argv[optind-1], NULL, 0x10);
247 + if (e->match.saddr)
248 + exit_error(PARAMETER_PROBLEM,
249 + "policy match: double --tunnel-src option");
251 + parse_hostnetworkmask(argv[optind-1], &addr, &mask, &naddr);
253 + exit_error(PARAMETER_PROBLEM,
254 + "policy match: name resolves to multiple IPs");
256 + e->match.saddr = 1;
257 + e->invert.saddr = invert;
258 + in6addrcpy(&e->daddr, addr);
259 + in6addrcpy(&e->dmask, &mask);
262 + if (e->match.daddr)
263 + exit_error(PARAMETER_PROBLEM,
264 + "policy match: double --tunnel-dst option");
266 + parse_hostnetworkmask(argv[optind-1], &addr, &mask, &naddr);
268 + exit_error(PARAMETER_PROBLEM,
269 + "policy match: name resolves to multiple IPs");
271 + e->match.daddr = 1;
272 + e->invert.daddr = invert;
273 + in6addrcpy(&e->daddr, addr);
274 + in6addrcpy(&e->dmask, &mask);
277 + if (e->match.proto)
278 + exit_error(PARAMETER_PROBLEM,
279 + "policy match: double --proto option");
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;
291 + exit_error(PARAMETER_PROBLEM,
292 + "policy match: double --mode option");
294 + mode = parse_mode(argv[optind-1]);
296 + e->invert.mode = invert;
301 + exit_error(PARAMETER_PROBLEM,
302 + "policy match: can't invert --next option");
304 + if (++info->len == POLICY_MAX_ELEM)
305 + exit_error(PARAMETER_PROBLEM,
306 + "policy match: maximum policy depth reached");
312 + policy_info = info;
316 +static void final_check(unsigned int flags)
318 + struct ip6t_policy_info *info = policy_info;
319 + struct ip6t_policy_elem *e;
323 + exit_error(PARAMETER_PROBLEM,
324 + "policy match: no parameters given");
326 + if (!(info->flags & (POLICY_MATCH_IN|POLICY_MATCH_OUT)))
327 + exit_error(PARAMETER_PROBLEM,
328 + "policy match: neither --in nor --out specified");
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");
335 + if (info->len != 0)
336 + exit_error(PARAMETER_PROBLEM,
337 + "policy match: policy none but policy given");
339 + info->len++; /* increase len by 1, no --next after last element */
341 + if (!(info->flags & POLICY_MATCH_STRICT) && info->len > 1)
342 + exit_error(PARAMETER_PROBLEM,
343 + "policy match: multiple elements but no --strict");
345 + for (i = 0; i < info->len; 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");
356 +static void print_mode(char *prefix, u_int8_t mode, int numeric)
358 + printf("%smode ", prefix);
361 + case POLICY_MODE_TRANSPORT:
362 + printf("transport ");
364 + case POLICY_MODE_TUNNEL:
373 +static void print_proto(char *prefix, u_int8_t proto, int numeric)
375 + struct protoent *p = NULL;
377 + printf("%sproto ", prefix);
379 + p = getprotobynumber(proto);
381 + printf("%s ", p->p_name);
383 + printf("%u ", proto);
386 +#define PRINT_INVERT(x) \
392 +static void print_entry(char *prefix, const struct ip6t_policy_elem *e,
395 + if (e->match.reqid) {
396 + PRINT_INVERT(e->invert.reqid);
397 + printf("%sreqid %u ", prefix, e->reqid);
399 + if (e->match.spi) {
400 + PRINT_INVERT(e->invert.spi);
401 + printf("%sspi 0x%x ", prefix, e->spi);
403 + if (e->match.proto) {
404 + PRINT_INVERT(e->invert.proto);
405 + print_proto(prefix, e->proto, numeric);
407 + if (e->match.mode) {
408 + PRINT_INVERT(e->invert.mode);
409 + print_mode(prefix, e->mode, numeric);
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));
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));
425 +static void print_flags(char *prefix, const struct ip6t_policy_info *info)
427 + if (info->flags & POLICY_MATCH_IN)
428 + printf("%sdir in ", prefix);
430 + printf("%sdir out ", prefix);
432 + if (info->flags & POLICY_MATCH_NONE)
433 + printf("%spol none ", prefix);
435 + printf("%spol ipsec ", prefix);
437 + if (info->flags & POLICY_MATCH_STRICT)
438 + printf("%sstrict ", prefix);
441 +static void print(const struct ip6t_ip6 *ip,
442 + const struct ip6t_entry_match *match,
445 + const struct ip6t_policy_info *info = (void *)match->data;
448 + printf("policy match ");
449 + print_flags("", info);
450 + for (i = 0; i < info->len; i++) {
452 + printf("[%u] ", i);
453 + print_entry("", &info->pol[i], numeric);
459 +static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
461 + const struct ip6t_policy_info *info = (void *)match->data;
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)
472 +struct ip6tables_match policy = {
474 + .version = IPTABLES_VERSION,
475 + .size = IP6T_ALIGN(sizeof(struct ip6t_policy_info)),
476 + .userspacesize = IP6T_ALIGN(sizeof(struct ip6t_policy_info)),
480 + .final_check = final_check,
488 + register_match6(&policy);
490 diff -Nur iptables.org/extensions/libipt_MARK.c iptables/extensions/libipt_MARK.c
491 --- iptables.org/extensions/libipt_MARK.c 2002-08-06 20:46:18.000000000 +0200
492 +++ iptables/extensions/libipt_MARK.c 2004-05-18 12:38:18.000000000 +0200
495 "MARK target v%s options:\n"
496 " --set-mark value Set nfmark value\n"
497 +" --and-mark value Binary AND the nfmark with value\n"
498 +" --or-mark value Binary OR the nfmark with value\n"
503 static struct option opts[] = {
504 { "set-mark", 1, 0, '1' },
505 + { "and-mark", 1, 0, '2' },
506 + { "or-mark", 1, 0, '3' },
511 struct ipt_mark_target_info *markinfo
512 = (struct ipt_mark_target_info *)(*target)->data;
516 + if ((c == '1') || (c == '2') || (c == '3')) {
518 + exit_error(PARAMETER_PROBLEM, "MARK: can only specify "
521 + exit_error(PARAMETER_PROBLEM, "MARK: unexpected `!'");
522 if (string_to_number(optarg, 0, 0xffffffff,
523 (unsigned int *)&markinfo->mark))
524 - exit_error(PARAMETER_PROBLEM, "Bad MARK value `%s'", optarg);
526 - exit_error(PARAMETER_PROBLEM,
527 - "MARK target: Can't specify --set-mark twice");
528 + exit_error(PARAMETER_PROBLEM, "Bad MARK value `%s'",
538 + markinfo->mode = IPT_MARK_SET;
541 + markinfo->mode = IPT_MARK_AND;
544 + markinfo->mode = IPT_MARK_OR;
552 "MARK target: Parameter --set-mark is required");
556 -print_mark(unsigned long mark, int numeric)
558 - printf("0x%lx ", mark);
561 /* Prints out the targinfo. */
563 print(const struct ipt_ip *ip,
566 const struct ipt_mark_target_info *markinfo =
567 (const struct ipt_mark_target_info *)target->data;
568 - printf("MARK set ");
569 - print_mark(markinfo->mark, numeric);
571 + switch (markinfo->mode) {
573 + printf("MARK set ");
576 + printf("MARK and ");
579 + printf("MARK or ");
582 + printf("0x%lx ", markinfo->mark);
585 /* Saves the union ipt_targinfo in parsable form to stdout. */
587 const struct ipt_mark_target_info *markinfo =
588 (const struct ipt_mark_target_info *)target->data;
590 - printf("--set-mark 0x%lx ", markinfo->mark);
591 + switch (markinfo->mode) {
593 + printf("--set-mark ");
596 + printf("--and-mark ");
599 + printf("--or-mark ");
602 + printf("0x%lx ", markinfo->mark);
606 diff -Nur iptables.org/extensions/libipt_helper.c iptables/extensions/libipt_helper.c
607 --- iptables.org/extensions/libipt_helper.c 2004-01-31 16:33:55.000000000 +0100
608 +++ iptables/extensions/libipt_helper.c 2004-05-18 12:39:27.000000000 +0200
612 check_inverse(optarg, &invert, &invert, 0);
613 - strncpy(info->name, optarg, 29);
614 - info->name[29] = '\0';
615 + memset(info->name, 0, sizeof(info->name));
616 + if (strcmp(info->name, "any"))
617 + strncpy(info->name, optarg, 29);
624 struct ipt_helper_info *info = (struct ipt_helper_info *)match->data;
625 + char *name = "any";
627 - printf("helper match %s\"%s\" ", info->invert ? "! " : "", info->name);
628 + if (info->name[0] != '\0')
631 + printf("helper match %s\"%s\" ", info->invert ? "! " : "", name);
634 /* Saves the union ipt_info in parsable form to stdout. */
635 diff -Nur iptables.org/extensions/libipt_policy.c iptables/extensions/libipt_policy.c
636 --- iptables.org/extensions/libipt_policy.c 1970-01-01 01:00:00.000000000 +0100
637 +++ iptables/extensions/libipt_policy.c 2004-05-18 12:39:55.000000000 +0200
639 +/* Shared library add-on to iptables to add policy support. */
648 +#include <sys/socket.h>
649 +#include <netinet/in.h>
650 +#include <arpa/inet.h>
651 +#include <iptables.h>
653 +#include <linux/netfilter_ipv4/ip_tables.h>
654 +#include <linux/netfilter_ipv4/ipt_policy.h>
657 + * HACK: global pointer to current matchinfo for making
658 + * final checks and adjustments in final_check.
660 +static struct ipt_policy_info *policy_info;
662 +static void help(void)
665 +"policy v%s options:\n"
666 +" --dir in|out match policy applied during decapsulation/\n"
667 +" policy to be applied during encapsulation\n"
668 +" --pol none|ipsec match policy\n"
669 +" --strict match entire policy instead of single element\n"
670 +" at any position\n"
671 +"[!] --reqid reqid match reqid\n"
672 +"[!] --spi spi match SPI\n"
673 +"[!] --proto proto match protocol (ah/esp/ipcomp)\n"
674 +"[!] --mode mode match mode (transport/tunnel)\n"
675 +"[!] --tunnel-src addr/mask match tunnel source\n"
676 +"[!] --tunnel-dst addr/mask match tunnel destination\n"
677 +" --next begin next element in policy\n",
681 +static struct option opts[] =
708 + .name = "tunnel-src",
713 + .name = "tunnel-dst",
734 +static void init(struct ipt_entry_match *m, unsigned int *nfcache)
736 + *nfcache |= NFC_UNKNOWN;
739 +static int parse_direction(char *s)
741 + if (strcmp(s, "in") == 0)
742 + return POLICY_MATCH_IN;
743 + if (strcmp(s, "out") == 0)
744 + return POLICY_MATCH_OUT;
745 + exit_error(PARAMETER_PROBLEM, "policy_match: invalid dir `%s'", s);
748 +static int parse_policy(char *s)
750 + if (strcmp(s, "none") == 0)
751 + return POLICY_MATCH_NONE;
752 + if (strcmp(s, "ipsec") == 0)
754 + exit_error(PARAMETER_PROBLEM, "policy match: invalid policy `%s'", s);
757 +static int parse_mode(char *s)
759 + if (strcmp(s, "transport") == 0)
760 + return POLICY_MODE_TRANSPORT;
761 + if (strcmp(s, "tunnel") == 0)
762 + return POLICY_MODE_TUNNEL;
763 + exit_error(PARAMETER_PROBLEM, "policy match: invalid mode `%s'", s);
766 +static int parse(int c, char **argv, int invert, unsigned int *flags,
767 + const struct ipt_entry *entry,
768 + unsigned int *nfcache,
769 + struct ipt_entry_match **match)
771 + struct ipt_policy_info *info = (void *)(*match)->data;
772 + struct ipt_policy_elem *e = &info->pol[info->len];
773 + struct in_addr *addr = NULL, mask;
774 + unsigned int naddr = 0;
777 + check_inverse(optarg, &invert, &optind, 0);
781 + if (info->flags & (POLICY_MATCH_IN|POLICY_MATCH_OUT))
782 + exit_error(PARAMETER_PROBLEM,
783 + "policy match: double --dir option");
785 + exit_error(PARAMETER_PROBLEM,
786 + "policy match: can't invert --dir option");
788 + info->flags |= parse_direction(argv[optind-1]);
792 + exit_error(PARAMETER_PROBLEM,
793 + "policy match: can't invert --policy option");
795 + info->flags |= parse_policy(argv[optind-1]);
798 + if (info->flags & POLICY_MATCH_STRICT)
799 + exit_error(PARAMETER_PROBLEM,
800 + "policy match: double --strict option");
803 + exit_error(PARAMETER_PROBLEM,
804 + "policy match: can't invert --strict option");
806 + info->flags |= POLICY_MATCH_STRICT;
809 + if (e->match.reqid)
810 + exit_error(PARAMETER_PROBLEM,
811 + "policy match: double --reqid option");
813 + e->match.reqid = 1;
814 + e->invert.reqid = invert;
815 + e->reqid = strtol(argv[optind-1], NULL, 10);
819 + exit_error(PARAMETER_PROBLEM,
820 + "policy match: double --spi option");
823 + e->invert.spi = invert;
824 + e->spi = strtol(argv[optind-1], NULL, 0x10);
827 + if (e->match.saddr)
828 + exit_error(PARAMETER_PROBLEM,
829 + "policy match: double --tunnel-src option");
831 + parse_hostnetworkmask(argv[optind-1], &addr, &mask, &naddr);
833 + exit_error(PARAMETER_PROBLEM,
834 + "policy match: name resolves to multiple IPs");
836 + e->match.saddr = 1;
837 + e->invert.saddr = invert;
838 + e->saddr = addr[0].s_addr;
839 + e->smask = mask.s_addr;
842 + if (e->match.daddr)
843 + exit_error(PARAMETER_PROBLEM,
844 + "policy match: double --tunnel-dst option");
846 + parse_hostnetworkmask(argv[optind-1], &addr, &mask, &naddr);
848 + exit_error(PARAMETER_PROBLEM,
849 + "policy match: name resolves to multiple IPs");
851 + e->match.daddr = 1;
852 + e->invert.daddr = invert;
853 + e->daddr = addr[0].s_addr;
854 + e->dmask = mask.s_addr;
857 + if (e->match.proto)
858 + exit_error(PARAMETER_PROBLEM,
859 + "policy match: double --proto option");
861 + e->proto = parse_protocol(argv[optind-1]);
862 + if (e->proto != IPPROTO_AH && e->proto != IPPROTO_ESP &&
863 + e->proto != IPPROTO_COMP)
864 + exit_error(PARAMETER_PROBLEM,
865 + "policy match: protocol must ah/esp/ipcomp");
866 + e->match.proto = 1;
867 + e->invert.proto = invert;
871 + exit_error(PARAMETER_PROBLEM,
872 + "policy match: double --mode option");
874 + mode = parse_mode(argv[optind-1]);
876 + e->invert.mode = invert;
881 + exit_error(PARAMETER_PROBLEM,
882 + "policy match: can't invert --next option");
884 + if (++info->len == POLICY_MAX_ELEM)
885 + exit_error(PARAMETER_PROBLEM,
886 + "policy match: maximum policy depth reached");
892 + policy_info = info;
896 +static void final_check(unsigned int flags)
898 + struct ipt_policy_info *info = policy_info;
899 + struct ipt_policy_elem *e;
903 + exit_error(PARAMETER_PROBLEM,
904 + "policy match: no parameters given");
906 + if (!(info->flags & (POLICY_MATCH_IN|POLICY_MATCH_OUT)))
907 + exit_error(PARAMETER_PROBLEM,
908 + "policy match: neither --in nor --out specified");
910 + if (info->flags & POLICY_MATCH_NONE) {
911 + if (info->flags & POLICY_MATCH_STRICT)
912 + exit_error(PARAMETER_PROBLEM,
913 + "policy match: policy none but --strict given");
915 + if (info->len != 0)
916 + exit_error(PARAMETER_PROBLEM,
917 + "policy match: policy none but policy given");
919 + info->len++; /* increase len by 1, no --next after last element */
921 + if (!(info->flags & POLICY_MATCH_STRICT) && info->len > 1)
922 + exit_error(PARAMETER_PROBLEM,
923 + "policy match: multiple elements but no --strict");
925 + for (i = 0; i < info->len; i++) {
927 + if ((e->match.saddr || e->match.daddr)
928 + && ((e->mode == POLICY_MODE_TUNNEL && e->invert.mode) ||
929 + (e->mode == POLICY_MODE_TRANSPORT && !e->invert.mode)))
930 + exit_error(PARAMETER_PROBLEM,
931 + "policy match: --tunnel-src/--tunnel-dst "
932 + "is only valid in tunnel mode");
936 +static void print_mode(char *prefix, u_int8_t mode, int numeric)
938 + printf("%smode ", prefix);
941 + case POLICY_MODE_TRANSPORT:
942 + printf("transport ");
944 + case POLICY_MODE_TUNNEL:
953 +static void print_proto(char *prefix, u_int8_t proto, int numeric)
955 + struct protoent *p = NULL;
957 + printf("%sproto ", prefix);
959 + p = getprotobynumber(proto);
961 + printf("%s ", p->p_name);
963 + printf("%u ", proto);
966 +#define PRINT_INVERT(x) \
972 +static void print_entry(char *prefix, const struct ipt_policy_elem *e,
975 + if (e->match.reqid) {
976 + PRINT_INVERT(e->invert.reqid);
977 + printf("%sreqid %u ", prefix, e->reqid);
979 + if (e->match.spi) {
980 + PRINT_INVERT(e->invert.spi);
981 + printf("%sspi 0x%x ", prefix, e->spi);
983 + if (e->match.proto) {
984 + PRINT_INVERT(e->invert.proto);
985 + print_proto(prefix, e->proto, numeric);
987 + if (e->match.mode) {
988 + PRINT_INVERT(e->invert.mode);
989 + print_mode(prefix, e->mode, numeric);
991 + if (e->match.daddr) {
992 + PRINT_INVERT(e->invert.daddr);
993 + printf("%stunnel-dst %s%s ", prefix,
994 + addr_to_dotted((struct in_addr *)&e->daddr),
995 + mask_to_dotted((struct in_addr *)&e->dmask));
997 + if (e->match.saddr) {
998 + PRINT_INVERT(e->invert.saddr);
999 + printf("%stunnel-src %s%s ", prefix,
1000 + addr_to_dotted((struct in_addr *)&e->saddr),
1001 + mask_to_dotted((struct in_addr *)&e->smask));
1005 +static void print_flags(char *prefix, const struct ipt_policy_info *info)
1007 + if (info->flags & POLICY_MATCH_IN)
1008 + printf("%sdir in ", prefix);
1010 + printf("%sdir out ", prefix);
1012 + if (info->flags & POLICY_MATCH_NONE)
1013 + printf("%spol none ", prefix);
1015 + printf("%spol ipsec ", prefix);
1017 + if (info->flags & POLICY_MATCH_STRICT)
1018 + printf("%sstrict ", prefix);
1021 +static void print(const struct ipt_ip *ip,
1022 + const struct ipt_entry_match *match,
1025 + const struct ipt_policy_info *info = (void *)match->data;
1028 + printf("policy match ");
1029 + print_flags("", info);
1030 + for (i = 0; i < info->len; i++) {
1031 + if (info->len > 1)
1032 + printf("[%u] ", i);
1033 + print_entry("", &info->pol[i], numeric);
1037 +static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
1039 + const struct ipt_policy_info *info = (void *)match->data;
1042 + print_flags("--", info);
1043 + for (i = 0; i < info->len; i++) {
1044 + print_entry("--", &info->pol[i], 0);
1045 + if (i + 1 < info->len)
1046 + printf("--next ");
1052 +struct iptables_match policy = {
1054 + .version = IPTABLES_VERSION,
1055 + .size = IPT_ALIGN(sizeof(struct ipt_policy_info)),
1056 + .userspacesize = IPT_ALIGN(sizeof(struct ipt_policy_info)),
1060 + .final_check = final_check,
1063 + .extra_opts = opts
1068 + register_match(&policy);
1070 diff -Nur iptables.org/extensions/libipt_policy.man iptables/extensions/libipt_policy.man
1071 --- iptables.org/extensions/libipt_policy.man 1970-01-01 01:00:00.000000000 +0100
1072 +++ iptables/extensions/libipt_policy.man 2004-05-18 12:39:55.000000000 +0200
1074 +This modules matches the policy used by IPsec for handling a packet.
1076 +.BI "--dir " "in|out"
1077 +Used to select whether to match the policy used for decapsulation or the
1078 +policy that will be used for encapsulation.
1081 +.B PREROUTING, INPUT and FORWARD
1085 +.B POSTROUTING, OUTPUT and FORWARD
1088 +.BI "--pol " "none|ipsec"
1089 +Matches if the packet is subject to IPsec processing.
1092 +Selects whether to match the exact policy or match if any rule of
1093 +the policy matches the given policy.
1095 +.BI "--reqid " "id"
1096 +Matches the reqid of the policy rule. The reqid can be specified with
1103 +Matches the SPI of the SA.
1105 +.BI "--proto " "ah|esp|ipcomp"
1106 +Matches the encapsulation protocol.
1108 +.BI "--mode " "tunnel|transport"
1109 +Matches the encapsulation mode.
1111 +.BI "--tunnel-src " "addr[/mask]"
1112 +Matches the source address of a tunnel. Only valid with --mode tunnel.
1114 +.BI "--tunnel-dst " "addr[/mask]"
1115 +Matches the destination address of a tunnel. Only valid with --mode tunnel.
1118 +Start the next element in the policy specification. Can only be used with
1120 diff -Nur iptables.org/ip6tables.c iptables/ip6tables.c
1121 --- iptables.org/ip6tables.c 2004-05-18 20:09:43.000000000 +0200
1122 +++ iptables/ip6tables.c 2004-04-07 11:36:29.000000000 +0200
1123 @@ -1433,8 +1433,6 @@
1124 ret &= ip6tc_delete_entry(chain, fw, mask, handle);
1132 @@ -1656,8 +1654,6 @@
1134 for (matchp = *matches; matchp;) {
1136 - if (matchp->match->m)
1137 - free(matchp->match->m);
1141 @@ -1692,6 +1688,9 @@
1143 memset(&fw, 0, sizeof(fw));
1145 + opts = original_opts;
1146 + global_option_offset = 0;
1148 /* re-set optind to 0 in case do_command gets called
1151 @@ -2197,9 +2196,6 @@
1152 printf("Warning: using chain %s, not extension\n",
1161 @@ -2229,7 +2225,6 @@
1162 find_target(jumpto, LOAD_MUST_SUCCEED);
1164 e = generate_entry(&fw, matches, target->t);
1169 @@ -2307,22 +2302,5 @@
1171 clear_rule_matches(&matches);
1178 - for (c = 0; c < nsaddrs; c++)
1181 - for (c = 0; c < ndaddrs; c++)
1184 - if (opts != original_opts) {
1186 - opts = original_opts;
1187 - global_option_offset = 0;
1192 diff -Nur iptables.org/iptables.8.in iptables/iptables.8.in
1193 --- iptables.org/iptables.8.in 2004-03-17 15:26:08.000000000 +0100
1194 +++ iptables/iptables.8.in 2004-05-18 12:39:16.000000000 +0200
1195 @@ -274,10 +274,18 @@
1196 the fate of the packet immediately, or an extension (see
1199 -option is omitted in a rule, then matching the rule will have no
1200 +option is omitted in a rule (and
1202 +is not used), then matching the rule will have no
1203 effect on the packet's fate, but the counters on the rule will be
1206 +.BI "-g, --goto " "chain"
1207 +This specifies that the processing should continue in a user
1208 +specified chain. Unlike the --jump option return will not continue
1209 +processing in this chain but instead in the chain that called us via
1212 .BR "-i, --in-interface " "[!] \fIname\fP"
1213 Name of an interface via which a packet was received (only for
1214 packets entering the
1215 diff -Nur iptables.org/iptables.c iptables/iptables.c
1216 --- iptables.org/iptables.c 2004-05-18 20:09:43.000000000 +0200
1217 +++ iptables/iptables.c 2004-05-18 12:39:16.000000000 +0200
1219 { "line-numbers", 0, 0, '0' },
1220 { "modprobe", 1, 0, 'M' },
1221 { "set-counters", 1, 0, 'c' },
1222 + { "goto", 1, 0, 'g' },
1226 @@ -397,6 +398,10 @@
1227 " network interface name ([+] for wildcard)\n"
1228 " --jump -j target\n"
1229 " target for rule (may load target extension)\n"
1231 +" --goto -g chain\n"
1232 +" jump to chain with no return\n"
1234 " --match -m match\n"
1235 " extended match (may load extension)\n"
1236 " --numeric -n numeric output of addresses and ports\n"
1237 @@ -1431,8 +1436,6 @@
1238 ret &= iptc_delete_entry(chain, fw, mask, handle);
1246 @@ -1654,8 +1657,6 @@
1248 for (matchp = *matches; matchp;) {
1250 - if (matchp->match->m)
1251 - free(matchp->match->m);
1255 @@ -1689,6 +1690,9 @@
1257 memset(&fw, 0, sizeof(fw));
1259 + opts = original_opts;
1260 + global_option_offset = 0;
1262 /* re-set optind to 0 in case do_command gets called
1265 @@ -1708,7 +1712,7 @@
1268 while ((c = getopt_long(argc, argv,
1269 - "-A:D:R:I:L::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:fbvnt:m:xc:",
1270 + "-A:D:R:I:L::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:fbvnt:m:xc:g:",
1271 opts, NULL)) != -1) {
1274 @@ -1879,6 +1883,15 @@
1275 fw.nfcache |= NFC_IP_DST;
1280 + set_option(&options, OPT_JUMP, &fw.ip.invflags,
1282 + fw.ip.flags |= IPT_F_GOTO;
1283 + jumpto = parse_target(optarg);
1288 set_option(&options, OPT_JUMP, &fw.ip.invflags,
1290 @@ -2197,9 +2210,6 @@
1291 printf("Warning: using chain %s, not extension\n",
1300 @@ -2226,10 +2236,14 @@
1301 * We cannot know if the plugin is corrupt, non
1302 * existant OR if the user just misspelled a
1305 + if (fw.ip.flags & IPT_F_GOTO)
1306 + exit_error(PARAMETER_PROBLEM,
1307 + "goto '%s' is not a chain\n", jumpto);
1309 find_target(jumpto, LOAD_MUST_SUCCEED);
1311 e = generate_entry(&fw, matches, target->t);
1316 @@ -2307,22 +2321,5 @@
1318 clear_rule_matches(&matches);
1325 - for (c = 0; c < nsaddrs; c++)
1328 - for (c = 0; c < ndaddrs; c++)
1331 - if (opts != original_opts) {
1333 - opts = original_opts;
1334 - global_option_offset = 0;