From 98e1769b65b71989e3f16b25529b40f374aef323 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 28 Dec 2011 14:27:47 +0100 Subject: extensions: add IPv6 capable ECN match extension Patrick submitted this patch by 9th Jun 2011, I'm recovering and applying it to iptables. Signed-off-by: Pablo Neira Ayuso --- extensions/libipt_ecn.c | 137 -------------------------------- extensions/libipt_ecn.man | 11 --- extensions/libxt_ecn.c | 138 +++++++++++++++++++++++++++++++++ extensions/libxt_ecn.man | 11 +++ include/linux/netfilter/xt_ecn.h | 33 ++++++++ include/linux/netfilter_ipv4/ipt_ecn.h | 35 --------- 6 files changed, 182 insertions(+), 183 deletions(-) delete mode 100644 extensions/libipt_ecn.c delete mode 100644 extensions/libipt_ecn.man create mode 100644 extensions/libxt_ecn.c create mode 100644 extensions/libxt_ecn.man create mode 100644 include/linux/netfilter/xt_ecn.h delete mode 100644 include/linux/netfilter_ipv4/ipt_ecn.h diff --git a/extensions/libipt_ecn.c b/extensions/libipt_ecn.c deleted file mode 100644 index 56a0347e..00000000 --- a/extensions/libipt_ecn.c +++ /dev/null @@ -1,137 +0,0 @@ -/* Shared library add-on to iptables for ECN matching - * - * (C) 2002 by Harald Welte - * - * This program is distributed under the terms of GNU GPL v2, 1991 - * - * libipt_ecn.c borrowed heavily from libipt_dscp.c - * - */ -#include -#include -#include - -enum { - O_ECN_TCP_CWR = 0, - O_ECN_TCP_ECE, - O_ECN_IP_ECT, -}; - -static void ecn_help(void) -{ - printf( -"ECN match options\n" -"[!] --ecn-tcp-cwr Match CWR bit of TCP header\n" -"[!] --ecn-tcp-ece Match ECE bit of TCP header\n" -"[!] --ecn-ip-ect [0..3] Match ECN codepoint in IPv4 header\n"); -} - -static const struct xt_option_entry ecn_opts[] = { - {.name = "ecn-tcp-cwr", .id = O_ECN_TCP_CWR, .type = XTTYPE_NONE, - .flags = XTOPT_INVERT}, - {.name = "ecn-tcp-ece", .id = O_ECN_TCP_ECE, .type = XTTYPE_NONE, - .flags = XTOPT_INVERT}, - {.name = "ecn-ip-ect", .id = O_ECN_IP_ECT, .type = XTTYPE_UINT8, - .min = 0, .max = 3, .flags = XTOPT_INVERT}, - XTOPT_TABLEEND, -}; - -static void ecn_parse(struct xt_option_call *cb) -{ - struct ipt_ecn_info *einfo = cb->data; - - xtables_option_parse(cb); - switch (cb->entry->id) { - case O_ECN_TCP_CWR: - einfo->operation |= IPT_ECN_OP_MATCH_CWR; - if (cb->invert) - einfo->invert |= IPT_ECN_OP_MATCH_CWR; - break; - case O_ECN_TCP_ECE: - einfo->operation |= IPT_ECN_OP_MATCH_ECE; - if (cb->invert) - einfo->invert |= IPT_ECN_OP_MATCH_ECE; - break; - case O_ECN_IP_ECT: - if (cb->invert) - einfo->invert |= IPT_ECN_OP_MATCH_IP; - einfo->operation |= IPT_ECN_OP_MATCH_IP; - einfo->ip_ect = cb->val.u8; - break; - } -} - -static void ecn_check(struct xt_fcheck_call *cb) -{ - if (cb->xflags == 0) - xtables_error(PARAMETER_PROBLEM, - "ECN match: some option required"); -} - -static void ecn_print(const void *ip, const struct xt_entry_match *match, - int numeric) -{ - const struct ipt_ecn_info *einfo = - (const struct ipt_ecn_info *)match->data; - - printf(" ECN match"); - - if (einfo->operation & IPT_ECN_OP_MATCH_ECE) { - printf(" %sECE", - (einfo->invert & IPT_ECN_OP_MATCH_ECE) ? "!" : ""); - } - - if (einfo->operation & IPT_ECN_OP_MATCH_CWR) { - printf(" %sCWR", - (einfo->invert & IPT_ECN_OP_MATCH_CWR) ? "!" : ""); - } - - if (einfo->operation & IPT_ECN_OP_MATCH_IP) { - printf(" %sECT=%d", - (einfo->invert & IPT_ECN_OP_MATCH_IP) ? "!" : "", - einfo->ip_ect); - } -} - -static void ecn_save(const void *ip, const struct xt_entry_match *match) -{ - const struct ipt_ecn_info *einfo = - (const struct ipt_ecn_info *)match->data; - - if (einfo->operation & IPT_ECN_OP_MATCH_ECE) { - if (einfo->invert & IPT_ECN_OP_MATCH_ECE) - printf(" !"); - printf(" --ecn-tcp-ece"); - } - - if (einfo->operation & IPT_ECN_OP_MATCH_CWR) { - if (einfo->invert & IPT_ECN_OP_MATCH_CWR) - printf(" !"); - printf(" --ecn-tcp-cwr"); - } - - if (einfo->operation & IPT_ECN_OP_MATCH_IP) { - if (einfo->invert & IPT_ECN_OP_MATCH_IP) - printf(" !"); - printf(" --ecn-ip-ect %d", einfo->ip_ect); - } -} - -static struct xtables_match ecn_mt_reg = { - .name = "ecn", - .version = XTABLES_VERSION, - .family = NFPROTO_IPV4, - .size = XT_ALIGN(sizeof(struct ipt_ecn_info)), - .userspacesize = XT_ALIGN(sizeof(struct ipt_ecn_info)), - .help = ecn_help, - .print = ecn_print, - .save = ecn_save, - .x6_parse = ecn_parse, - .x6_fcheck = ecn_check, - .x6_options = ecn_opts, -}; - -void _init(void) -{ - xtables_register_match(&ecn_mt_reg); -} diff --git a/extensions/libipt_ecn.man b/extensions/libipt_ecn.man deleted file mode 100644 index 7f806477..00000000 --- a/extensions/libipt_ecn.man +++ /dev/null @@ -1,11 +0,0 @@ -This allows you to match the ECN bits of the IPv4 and TCP header. ECN is the Explicit Congestion Notification mechanism as specified in RFC3168 -.TP -[\fB!\fP] \fB\-\-ecn\-tcp\-cwr\fP -This matches if the TCP ECN CWR (Congestion Window Received) bit is set. -.TP -[\fB!\fP] \fB\-\-ecn\-tcp\-ece\fP -This matches if the TCP ECN ECE (ECN Echo) bit is set. -.TP -[\fB!\fP] \fB\-\-ecn\-ip\-ect\fP \fInum\fP -This matches a particular IPv4 ECT (ECN-Capable Transport). You have to specify -a number between `0' and `3'. diff --git a/extensions/libxt_ecn.c b/extensions/libxt_ecn.c new file mode 100644 index 00000000..286782a3 --- /dev/null +++ b/extensions/libxt_ecn.c @@ -0,0 +1,138 @@ +/* Shared library add-on to iptables for ECN matching + * + * (C) 2002 by Harald Welte + * (C) 2011 by Patrick McHardy + * + * This program is distributed under the terms of GNU GPL v2, 1991 + * + * libipt_ecn.c borrowed heavily from libipt_dscp.c + * + */ +#include +#include +#include + +enum { + O_ECN_TCP_CWR = 0, + O_ECN_TCP_ECE, + O_ECN_IP_ECT, +}; + +static void ecn_help(void) +{ + printf( +"ECN match options\n" +"[!] --ecn-tcp-cwr Match CWR bit of TCP header\n" +"[!] --ecn-tcp-ece Match ECE bit of TCP header\n" +"[!] --ecn-ip-ect [0..3] Match ECN codepoint in IPv4/IPv6 header\n"); +} + +static const struct xt_option_entry ecn_opts[] = { + {.name = "ecn-tcp-cwr", .id = O_ECN_TCP_CWR, .type = XTTYPE_NONE, + .flags = XTOPT_INVERT}, + {.name = "ecn-tcp-ece", .id = O_ECN_TCP_ECE, .type = XTTYPE_NONE, + .flags = XTOPT_INVERT}, + {.name = "ecn-ip-ect", .id = O_ECN_IP_ECT, .type = XTTYPE_UINT8, + .min = 0, .max = 3, .flags = XTOPT_INVERT}, + XTOPT_TABLEEND, +}; + +static void ecn_parse(struct xt_option_call *cb) +{ + struct xt_ecn_info *einfo = cb->data; + + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_ECN_TCP_CWR: + einfo->operation |= XT_ECN_OP_MATCH_CWR; + if (cb->invert) + einfo->invert |= XT_ECN_OP_MATCH_CWR; + break; + case O_ECN_TCP_ECE: + einfo->operation |= XT_ECN_OP_MATCH_ECE; + if (cb->invert) + einfo->invert |= XT_ECN_OP_MATCH_ECE; + break; + case O_ECN_IP_ECT: + if (cb->invert) + einfo->invert |= XT_ECN_OP_MATCH_IP; + einfo->operation |= XT_ECN_OP_MATCH_IP; + einfo->ip_ect = cb->val.u8; + break; + } +} + +static void ecn_check(struct xt_fcheck_call *cb) +{ + if (cb->xflags == 0) + xtables_error(PARAMETER_PROBLEM, + "ECN match: some option required"); +} + +static void ecn_print(const void *ip, const struct xt_entry_match *match, + int numeric) +{ + const struct xt_ecn_info *einfo = + (const struct xt_ecn_info *)match->data; + + printf(" ECN match"); + + if (einfo->operation & XT_ECN_OP_MATCH_ECE) { + printf(" %sECE", + (einfo->invert & XT_ECN_OP_MATCH_ECE) ? "!" : ""); + } + + if (einfo->operation & XT_ECN_OP_MATCH_CWR) { + printf(" %sCWR", + (einfo->invert & XT_ECN_OP_MATCH_CWR) ? "!" : ""); + } + + if (einfo->operation & XT_ECN_OP_MATCH_IP) { + printf(" %sECT=%d", + (einfo->invert & XT_ECN_OP_MATCH_IP) ? "!" : "", + einfo->ip_ect); + } +} + +static void ecn_save(const void *ip, const struct xt_entry_match *match) +{ + const struct xt_ecn_info *einfo = + (const struct xt_ecn_info *)match->data; + + if (einfo->operation & XT_ECN_OP_MATCH_ECE) { + if (einfo->invert & XT_ECN_OP_MATCH_ECE) + printf(" !"); + printf(" --ecn-tcp-ece"); + } + + if (einfo->operation & XT_ECN_OP_MATCH_CWR) { + if (einfo->invert & XT_ECN_OP_MATCH_CWR) + printf(" !"); + printf(" --ecn-tcp-cwr"); + } + + if (einfo->operation & XT_ECN_OP_MATCH_IP) { + if (einfo->invert & XT_ECN_OP_MATCH_IP) + printf(" !"); + printf(" --ecn-ip-ect %d", einfo->ip_ect); + } +} + +static struct xtables_match ecn_mt_reg = { + .name = "ecn", + .version = XTABLES_VERSION, + .family = NFPROTO_UNSPEC, + .size = XT_ALIGN(sizeof(struct xt_ecn_info)), + .userspacesize = XT_ALIGN(sizeof(struct xt_ecn_info)), + .help = ecn_help, + .print = ecn_print, + .save = ecn_save, + .x6_parse = ecn_parse, + .x6_fcheck = ecn_check, + .x6_options = ecn_opts, +}; + +void _init(void) +{ + xtables_register_match(&ecn_mt_reg); +} diff --git a/extensions/libxt_ecn.man b/extensions/libxt_ecn.man new file mode 100644 index 00000000..31c0a3e8 --- /dev/null +++ b/extensions/libxt_ecn.man @@ -0,0 +1,11 @@ +This allows you to match the ECN bits of the IPv4/IPv6 and TCP header. ECN is the Explicit Congestion Notification mechanism as specified in RFC3168 +.TP +[\fB!\fP] \fB\-\-ecn\-tcp\-cwr\fP +This matches if the TCP ECN CWR (Congestion Window Received) bit is set. +.TP +[\fB!\fP] \fB\-\-ecn\-tcp\-ece\fP +This matches if the TCP ECN ECE (ECN Echo) bit is set. +.TP +[\fB!\fP] \fB\-\-ecn\-ip\-ect\fP \fInum\fP +This matches a particular IPv4/IPv6 ECT (ECN-Capable Transport). You have to specify +a number between `0' and `3'. diff --git a/include/linux/netfilter/xt_ecn.h b/include/linux/netfilter/xt_ecn.h new file mode 100644 index 00000000..c21cc280 --- /dev/null +++ b/include/linux/netfilter/xt_ecn.h @@ -0,0 +1,33 @@ +/* iptables module for matching the ECN header in IPv4 and TCP header + * + * (C) 2002 Harald Welte + * + * This software is distributed under GNU GPL v2, 1991 +*/ +#ifndef _XT_ECN_H +#define _XT_ECN_H + +#include +#include + +#define XT_ECN_IP_MASK (~XT_DSCP_MASK) + +#define XT_ECN_OP_MATCH_IP 0x01 +#define XT_ECN_OP_MATCH_ECE 0x10 +#define XT_ECN_OP_MATCH_CWR 0x20 + +#define XT_ECN_OP_MATCH_MASK 0xce + +/* match info */ +struct xt_ecn_info { + __u8 operation; + __u8 invert; + __u8 ip_ect; + union { + struct { + __u8 ect; + } tcp; + } proto; +}; + +#endif /* _XT_ECN_H */ diff --git a/include/linux/netfilter_ipv4/ipt_ecn.h b/include/linux/netfilter_ipv4/ipt_ecn.h deleted file mode 100644 index eabf95fb..00000000 --- a/include/linux/netfilter_ipv4/ipt_ecn.h +++ /dev/null @@ -1,35 +0,0 @@ -/* iptables module for matching the ECN header in IPv4 and TCP header - * - * (C) 2002 Harald Welte - * - * This software is distributed under GNU GPL v2, 1991 - * - * ipt_ecn.h,v 1.4 2002/08/05 19:39:00 laforge Exp -*/ -#ifndef _IPT_ECN_H -#define _IPT_ECN_H - -#include -#include - -#define IPT_ECN_IP_MASK (~XT_DSCP_MASK) - -#define IPT_ECN_OP_MATCH_IP 0x01 -#define IPT_ECN_OP_MATCH_ECE 0x10 -#define IPT_ECN_OP_MATCH_CWR 0x20 - -#define IPT_ECN_OP_MATCH_MASK 0xce - -/* match info */ -struct ipt_ecn_info { - __u8 operation; - __u8 invert; - __u8 ip_ect; - union { - struct { - __u8 ect; - } tcp; - } proto; -}; - -#endif /* _IPT_ECN_H */ -- cgit v1.2.3