From patchwork Fri Dec 29 11:08:25 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ahmed Abdelsalam X-Patchwork-Id: 853936 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="G2jTMlH+"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3z7VVW1W2Dz9s74 for ; Sat, 30 Dec 2017 02:14:11 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751378AbdL2PN4 (ORCPT ); Fri, 29 Dec 2017 10:13:56 -0500 Received: from mail-wm0-f66.google.com ([74.125.82.66]:37728 "EHLO mail-wm0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751152AbdL2PNy (ORCPT ); Fri, 29 Dec 2017 10:13:54 -0500 Received: by mail-wm0-f66.google.com with SMTP id f140so48436787wmd.2; Fri, 29 Dec 2017 07:13:53 -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=QGwFn8tVVOU7pDGrrsBmU0QOwVGbB0w19Gyu550zzos=; b=G2jTMlH+8yKQrK5Xa6GHxlpTqcBIVYZeLWyefAP9hBZoJLTo9xkMOcpJaxt4CJV8gn g7Y1qpDeYbJa9upzC3htk2rMLYc8gcrI+L6m8/rihfaewcl+BXiIPDRp/esP37Ex/tr2 qcuq0/3QR24r1xOx/MtGpWIgX42nZy/mP/TEcZEL/4gqJctR1BWmoyTwIOXYXj2wCygM zTUYkDSCIAp2ksq0IFWPQubLbcI+VRobMlRGh45gokBxbVU6xDMlcyfC8NJDzdcQDzvp cMndZwFTFPYlZ3TtJA36dmQEfIJub19bAtW7rymqpnw+5ccju0lZTCQJjD6boL8ft6zz TUzA== 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=QGwFn8tVVOU7pDGrrsBmU0QOwVGbB0w19Gyu550zzos=; b=GDBNUDrDyqk/7Vc5sENKQZ3hxpCRAY1chhBUQEUV7WIfbdEUQ9Kn/SIPEoitumtyc5 yXSO6sjX0R2h/fXwjqfhOzPlFCExxJQiwpMTbSFStGzoCOIQfOnJ78HGfYtQyuRtm56F BnghET5ZLJw+W2glYHJ8RMc72Kcs9+c6l6B564kc/fEoF0QEwFZdNnXyMPSkTCH6TX4b cmHYJhHpEg7/xeG8peKZIFiiobYtoTEFCHGyV60J8vJslra6pN8QbvGoZixhLP96MPw0 YcFk9u25HboSNLr3swagcQO44NRlYeHt1C5G8sX37subKNhRipNuCvQC18kHtiVzOHlD eNOQ== X-Gm-Message-State: AKGB3mK70pKlH2OT+iooh0WaVXtAfW1+7gW6PEPQN6hf5inXZRcGdoOM GyrRqgGREe84EQwh/xRMIzc= X-Google-Smtp-Source: ACJfBotZHYgrO/EzSM1Dxfg3nONRdJKjMK3MY85H7wTy2mwpSP2Hyl9Iavgshm59HV2ZDQifB3eaDg== X-Received: by 10.28.91.20 with SMTP id p20mr29187090wmb.126.1514560432761; Fri, 29 Dec 2017 07:13:52 -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 e197sm101328404wmf.4.2017.12.29.07.13.50 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 29 Dec 2017 07:13:52 -0800 (PST) From: Ahmed Abdelsalam To: pablo@netfilter.org, kadlec@blackhole.kfki.hu, fw@strlen.de, davem@davemloft.net, kuznet@ms2.inr.ac.ru, yoshfuji@linux-ipv6.org Cc: linux-kernel@vger.kernel.org, netfilter-devel@vger.kernel.org, coreteam@netfilter.org, netdev@vger.kernel.org, amsalam20@gmail.com Subject: [iptables] extensions: add support for 'srh' match Date: Fri, 29 Dec 2017 12:08:25 +0100 Message-Id: <1514545705-13868-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 | 283 ++++++++++++++++++++++++++++++++ include/linux/netfilter_ipv6/ip6t_srh.h | 63 +++++++ 2 files changed, 346 insertions(+) create mode 100644 extensions/libip6t_srh.c 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..fd92ba1 --- /dev/null +++ b/extensions/libip6t_srh.c @@ -0,0 +1,283 @@ +/** + * Segment Routing Header 'srh' match extension + * + * 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-len-eq hdr_len Hdr Ext Len value of SRH\n" +"[!] --srh-len-gt hdr_len Hdr Ext Len value of SRH\n" +"[!] --srh-len-lt hdr_len Hdr Ext Len value of SRH\n" +"[!] --srh-segs-eq segs_left Segments Left value of SRH\n" +"[!] --srh-segs-gt segs_left Segments Left value of SRH\n" +"[!] --srh-segs-lt segs_left Segments Left value of SRH\n" +"[!] --srh-last-eq last_entry Last Entry value of SRH\n" +"[!] --srh-last-gt last_entry Last Entry value of SRH\n" +"[!] --srh-last-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-len-eq", .id = O_SRH_LEN_EQ, .type = XTTYPE_UINT8, + .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, hdr_len)}, + { .name = "srh-len-gt", .id = O_SRH_LEN_GT, .type = XTTYPE_UINT8, + .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, hdr_len)}, + { .name = "srh-len-lt", .id = O_SRH_LEN_LT, .type = XTTYPE_UINT8, + .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, hdr_len)}, + { .name = "srh-segs-eq", .id = O_SRH_SEGS_EQ, .type = XTTYPE_UINT8, + .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, segs_left)}, + { .name = "srh-segs-gt", .id = O_SRH_SEGS_GT, .type = XTTYPE_UINT8, + .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, segs_left)}, + { .name = "srh-segs-lt", .id = O_SRH_SEGS_LT, .type = XTTYPE_UINT8, + .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, segs_left)}, + { .name = "srh-last-eq", .id = O_SRH_LAST_EQ, .type = XTTYPE_UINT8, + .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, last_entry)}, + { .name = "srh-last-gt", .id = O_SRH_LAST_GT, .type = XTTYPE_UINT8, + flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, last_entry)}, + { .name = "srh-last-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 const char *pinv(bool invert) +{ + const char *inv = invert ? "!" : " "; + return inv; +} + +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 ", + pinv(srhinfo->mt_invflags & IP6T_SRH_INV_NEXTHDR), + srhinfo->next_hdr); + + if (srhinfo->mt_flags & IP6T_SRH_LEN_EQ) + printf("hdr-len %s=%d ", + pinv(srhinfo->mt_invflags & IP6T_SRH_INV_LEN_EQ), + srhinfo->hdr_len); + if (srhinfo->mt_flags & IP6T_SRH_LEN_GT) + printf("hdr-len %s>%d ", + pinv(srhinfo->mt_invflags & IP6T_SRH_INV_LEN_GT), + srhinfo->hdr_len); + if (srhinfo->mt_flags & IP6T_SRH_LEN_LT) + printf("hdr-len %s<%d ", + pinv(srhinfo->mt_invflags & IP6T_SRH_INV_LEN_LT), + srhinfo->hdr_len); + + if (srhinfo->mt_flags & IP6T_SRH_SEGS_EQ) + printf("segs-left %s=%d ", + pinv(srhinfo->mt_invflags & IP6T_SRH_INV_SEGS_EQ), + srhinfo->segs_left); + if (srhinfo->mt_flags & IP6T_SRH_SEGS_GT) + printf("segs-left %s>%d ", + pinv(srhinfo->mt_invflags & IP6T_SRH_INV_SEGS_GT), + srhinfo->segs_left); + if (srhinfo->mt_flags & IP6T_SRH_SEGS_LT) + printf("segs-left %s<%d ", + pinv(srhinfo->mt_invflags & IP6T_SRH_INV_SEGS_LT), + srhinfo->segs_left); + + if (srhinfo->mt_flags & IP6T_SRH_LAST_EQ) + printf("last-entry %s=%d ", + pinv(srhinfo->mt_invflags & IP6T_SRH_INV_LAST_EQ), + srhinfo->last_entry); + if (srhinfo->mt_flags & IP6T_SRH_LAST_GT) + printf("last-entry %s>%d ", + pinv(srhinfo->mt_invflags & IP6T_SRH_INV_LAST_GT), + srhinfo->last_entry); + if (srhinfo->mt_flags & IP6T_SRH_LAST_LT) + printf("last-entry %s<%d ", + pinv(srhinfo->mt_invflags & IP6T_SRH_INV_LAST_LT), + srhinfo->last_entry); + + if (srhinfo->mt_flags & IP6T_SRH_TAG) + printf("tag %s=%d ", + pinv(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; + + printf(" srh "); + + if (srhinfo->mt_flags & IP6T_SRH_NEXTHDR) + printf("next-hdr %s=%d ", + pinv(srhinfo->mt_invflags & IP6T_SRH_INV_NEXTHDR), + srhinfo->next_hdr); + + if (srhinfo->mt_flags & IP6T_SRH_LEN_EQ) + printf("hdr-len %s=%d ", + pinv(srhinfo->mt_invflags & IP6T_SRH_INV_LEN_EQ), + srhinfo->hdr_len); + if (srhinfo->mt_flags & IP6T_SRH_LEN_GT) + printf("hdr-len %s>%d ", + pinv(srhinfo->mt_invflags & IP6T_SRH_INV_LEN_GT), + srhinfo->hdr_len); + if (srhinfo->mt_flags & IP6T_SRH_LEN_LT) + printf("hdr-len %s<%d ", + pinv(srhinfo->mt_invflags & IP6T_SRH_INV_LEN_LT), + srhinfo->hdr_len); + + if (srhinfo->mt_flags & IP6T_SRH_SEGS_EQ) + printf("segs-left %s=%d ", + pinv(srhinfo->mt_invflags & IP6T_SRH_INV_SEGS_EQ), + srhinfo->segs_left); + if (srhinfo->mt_flags & IP6T_SRH_SEGS_GT) + printf("segs-left %s>%d ", + pinv(srhinfo->mt_invflags & IP6T_SRH_INV_SEGS_GT), + srhinfo->segs_left); + if (srhinfo->mt_flags & IP6T_SRH_SEGS_LT) + printf("segs-left %s<%d ", + pinv(srhinfo->mt_invflags & IP6T_SRH_INV_SEGS_LT), + srhinfo->segs_left); + + if (srhinfo->mt_flags & IP6T_SRH_LAST_EQ) + printf("last-entry %s=%d ", + pinv(srhinfo->mt_invflags & IP6T_SRH_INV_LAST_EQ), + srhinfo->last_entry); + if (srhinfo->mt_flags & IP6T_SRH_LAST_GT) + printf("last-entry %s>%d ", + pinv(srhinfo->mt_invflags & IP6T_SRH_INV_LAST_GT), + srhinfo->last_entry); + if (srhinfo->mt_flags & IP6T_SRH_LAST_LT) + printf("last-entry %s<%d ", + pinv(srhinfo->mt_invflags & IP6T_SRH_INV_LAST_LT), + srhinfo->last_entry); + + if (srhinfo->mt_flags & IP6T_SRH_TAG) + printf("tag %s=%d ", + pinv(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/include/linux/netfilter_ipv6/ip6t_srh.h b/include/linux/netfilter_ipv6/ip6t_srh.h new file mode 100644 index 0000000..bc27197 --- /dev/null +++ b/include/linux/netfilter_ipv6/ip6t_srh.h @@ -0,0 +1,63 @@ +/** + * Definitions for Segment Routing Header 'srh' match + * + * Author: + * Ahmed Abdelsalam + */ + +#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*/