diff options
author | Jan Engelhardt <jengelh@medozas.de> | 2011-06-09 15:03:07 -0400 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2011-12-27 14:31:31 -0500 |
commit | d446a8202c81d95f91b1682fc67e7fadd9a31389 (patch) | |
tree | e3e7dcc79eab38846b53af613929b68aa0318752 /net/netfilter | |
parent | c0d2b8376ae2d74aa862e946a372502603e9066d (diff) |
netfilter: xtables: move ipt_ecn to xt_ecn
Prepare the ECN match for augmentation by an IPv6 counterpart. Since
no symbol dependencies to ipv6.ko are added, having a single ecn match
module is the more so welcome.
Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net/netfilter')
-rw-r--r-- | net/netfilter/Kconfig | 9 | ||||
-rw-r--r-- | net/netfilter/Makefile | 1 | ||||
-rw-r--r-- | net/netfilter/xt_ecn.c | 128 |
3 files changed, 138 insertions, 0 deletions
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index bac93ba6077..20388a97df6 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig | |||
@@ -778,6 +778,15 @@ config NETFILTER_XT_MATCH_DSCP | |||
778 | 778 | ||
779 | To compile it as a module, choose M here. If unsure, say N. | 779 | To compile it as a module, choose M here. If unsure, say N. |
780 | 780 | ||
781 | config NETFILTER_XT_MATCH_ECN | ||
782 | tristate '"ecn" match support' | ||
783 | depends on NETFILTER_ADVANCED | ||
784 | ---help--- | ||
785 | This option adds an "ECN" match, which allows you to match against | ||
786 | the IPv4 and TCP header ECN fields. | ||
787 | |||
788 | To compile it as a module, choose M here. If unsure, say N. | ||
789 | |||
781 | config NETFILTER_XT_MATCH_ESP | 790 | config NETFILTER_XT_MATCH_ESP |
782 | tristate '"esp" match support' | 791 | tristate '"esp" match support' |
783 | depends on NETFILTER_ADVANCED | 792 | depends on NETFILTER_ADVANCED |
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index b2eee4df816..40f4c3d636c 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile | |||
@@ -81,6 +81,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_CPU) += xt_cpu.o | |||
81 | obj-$(CONFIG_NETFILTER_XT_MATCH_DCCP) += xt_dccp.o | 81 | obj-$(CONFIG_NETFILTER_XT_MATCH_DCCP) += xt_dccp.o |
82 | obj-$(CONFIG_NETFILTER_XT_MATCH_DEVGROUP) += xt_devgroup.o | 82 | obj-$(CONFIG_NETFILTER_XT_MATCH_DEVGROUP) += xt_devgroup.o |
83 | obj-$(CONFIG_NETFILTER_XT_MATCH_DSCP) += xt_dscp.o | 83 | obj-$(CONFIG_NETFILTER_XT_MATCH_DSCP) += xt_dscp.o |
84 | obj-$(CONFIG_NETFILTER_XT_MATCH_ECN) += xt_ecn.o | ||
84 | obj-$(CONFIG_NETFILTER_XT_MATCH_ESP) += xt_esp.o | 85 | obj-$(CONFIG_NETFILTER_XT_MATCH_ESP) += xt_esp.o |
85 | obj-$(CONFIG_NETFILTER_XT_MATCH_HASHLIMIT) += xt_hashlimit.o | 86 | obj-$(CONFIG_NETFILTER_XT_MATCH_HASHLIMIT) += xt_hashlimit.o |
86 | obj-$(CONFIG_NETFILTER_XT_MATCH_HELPER) += xt_helper.o | 87 | obj-$(CONFIG_NETFILTER_XT_MATCH_HELPER) += xt_helper.o |
diff --git a/net/netfilter/xt_ecn.c b/net/netfilter/xt_ecn.c new file mode 100644 index 00000000000..2c198f5e3ef --- /dev/null +++ b/net/netfilter/xt_ecn.c | |||
@@ -0,0 +1,128 @@ | |||
1 | /* IP tables module for matching the value of the IPv4 and TCP ECN bits | ||
2 | * | ||
3 | * (C) 2002 by Harald Welte <laforge@gnumonks.org> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | */ | ||
9 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
10 | #include <linux/in.h> | ||
11 | #include <linux/ip.h> | ||
12 | #include <net/ip.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/skbuff.h> | ||
15 | #include <linux/tcp.h> | ||
16 | |||
17 | #include <linux/netfilter/x_tables.h> | ||
18 | #include <linux/netfilter_ipv4/ip_tables.h> | ||
19 | #include <linux/netfilter_ipv4/ipt_ecn.h> | ||
20 | |||
21 | MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); | ||
22 | MODULE_DESCRIPTION("Xtables: Explicit Congestion Notification (ECN) flag match for IPv4"); | ||
23 | MODULE_LICENSE("GPL"); | ||
24 | MODULE_ALIAS("ipt_ecn"); | ||
25 | |||
26 | static inline bool match_ip(const struct sk_buff *skb, | ||
27 | const struct ipt_ecn_info *einfo) | ||
28 | { | ||
29 | return ((ip_hdr(skb)->tos & IPT_ECN_IP_MASK) == einfo->ip_ect) ^ | ||
30 | !!(einfo->invert & IPT_ECN_OP_MATCH_IP); | ||
31 | } | ||
32 | |||
33 | static inline bool match_tcp(const struct sk_buff *skb, | ||
34 | const struct ipt_ecn_info *einfo, | ||
35 | bool *hotdrop) | ||
36 | { | ||
37 | struct tcphdr _tcph; | ||
38 | const struct tcphdr *th; | ||
39 | |||
40 | /* In practice, TCP match does this, so can't fail. But let's | ||
41 | * be good citizens. | ||
42 | */ | ||
43 | th = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_tcph), &_tcph); | ||
44 | if (th == NULL) { | ||
45 | *hotdrop = false; | ||
46 | return false; | ||
47 | } | ||
48 | |||
49 | if (einfo->operation & IPT_ECN_OP_MATCH_ECE) { | ||
50 | if (einfo->invert & IPT_ECN_OP_MATCH_ECE) { | ||
51 | if (th->ece == 1) | ||
52 | return false; | ||
53 | } else { | ||
54 | if (th->ece == 0) | ||
55 | return false; | ||
56 | } | ||
57 | } | ||
58 | |||
59 | if (einfo->operation & IPT_ECN_OP_MATCH_CWR) { | ||
60 | if (einfo->invert & IPT_ECN_OP_MATCH_CWR) { | ||
61 | if (th->cwr == 1) | ||
62 | return false; | ||
63 | } else { | ||
64 | if (th->cwr == 0) | ||
65 | return false; | ||
66 | } | ||
67 | } | ||
68 | |||
69 | return true; | ||
70 | } | ||
71 | |||
72 | static bool ecn_mt(const struct sk_buff *skb, struct xt_action_param *par) | ||
73 | { | ||
74 | const struct ipt_ecn_info *info = par->matchinfo; | ||
75 | |||
76 | if (info->operation & IPT_ECN_OP_MATCH_IP) | ||
77 | if (!match_ip(skb, info)) | ||
78 | return false; | ||
79 | |||
80 | if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR)) { | ||
81 | if (!match_tcp(skb, info, &par->hotdrop)) | ||
82 | return false; | ||
83 | } | ||
84 | |||
85 | return true; | ||
86 | } | ||
87 | |||
88 | static int ecn_mt_check(const struct xt_mtchk_param *par) | ||
89 | { | ||
90 | const struct ipt_ecn_info *info = par->matchinfo; | ||
91 | const struct ipt_ip *ip = par->entryinfo; | ||
92 | |||
93 | if (info->operation & IPT_ECN_OP_MATCH_MASK) | ||
94 | return -EINVAL; | ||
95 | |||
96 | if (info->invert & IPT_ECN_OP_MATCH_MASK) | ||
97 | return -EINVAL; | ||
98 | |||
99 | if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR) && | ||
100 | (ip->proto != IPPROTO_TCP || ip->invflags & IPT_INV_PROTO)) { | ||
101 | pr_info("cannot match TCP bits in rule for non-tcp packets\n"); | ||
102 | return -EINVAL; | ||
103 | } | ||
104 | |||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | static struct xt_match ecn_mt_reg __read_mostly = { | ||
109 | .name = "ecn", | ||
110 | .family = NFPROTO_IPV4, | ||
111 | .match = ecn_mt, | ||
112 | .matchsize = sizeof(struct ipt_ecn_info), | ||
113 | .checkentry = ecn_mt_check, | ||
114 | .me = THIS_MODULE, | ||
115 | }; | ||
116 | |||
117 | static int __init ecn_mt_init(void) | ||
118 | { | ||
119 | return xt_register_match(&ecn_mt_reg); | ||
120 | } | ||
121 | |||
122 | static void __exit ecn_mt_exit(void) | ||
123 | { | ||
124 | xt_unregister_match(&ecn_mt_reg); | ||
125 | } | ||
126 | |||
127 | module_init(ecn_mt_init); | ||
128 | module_exit(ecn_mt_exit); | ||