From patchwork Thu Jan 11 17:12:41 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ahmed Abdelsalam X-Patchwork-Id: 859206 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="bLpJOBfB"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3zHXWS1ynMz9s4q for ; Fri, 12 Jan 2018 04:12:52 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754230AbeAKRMv (ORCPT ); Thu, 11 Jan 2018 12:12:51 -0500 Received: from mail-wm0-f67.google.com ([74.125.82.67]:36749 "EHLO mail-wm0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751923AbeAKRMu (ORCPT ); Thu, 11 Jan 2018 12:12:50 -0500 Received: by mail-wm0-f67.google.com with SMTP id b76so6877397wmg.1 for ; Thu, 11 Jan 2018 09:12:49 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=/gUaTuvj9BpnwE7zty3nU8pAlTL7owHJz6SlJDEkBPg=; b=bLpJOBfB74Pr+Rikpe4/lSojwr+FrEYhcY7JEHA754Uaa0jYKYza23f4CA46LrmXS9 f1OJmvg/89wKxhNWXzh7w0RhyONaEpXM9kpRRZhraOEKiHFZLdtySCYcm9dmYCGN1b9H gZNNH03JIQx/VN/FzYUb+aU7se0lnMl4K1dRwPBqXp8TTQCqFoaDfiuNfwrUdxzdtl/g LxE9ol1cgBp937VL/o1ee62zcI2+rPjVy5FmjncA3yn0LEu8UC+PsYC1l6EFmBpiqDZb AuLAEauIFH+SkI7bGaJlJlaJwR5riHu4P3vn3iVC3nXUM5TC/OC02q3knGrF9XoVkgmv JvoA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=/gUaTuvj9BpnwE7zty3nU8pAlTL7owHJz6SlJDEkBPg=; b=Xbeml9rm4PG8WoUMhPKJYOiXjkzF8NAoby3N0N321/Jm71QEa3V2awf+Rhvvg/4p6v n7flAunAK+PW4bl4/egXrLKB14mjbi7Z4IfxYqmw13o7t8uUZ9gGG5DRPP83WNPtvHMc L5VFVnansyYZSltthaL+/VKHhIyMtprJLB8V4x4iEFhG4rmg8DN/whRecMOALxVONl9w wTFlUZBJnIST9AhxhvFXG5S6FPkCNfVW84Hc2WyTU+4cwRT7s5w3CYxBwvb3iQ6Ag5Fj LgCEWRg+vhHfwCf/PZOivjgEQBKfaOSFRQ0VBrWwCLZH7ZTbPMLLNqa/erHXqNpx5fZ6 1PzA== X-Gm-Message-State: AKwxytc01L1rU1zMH3MBxd1/lARemhB02hqxDsz2WvckCxKGtq3GwsnX Nm8Ve8YFEHb1sp7REb98Zbk= X-Google-Smtp-Source: ACJfBouEwuZ82dUGx5oS5kYtVNs0Yfi5RpM18TpOPYWJHb+JPBqF5l6HGGXxo1xZq2GHSqCQ5yhesA== X-Received: by 10.28.64.67 with SMTP id n64mr1600728wma.147.1515690768354; Thu, 11 Jan 2018 09:12:48 -0800 (PST) Received: from sr6.gssi.infn.it (wifi-guest-target.gssi.infn.it. [192.135.27.147]) by smtp.gmail.com with ESMTPSA id w16sm9532500wrc.60.2018.01.11.09.12.47 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 11 Jan 2018 09:12:47 -0800 (PST) From: Ahmed Abdelsalam To: pablo@netfilter.org Cc: davem@davemloft.net, netfilter-devel@vger.kernel.org, coreteam@netfilter.org, amsalam20@gmail.com Subject: [iptables v2] extensions: add support for 'srh' match Date: Thu, 11 Jan 2018 18:12:41 +0100 Message-Id: <1515690761-4836-1-git-send-email-amsalam20@gmail.com> X-Mailer: git-send-email 2.1.4 Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org 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 --- extensions/libip6t_srh.c | 242 ++++++++++++++++++++++++++++++++ extensions/libip6t_srh.t | 26 ++++ include/linux/netfilter_ipv6/ip6t_srh.h | 56 ++++++++ 3 files changed, 324 insertions(+) create mode 100644 extensions/libip6t_srh.c create mode 100644 extensions/libip6t_srh.t create mode 100644 include/linux/netfilter_ipv6/ip6t_srh.h diff --git a/extensions/libip6t_srh.c b/extensions/libip6t_srh.c new file mode 100644 index 0000000..ac0ae08 --- /dev/null +++ b/extensions/libip6t_srh.c @@ -0,0 +1,242 @@ +/* Shared library to add Segment Routing Header (SRH) matching support. + * + * Author: + * Ahmed Abdelsalam + */ + +#include +#include +#include +#include + +/* 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 0000000..08897d5 --- /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 diff --git a/include/linux/netfilter_ipv6/ip6t_srh.h b/include/linux/netfilter_ipv6/ip6t_srh.h new file mode 100644 index 0000000..087efa1 --- /dev/null +++ b/include/linux/netfilter_ipv6/ip6t_srh.h @@ -0,0 +1,56 @@ +#ifndef _IP6T_SRH_H +#define _IP6T_SRH_H + +#include +#include + +/* Values for "mt_flags" field in struct ip6t_srh */ +#define IP6T_SRH_NEXTHDR 0x0001 +#define IP6T_SRH_LEN_EQ 0x0002 +#define IP6T_SRH_LEN_GT 0x0004 +#define IP6T_SRH_LEN_LT 0x0008 +#define IP6T_SRH_SEGS_EQ 0x0010 +#define IP6T_SRH_SEGS_GT 0x0020 +#define IP6T_SRH_SEGS_LT 0x0040 +#define IP6T_SRH_LAST_EQ 0x0080 +#define IP6T_SRH_LAST_GT 0x0100 +#define IP6T_SRH_LAST_LT 0x0200 +#define IP6T_SRH_TAG 0x0400 +#define IP6T_SRH_MASK 0x07FF + +/* Values for "mt_invflags" field in struct ip6t_srh */ +#define IP6T_SRH_INV_NEXTHDR 0x0001 +#define IP6T_SRH_INV_LEN_EQ 0x0002 +#define IP6T_SRH_INV_LEN_GT 0x0004 +#define IP6T_SRH_INV_LEN_LT 0x0008 +#define IP6T_SRH_INV_SEGS_EQ 0x0010 +#define IP6T_SRH_INV_SEGS_GT 0x0020 +#define IP6T_SRH_INV_SEGS_LT 0x0040 +#define IP6T_SRH_INV_LAST_EQ 0x0080 +#define IP6T_SRH_INV_LAST_GT 0x0100 +#define IP6T_SRH_INV_LAST_LT 0x0200 +#define IP6T_SRH_INV_TAG 0x0400 +#define IP6T_SRH_INV_MASK 0x07FF + +/** + * struct ip6t_srh - SRH match options + * @ next_hdr: Next header field of SRH + * @ hdr_len: Extension header length field of SRH + * @ segs_left: Segments left field of SRH + * @ last_entry: Last entry field of SRH + * @ tag: Tag field of SRH + * @ mt_flags: match options + * @ mt_invflags: Invert the sense of match options + */ + +struct ip6t_srh { + __u8 next_hdr; + __u8 hdr_len; + __u8 segs_left; + __u8 last_entry; + __u16 tag; + __u16 mt_flags; + __u16 mt_invflags; +}; + +#endif /*_IP6T_SRH_H*/