]>
Commit | Line | Data |
---|---|---|
00e5a55c BS |
1 | From: Fabrice MARIE <fabrice@netfilter.org> |
2 | From: Harald Welte <laforge@netfilter.org> | |
3 | Subject: netfilter ipv4options match from patch-o-matic-ng | |
4 | References: bnc#131728 - FATE#182 | |
5 | ||
6 | This is a module which is used to match ipv4 options. | |
7 | ||
8 | Updated-by: Jeff Mahoney <jeffm@suse.com> | |
9 | ||
10 | Acked-by: Olaf Kirch <okir@suse.de> | |
11 | Acked-by: Jaroslav Kysela <perex@suse.de> | |
12 | --- | |
13 | ||
14 | include/linux/netfilter_ipv4/ipt_ipv4options.h | 21 +++ | |
15 | net/ipv4/netfilter/Kconfig | 14 ++ | |
16 | net/ipv4/netfilter/Makefile | 1 | |
17 | net/ipv4/netfilter/ipt_ipv4options.c | 175 +++++++++++++++++++++++++ | |
18 | 4 files changed, 211 insertions(+) | |
19 | ||
20 | --- /dev/null | |
21 | +++ b/include/linux/netfilter_ipv4/ipt_ipv4options.h | |
22 | @@ -0,0 +1,21 @@ | |
23 | +#ifndef __ipt_ipv4options_h_included__ | |
24 | +#define __ipt_ipv4options_h_included__ | |
25 | + | |
26 | +#define IPT_IPV4OPTION_MATCH_SSRR 0x01 /* For strict source routing */ | |
27 | +#define IPT_IPV4OPTION_MATCH_LSRR 0x02 /* For loose source routing */ | |
28 | +#define IPT_IPV4OPTION_DONT_MATCH_SRR 0x04 /* any source routing */ | |
29 | +#define IPT_IPV4OPTION_MATCH_RR 0x08 /* For Record route */ | |
30 | +#define IPT_IPV4OPTION_DONT_MATCH_RR 0x10 | |
31 | +#define IPT_IPV4OPTION_MATCH_TIMESTAMP 0x20 /* For timestamp request */ | |
32 | +#define IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP 0x40 | |
33 | +#define IPT_IPV4OPTION_MATCH_ROUTER_ALERT 0x80 /* For router-alert */ | |
34 | +#define IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT 0x100 | |
35 | +#define IPT_IPV4OPTION_MATCH_ANY_OPT 0x200 /* match packet with any option */ | |
36 | +#define IPT_IPV4OPTION_DONT_MATCH_ANY_OPT 0x400 /* match packet with no option */ | |
37 | + | |
38 | +struct ipt_ipv4options_info { | |
39 | + u_int16_t options; | |
40 | +}; | |
41 | + | |
42 | + | |
43 | +#endif /* __ipt_ipv4options_h_included__ */ | |
44 | --- a/net/ipv4/netfilter/Kconfig | |
45 | +++ b/net/ipv4/netfilter/Kconfig | |
46 | @@ -111,6 +111,20 @@ config IP_NF_MATCH_ADDRTYPE | |
47 | If you want to compile it as a module, say M here and read | |
48 | <file:Documentation/kbuild/modules.txt>. If unsure, say `N'. | |
49 | ||
50 | +config IP_NF_MATCH_IPV4OPTIONS | |
51 | + tristate 'IPV4OPTIONS match support' | |
52 | + depends on IP_NF_IPTABLES | |
53 | + help | |
54 | + This option adds a IPV4OPTIONS match. | |
55 | + It allows you to filter options like source routing, | |
56 | + record route, timestamp and router-altert. | |
57 | + | |
58 | + If you say Y here, try iptables -m ipv4options --help for more information. | |
59 | + | |
60 | + If you want to compile it as a module, say M here and read | |
61 | + Documentation/modules.txt. If unsure, say 'N'. | |
62 | + | |
63 | + | |
64 | # `filter', generic and specific targets | |
65 | config IP_NF_FILTER | |
66 | tristate "Packet filtering" | |
67 | --- a/net/ipv4/netfilter/Makefile | |
68 | +++ b/net/ipv4/netfilter/Makefile | |
69 | @@ -50,6 +50,7 @@ obj-$(CONFIG_IP_NF_MATCH_AH) += ipt_ah.o | |
70 | obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o | |
71 | obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o | |
72 | obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o | |
73 | +obj-$(CONFIG_IP_NF_MATCH_IPV4OPTIONS) += ipt_ipv4options.o | |
74 | ||
75 | # targets | |
76 | obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o | |
77 | --- /dev/null | |
78 | +++ b/net/ipv4/netfilter/ipt_ipv4options.c | |
79 | @@ -0,0 +1,175 @@ | |
80 | +/* | |
81 | + This is a module which is used to match ipv4 options. | |
82 | + This file is distributed under the terms of the GNU General Public | |
83 | + License (GPL). Copies of the GPL can be obtained from: | |
84 | + ftp://prep.ai.mit.edu/pub/gnu/GPL | |
85 | + | |
86 | + 11-mars-2001 Fabrice MARIE <fabrice@netfilter.org> : initial development. | |
87 | + 12-july-2001 Fabrice MARIE <fabrice@netfilter.org> : added router-alert otions matching. Fixed a bug with no-srr | |
88 | + 12-august-2001 Imran Patel <ipatel@crosswinds.net> : optimization of the match. | |
89 | + 18-november-2001 Fabrice MARIE <fabrice@netfilter.org> : added [!] 'any' option match. | |
90 | + 19-february-2004 Harald Welte <laforge@netfilter.org> : merge with 2.6.x | |
91 | +*/ | |
92 | + | |
93 | +#include <linux/module.h> | |
94 | +#include <linux/skbuff.h> | |
95 | +#include <net/ip.h> | |
96 | + | |
97 | +#include <linux/netfilter_ipv4/ip_tables.h> | |
98 | +#include <linux/netfilter_ipv4/ipt_ipv4options.h> | |
99 | + | |
100 | +MODULE_LICENSE("GPL"); | |
101 | +MODULE_AUTHOR("Fabrice Marie <fabrice@netfilter.org>"); | |
102 | + | |
103 | +static bool | |
104 | +match(const struct sk_buff *skb, | |
105 | + const struct net_device *in, | |
106 | + const struct net_device *out, | |
107 | + const struct xt_match *match, | |
108 | + const void *matchinfo, | |
109 | + int offset, | |
110 | + unsigned int protoff, | |
111 | + bool *hotdrop) | |
112 | +{ | |
113 | + const struct ipt_ipv4options_info *info = matchinfo; /* match info for rule */ | |
114 | + const struct iphdr *iph = ip_hdr(skb); | |
115 | + const struct ip_options *opt; | |
116 | + | |
117 | + if (iph->ihl * 4 == sizeof(struct iphdr)) { | |
118 | + /* No options, so we match only the "DONTs" and the "IGNOREs" */ | |
119 | + | |
120 | + if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) || | |
121 | + ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) || | |
122 | + ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) || | |
123 | + ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) || | |
124 | + ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) || | |
125 | + ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT)) | |
126 | + return 0; | |
127 | + return 1; | |
128 | + } | |
129 | + else { | |
130 | + if ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) | |
131 | + /* there are options, and we don't need to care which one */ | |
132 | + return 1; | |
133 | + else { | |
134 | + if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) | |
135 | + /* there are options but we don't want any ! */ | |
136 | + return 0; | |
137 | + } | |
138 | + } | |
139 | + | |
140 | + opt = &(IPCB(skb)->opt); | |
141 | + | |
142 | + /* source routing */ | |
143 | + if ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) { | |
144 | + if (!((opt->srr) && (opt->is_strictroute))) | |
145 | + return 0; | |
146 | + } | |
147 | + else if ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) { | |
148 | + if (!((opt->srr) && (!opt->is_strictroute))) | |
149 | + return 0; | |
150 | + } | |
151 | + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) { | |
152 | + if (opt->srr) | |
153 | + return 0; | |
154 | + } | |
155 | + /* record route */ | |
156 | + if ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) { | |
157 | + if (!opt->rr) | |
158 | + return 0; | |
159 | + } | |
160 | + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) { | |
161 | + if (opt->rr) | |
162 | + return 0; | |
163 | + } | |
164 | + /* timestamp */ | |
165 | + if ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) { | |
166 | + if (!opt->ts) | |
167 | + return 0; | |
168 | + } | |
169 | + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) { | |
170 | + if (opt->ts) | |
171 | + return 0; | |
172 | + } | |
173 | + /* router-alert option */ | |
174 | + if ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) { | |
175 | + if (!opt->router_alert) | |
176 | + return 0; | |
177 | + } | |
178 | + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) { | |
179 | + if (opt->router_alert) | |
180 | + return 0; | |
181 | + } | |
182 | + | |
183 | + /* we match ! */ | |
184 | + return 1; | |
185 | +} | |
186 | + | |
187 | +static bool | |
188 | +checkentry(const char *tablename, | |
189 | + const void *ip, | |
190 | + const struct xt_match *match, | |
191 | + void *matchinfo, | |
192 | + unsigned int hook_mask) | |
193 | +{ | |
194 | + const struct ipt_ipv4options_info *info = matchinfo; /* match info for rule */ | |
195 | + /* Check the size */ | |
196 | + if (match->matchsize != IPT_ALIGN(sizeof(struct ipt_ipv4options_info))) | |
197 | + return 0; | |
198 | + /* Now check the coherence of the data ... */ | |
199 | + if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) && | |
200 | + (((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) || | |
201 | + ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) || | |
202 | + ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) || | |
203 | + ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) || | |
204 | + ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT))) | |
205 | + return 0; /* opposites */ | |
206 | + if (((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) && | |
207 | + (((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) || | |
208 | + ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) || | |
209 | + ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) || | |
210 | + ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) || | |
211 | + ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) || | |
212 | + ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT))) | |
213 | + return 0; /* opposites */ | |
214 | + if (((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) && | |
215 | + ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR)) | |
216 | + return 0; /* cannot match in the same time loose and strict source routing */ | |
217 | + if ((((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) || | |
218 | + ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR)) && | |
219 | + ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR)) | |
220 | + return 0; /* opposites */ | |
221 | + if (((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) && | |
222 | + ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR)) | |
223 | + return 0; /* opposites */ | |
224 | + if (((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) && | |
225 | + ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP)) | |
226 | + return 0; /* opposites */ | |
227 | + if (((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) && | |
228 | + ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT)) | |
229 | + return 0; /* opposites */ | |
230 | + | |
231 | + /* everything looks ok. */ | |
232 | + return 1; | |
233 | +} | |
234 | + | |
235 | +static struct xt_match ipv4options_match = { | |
236 | + .name = "ipv4options", | |
237 | + .match = match, | |
238 | + .matchsize = sizeof(struct ipt_ipv4options_info), | |
239 | + .checkentry = checkentry, | |
240 | + .me = THIS_MODULE | |
241 | +}; | |
242 | + | |
243 | +static int __init init(void) | |
244 | +{ | |
245 | + return xt_register_match(&ipv4options_match); | |
246 | +} | |
247 | + | |
248 | +static void __exit fini(void) | |
249 | +{ | |
250 | + xt_unregister_match(&ipv4options_match); | |
251 | +} | |
252 | + | |
253 | +module_init(init); | |
254 | +module_exit(fini); |