summaryrefslogtreecommitdiffstats
path: root/extensions
diff options
context:
space:
mode:
authorAhmed Abdelsalam <amsalam20@gmail.com>2018-01-11 18:12:41 +0100
committerPablo Neira Ayuso <pablo@netfilter.org>2018-01-12 01:23:23 +0100
commit6067208f421554056d0c76d190d4aa55c77790bd (patch)
treee0525b68c7a157913c83e3bba0062773c8810057 /extensions
parent0f387b070ae7630c47bd3daeb395d27a1214d4e9 (diff)
extensions: add support for 'srh' match
This patch adds a new exetension to iptables to supprt 'srh' match The implementation considers revision 7 of the SRH draft. https://tools.ietf.org/html/draft-ietf-6man-segment-routing-header-07 Signed-off-by: Ahmed Abdelsalam <amsalam20@gmail.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'extensions')
-rw-r--r--extensions/libip6t_srh.c242
-rw-r--r--extensions/libip6t_srh.t26
2 files changed, 268 insertions, 0 deletions
diff --git a/extensions/libip6t_srh.c b/extensions/libip6t_srh.c
new file mode 100644
index 00000000..ac0ae084
--- /dev/null
+++ b/extensions/libip6t_srh.c
@@ -0,0 +1,242 @@
+/* Shared library to add Segment Routing Header (SRH) matching support.
+ *
+ * Author:
+ * Ahmed Abdelsalam <amsalam20@gmail.com>
+ */
+
+#include <stdio.h>
+#include <xtables.h>
+#include <linux/netfilter_ipv6/ip6t_srh.h>
+#include <string.h>
+
+/* srh command-line options */
+enum {
+ O_SRH_NEXTHDR,
+ O_SRH_LEN_EQ,
+ O_SRH_LEN_GT,
+ O_SRH_LEN_LT,
+ O_SRH_SEGS_EQ,
+ O_SRH_SEGS_GT,
+ O_SRH_SEGS_LT,
+ O_SRH_LAST_EQ,
+ O_SRH_LAST_GT,
+ O_SRH_LAST_LT,
+ O_SRH_TAG,
+};
+
+static void srh_help(void)
+{
+ printf(
+"srh match options:\n"
+"[!] --srh-next-hdr next-hdr Next Header value of SRH\n"
+"[!] --srh-hdr-len-eq hdr_len Hdr Ext Len value of SRH\n"
+"[!] --srh-hdr-len-gt hdr_len Hdr Ext Len value of SRH\n"
+"[!] --srh-hdr-len-lt hdr_len Hdr Ext Len value of SRH\n"
+"[!] --srh-segs-left-eq segs_left Segments Left value of SRH\n"
+"[!] --srh-segs-left-gt segs_left Segments Left value of SRH\n"
+"[!] --srh-segs-left-lt segs_left Segments Left value of SRH\n"
+"[!] --srh-last-entry-eq last_entry Last Entry value of SRH\n"
+"[!] --srh-last-entry-gt last_entry Last Entry value of SRH\n"
+"[!] --srh-last-entry-lt last_entry Last Entry value of SRH\n"
+"[!] --srh-tag tag Tag value of SRH\n");
+}
+
+#define s struct ip6t_srh
+static const struct xt_option_entry srh_opts[] = {
+ { .name = "srh-next-hdr", .id = O_SRH_NEXTHDR, .type = XTTYPE_UINT8,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, next_hdr)},
+ { .name = "srh-hdr-len-eq", .id = O_SRH_LEN_EQ, .type = XTTYPE_UINT8,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, hdr_len)},
+ { .name = "srh-hdr-len-gt", .id = O_SRH_LEN_GT, .type = XTTYPE_UINT8,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, hdr_len)},
+ { .name = "srh-hdr-len-lt", .id = O_SRH_LEN_LT, .type = XTTYPE_UINT8,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, hdr_len)},
+ { .name = "srh-segs-left-eq", .id = O_SRH_SEGS_EQ, .type = XTTYPE_UINT8,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, segs_left)},
+ { .name = "srh-segs-left-gt", .id = O_SRH_SEGS_GT, .type = XTTYPE_UINT8,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, segs_left)},
+ { .name = "srh-segs-left-lt", .id = O_SRH_SEGS_LT, .type = XTTYPE_UINT8,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, segs_left)},
+ { .name = "srh-last-entry-eq", .id = O_SRH_LAST_EQ, .type = XTTYPE_UINT8,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, last_entry)},
+ { .name = "srh-last-entry-gt", .id = O_SRH_LAST_GT, .type = XTTYPE_UINT8,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, last_entry)},
+ { .name = "srh-last-entry-lt", .id = O_SRH_LAST_LT, .type = XTTYPE_UINT8,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, last_entry)},
+ { .name = "srh-tag", .id = O_SRH_TAG, .type = XTTYPE_UINT16,
+ .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, tag)},
+ { }
+};
+#undef s
+
+static void srh_init(struct xt_entry_match *m)
+{
+ struct ip6t_srh *srhinfo = (void *)m->data;
+
+ srhinfo->mt_flags = 0;
+ srhinfo->mt_invflags = 0;
+}
+
+static void srh_parse(struct xt_option_call *cb)
+{
+ struct ip6t_srh *srhinfo = cb->data;
+
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_SRH_NEXTHDR:
+ srhinfo->mt_flags |= IP6T_SRH_NEXTHDR;
+ if (cb->invert)
+ srhinfo->mt_invflags |= IP6T_SRH_INV_NEXTHDR;
+ break;
+ case O_SRH_LEN_EQ:
+ srhinfo->mt_flags |= IP6T_SRH_LEN_EQ;
+ if (cb->invert)
+ srhinfo->mt_invflags |= IP6T_SRH_INV_LEN_EQ;
+ break;
+ case O_SRH_LEN_GT:
+ srhinfo->mt_flags |= IP6T_SRH_LEN_GT;
+ if (cb->invert)
+ srhinfo->mt_invflags |= IP6T_SRH_INV_LEN_GT;
+ break;
+ case O_SRH_LEN_LT:
+ srhinfo->mt_flags |= IP6T_SRH_LEN_LT;
+ if (cb->invert)
+ srhinfo->mt_invflags |= IP6T_SRH_INV_LEN_LT;
+ break;
+ case O_SRH_SEGS_EQ:
+ srhinfo->mt_flags |= IP6T_SRH_SEGS_EQ;
+ if (cb->invert)
+ srhinfo->mt_invflags |= IP6T_SRH_INV_SEGS_EQ;
+ break;
+ case O_SRH_SEGS_GT:
+ srhinfo->mt_flags |= IP6T_SRH_SEGS_GT;
+ if (cb->invert)
+ srhinfo->mt_invflags |= IP6T_SRH_INV_SEGS_GT;
+ break;
+ case O_SRH_SEGS_LT:
+ srhinfo->mt_flags |= IP6T_SRH_SEGS_LT;
+ if (cb->invert)
+ srhinfo->mt_invflags |= IP6T_SRH_INV_SEGS_LT;
+ break;
+ case O_SRH_LAST_EQ:
+ srhinfo->mt_flags |= IP6T_SRH_LAST_EQ;
+ if (cb->invert)
+ srhinfo->mt_invflags |= IP6T_SRH_INV_LAST_EQ;
+ break;
+ case O_SRH_LAST_GT:
+ srhinfo->mt_flags |= IP6T_SRH_LAST_GT;
+ if (cb->invert)
+ srhinfo->mt_invflags |= IP6T_SRH_INV_LAST_GT;
+ break;
+ case O_SRH_LAST_LT:
+ srhinfo->mt_flags |= IP6T_SRH_LAST_LT;
+ if (cb->invert)
+ srhinfo->mt_invflags |= IP6T_SRH_INV_LAST_LT;
+ break;
+ case O_SRH_TAG:
+ srhinfo->mt_flags |= IP6T_SRH_TAG;
+ if (cb->invert)
+ srhinfo->mt_invflags |= IP6T_SRH_INV_TAG;
+ break;
+ }
+}
+
+static void srh_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
+{
+ const struct ip6t_srh *srhinfo = (struct ip6t_srh *)match->data;
+
+ printf(" srh");
+ if (srhinfo->mt_flags & IP6T_SRH_NEXTHDR)
+ printf(" next-hdr:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_NEXTHDR ? "!" : "",
+ srhinfo->next_hdr);
+ if (srhinfo->mt_flags & IP6T_SRH_LEN_EQ)
+ printf(" hdr-len-eq:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_LEN_EQ ? "!" : "",
+ srhinfo->hdr_len);
+ if (srhinfo->mt_flags & IP6T_SRH_LEN_GT)
+ printf(" hdr-len-gt:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_LEN_GT ? "!" : "",
+ srhinfo->hdr_len);
+ if (srhinfo->mt_flags & IP6T_SRH_LEN_LT)
+ printf(" hdr-len-lt:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_LEN_LT ? "!" : "",
+ srhinfo->hdr_len);
+ if (srhinfo->mt_flags & IP6T_SRH_SEGS_EQ)
+ printf(" segs-left-eq:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_SEGS_EQ ? "!" : "",
+ srhinfo->segs_left);
+ if (srhinfo->mt_flags & IP6T_SRH_SEGS_GT)
+ printf(" segs-left-gt:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_SEGS_GT ? "!" : "",
+ srhinfo->segs_left);
+ if (srhinfo->mt_flags & IP6T_SRH_SEGS_LT)
+ printf(" segs-left-lt:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_SEGS_LT ? "!" : "",
+ srhinfo->segs_left);
+ if (srhinfo->mt_flags & IP6T_SRH_LAST_EQ)
+ printf(" last-entry-eq:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_LAST_EQ ? "!" : "",
+ srhinfo->last_entry);
+ if (srhinfo->mt_flags & IP6T_SRH_LAST_GT)
+ printf(" last-entry-gt:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_LAST_GT ? "!" : "",
+ srhinfo->last_entry);
+ if (srhinfo->mt_flags & IP6T_SRH_LAST_LT)
+ printf(" last-entry-lt:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_LAST_LT ? "!" : "",
+ srhinfo->last_entry);
+ if (srhinfo->mt_flags & IP6T_SRH_TAG)
+ printf(" tag:%s%d", srhinfo->mt_invflags & IP6T_SRH_INV_TAG ? "!" : "",
+ srhinfo->tag);
+}
+
+static void srh_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct ip6t_srh *srhinfo = (struct ip6t_srh *)match->data;
+
+ if (srhinfo->mt_flags & IP6T_SRH_NEXTHDR)
+ printf("%s --srh-next-hdr %u", (srhinfo->mt_invflags & IP6T_SRH_INV_NEXTHDR) ? " !" : "",
+ srhinfo->next_hdr);
+ if (srhinfo->mt_flags & IP6T_SRH_LEN_EQ)
+ printf("%s --srh-hdr-len-eq %u", (srhinfo->mt_invflags & IP6T_SRH_INV_LEN_EQ) ? " !" : "",
+ srhinfo->hdr_len);
+ if (srhinfo->mt_flags & IP6T_SRH_LEN_GT)
+ printf("%s --srh-hdr-len-gt %u", (srhinfo->mt_invflags & IP6T_SRH_INV_LEN_GT) ? " !" : "",
+ srhinfo->hdr_len);
+ if (srhinfo->mt_flags & IP6T_SRH_LEN_LT)
+ printf("%s --srh-hdr-len-lt %u", (srhinfo->mt_invflags & IP6T_SRH_INV_LEN_LT) ? " !" : "",
+ srhinfo->hdr_len);
+ if (srhinfo->mt_flags & IP6T_SRH_SEGS_EQ)
+ printf("%s --srh-segs-left-eq %u", (srhinfo->mt_invflags & IP6T_SRH_INV_SEGS_EQ) ? " !" : "",
+ srhinfo->segs_left);
+ if (srhinfo->mt_flags & IP6T_SRH_SEGS_GT)
+ printf("%s --srh-segs-left-gt %u", (srhinfo->mt_invflags & IP6T_SRH_INV_SEGS_GT) ? " !" : "",
+ srhinfo->segs_left);
+ if (srhinfo->mt_flags & IP6T_SRH_SEGS_LT)
+ printf("%s --srh-segs-left-lt %u", (srhinfo->mt_invflags & IP6T_SRH_INV_SEGS_LT) ? " !" : "",
+ srhinfo->segs_left);
+ if (srhinfo->mt_flags & IP6T_SRH_LAST_EQ)
+ printf("%s --srh-last-entry-eq %u", (srhinfo->mt_invflags & IP6T_SRH_INV_LAST_EQ) ? " !" : "",
+ srhinfo->last_entry);
+ if (srhinfo->mt_flags & IP6T_SRH_LAST_GT)
+ printf("%s --srh-last-entry-gt %u", (srhinfo->mt_invflags & IP6T_SRH_INV_LAST_GT) ? " !" : "",
+ srhinfo->last_entry);
+ if (srhinfo->mt_flags & IP6T_SRH_LAST_LT)
+ printf("%s --srh-last-entry-lt %u", (srhinfo->mt_invflags & IP6T_SRH_INV_LAST_LT) ? " !" : "",
+ srhinfo->last_entry);
+ if (srhinfo->mt_flags & IP6T_SRH_TAG)
+ printf("%s --srh-tag %u", (srhinfo->mt_invflags & IP6T_SRH_INV_TAG) ? " !" : "",
+ srhinfo->tag);
+}
+
+static struct xtables_match srh_mt6_reg = {
+ .name = "srh",
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV6,
+ .size = XT_ALIGN(sizeof(struct ip6t_srh)),
+ .userspacesize = XT_ALIGN(sizeof(struct ip6t_srh)),
+ .help = srh_help,
+ .init = srh_init,
+ .print = srh_print,
+ .save = srh_save,
+ .x6_parse = srh_parse,
+ .x6_options = srh_opts,
+};
+
+void
+_init(void)
+{
+ xtables_register_match(&srh_mt6_reg);
+}
diff --git a/extensions/libip6t_srh.t b/extensions/libip6t_srh.t
new file mode 100644
index 00000000..08897d5c
--- /dev/null
+++ b/extensions/libip6t_srh.t
@@ -0,0 +1,26 @@
+:INPUT,FORWARD,OUTPUT
+-m srh --srh-next-hdr 17;=;OK
+-m srh --srh-hdr-len-eq 8;=;OK
+-m srh --srh-hdr-len-gt 8;=;OK
+-m srh --srh-hdr-len-lt 8;=;OK
+-m srh --srh-segs-left-eq 1;=;OK
+-m srh --srh-segs-left-gt 1;=;OK
+-m srh --srh-segs-left-lt 1;=;OK
+-m srh --srh-last-entry-eq 4;=;OK
+-m srh --srh-last-entry-gt 4;=;OK
+-m srh --srh-last-entry-lt 4;=;OK
+-m srh --srh-tag 0;=;OK
+-m srh ! --srh-next-hdr 17;=;OK
+-m srh ! --srh-hdr-len-eq 8;=;OK
+-m srh ! --srh-hdr-len-gt 8;=;OK
+-m srh ! --srh-hdr-len-lt 8;=;OK
+-m srh ! --srh-segs-left-eq 1;=;OK
+-m srh ! --srh-segs-left-gt 1;=;OK
+-m srh ! --srh-segs-left-lt 1;=;OK
+-m srh ! --srh-last-entry-eq 4;=;OK
+-m srh ! --srh-last-entry-gt 4;=;OK
+-m srh ! --srh-last-entry-lt 4;=;OK
+-m srh ! --srh-tag 0;=;OK
+-m srh --srh-next-hdr 17 --srh-segs-left-eq 1 --srh-last-entry-eq 4 --srh-tag 0;=;OK
+-m srh ! --srh-next-hdr 17 ! --srh-segs-left-eq 0 --srh-tag 0;=;OK
+-m srh;=;OK