]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
iptables: Add IPv4/6 IPcomp match support
authorfan.du <fan.du@windriver.com>
Wed, 18 Dec 2013 03:27:22 +0000 (11:27 +0800)
committerPablo Neira Ayuso <pablo@netfilter.org>
Tue, 24 Dec 2013 11:46:20 +0000 (12:46 +0100)
This patch enables user to set iptables ACTIONs for IPcomp
flow specified by its SPI value.

For example:
iptables  -A OUTPUT -p 108 -m ipcomp --ipcompspi 0x12 -j DROP
ip6tables -A OUTPUT -p 108 -m ipcomp --ipcompspi 0x12 -j DROP

IPcomp packet with spi as 0x12 will be dropped.

Signed-off-by: Fan Du <fan.du@windriver.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
extensions/libxt_ipcomp.c [new file with mode: 0644]
extensions/libxt_ipcomp.c.man [new file with mode: 0644]
include/linux/netfilter/xt_ipcomp.h [new file with mode: 0644]

diff --git a/extensions/libxt_ipcomp.c b/extensions/libxt_ipcomp.c
new file mode 100644 (file)
index 0000000..b157e7b
--- /dev/null
@@ -0,0 +1,116 @@
+#include <stdio.h>
+#include <xtables.h>
+#include <linux/netfilter/xt_ipcomp.h>
+
+enum {
+       O_compSPI = 0,
+       O_compRES,
+};
+
+static void comp_help(void)
+{
+       printf(
+"comp match options:\n"
+"[!] --ipcompspi spi[:spi]\n"
+"                              match spi (range)\n");
+}
+
+static const struct xt_option_entry comp_opts[] = {
+       {.name = "ipcompspi", .id = O_compSPI, .type = XTTYPE_UINT32RC,
+        .flags = XTOPT_INVERT | XTOPT_PUT,
+        XTOPT_POINTER(struct xt_ipcomp, spis)},
+       {.name = "compres", .id = O_compRES, .type = XTTYPE_NONE},
+       XTOPT_TABLEEND,
+};
+#undef s
+
+static void comp_parse(struct xt_option_call *cb)
+{
+       struct xt_ipcomp *compinfo = cb->data;
+
+       xtables_option_parse(cb);
+       switch (cb->entry->id) {
+       case O_compSPI:
+               if (cb->nvals == 1)
+                       compinfo->spis[1] = compinfo->spis[0];
+               if (cb->invert)
+                       compinfo->invflags |= XT_IPCOMP_INV_SPI;
+               break;
+       case O_compRES:
+               compinfo->hdrres = 1;
+               break;
+       }
+}
+
+static void
+print_spis(const char *name, uint32_t min, uint32_t max,
+           int invert)
+{
+       const char *inv = invert ? "!" : "";
+
+       if (min != 0 || max != 0xFFFFFFFF || invert) {
+               if (min == max)
+                       printf("%s:%s%u", name, inv, min);
+               else
+                       printf("%ss:%s%u:%u", name, inv, min, max);
+       }
+}
+
+static void comp_print(const void *ip, const struct xt_entry_match *match,
+                     int numeric)
+{
+       const struct xt_ipcomp *comp = (struct xt_ipcomp *)match->data;
+
+       printf(" comp ");
+       print_spis("spi", comp->spis[0], comp->spis[1],
+                   comp->invflags & XT_IPCOMP_INV_SPI);
+
+       if (comp->hdrres)
+               printf(" reserved");
+
+       if (comp->invflags & ~XT_IPCOMP_INV_MASK)
+               printf(" Unknown invflags: 0x%X",
+                      comp->invflags & ~XT_IPCOMP_INV_MASK);
+}
+
+static void comp_save(const void *ip, const struct xt_entry_match *match)
+{
+       const struct xt_ipcomp *compinfo = (struct xt_ipcomp *)match->data;
+
+       if (!(compinfo->spis[0] == 0
+           && compinfo->spis[1] == 0xFFFFFFFF)) {
+               printf("%s --ipcompspi ",
+                       (compinfo->invflags & XT_IPCOMP_INV_SPI) ? " !" : "");
+               if (compinfo->spis[0]
+                   != compinfo->spis[1])
+                       printf("%u:%u",
+                              compinfo->spis[0],
+                              compinfo->spis[1]);
+               else
+                       printf("%u",
+                              compinfo->spis[0]);
+       }
+
+       if (compinfo->hdrres != 0 )
+               printf(" --compres");
+}
+
+static struct xtables_match comp_mt_reg = {
+       .name          = "ipcomp",
+       .version       = XTABLES_VERSION,
+       .family        = NFPROTO_UNSPEC,
+       .size          = XT_ALIGN(sizeof(struct xt_ipcomp)),
+       .userspacesize = XT_ALIGN(sizeof(struct xt_ipcomp)),
+       .help          = comp_help,
+       .print         = comp_print,
+       .save          = comp_save,
+       .x6_parse      = comp_parse,
+       .x6_options    = comp_opts,
+};
+
+void
+_init(void)
+{
+       xtables_register_match(&comp_mt_reg);
+};
+
diff --git a/extensions/libxt_ipcomp.c.man b/extensions/libxt_ipcomp.c.man
new file mode 100644 (file)
index 0000000..f3b17d2
--- /dev/null
@@ -0,0 +1,7 @@
+This module matches the parameters in IPcomp header of IPsec packets.
+.TP
+[\fB!\fP] \fB\-\-ipcompspi\fP \fIspi\fP[\fB:\fP\fIspi\fP]
+Matches IPcomp header CPI value.
+.TP
+\fB\-\-compres\fP
+Matches if the reserved field is filled with zero.
diff --git a/include/linux/netfilter/xt_ipcomp.h b/include/linux/netfilter/xt_ipcomp.h
new file mode 100644 (file)
index 0000000..45c7e40
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef _XT_IPCOMP_H
+#define _XT_IPCOMP_H
+
+#include <linux/types.h>
+
+struct xt_ipcomp {
+       __u32 spis[2];  /* Security Parameter Index */
+       __u8 invflags;  /* Inverse flags */
+       __u8 hdrres;    /* Test of the Reserved Filed */
+};
+
+/* Values for "invflags" field in struct xt_ipcomp. */
+#define XT_IPCOMP_INV_SPI      0x01    /* Invert the sense of spi. */
+#define XT_IPCOMP_INV_MASK     0x01    /* All possible flags. */
+
+#endif /*_XT_IPCOMP_H*/