This commit was manufactured by cvs2svn to create branch
authorPlanet-Lab Support <support@planet-lab.org>
Fri, 28 Jul 2006 14:34:29 +0000 (14:34 +0000)
committerPlanet-Lab Support <support@planet-lab.org>
Fri, 28 Jul 2006 14:34:29 +0000 (14:34 +0000)
'myplc-0_4-branch'.

18 files changed:
extensions/.dccp-test [new file with mode: 0755]
extensions/libip6t_CONNMARK.c [new file with mode: 0644]
extensions/libip6t_NFQUEUE.c [new file with mode: 0644]
extensions/libip6t_NFQUEUE.man [new file with mode: 0644]
extensions/libip6t_connmark.c [new file with mode: 0644]
extensions/libip6t_policy.c [new file with mode: 0644]
extensions/libip6t_policy.man [new file with mode: 0644]
extensions/libip6t_state.c [new file with mode: 0644]
extensions/libipt_NFQUEUE.c [new file with mode: 0644]
extensions/libipt_NFQUEUE.man [new file with mode: 0644]
extensions/libipt_dccp.c [new file with mode: 0644]
extensions/libipt_dccp.man [new file with mode: 0644]
extensions/libipt_policy.c [new file with mode: 0644]
extensions/libipt_policy.man [new file with mode: 0644]
extensions/libipt_string.man [new file with mode: 0644]
include/linux/netfilter_ipv4/ipt_NFQUEUE.h [new file with mode: 0644]
include/linux/netfilter_ipv4/ipt_policy.h [new file with mode: 0644]
include/linux/netfilter_ipv6/ip6t_policy.h [new file with mode: 0644]

diff --git a/extensions/.dccp-test b/extensions/.dccp-test
new file mode 100755 (executable)
index 0000000..5b67527
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh
+# True if dccp is applied.
+[ -f $KERNEL_DIR/include/linux/netfilter_ipv4/ipt_dccp.h ] && echo dccp
diff --git a/extensions/libip6t_CONNMARK.c b/extensions/libip6t_CONNMARK.c
new file mode 100644 (file)
index 0000000..9506f26
--- /dev/null
@@ -0,0 +1,220 @@
+/* Shared library add-on to iptables to add CONNMARK target support.
+ *
+ * (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
+ * by Henrik Nordstrom <hno@marasystems.com>
+ *
+ * Version 1.1
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+#include <ip6tables.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include "../include/linux/netfilter_ipv4/ipt_CONNMARK.h"
+
+#if 0
+struct markinfo {
+       struct ipt_entry_target t;
+       struct ipt_connmark_target_info mark;
+};
+#endif
+
+/* Function which prints out usage message. */
+static void
+help(void)
+{
+       printf(
+"CONNMARK target v%s options:\n"
+"  --set-mark value[/mask]       Set conntrack mark value\n"
+"  --save-mark [--mask mask]     Save the packet nfmark in the connection\n"
+"  --restore-mark [--mask mask]  Restore saved nfmark value\n"
+"\n",
+IPTABLES_VERSION);
+}
+
+static struct option opts[] = {
+       { "set-mark", 1, 0, '1' },
+       { "save-mark", 0, 0, '2' },
+       { "restore-mark", 0, 0, '3' },
+       { "mask", 1, 0, '4' },
+       { 0 }
+};
+
+/* Initialize the target. */
+static void
+init(struct ip6t_entry_target *t, unsigned int *nfcache)
+{
+}
+
+/* Function which parses command options; returns true if it
+   ate an option */
+static int
+parse(int c, char **argv, int invert, unsigned int *flags,
+      const struct ip6t_entry *entry,
+      struct ip6t_entry_target **target)
+{
+       struct ipt_connmark_target_info *markinfo
+               = (struct ipt_connmark_target_info *)(*target)->data;
+
+       markinfo->mask = 0xffffffffUL;
+
+       switch (c) {
+               char *end;
+       case '1':
+               markinfo->mode = IPT_CONNMARK_SET;
+
+               markinfo->mark = strtoul(optarg, &end, 0);
+               if (*end == '/' && end[1] != '\0')
+                   markinfo->mask = strtoul(end+1, &end, 0);
+
+               if (*end != '\0' || end == optarg)
+                       exit_error(PARAMETER_PROBLEM, "Bad MARK value `%s'", optarg);
+               if (*flags)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "CONNMARK target: Can't specify --set-mark twice");
+               *flags = 1;
+               break;
+       case '2':
+               markinfo->mode = IPT_CONNMARK_SAVE;
+               if (*flags)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "CONNMARK target: Can't specify --save-mark twice");
+               *flags = 1;
+               break;
+       case '3':
+               markinfo->mode = IPT_CONNMARK_RESTORE;
+               if (*flags)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "CONNMARK target: Can't specify --restore-mark twice");
+               *flags = 1;
+               break;
+       case '4':
+               if (!*flags)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "CONNMARK target: Can't specify --mask without a operation");
+               markinfo->mask = strtoul(optarg, &end, 0);
+
+               if (*end != '\0' || end == optarg)
+                       exit_error(PARAMETER_PROBLEM, "Bad MASK value `%s'", optarg);
+               break;
+       default:
+               return 0;
+       }
+
+       return 1;
+}
+
+static void
+final_check(unsigned int flags)
+{
+       if (!flags)
+               exit_error(PARAMETER_PROBLEM,
+                          "CONNMARK target: No operation specified");
+}
+
+static void
+print_mark(unsigned long mark)
+{
+       printf("0x%lx", mark);
+}
+
+static void
+print_mask(const char *text, unsigned long mask)
+{
+       if (mask != 0xffffffffUL)
+               printf("%s0x%lx", text, mask);
+}
+
+
+/* Prints out the target info. */
+static void
+print(const struct ip6t_ip6 *ip,
+      const struct ip6t_entry_target *target,
+      int numeric)
+{
+       const struct ipt_connmark_target_info *markinfo =
+               (const struct ipt_connmark_target_info *)target->data;
+       switch (markinfo->mode) {
+       case IPT_CONNMARK_SET:
+           printf("CONNMARK set ");
+           print_mark(markinfo->mark);
+           print_mask("/", markinfo->mask);
+           printf(" ");
+           break;
+       case IPT_CONNMARK_SAVE:
+           printf("CONNMARK save ");
+           print_mask("mask ", markinfo->mask);
+           printf(" ");
+           break;
+       case IPT_CONNMARK_RESTORE:
+           printf("CONNMARK restore ");
+           print_mask("mask ", markinfo->mask);
+           break;
+       default:
+           printf("ERROR: UNKNOWN CONNMARK MODE ");
+           break;
+       }
+}
+
+/* Saves the target into in parsable form to stdout. */
+static void
+save(const struct ip6t_ip6 *ip, const struct ip6t_entry_target *target)
+{
+       const struct ipt_connmark_target_info *markinfo =
+               (const struct ipt_connmark_target_info *)target->data;
+
+       switch (markinfo->mode) {
+       case IPT_CONNMARK_SET:
+           printf("--set-mark ");
+           print_mark(markinfo->mark);
+           print_mask("/", markinfo->mask);
+           printf(" ");
+           break;
+       case IPT_CONNMARK_SAVE:
+           printf("--save-mark ");
+           print_mask("--mask ", markinfo->mask);
+           break;
+       case IPT_CONNMARK_RESTORE:
+           printf("--restore-mark ");
+           print_mask("--mask ", markinfo->mask);
+           break;
+       default:
+           printf("ERROR: UNKNOWN CONNMARK MODE ");
+           break;
+       }
+}
+
+static struct ip6tables_target connmark_target = {
+    .name          = "CONNMARK",
+    .version       = IPTABLES_VERSION,
+    .size          = IP6T_ALIGN(sizeof(struct ipt_connmark_target_info)),
+    .userspacesize = IP6T_ALIGN(sizeof(struct ipt_connmark_target_info)),
+    .help          = &help,
+    .init          = &init,
+    .parse         = &parse,
+    .final_check   = &final_check,
+    .print         = &print,
+    .save          = &save,
+    .extra_opts    = opts
+};
+
+void _init(void)
+{
+       register_target6(&connmark_target);
+}
diff --git a/extensions/libip6t_NFQUEUE.c b/extensions/libip6t_NFQUEUE.c
new file mode 100644 (file)
index 0000000..e1964af
--- /dev/null
@@ -0,0 +1,114 @@
+/* Shared library add-on to ip666666tables for NFQ
+ *
+ * (C) 2005 by Harald Welte <laforge@netfilter.org>
+ *
+ * This program is distributed under the terms of GNU GPL v2, 1991
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+#include <ip6tables.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter_ipv4/ipt_NFQUEUE.h>
+
+static void init(struct ip6t_entry_target *t, unsigned int *nfcache) 
+{
+}
+
+static void help(void) 
+{
+       printf(
+"NFQUEUE target options\n"
+"  --queue-num value           Send packet to QUEUE number <value>.\n"
+"                              Valid queue numbers are 0-65535\n"
+);
+}
+
+static struct option opts[] = {
+       { "queue-num", 1, 0, 'F' },
+       { 0 }
+};
+
+static void
+parse_num(const char *s, struct ipt_NFQ_info *tinfo)
+{
+       unsigned int num;
+       
+       if (string_to_number(s, 0, 65535, &num) == -1)
+               exit_error(PARAMETER_PROBLEM,
+                          "Invalid queue number `%s'\n", s);
+
+       tinfo->queuenum = num & 0xffff;
+       return;
+}
+
+static int
+parse(int c, char **argv, int invert, unsigned int *flags,
+      const struct ip6t_entry *entry,
+      struct ip6t_entry_target **target)
+{
+       struct ipt_NFQ_info *tinfo
+               = (struct ipt_NFQ_info *)(*target)->data;
+
+       switch (c) {
+       case 'F':
+               if (*flags)
+                       exit_error(PARAMETER_PROBLEM, "NFQUEUE target: "
+                                  "Only use --queue-num ONCE!");
+               parse_num(optarg, tinfo);
+               break;
+       default:
+               return 0;
+       }
+
+       return 1;
+}
+
+static void
+final_check(unsigned int flags)
+{
+}
+
+/* Prints out the targinfo. */
+static void
+print(const struct ip6t_ip6 *ip,
+      const struct ip6t_entry_target *target,
+      int numeric)
+{
+       const struct ipt_NFQ_info *tinfo =
+               (const struct ipt_NFQ_info *)target->data;
+       printf("NFQUEUE num %u", tinfo->queuenum);
+}
+
+/* Saves the union ip6t_targinfo in parsable form to stdout. */
+static void
+save(const struct ip6t_ip6 *ip, const struct ip6t_entry_target *target)
+{
+       const struct ipt_NFQ_info *tinfo =
+               (const struct ipt_NFQ_info *)target->data;
+
+       printf("--queue-num %u ", tinfo->queuenum);
+}
+
+static struct ip6tables_target nfqueue = { 
+       .next           = NULL,
+       .name           = "NFQUEUE",
+       .version        = IPTABLES_VERSION,
+       .size           = IP6T_ALIGN(sizeof(struct ipt_NFQ_info)),
+       .userspacesize  = IP6T_ALIGN(sizeof(struct ipt_NFQ_info)),
+       .help           = &help,
+       .init           = &init,
+       .parse          = &parse,
+       .final_check    = &final_check,
+       .print          = &print,
+       .save           = &save,
+       .extra_opts     = opts
+};
+
+void _init(void)
+{
+       register_target6(&nfqueue);
+}
diff --git a/extensions/libip6t_NFQUEUE.man b/extensions/libip6t_NFQUEUE.man
new file mode 100644 (file)
index 0000000..c4e9d11
--- /dev/null
@@ -0,0 +1,12 @@
+This target is an extension of the QUEUE target. As opposed to QUEUE, it allows
+you to put a packet into any specific queue, identified by its 16-bit queue
+number.  
+.TP
+.BR "--queue-num " "\fIvalue"
+This specifies the QUEUE number to use. Valud queue numbers are 0 to 65535. The default value is 0.
+.TP
+It can only be used with Kernel versions 2.6.14 or later, since it requires
+the
+.B
+nfnetlink_queue
+kernel support.
diff --git a/extensions/libip6t_connmark.c b/extensions/libip6t_connmark.c
new file mode 100644 (file)
index 0000000..419da30
--- /dev/null
@@ -0,0 +1,151 @@
+/* Shared library add-on to iptables to add connmark matching support.
+ *
+ * (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
+ * by Henrik Nordstrom <hno@marasystems.com>
+ *
+ * Version 1.1
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+#include <ip6tables.h>
+#include "../include/linux/netfilter_ipv4/ipt_connmark.h"
+
+/* Function which prints out usage message. */
+static void
+help(void)
+{
+       printf(
+"CONNMARK match v%s options:\n"
+"[!] --mark value[/mask]         Match nfmark value with optional mask\n"
+"\n",
+IPTABLES_VERSION);
+}
+
+static struct option opts[] = {
+       { "mark", 1, 0, '1' },
+       {0}
+};
+
+/* Initialize the match. */
+static void
+init(struct ip6t_entry_match *m, unsigned int *nfcache)
+{
+       /* Can't cache this. */
+       *nfcache |= NFC_UNKNOWN;
+}
+
+/* Function which parses command options; returns true if it
+   ate an option */
+static int
+parse(int c, char **argv, int invert, unsigned int *flags,
+      const struct ip6t_entry *entry,
+      unsigned int *nfcache,
+      struct ip6t_entry_match **match)
+{
+       struct ipt_connmark_info *markinfo = (struct ipt_connmark_info *)(*match)->data;
+
+       switch (c) {
+               char *end;
+       case '1':
+               check_inverse(optarg, &invert, &optind, 0);
+
+               markinfo->mark = strtoul(optarg, &end, 0);
+               markinfo->mask = 0xffffffffUL;
+               
+               if (*end == '/')
+                       markinfo->mask = strtoul(end+1, &end, 0);
+
+               if (*end != '\0' || end == optarg)
+                       exit_error(PARAMETER_PROBLEM, "Bad MARK value `%s'", optarg);
+               if (invert)
+                       markinfo->invert = 1;
+               *flags = 1;
+               break;
+
+       default:
+               return 0;
+       }
+       return 1;
+}
+
+static void
+print_mark(unsigned long mark, unsigned long mask, int numeric)
+{
+       if(mask != 0xffffffffUL)
+               printf("0x%lx/0x%lx ", mark, mask);
+       else
+               printf("0x%lx ", mark);
+}
+
+/* Final check; must have specified --mark. */
+static void
+final_check(unsigned int flags)
+{
+       if (!flags)
+               exit_error(PARAMETER_PROBLEM,
+                          "MARK match: You must specify `--mark'");
+}
+
+/* Prints out the matchinfo. */
+static void
+print(const struct ip6t_ip6 *ip,
+      const struct ip6t_entry_match *match,
+      int numeric)
+{
+       struct ipt_connmark_info *info = (struct ipt_connmark_info *)match->data;
+
+       printf("CONNMARK match ");
+       if (info->invert)
+               printf("!");
+       print_mark(info->mark, info->mask, numeric);
+}
+
+/* Saves the matchinfo in parsable form to stdout. */
+static void
+save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
+{
+       struct ipt_connmark_info *info = (struct ipt_connmark_info *)match->data;
+
+       if (info->invert)
+               printf("! ");
+
+       printf("--mark ");
+       print_mark(info->mark, info->mask, 0);
+}
+
+static struct ip6tables_match connmark_match = {
+    .name          = "connmark",
+    .version       = IPTABLES_VERSION,
+    .size          = IP6T_ALIGN(sizeof(struct ipt_connmark_info)),
+    .userspacesize = IP6T_ALIGN(sizeof(struct ipt_connmark_info)),
+    .help          = &help,
+    .init          = &init,
+    .parse         = &parse,
+    .final_check   = &final_check,
+    .print         = &print,
+    .save          = &save,
+    .extra_opts    = opts
+};
+
+void _init(void)
+{
+       register_match6(&connmark_match);
+}
diff --git a/extensions/libip6t_policy.c b/extensions/libip6t_policy.c
new file mode 100644 (file)
index 0000000..2f4453e
--- /dev/null
@@ -0,0 +1,478 @@
+/* Shared library add-on to iptables to add policy support. */
+
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include <getopt.h>
+#include <netdb.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <ip6tables.h>
+
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include "../include/linux/netfilter_ipv6/ip6t_policy.h"
+
+/*
+ * HACK: global pointer to current matchinfo for making
+ * final checks and adjustments in final_check.
+ */
+static struct ip6t_policy_info *policy_info;
+
+static void help(void)
+{
+       printf(
+"policy v%s options:\n"
+"  --dir in|out                        match policy applied during decapsulation/\n"
+"                              policy to be applied during encapsulation\n"
+"  --pol none|ipsec            match policy\n"
+"  --strict                    match entire policy instead of single element\n"
+"                              at any position\n"
+"[!] --reqid reqid             match reqid\n"
+"[!] --spi spi                 match SPI\n"
+"[!] --proto proto             match protocol (ah/esp/ipcomp)\n"
+"[!] --mode mode               match mode (transport/tunnel)\n"
+"[!] --tunnel-src addr/masklen match tunnel source\n"
+"[!] --tunnel-dst addr/masklen match tunnel destination\n"
+"  --next                      begin next element in policy\n",
+       IPTABLES_VERSION);
+}
+
+static struct option opts[] =
+{
+       {
+               .name           = "dir",
+               .has_arg        = 1,
+               .val            = '1',
+       },
+       {
+               .name           = "pol",
+               .has_arg        = 1,
+               .val            = '2',
+       },
+       {
+               .name           = "strict",
+               .val            = '3'
+       },
+       {
+               .name           = "reqid",
+               .has_arg        = 1,
+               .val            = '4',
+       },
+       {
+               .name           = "spi",
+               .has_arg        = 1,
+               .val            = '5'
+       },
+       {
+               .name           = "tunnel-src",
+               .has_arg        = 1,
+               .val            = '6'
+       },
+       {
+               .name           = "tunnel-dst",
+               .has_arg        = 1,
+               .val            = '7'
+       },
+       {
+               .name           = "proto",
+               .has_arg        = 1,
+               .val            = '8'
+       },
+       {
+               .name           = "mode",
+               .has_arg        = 1,
+               .val            = '9'
+       },
+       {
+               .name           = "next",
+               .val            = 'a'
+       },
+       { }
+};
+
+/* FIXME - Duplicated code from ip6tables.c */
+/* Duplicated to stop too many changes in other files .... */
+static void
+in6addrcpy(struct in6_addr *dst, struct in6_addr *src)
+{
+        memcpy(dst, src, sizeof(struct in6_addr));
+        /* dst->s6_addr = src->s6_addr; */
+}
+
+static char *
+addr_to_numeric(const struct in6_addr *addrp)
+{
+        /* 0000:0000:0000:0000:0000:000.000.000.000
+        * 0000:0000:0000:0000:0000:0000:0000:0000 */
+        static char buf[50+1];
+        return (char *)inet_ntop(AF_INET6, addrp, buf, sizeof(buf));
+}
+
+static char *
+mask_to_numeric(const struct in6_addr *addrp)
+{
+        static char buf[50+2];
+        int l = ipv6_prefix_length(addrp);
+        if (l == -1) {
+               strcpy(buf, "/");
+               strcat(buf, addr_to_numeric(addrp));
+               return buf;
+       }
+       sprintf(buf, "/%d", l);
+       return buf;
+}
+
+/* These should be in include/ip6tables.h... */
+extern u_int16_t parse_protocol(const char *s);
+extern void parse_hostnetworkmask(const char *name, struct in6_addr **addrpp,
+               struct in6_addr *maskp, unsigned int *naddrs);
+
+/* End duplicated code from ip6tables.c */
+
+static void init(struct ip6t_entry_match *m, unsigned int *nfcache)
+{
+       *nfcache |= NFC_UNKNOWN;
+}
+
+static int parse_direction(char *s)
+{
+       if (strcmp(s, "in") == 0)
+               return IP6T_POLICY_MATCH_IN;
+       if (strcmp(s, "out") == 0)
+               return IP6T_POLICY_MATCH_OUT;
+       exit_error(PARAMETER_PROBLEM, "policy_match: invalid dir `%s'", s);
+}
+
+static int parse_policy(char *s)
+{
+       if (strcmp(s, "none") == 0)
+               return IP6T_POLICY_MATCH_NONE;
+       if (strcmp(s, "ipsec") == 0)
+               return 0;
+       exit_error(PARAMETER_PROBLEM, "policy match: invalid policy `%s'", s);
+}
+
+static int parse_mode(char *s)
+{
+       if (strcmp(s, "transport") == 0)
+               return IP6T_POLICY_MODE_TRANSPORT;
+       if (strcmp(s, "tunnel") == 0)
+               return IP6T_POLICY_MODE_TUNNEL;
+       exit_error(PARAMETER_PROBLEM, "policy match: invalid mode `%s'", s);
+}
+
+static int parse(int c, char **argv, int invert, unsigned int *flags,
+                 const struct ip6t_entry *entry,
+                 unsigned int *nfcache,
+                 struct ip6t_entry_match **match)
+{
+       struct ip6t_policy_info *info = (void *)(*match)->data;
+       struct ip6t_policy_elem *e = &info->pol[info->len];
+       struct in6_addr *addr = NULL, mask;
+       unsigned int naddr = 0;
+       int mode;
+
+       check_inverse(optarg, &invert, &optind, 0);
+
+       switch (c) {
+       case '1':
+               if (info->flags & (IP6T_POLICY_MATCH_IN|IP6T_POLICY_MATCH_OUT))
+                       exit_error(PARAMETER_PROBLEM,
+                                  "policy match: double --dir option");
+               if (invert)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "policy match: can't invert --dir option");
+
+               info->flags |= parse_direction(argv[optind-1]);
+               break;
+       case '2':
+               if (invert)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "policy match: can't invert --policy option");
+
+               info->flags |= parse_policy(argv[optind-1]);
+               break;
+       case '3':
+               if (info->flags & IP6T_POLICY_MATCH_STRICT)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "policy match: double --strict option");
+
+               if (invert)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "policy match: can't invert --strict option");
+
+               info->flags |= IP6T_POLICY_MATCH_STRICT;
+               break;
+       case '4':
+               if (e->match.reqid)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "policy match: double --reqid option");
+
+               e->match.reqid = 1;
+               e->invert.reqid = invert;
+               e->reqid = strtol(argv[optind-1], NULL, 10);
+               break;
+       case '5':
+               if (e->match.spi)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "policy match: double --spi option");
+
+               e->match.spi = 1;
+               e->invert.spi = invert;
+               e->spi = strtol(argv[optind-1], NULL, 0x10);
+               break;
+       case '6':
+               if (e->match.saddr)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "policy match: double --tunnel-src option");
+
+               parse_hostnetworkmask(argv[optind-1], &addr, &mask, &naddr);
+               if (naddr > 1)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "policy match: name resolves to multiple IPs");
+
+               e->match.saddr = 1;
+               e->invert.saddr = invert;
+               in6addrcpy(&e->saddr.a6, addr);
+               in6addrcpy(&e->smask.a6, &mask);
+                break;
+       case '7':
+               if (e->match.daddr)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "policy match: double --tunnel-dst option");
+
+               parse_hostnetworkmask(argv[optind-1], &addr, &mask, &naddr);
+               if (naddr > 1)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "policy match: name resolves to multiple IPs");
+
+               e->match.daddr = 1;
+               e->invert.daddr = invert;
+               in6addrcpy(&e->daddr.a6, addr);
+               in6addrcpy(&e->dmask.a6, &mask);
+               break;
+       case '8':
+               if (e->match.proto)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "policy match: double --proto option");
+
+               e->proto = parse_protocol(argv[optind-1]);
+               if (e->proto != IPPROTO_AH && e->proto != IPPROTO_ESP &&
+                   e->proto != IPPROTO_COMP)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "policy match: protocol must ah/esp/ipcomp");
+               e->match.proto = 1;
+               e->invert.proto = invert;
+               break;
+       case '9':
+               if (e->match.mode)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "policy match: double --mode option");
+
+               mode = parse_mode(argv[optind-1]);
+               e->match.mode = 1;
+               e->invert.mode = invert;
+               e->mode = mode;
+               break;
+       case 'a':
+               if (invert)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "policy match: can't invert --next option");
+
+               if (++info->len == IP6T_POLICY_MAX_ELEM)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "policy match: maximum policy depth reached");
+               break;
+       default:
+               return 0;
+       }
+
+       policy_info = info;
+       return 1;
+}
+
+static void final_check(unsigned int flags)
+{
+       struct ip6t_policy_info *info = policy_info;
+       struct ip6t_policy_elem *e;
+       int i;
+
+       if (info == NULL)
+               exit_error(PARAMETER_PROBLEM,
+                          "policy match: no parameters given");
+
+       if (!(info->flags & (IP6T_POLICY_MATCH_IN|IP6T_POLICY_MATCH_OUT)))
+               exit_error(PARAMETER_PROBLEM,
+                          "policy match: neither --in nor --out specified");
+
+       if (info->flags & IP6T_POLICY_MATCH_NONE) {
+               if (info->flags & IP6T_POLICY_MATCH_STRICT)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "policy match: policy none but --strict given");
+
+               if (info->len != 0)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "policy match: policy none but policy given");
+       } else
+               info->len++;    /* increase len by 1, no --next after last element */
+
+       if (!(info->flags & IP6T_POLICY_MATCH_STRICT) && info->len > 1)
+               exit_error(PARAMETER_PROBLEM,
+                          "policy match: multiple elements but no --strict");
+
+       for (i = 0; i < info->len; i++) {
+               e = &info->pol[i];
+
+                if (info->flags & IP6T_POLICY_MATCH_STRICT &&
+                   !(e->match.reqid || e->match.spi || e->match.saddr ||
+                      e->match.daddr || e->match.proto || e->match.mode))
+                        exit_error(PARAMETER_PROBLEM,
+                                   "policy match: empty policy element");
+
+               if ((e->match.saddr || e->match.daddr)
+                   && ((e->mode == IP6T_POLICY_MODE_TUNNEL && e->invert.mode) ||
+                       (e->mode == IP6T_POLICY_MODE_TRANSPORT && !e->invert.mode)))
+                       exit_error(PARAMETER_PROBLEM,
+                                  "policy match: --tunnel-src/--tunnel-dst "
+                                  "is only valid in tunnel mode");
+       }
+}
+
+static void print_mode(char *prefix, u_int8_t mode, int numeric)
+{
+       printf("%smode ", prefix);
+
+       switch (mode) {
+       case IP6T_POLICY_MODE_TRANSPORT:
+               printf("transport ");
+               break;
+       case IP6T_POLICY_MODE_TUNNEL:
+               printf("tunnel ");
+               break;
+       default:
+               printf("??? ");
+               break;
+       }
+}
+
+static void print_proto(char *prefix, u_int8_t proto, int numeric)
+{
+       struct protoent *p = NULL;
+
+       printf("%sproto ", prefix);
+       if (!numeric)
+               p = getprotobynumber(proto);
+       if (p != NULL)
+               printf("%s ", p->p_name);
+       else
+               printf("%u ", proto);
+}
+
+#define PRINT_INVERT(x)                \
+do {                           \
+       if (x)                  \
+               printf("! ");   \
+} while(0)
+
+static void print_entry(char *prefix, const struct ip6t_policy_elem *e,
+                        int numeric)
+{
+       if (e->match.reqid) {
+               PRINT_INVERT(e->invert.reqid);
+               printf("%sreqid %u ", prefix, e->reqid);
+       }
+       if (e->match.spi) {
+               PRINT_INVERT(e->invert.spi);
+               printf("%sspi 0x%x ", prefix, e->spi);
+       }
+       if (e->match.proto) {
+               PRINT_INVERT(e->invert.proto);
+               print_proto(prefix, e->proto, numeric);
+       }
+       if (e->match.mode) {
+               PRINT_INVERT(e->invert.mode);
+               print_mode(prefix, e->mode, numeric);
+       }
+       if (e->match.daddr) {
+               PRINT_INVERT(e->invert.daddr);
+               printf("%stunnel-dst %s%s ", prefix,
+                      addr_to_numeric((struct in6_addr *)&e->daddr),
+                      mask_to_numeric((struct in6_addr *)&e->dmask));
+       }
+       if (e->match.saddr) {
+               PRINT_INVERT(e->invert.saddr);
+               printf("%stunnel-src %s%s ", prefix,
+                      addr_to_numeric((struct in6_addr *)&e->saddr),
+                      mask_to_numeric((struct in6_addr *)&e->smask));
+       }
+}
+
+static void print_flags(char *prefix, const struct ip6t_policy_info *info)
+{
+       if (info->flags & IP6T_POLICY_MATCH_IN)
+               printf("%sdir in ", prefix);
+       else
+               printf("%sdir out ", prefix);
+
+       if (info->flags & IP6T_POLICY_MATCH_NONE)
+               printf("%spol none ", prefix);
+       else
+               printf("%spol ipsec ", prefix);
+
+       if (info->flags & IP6T_POLICY_MATCH_STRICT)
+               printf("%sstrict ", prefix);
+}
+
+static void print(const struct ip6t_ip6 *ip,
+                  const struct ip6t_entry_match *match,
+                 int numeric)
+{
+       const struct ip6t_policy_info *info = (void *)match->data;
+       unsigned int i;
+
+       printf("policy match ");
+       print_flags("", info);
+       for (i = 0; i < info->len; i++) {
+               if (info->len > 1)
+                       printf("[%u] ", i);
+               print_entry("", &info->pol[i], numeric);
+       }
+
+       printf("\n");
+}
+
+static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
+{
+       const struct ip6t_policy_info *info = (void *)match->data;
+       unsigned int i;
+
+       print_flags("--", info);
+       for (i = 0; i < info->len; i++) {
+               print_entry("--", &info->pol[i], 0);
+               if (i + 1 < info->len)
+                       printf("--next ");
+       }
+}
+
+struct ip6tables_match policy = {
+       .name           = "policy",
+       .version        = IPTABLES_VERSION,
+       .size           = IP6T_ALIGN(sizeof(struct ip6t_policy_info)),
+       .userspacesize  = IP6T_ALIGN(sizeof(struct ip6t_policy_info)),
+       .help           = help,
+       .init           = init,
+       .parse          = parse,
+       .final_check    = final_check,
+       .print          = print,
+       .save           = save,
+       .extra_opts     = opts
+};
+
+void _init(void)
+{
+       register_match6(&policy);
+}
diff --git a/extensions/libip6t_policy.man b/extensions/libip6t_policy.man
new file mode 100644 (file)
index 0000000..eed163e
--- /dev/null
@@ -0,0 +1,48 @@
+This modules matches the policy used by IPsec for handling a packet.
+.TP
+.BI "--dir " "in|out"
+Used to select whether to match the policy used for decapsulation or the
+policy that will be used for encapsulation.
+.B in
+is valid in the
+.B PREROUTING, INPUT and FORWARD
+chains,
+.B out
+is valid in the
+.B POSTROUTING, OUTPUT and FORWARD
+chains.
+.TP
+.BI "--pol " "none|ipsec"
+Matches if the packet is subject to IPsec processing.
+.TP
+.BI "--strict"
+Selects whether to match the exact policy or match if any rule of
+the policy matches the given policy.
+.TP
+.BI "--reqid " "id"
+Matches the reqid of the policy rule. The reqid can be specified with
+.B setkey(8)
+using
+.B unique:id
+as level.
+.TP
+.BI "--spi " "spi"
+Matches the SPI of the SA.
+.TP
+.BI "--proto " "ah|esp|ipcomp"
+Matches the encapsulation protocol.
+.TP
+.BI "--mode " "tunnel|transport"
+Matches the encapsulation mode.
+.TP
+.BI "--tunnel-src " "addr[/mask]"
+Matches the source end-point address of a tunnel mode SA.
+Only valid with --mode tunnel.
+.TP
+.BI "--tunnel-dst " "addr[/mask]"
+Matches the destination end-point address of a tunnel mode SA.
+Only valid with --mode tunnel.
+.TP
+.BI "--next"
+Start the next element in the policy specification. Can only be used with
+--strict
diff --git a/extensions/libip6t_state.c b/extensions/libip6t_state.c
new file mode 100644 (file)
index 0000000..84fd1a4
--- /dev/null
@@ -0,0 +1,163 @@
+/* Ugly hack to make state matching for ipv6 work before iptables-1.4.x is finished */
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <ip6tables.h>
+#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/netfilter_ipv4/ipt_state.h>
+
+#ifndef IPT_STATE_UNTRACKED
+#define IPT_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 1))
+#endif
+
+/* Function which prints out usage message. */
+static void
+help(void)
+{
+       printf(
+"state v%s options:\n"
+" [!] --state [INVALID|ESTABLISHED|NEW|RELATED|UNTRACKED][,...]\n"
+"                              State(s) to match\n"
+"\n", IPTABLES_VERSION);
+}
+
+static struct option opts[] = {
+       { "state", 1, 0, '1' },
+       {0}
+};
+
+static int
+parse_state(const char *state, size_t strlen, struct ipt_state_info *sinfo)
+{
+       if (strncasecmp(state, "INVALID", strlen) == 0)
+               sinfo->statemask |= IPT_STATE_INVALID;
+       else if (strncasecmp(state, "NEW", strlen) == 0)
+               sinfo->statemask |= IPT_STATE_BIT(IP_CT_NEW);
+       else if (strncasecmp(state, "ESTABLISHED", strlen) == 0)
+               sinfo->statemask |= IPT_STATE_BIT(IP_CT_ESTABLISHED);
+       else if (strncasecmp(state, "RELATED", strlen) == 0)
+               sinfo->statemask |= IPT_STATE_BIT(IP_CT_RELATED);
+       else if (strncasecmp(state, "UNTRACKED", strlen) == 0)
+               sinfo->statemask |= IPT_STATE_UNTRACKED;
+       else
+               return 0;
+       return 1;
+}
+
+static void
+parse_states(const char *arg, struct ipt_state_info *sinfo)
+{
+       const char *comma;
+
+       while ((comma = strchr(arg, ',')) != NULL) {
+               if (comma == arg || !parse_state(arg, comma-arg, sinfo))
+                       exit_error(PARAMETER_PROBLEM, "Bad state `%s'", arg);
+               arg = comma+1;
+       }
+
+       if (strlen(arg) == 0 || !parse_state(arg, strlen(arg), sinfo))
+               exit_error(PARAMETER_PROBLEM, "Bad state `%s'", arg);
+}
+
+/* Function which parses command options; returns true if it
+   ate an option */
+static int
+parse(int c, char **argv, int invert, unsigned int *flags,
+      const struct ip6t_entry *entry,
+      unsigned int *nfcache,
+      struct ip6t_entry_match **match)
+{
+       struct ipt_state_info *sinfo = (struct ipt_state_info *)(*match)->data;
+
+       switch (c) {
+       case '1':
+               check_inverse(optarg, &invert, &optind, 0);
+
+               parse_states(argv[optind-1], sinfo);
+               if (invert)
+                       sinfo->statemask = ~sinfo->statemask;
+               *flags = 1;
+               break;
+
+       default:
+               return 0;
+       }
+
+       return 1;
+}
+
+/* Final check; must have specified --state. */
+static void final_check(unsigned int flags)
+{
+       if (!flags)
+               exit_error(PARAMETER_PROBLEM, "You must specify `--state'");
+}
+
+static void print_state(unsigned int statemask)
+{
+       const char *sep = "";
+
+       if (statemask & IPT_STATE_INVALID) {
+               printf("%sINVALID", sep);
+               sep = ",";
+       }
+       if (statemask & IPT_STATE_BIT(IP_CT_NEW)) {
+               printf("%sNEW", sep);
+               sep = ",";
+       }
+       if (statemask & IPT_STATE_BIT(IP_CT_RELATED)) {
+               printf("%sRELATED", sep);
+               sep = ",";
+       }
+       if (statemask & IPT_STATE_BIT(IP_CT_ESTABLISHED)) {
+               printf("%sESTABLISHED", sep);
+               sep = ",";
+       }
+       if (statemask & IPT_STATE_UNTRACKED) {
+               printf("%sUNTRACKED", sep);
+               sep = ",";
+       }
+       printf(" ");
+}
+
+/* Prints out the matchinfo. */
+static void
+print(const struct ip6t_ip6 *ip,
+      const struct ip6t_entry_match *match,
+      int numeric)
+{
+       struct ipt_state_info *sinfo = (struct ipt_state_info *)match->data;
+
+       printf("state ");
+       print_state(sinfo->statemask);
+}
+
+/* Saves the matchinfo in parsable form to stdout. */
+static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
+{
+       struct ipt_state_info *sinfo = (struct ipt_state_info *)match->data;
+
+       printf("--state ");
+       print_state(sinfo->statemask);
+}
+
+static struct ip6tables_match state = { 
+       .next           = NULL,
+       .name           = "state",
+       .version        = IPTABLES_VERSION,
+       .size           = IP6T_ALIGN(sizeof(struct ipt_state_info)),
+       .userspacesize  = IP6T_ALIGN(sizeof(struct ipt_state_info)),
+       .help           = &help,
+       .parse          = &parse,
+       .final_check    = &final_check,
+       .print          = &print,
+       .save           = &save,
+       .extra_opts     = opts
+};
+
+void _init(void)
+{
+       register_match6(&state);
+}
diff --git a/extensions/libipt_NFQUEUE.c b/extensions/libipt_NFQUEUE.c
new file mode 100644 (file)
index 0000000..bc4e82f
--- /dev/null
@@ -0,0 +1,114 @@
+/* Shared library add-on to iptables for NFQ
+ *
+ * (C) 2005 by Harald Welte <laforge@netfilter.org>
+ *
+ * This program is distributed under the terms of GNU GPL v2, 1991
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+#include <iptables.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_NFQUEUE.h>
+
+static void init(struct ipt_entry_target *t, unsigned int *nfcache) 
+{
+}
+
+static void help(void) 
+{
+       printf(
+"NFQUEUE target options\n"
+"  --queue-num value           Send packet to QUEUE number <value>.\n"
+"                              Valid queue numbers are 0-65535\n"
+);
+}
+
+static struct option opts[] = {
+       { "queue-num", 1, 0, 'F' },
+       { 0 }
+};
+
+static void
+parse_num(const char *s, struct ipt_NFQ_info *tinfo)
+{
+       unsigned int num;
+       
+       if (string_to_number(s, 0, 65535, &num) == -1)
+               exit_error(PARAMETER_PROBLEM,
+                          "Invalid queue number `%s'\n", s);
+
+       tinfo->queuenum = num & 0xffff;
+       return;
+}
+
+static int
+parse(int c, char **argv, int invert, unsigned int *flags,
+      const struct ipt_entry *entry,
+      struct ipt_entry_target **target)
+{
+       struct ipt_NFQ_info *tinfo
+               = (struct ipt_NFQ_info *)(*target)->data;
+
+       switch (c) {
+       case 'F':
+               if (*flags)
+                       exit_error(PARAMETER_PROBLEM, "NFQUEUE target: "
+                                  "Only use --queue-num ONCE!");
+               parse_num(optarg, tinfo);
+               break;
+       default:
+               return 0;
+       }
+
+       return 1;
+}
+
+static void
+final_check(unsigned int flags)
+{
+}
+
+/* Prints out the targinfo. */
+static void
+print(const struct ipt_ip *ip,
+      const struct ipt_entry_target *target,
+      int numeric)
+{
+       const struct ipt_NFQ_info *tinfo =
+               (const struct ipt_NFQ_info *)target->data;
+       printf("NFQUEUE num %u", tinfo->queuenum);
+}
+
+/* Saves the union ipt_targinfo in parsable form to stdout. */
+static void
+save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
+{
+       const struct ipt_NFQ_info *tinfo =
+               (const struct ipt_NFQ_info *)target->data;
+
+       printf("--queue-num %u ", tinfo->queuenum);
+}
+
+static struct iptables_target nfqueue = { 
+       .next           = NULL,
+       .name           = "NFQUEUE",
+       .version        = IPTABLES_VERSION,
+       .size           = IPT_ALIGN(sizeof(struct ipt_NFQ_info)),
+       .userspacesize  = IPT_ALIGN(sizeof(struct ipt_NFQ_info)),
+       .help           = &help,
+       .init           = &init,
+       .parse          = &parse,
+       .final_check    = &final_check,
+       .print          = &print,
+       .save           = &save,
+       .extra_opts     = opts
+};
+
+void _init(void)
+{
+       register_target(&nfqueue);
+}
diff --git a/extensions/libipt_NFQUEUE.man b/extensions/libipt_NFQUEUE.man
new file mode 100644 (file)
index 0000000..c4e9d11
--- /dev/null
@@ -0,0 +1,12 @@
+This target is an extension of the QUEUE target. As opposed to QUEUE, it allows
+you to put a packet into any specific queue, identified by its 16-bit queue
+number.  
+.TP
+.BR "--queue-num " "\fIvalue"
+This specifies the QUEUE number to use. Valud queue numbers are 0 to 65535. The default value is 0.
+.TP
+It can only be used with Kernel versions 2.6.14 or later, since it requires
+the
+.B
+nfnetlink_queue
+kernel support.
diff --git a/extensions/libipt_dccp.c b/extensions/libipt_dccp.c
new file mode 100644 (file)
index 0000000..af1d20e
--- /dev/null
@@ -0,0 +1,399 @@
+/* Shared library add-on to iptables for DCCP matching
+ *
+ * (C) 2005 by Harald Welte <laforge@netfilter.org>
+ *
+ * This program is distributed under the terms of GNU GPL v2, 1991
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <netdb.h>
+#include <ctype.h>
+
+#include <iptables.h>
+#include <linux/dccp.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_dccp.h>
+
+#if 0
+#define DEBUGP(format, first...) printf(format, ##first)
+#define static
+#else
+#define DEBUGP(format, fist...) 
+#endif
+
+/* Initialize the match. */
+static void
+init(struct ipt_entry_match *m, 
+     unsigned int *nfcache)
+{
+       struct ipt_dccp_info *einfo = (struct ipt_dccp_info *)m->data;
+
+       memset(einfo, 0, sizeof(struct ipt_dccp_info));
+}
+
+static void help(void)
+{
+       printf(
+"DCCP match v%s options\n"
+" --source-port [!] port[:port]                          match source port(s)\n"
+" --sport ...\n"
+" --destination-port [!] port[:port]                     match destination port(s)\n"
+" --dport ...\n"
+,
+       IPTABLES_VERSION);
+}
+
+static struct option opts[] = {
+       { .name = "source-port", .has_arg = 1, .flag = 0, .val = '1' },
+       { .name = "sport", .has_arg = 1, .flag = 0, .val = '1' },
+       { .name = "destination-port", .has_arg = 1, .flag = 0, .val = '2' },
+       { .name = "dport", .has_arg = 1, .flag = 0, .val = '2' },
+       { .name = "dccp-types", .has_arg = 1, .flag = 0, .val = '3' },
+       { .name = "dccp-option", .has_arg = 1, .flag = 0, .val = '4' },
+       { .name = 0 }
+};
+
+static int
+service_to_port(const char *name)
+{
+       struct servent *service;
+
+       if ((service = getservbyname(name, "dccp")) != NULL)
+               return ntohs((unsigned short) service->s_port);
+
+       return -1;
+}
+
+static u_int16_t
+parse_dccp_port(const char *port)
+{
+       unsigned int portnum;
+
+       DEBUGP("%s\n", port);
+       if (string_to_number(port, 0, 65535, &portnum) != -1 ||
+           (portnum = service_to_port(port)) != -1)
+               return (u_int16_t)portnum;
+
+       exit_error(PARAMETER_PROBLEM,
+                  "invalid DCCP port/service `%s' specified", port);
+}
+
+static void
+parse_dccp_ports(const char *portstring, 
+                u_int16_t *ports)
+{
+       char *buffer;
+       char *cp;
+
+       buffer = strdup(portstring);
+       DEBUGP("%s\n", portstring);
+       if ((cp = strchr(buffer, ':')) == NULL) {
+               ports[0] = ports[1] = parse_dccp_port(buffer);
+       }
+       else {
+               *cp = '\0';
+               cp++;
+
+               ports[0] = buffer[0] ? parse_dccp_port(buffer) : 0;
+               ports[1] = cp[0] ? parse_dccp_port(cp) : 0xFFFF;
+
+               if (ports[0] > ports[1])
+                       exit_error(PARAMETER_PROBLEM,
+                                  "invalid portrange (min > max)");
+       }
+       free(buffer);
+}
+
+static char *dccp_pkt_types[] = {
+       [DCCP_PKT_REQUEST]      = "REQUEST",
+       [DCCP_PKT_RESPONSE]     = "RESPONSE",
+       [DCCP_PKT_DATA]         = "DATA",
+       [DCCP_PKT_ACK]          = "ACK",
+       [DCCP_PKT_DATAACK]      = "DATAACK",
+       [DCCP_PKT_CLOSEREQ]     = "CLOSEREQ",
+       [DCCP_PKT_CLOSE]        = "CLOSE",
+       [DCCP_PKT_RESET]        = "RESET",
+       [DCCP_PKT_SYNC]         = "SYNC",
+       [DCCP_PKT_SYNCACK]      = "SYNCACK",
+       [DCCP_PKT_INVALID]      = "INVALID",
+};
+
+static u_int16_t
+parse_dccp_types(const char *typestring)
+{
+       u_int16_t typemask = 0;
+       char *ptr, *buffer;
+
+       buffer = strdup(typestring);
+
+       for (ptr = strtok(buffer, ","); ptr; ptr = strtok(NULL, ",")) {
+               unsigned int i;
+               for (i = 0; i < sizeof(dccp_pkt_types)/sizeof(char *); i++) {
+                       if (!strcasecmp(dccp_pkt_types[i], ptr)) {
+                               typemask |= (1 << i);
+                               break;
+                       }
+               }
+               if (i == sizeof(dccp_pkt_types)/sizeof(char *))
+                       exit_error(PARAMETER_PROBLEM,
+                                  "Unknown DCCP type `%s'", ptr);
+       }
+
+       free(buffer);
+       return typemask;
+}
+
+static u_int8_t parse_dccp_option(char *optstring)
+{
+       unsigned int ret;
+
+       if (string_to_number(optstring, 1, 255, &ret) == -1)
+               exit_error(PARAMETER_PROBLEM, "Bad DCCP option `%s'",
+                          optstring);
+
+       return (u_int8_t)ret;
+}
+
+static int
+parse(int c, char **argv, int invert, unsigned int *flags,
+      const struct ipt_entry *entry,
+      unsigned int *nfcache,
+      struct ipt_entry_match **match)
+{
+       struct ipt_dccp_info *einfo
+               = (struct ipt_dccp_info *)(*match)->data;
+
+       switch (c) {
+       case '1':
+               if (*flags & IPT_DCCP_SRC_PORTS)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "Only one `--source-port' allowed");
+               einfo->flags |= IPT_DCCP_SRC_PORTS;
+               check_inverse(optarg, &invert, &optind, 0);
+               parse_dccp_ports(argv[optind-1], einfo->spts);
+               if (invert)
+                       einfo->invflags |= IPT_DCCP_SRC_PORTS;
+               *flags |= IPT_DCCP_SRC_PORTS;
+               break;
+
+       case '2':
+               if (*flags & IPT_DCCP_DEST_PORTS)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "Only one `--destination-port' allowed");
+               einfo->flags |= IPT_DCCP_DEST_PORTS;
+               check_inverse(optarg, &invert, &optind, 0);
+               parse_dccp_ports(argv[optind-1], einfo->dpts);
+               if (invert)
+                       einfo->invflags |= IPT_DCCP_DEST_PORTS;
+               *flags |= IPT_DCCP_DEST_PORTS;
+               break;
+
+       case '3':
+               if (*flags & IPT_DCCP_TYPE)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "Only one `--dccp-types' allowed");
+               einfo->flags |= IPT_DCCP_TYPE;
+               check_inverse(optarg, &invert, &optind, 0);
+               einfo->typemask = parse_dccp_types(argv[optind-1]);
+               if (invert)
+                       einfo->invflags |= IPT_DCCP_TYPE;
+               *flags |= IPT_DCCP_TYPE;
+               break;
+
+       case '4':
+               if (*flags & IPT_DCCP_OPTION)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "Only one `--dccp-option' allowed");
+               einfo->flags |= IPT_DCCP_OPTION;
+               check_inverse(optarg, &invert, &optind, 0);
+               einfo->option = parse_dccp_option(argv[optind-1]);
+               if (invert)
+                       einfo->invflags |= IPT_DCCP_OPTION;
+               *flags |= IPT_DCCP_OPTION;
+               break;
+       default:
+               return 0;
+       }
+       return 1;
+}
+
+static void
+final_check(unsigned int flags)
+{
+}
+
+static char *
+port_to_service(int port)
+{
+       struct servent *service;
+
+       if ((service = getservbyport(htons(port), "dccp")))
+               return service->s_name;
+
+       return NULL;
+}
+
+static void
+print_port(u_int16_t port, int numeric)
+{
+       char *service;
+
+       if (numeric || (service = port_to_service(port)) == NULL)
+               printf("%u", port);
+       else
+               printf("%s", service);
+}
+
+static void
+print_ports(const char *name, u_int16_t min, u_int16_t max,
+           int invert, int numeric)
+{
+       const char *inv = invert ? "!" : "";
+
+       if (min != 0 || max != 0xFFFF || invert) {
+               printf("%s", name);
+               if (min == max) {
+                       printf(":%s", inv);
+                       print_port(min, numeric);
+               } else {
+                       printf("s:%s", inv);
+                       print_port(min, numeric);
+                       printf(":");
+                       print_port(max, numeric);
+               }
+               printf(" ");
+       }
+}
+
+static void
+print_types(u_int16_t types, int inverted, int numeric)
+{
+       int have_type = 0;
+
+       if (inverted)
+               printf("! ");
+
+       while (types) {
+               unsigned int i;
+
+               for (i = 0; !(types & (1 << i)); i++);
+
+               if (have_type)
+                       printf(",");
+               else
+                       have_type = 1;
+
+               if (numeric)
+                       printf("%u", i);
+               else
+                       printf("%s", dccp_pkt_types[i]);
+
+               types &= ~(1 << i);
+       }
+}
+
+static void
+print_option(u_int8_t option, int invert, int numeric)
+{
+       if (option || invert)
+               printf("option=%s%u ", invert ? "!" : "", option);
+}
+
+/* Prints out the matchinfo. */
+static void
+print(const struct ipt_ip *ip,
+      const struct ipt_entry_match *match,
+      int numeric)
+{
+       const struct ipt_dccp_info *einfo =
+               (const struct ipt_dccp_info *)match->data;
+
+       printf("dccp ");
+
+       if (einfo->flags & IPT_DCCP_SRC_PORTS) {
+               print_ports("spt", einfo->spts[0], einfo->spts[1],
+                       einfo->invflags & IPT_DCCP_SRC_PORTS,
+                       numeric);
+       }
+
+       if (einfo->flags & IPT_DCCP_DEST_PORTS) {
+               print_ports("dpt", einfo->dpts[0], einfo->dpts[1],
+                       einfo->invflags & IPT_DCCP_DEST_PORTS,
+                       numeric);
+       }
+
+       if (einfo->flags & IPT_DCCP_TYPE) {
+               print_types(einfo->typemask,
+                          einfo->invflags & IPT_DCCP_TYPE,
+                          numeric);
+       }
+
+       if (einfo->flags & IPT_DCCP_OPTION) {
+               print_option(einfo->option,
+                            einfo->invflags & IPT_DCCP_OPTION, numeric);
+       }
+}
+
+/* Saves the union ipt_matchinfo in parsable form to stdout. */
+static void
+save(const struct ipt_ip *ip, 
+     const struct ipt_entry_match *match)
+{
+       const struct ipt_dccp_info *einfo =
+               (const struct ipt_dccp_info *)match->data;
+
+       if (einfo->flags & IPT_DCCP_SRC_PORTS) {
+               if (einfo->invflags & IPT_DCCP_SRC_PORTS)
+                       printf("! ");
+               if (einfo->spts[0] != einfo->spts[1])
+                       printf("--sport %u:%u ", 
+                              einfo->spts[0], einfo->spts[1]);
+               else
+                       printf("--sport %u ", einfo->spts[0]);
+       }
+
+       if (einfo->flags & IPT_DCCP_DEST_PORTS) {
+               if (einfo->invflags & IPT_DCCP_DEST_PORTS)
+                       printf("! ");
+               if (einfo->dpts[0] != einfo->dpts[1])
+                       printf("--dport %u:%u ",
+                              einfo->dpts[0], einfo->dpts[1]);
+               else
+                       printf("--dport %u ", einfo->dpts[0]);
+       }
+
+       if (einfo->flags & IPT_DCCP_TYPE) {
+               printf("--dccp-type ");
+               print_types(einfo->typemask, einfo->invflags & IPT_DCCP_TYPE,0);
+       }
+
+       if (einfo->flags & IPT_DCCP_OPTION) {
+               printf("--dccp-option %s%u ", 
+                       einfo->typemask & IPT_DCCP_OPTION ? "! " : "",
+                       einfo->option);
+       }
+}
+
+static
+struct iptables_match dccp
+= { .name          = "dccp",
+    .version       = IPTABLES_VERSION,
+    .size          = IPT_ALIGN(sizeof(struct ipt_dccp_info)),
+    .userspacesize = IPT_ALIGN(sizeof(struct ipt_dccp_info)),
+    .help          = &help,
+    .init          = &init,
+    .parse         = &parse,
+    .final_check   = &final_check,
+    .print         = &print,
+    .save          = &save,
+    .extra_opts    = opts
+};
+
+void _init(void)
+{
+       register_match(&dccp);
+}
+
diff --git a/extensions/libipt_dccp.man b/extensions/libipt_dccp.man
new file mode 100644 (file)
index 0000000..6443ec3
--- /dev/null
@@ -0,0 +1,12 @@
+.TP
+\fB--source-port\fR,\fB--sport \fR[\fB!\fR] \fIport\fR[\fB:\fIport\fR]
+.TP
+\fB--destination-port\fR,\fB--dport \fR[\fB!\fR] \fIport\fR[\fB:\fIport\fR]
+.TP
+\fB--dccp-types\fR [\fB!\fR] \fImask\fP
+Match when the DCCP packet type is one of 'mask'. 'mask' is a comma-separated
+list of packet types.  Packet types are: 
+.BR "REQUEST RESPONSE DATA ACK DATAACK CLOSEREQ CLOSE RESET SYNC SYNCACK INVALID" .
+.TP
+\fB--dccp-option\fR [\fB!\fR\] \fInumber\fP
+Match if DCP option set.
diff --git a/extensions/libipt_policy.c b/extensions/libipt_policy.c
new file mode 100644 (file)
index 0000000..681995a
--- /dev/null
@@ -0,0 +1,436 @@
+/* Shared library add-on to iptables to add policy support. */
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include <getopt.h>
+#include <netdb.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <iptables.h>
+
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include "../include/linux/netfilter_ipv4/ipt_policy.h"
+
+/*
+ * HACK: global pointer to current matchinfo for making
+ * final checks and adjustments in final_check.
+ */
+static struct ipt_policy_info *policy_info;
+
+static void help(void)
+{
+       printf(
+"policy v%s options:\n"
+"  --dir in|out                        match policy applied during decapsulation/\n"
+"                              policy to be applied during encapsulation\n"
+"  --pol none|ipsec            match policy\n"
+"  --strict                    match entire policy instead of single element\n"
+"                              at any position\n"
+"[!] --reqid reqid             match reqid\n"
+"[!] --spi spi                 match SPI\n"
+"[!] --proto proto             match protocol (ah/esp/ipcomp)\n"
+"[!] --mode mode               match mode (transport/tunnel)\n"
+"[!] --tunnel-src addr/mask    match tunnel source\n"
+"[!] --tunnel-dst addr/mask    match tunnel destination\n"
+"  --next                      begin next element in policy\n",
+       IPTABLES_VERSION);
+}
+
+static struct option opts[] =
+{
+       {
+               .name           = "dir",
+               .has_arg        = 1,
+               .val            = '1',
+       },
+       {
+               .name           = "pol",
+               .has_arg        = 1,
+               .val            = '2',
+       },
+       {
+               .name           = "strict",
+               .val            = '3'
+       },
+       {
+               .name           = "reqid",
+               .has_arg        = 1,
+               .val            = '4',
+       },
+       {
+               .name           = "spi",
+               .has_arg        = 1,
+               .val            = '5'
+       },
+       {
+               .name           = "tunnel-src",
+               .has_arg        = 1,
+               .val            = '6'
+       },
+       {
+               .name           = "tunnel-dst",
+               .has_arg        = 1,
+               .val            = '7'
+       },
+       {
+               .name           = "proto",
+               .has_arg        = 1,
+               .val            = '8'
+       },
+       {
+               .name           = "mode",
+               .has_arg        = 1,
+               .val            = '9'
+       },
+       {
+               .name           = "next",
+               .val            = 'a'
+       },
+       { }
+};
+
+static void init(struct ipt_entry_match *m, unsigned int *nfcache)
+{
+       *nfcache |= NFC_UNKNOWN;
+}
+
+static int parse_direction(char *s)
+{
+       if (strcmp(s, "in") == 0)
+               return IPT_POLICY_MATCH_IN;
+       if (strcmp(s, "out") == 0)
+               return IPT_POLICY_MATCH_OUT;
+       exit_error(PARAMETER_PROBLEM, "policy_match: invalid dir `%s'", s);
+}
+
+static int parse_policy(char *s)
+{
+       if (strcmp(s, "none") == 0)
+               return IPT_POLICY_MATCH_NONE;
+       if (strcmp(s, "ipsec") == 0)
+               return 0;
+       exit_error(PARAMETER_PROBLEM, "policy match: invalid policy `%s'", s);
+}
+
+static int parse_mode(char *s)
+{
+       if (strcmp(s, "transport") == 0)
+               return IPT_POLICY_MODE_TRANSPORT;
+       if (strcmp(s, "tunnel") == 0)
+               return IPT_POLICY_MODE_TUNNEL;
+       exit_error(PARAMETER_PROBLEM, "policy match: invalid mode `%s'", s);
+}
+
+static int parse(int c, char **argv, int invert, unsigned int *flags,
+                 const struct ipt_entry *entry,
+                 unsigned int *nfcache,
+                 struct ipt_entry_match **match)
+{
+       struct ipt_policy_info *info = (void *)(*match)->data;
+       struct ipt_policy_elem *e = &info->pol[info->len];
+       struct in_addr *addr = NULL, mask;
+       unsigned int naddr = 0;
+       int mode;
+
+       check_inverse(optarg, &invert, &optind, 0);
+
+       switch (c) {
+       case '1':
+               if (info->flags & (IPT_POLICY_MATCH_IN|IPT_POLICY_MATCH_OUT))
+                       exit_error(PARAMETER_PROBLEM,
+                                  "policy match: double --dir option");
+               if (invert)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "policy match: can't invert --dir option");
+
+               info->flags |= parse_direction(argv[optind-1]);
+               break;
+       case '2':
+               if (invert)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "policy match: can't invert --policy option");
+
+               info->flags |= parse_policy(argv[optind-1]);
+               break;
+       case '3':
+               if (info->flags & IPT_POLICY_MATCH_STRICT)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "policy match: double --strict option");
+
+               if (invert)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "policy match: can't invert --strict option");
+
+               info->flags |= IPT_POLICY_MATCH_STRICT;
+               break;
+       case '4':
+               if (e->match.reqid)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "policy match: double --reqid option");
+
+               e->match.reqid = 1;
+               e->invert.reqid = invert;
+               e->reqid = strtol(argv[optind-1], NULL, 10);
+               break;
+       case '5':
+               if (e->match.spi)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "policy match: double --spi option");
+
+               e->match.spi = 1;
+               e->invert.spi = invert;
+               e->spi = strtol(argv[optind-1], NULL, 0x10);
+               break;
+       case '6':
+               if (e->match.saddr)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "policy match: double --tunnel-src option");
+
+               parse_hostnetworkmask(argv[optind-1], &addr, &mask, &naddr);
+               if (naddr > 1)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "policy match: name resolves to multiple IPs");
+
+               e->match.saddr = 1;
+               e->invert.saddr = invert;
+               e->saddr.a4 = addr[0];
+               e->smask.a4 = mask;
+                break;
+       case '7':
+               if (e->match.daddr)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "policy match: double --tunnel-dst option");
+
+               parse_hostnetworkmask(argv[optind-1], &addr, &mask, &naddr);
+               if (naddr > 1)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "policy match: name resolves to multiple IPs");
+
+               e->match.daddr = 1;
+               e->invert.daddr = invert;
+               e->daddr.a4 = addr[0];
+               e->dmask.a4 = mask;
+               break;
+       case '8':
+               if (e->match.proto)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "policy match: double --proto option");
+
+               e->proto = parse_protocol(argv[optind-1]);
+               if (e->proto != IPPROTO_AH && e->proto != IPPROTO_ESP &&
+                   e->proto != IPPROTO_COMP)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "policy match: protocol must ah/esp/ipcomp");
+               e->match.proto = 1;
+               e->invert.proto = invert;
+               break;
+       case '9':
+               if (e->match.mode)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "policy match: double --mode option");
+
+               mode = parse_mode(argv[optind-1]);
+               e->match.mode = 1;
+               e->invert.mode = invert;
+               e->mode = mode;
+               break;
+       case 'a':
+               if (invert)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "policy match: can't invert --next option");
+
+               if (++info->len == IPT_POLICY_MAX_ELEM)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "policy match: maximum policy depth reached");
+               break;
+       default:
+               return 0;
+       }
+
+       policy_info = info;
+       return 1;
+}
+
+static void final_check(unsigned int flags)
+{
+       struct ipt_policy_info *info = policy_info;
+       struct ipt_policy_elem *e;
+       int i;
+
+       if (info == NULL)
+               exit_error(PARAMETER_PROBLEM,
+                          "policy match: no parameters given");
+
+       if (!(info->flags & (IPT_POLICY_MATCH_IN|IPT_POLICY_MATCH_OUT)))
+               exit_error(PARAMETER_PROBLEM,
+                          "policy match: neither --in nor --out specified");
+
+       if (info->flags & IPT_POLICY_MATCH_NONE) {
+               if (info->flags & IPT_POLICY_MATCH_STRICT)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "policy match: policy none but --strict given");
+
+               if (info->len != 0)
+                       exit_error(PARAMETER_PROBLEM,
+                                  "policy match: policy none but policy given");
+       } else
+               info->len++;    /* increase len by 1, no --next after last element */
+
+       if (!(info->flags & IPT_POLICY_MATCH_STRICT) && info->len > 1)
+               exit_error(PARAMETER_PROBLEM,
+                          "policy match: multiple elements but no --strict");
+
+       for (i = 0; i < info->len; i++) {
+               e = &info->pol[i];
+
+               if (info->flags & IPT_POLICY_MATCH_STRICT &&
+                   !(e->match.reqid || e->match.spi || e->match.saddr ||
+                     e->match.daddr || e->match.proto || e->match.mode))
+                       exit_error(PARAMETER_PROBLEM,
+                                  "policy match: empty policy element");
+
+               if ((e->match.saddr || e->match.daddr)
+                   && ((e->mode == IPT_POLICY_MODE_TUNNEL && e->invert.mode) ||
+                       (e->mode == IPT_POLICY_MODE_TRANSPORT && !e->invert.mode)))
+                       exit_error(PARAMETER_PROBLEM,
+                                  "policy match: --tunnel-src/--tunnel-dst "
+                                  "is only valid in tunnel mode");
+       }
+}
+
+static void print_mode(char *prefix, u_int8_t mode, int numeric)
+{
+       printf("%smode ", prefix);
+
+       switch (mode) {
+       case IPT_POLICY_MODE_TRANSPORT:
+               printf("transport ");
+               break;
+       case IPT_POLICY_MODE_TUNNEL:
+               printf("tunnel ");
+               break;
+       default:
+               printf("??? ");
+               break;
+       }
+}
+
+static void print_proto(char *prefix, u_int8_t proto, int numeric)
+{
+       struct protoent *p = NULL;
+
+       printf("%sproto ", prefix);
+       if (!numeric)
+               p = getprotobynumber(proto);
+       if (p != NULL)
+               printf("%s ", p->p_name);
+       else
+               printf("%u ", proto);
+}
+
+#define PRINT_INVERT(x)                \
+do {                           \
+       if (x)                  \
+               printf("! ");   \
+} while(0)
+
+static void print_entry(char *prefix, const struct ipt_policy_elem *e,
+                        int numeric)
+{
+       if (e->match.reqid) {
+               PRINT_INVERT(e->invert.reqid);
+               printf("%sreqid %u ", prefix, e->reqid);
+       }
+       if (e->match.spi) {
+               PRINT_INVERT(e->invert.spi);
+               printf("%sspi 0x%x ", prefix, e->spi);
+       }
+       if (e->match.proto) {
+               PRINT_INVERT(e->invert.proto);
+               print_proto(prefix, e->proto, numeric);
+       }
+       if (e->match.mode) {
+               PRINT_INVERT(e->invert.mode);
+               print_mode(prefix, e->mode, numeric);
+       }
+       if (e->match.daddr) {
+               PRINT_INVERT(e->invert.daddr);
+               printf("%stunnel-dst %s%s ", prefix,
+                      addr_to_dotted((struct in_addr *)&e->daddr),
+                      mask_to_dotted((struct in_addr *)&e->dmask));
+       }
+       if (e->match.saddr) {
+               PRINT_INVERT(e->invert.saddr);
+               printf("%stunnel-src %s%s ", prefix,
+                      addr_to_dotted((struct in_addr *)&e->saddr),
+                      mask_to_dotted((struct in_addr *)&e->smask));
+       }
+}
+
+static void print_flags(char *prefix, const struct ipt_policy_info *info)
+{
+       if (info->flags & IPT_POLICY_MATCH_IN)
+               printf("%sdir in ", prefix);
+       else
+               printf("%sdir out ", prefix);
+
+       if (info->flags & IPT_POLICY_MATCH_NONE)
+               printf("%spol none ", prefix);
+       else
+               printf("%spol ipsec ", prefix);
+
+       if (info->flags & IPT_POLICY_MATCH_STRICT)
+               printf("%sstrict ", prefix);
+}
+
+static void print(const struct ipt_ip *ip,
+                  const struct ipt_entry_match *match,
+                 int numeric)
+{
+       const struct ipt_policy_info *info = (void *)match->data;
+       unsigned int i;
+
+       printf("policy match ");
+       print_flags("", info);
+       for (i = 0; i < info->len; i++) {
+               if (info->len > 1)
+                       printf("[%u] ", i);
+               print_entry("", &info->pol[i], numeric);
+       }
+}
+
+static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
+{
+       const struct ipt_policy_info *info = (void *)match->data;
+       unsigned int i;
+
+       print_flags("--", info);
+       for (i = 0; i < info->len; i++) {
+               print_entry("--", &info->pol[i], 0);
+               if (i + 1 < info->len)
+                       printf("--next ");
+       }
+}
+
+struct iptables_match policy = {
+       .name           = "policy",
+       .version        = IPTABLES_VERSION,
+       .size           = IPT_ALIGN(sizeof(struct ipt_policy_info)),
+       .userspacesize  = IPT_ALIGN(sizeof(struct ipt_policy_info)),
+       .help           = help,
+       .init           = init,
+       .parse          = parse,
+       .final_check    = final_check,
+       .print          = print,
+       .save           = save,
+       .extra_opts     = opts
+};
+
+void _init(void)
+{
+       register_match(&policy);
+}
diff --git a/extensions/libipt_policy.man b/extensions/libipt_policy.man
new file mode 100644 (file)
index 0000000..eed163e
--- /dev/null
@@ -0,0 +1,48 @@
+This modules matches the policy used by IPsec for handling a packet.
+.TP
+.BI "--dir " "in|out"
+Used to select whether to match the policy used for decapsulation or the
+policy that will be used for encapsulation.
+.B in
+is valid in the
+.B PREROUTING, INPUT and FORWARD
+chains,
+.B out
+is valid in the
+.B POSTROUTING, OUTPUT and FORWARD
+chains.
+.TP
+.BI "--pol " "none|ipsec"
+Matches if the packet is subject to IPsec processing.
+.TP
+.BI "--strict"
+Selects whether to match the exact policy or match if any rule of
+the policy matches the given policy.
+.TP
+.BI "--reqid " "id"
+Matches the reqid of the policy rule. The reqid can be specified with
+.B setkey(8)
+using
+.B unique:id
+as level.
+.TP
+.BI "--spi " "spi"
+Matches the SPI of the SA.
+.TP
+.BI "--proto " "ah|esp|ipcomp"
+Matches the encapsulation protocol.
+.TP
+.BI "--mode " "tunnel|transport"
+Matches the encapsulation mode.
+.TP
+.BI "--tunnel-src " "addr[/mask]"
+Matches the source end-point address of a tunnel mode SA.
+Only valid with --mode tunnel.
+.TP
+.BI "--tunnel-dst " "addr[/mask]"
+Matches the destination end-point address of a tunnel mode SA.
+Only valid with --mode tunnel.
+.TP
+.BI "--next"
+Start the next element in the policy specification. Can only be used with
+--strict
diff --git a/extensions/libipt_string.man b/extensions/libipt_string.man
new file mode 100644 (file)
index 0000000..3f3e5b7
--- /dev/null
@@ -0,0 +1,15 @@
+This modules matches a given string by using some pattern matching strategy. It requires a linux kernel >= 2.6.14.
+.TP
+.BI "--algo  " "bm|kmp"
+Select the pattern matching strategy. (bm = Boyer-Moore, kmp = Knuth-Pratt-Morris)
+.TP
+.BI "--from " "offset"
+Set the offset from which it starts looking for any matching. If not passed, default is 0.
+.TP
+.BI "--to " "offset"
+Set the offset from which it starts looking for any matching. If not passed, default is the packet size.
+.TP
+.BI "--string " "pattern"
+Matches the given pattern.
+.BI "--hex-string " "pattern"
+Matches the given pattern in hex notation.
diff --git a/include/linux/netfilter_ipv4/ipt_NFQUEUE.h b/include/linux/netfilter_ipv4/ipt_NFQUEUE.h
new file mode 100644 (file)
index 0000000..b5b2943
--- /dev/null
@@ -0,0 +1,16 @@
+/* iptables module for using NFQUEUE mechanism
+ *
+ * (C) 2005 Harald Welte <laforge@netfilter.org>
+ *
+ * This software is distributed under GNU GPL v2, 1991
+ * 
+*/
+#ifndef _IPT_NFQ_TARGET_H
+#define _IPT_NFQ_TARGET_H
+
+/* target info */
+struct ipt_NFQ_info {
+       u_int16_t queuenum;
+};
+
+#endif /* _IPT_DSCP_TARGET_H */
diff --git a/include/linux/netfilter_ipv4/ipt_policy.h b/include/linux/netfilter_ipv4/ipt_policy.h
new file mode 100644 (file)
index 0000000..74ca65c
--- /dev/null
@@ -0,0 +1,62 @@
+#ifndef _IPT_POLICY_H
+#define _IPT_POLICY_H
+
+#define IPT_POLICY_MAX_ELEM    4
+
+#ifndef __KERNEL__
+#include <netinet/in.h>
+#endif
+
+enum ipt_policy_flags
+{
+       IPT_POLICY_MATCH_IN     = 0x1,
+       IPT_POLICY_MATCH_OUT    = 0x2,
+       IPT_POLICY_MATCH_NONE   = 0x4,
+       IPT_POLICY_MATCH_STRICT = 0x8,
+};
+
+enum ipt_policy_modes
+{
+       IPT_POLICY_MODE_TRANSPORT,
+       IPT_POLICY_MODE_TUNNEL
+};
+
+struct ipt_policy_spec
+{
+       u_int8_t        saddr:1,
+                       daddr:1,
+                       proto:1,
+                       mode:1,
+                       spi:1,
+                       reqid:1;
+};
+
+union ipt_policy_addr
+{
+       struct in_addr  a4;
+       struct in6_addr a6;
+};
+
+struct ipt_policy_elem
+{
+       union ipt_policy_addr   saddr;
+       union ipt_policy_addr   smask;
+       union ipt_policy_addr   daddr;
+       union ipt_policy_addr   dmask;
+       u_int32_t               spi;
+       u_int32_t               reqid;
+       u_int8_t                proto;
+       u_int8_t                mode;
+
+       struct ipt_policy_spec  match;
+       struct ipt_policy_spec  invert;
+};
+
+struct ipt_policy_info
+{
+       struct ipt_policy_elem pol[IPT_POLICY_MAX_ELEM];
+       u_int16_t flags;
+       u_int16_t len;
+};
+
+#endif /* _IPT_POLICY_H */
diff --git a/include/linux/netfilter_ipv6/ip6t_policy.h b/include/linux/netfilter_ipv6/ip6t_policy.h
new file mode 100644 (file)
index 0000000..671bd81
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef _IP6T_POLICY_H
+#define _IP6T_POLICY_H
+
+#define IP6T_POLICY_MAX_ELEM   4
+
+enum ip6t_policy_flags
+{
+       IP6T_POLICY_MATCH_IN            = 0x1,
+       IP6T_POLICY_MATCH_OUT           = 0x2,
+       IP6T_POLICY_MATCH_NONE          = 0x4,
+       IP6T_POLICY_MATCH_STRICT        = 0x8,
+};
+
+enum ip6t_policy_modes
+{
+       IP6T_POLICY_MODE_TRANSPORT,
+       IP6T_POLICY_MODE_TUNNEL
+};
+
+struct ip6t_policy_spec
+{
+       u_int8_t        saddr:1,
+                       daddr:1,
+                       proto:1,
+                       mode:1,
+                       spi:1,
+                       reqid:1;
+};
+
+union ip6t_policy_addr
+{
+       struct in_addr  a4;
+       struct in6_addr a6;
+};
+
+struct ip6t_policy_elem
+{
+       union ip6t_policy_addr  saddr;
+       union ip6t_policy_addr  smask;
+       union ip6t_policy_addr  daddr;
+       union ip6t_policy_addr  dmask;
+       u_int32_t               spi;
+       u_int32_t               reqid;
+       u_int8_t                proto;
+       u_int8_t                mode;
+
+       struct ip6t_policy_spec match;
+       struct ip6t_policy_spec invert;
+};
+
+struct ip6t_policy_info
+{
+       struct ip6t_policy_elem pol[IP6T_POLICY_MAX_ELEM];
+       u_int16_t flags;
+       u_int16_t len;
+};
+
+#endif /* _IP6T_POLICY_H */