2 This is a module which is used to match ipv4 options.
3 This file is distributed under the terms of the GNU General Public
4 License (GPL). Copies of the GPL can be obtained from:
5 ftp://prep.ai.mit.edu/pub/gnu/GPL
7 11-mars-2001 Fabrice MARIE <fabrice@netfilter.org> : initial development.
8 12-july-2001 Fabrice MARIE <fabrice@netfilter.org> : added router-alert otions matching. Fixed a bug with no-srr
9 12-august-2001 Imran Patel <ipatel@crosswinds.net> : optimization of the match.
10 18-november-2001 Fabrice MARIE <fabrice@netfilter.org> : added [!] 'any' option match.
11 19-february-2004 Harald Welte <laforge@netfilter.org> : merge with 2.6.x
14 #include <linux/module.h>
15 #include <linux/skbuff.h>
16 #include <linux/version.h>
19 #include <linux/netfilter_ipv4/ip_tables.h>
20 #include <linux/netfilter_ipv4/ipt_ipv4options.h>
22 MODULE_LICENSE("GPL");
23 MODULE_AUTHOR("Fabrice Marie <fabrice@netfilter.org>");
25 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
27 match(const struct sk_buff
*skb
,
28 const struct net_device
*in
,
29 const struct net_device
*out
,
30 const void *matchinfo
,
35 #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
37 match(const struct sk_buff
*skb
,
38 const struct net_device
*in
,
39 const struct net_device
*out
,
40 const void *matchinfo
,
43 #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
45 match(const struct sk_buff
*skb
,
46 const struct net_device
*in
,
47 const struct net_device
*out
,
48 const void *matchinfo
,
52 #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
54 match(const struct sk_buff
*skb
,
55 const struct net_device
*in
,
56 const struct net_device
*out
,
57 const struct xt_match
*match
,
58 const void *matchinfo
,
62 #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
64 match(const struct sk_buff
*skb
,
65 const struct net_device
*in
,
66 const struct net_device
*out
,
67 const struct xt_match
*match
,
68 const void *matchinfo
,
72 #else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) */
74 match(const struct sk_buff
*skb
,
75 const struct xt_match_param
*par
)
78 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
79 const struct ipt_ipv4options_info
*info
= matchinfo
;
81 const struct ipt_ipv4options_info
*info
= par
->matchinfo
;
83 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
84 const struct iphdr
*iph
= ip_hdr(skb
);
86 const struct iphdr
*iph
= skb
->nh
.iph
;
88 const struct ip_options
*opt
;
90 if (iph
->ihl
* 4 == sizeof(struct iphdr
)) {
91 /* No options, so we match only the "DONTs" and the "IGNOREs" */
93 if (((info
->options
& IPT_IPV4OPTION_MATCH_ANY_OPT
) == IPT_IPV4OPTION_MATCH_ANY_OPT
) ||
94 ((info
->options
& IPT_IPV4OPTION_MATCH_SSRR
) == IPT_IPV4OPTION_MATCH_SSRR
) ||
95 ((info
->options
& IPT_IPV4OPTION_MATCH_LSRR
) == IPT_IPV4OPTION_MATCH_LSRR
) ||
96 ((info
->options
& IPT_IPV4OPTION_MATCH_RR
) == IPT_IPV4OPTION_MATCH_RR
) ||
97 ((info
->options
& IPT_IPV4OPTION_MATCH_TIMESTAMP
) == IPT_IPV4OPTION_MATCH_TIMESTAMP
) ||
98 ((info
->options
& IPT_IPV4OPTION_MATCH_ROUTER_ALERT
) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT
))
103 if ((info
->options
& IPT_IPV4OPTION_MATCH_ANY_OPT
) == IPT_IPV4OPTION_MATCH_ANY_OPT
)
104 /* there are options, and we don't need to care which one */
107 if ((info
->options
& IPT_IPV4OPTION_DONT_MATCH_ANY_OPT
) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT
)
108 /* there are options but we don't want any ! */
113 opt
= &(IPCB(skb
)->opt
);
116 if ((info
->options
& IPT_IPV4OPTION_MATCH_SSRR
) == IPT_IPV4OPTION_MATCH_SSRR
) {
117 if (!((opt
->srr
) && (opt
->is_strictroute
)))
120 else if ((info
->options
& IPT_IPV4OPTION_MATCH_LSRR
) == IPT_IPV4OPTION_MATCH_LSRR
) {
121 if (!((opt
->srr
) && (!opt
->is_strictroute
)))
124 else if ((info
->options
& IPT_IPV4OPTION_DONT_MATCH_SRR
) == IPT_IPV4OPTION_DONT_MATCH_SRR
) {
129 if ((info
->options
& IPT_IPV4OPTION_MATCH_RR
) == IPT_IPV4OPTION_MATCH_RR
) {
133 else if ((info
->options
& IPT_IPV4OPTION_DONT_MATCH_RR
) == IPT_IPV4OPTION_DONT_MATCH_RR
) {
138 if ((info
->options
& IPT_IPV4OPTION_MATCH_TIMESTAMP
) == IPT_IPV4OPTION_MATCH_TIMESTAMP
) {
142 else if ((info
->options
& IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP
) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP
) {
146 /* router-alert option */
147 if ((info
->options
& IPT_IPV4OPTION_MATCH_ROUTER_ALERT
) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT
) {
148 if (!opt
->router_alert
)
151 else if ((info
->options
& IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT
) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT
) {
152 if (opt
->router_alert
)
160 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
162 checkentry(const char *tablename
,
163 const struct ipt_ip
*ip
,
165 unsigned int matchsize
,
166 unsigned int hook_mask
)
167 #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
169 checkentry(const char *tablename
,
172 unsigned int matchsize
,
173 unsigned int hook_mask
)
174 #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
176 checkentry(const char *tablename
,
178 const struct xt_match
*match
,
180 unsigned int matchsize
,
181 unsigned int hook_mask
)
182 #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
184 checkentry(const char *tablename
,
186 const struct xt_match
*match
,
188 unsigned int hook_mask
)
189 #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
191 checkentry(const char *tablename
,
193 const struct xt_match
*match
,
195 unsigned int hook_mask
)
196 #else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) */
198 checkentry(const struct xt_mtchk_param
*par
)
201 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
202 struct ipt_ipv4options_info
*info
= matchinfo
;
204 struct ipt_ipv4options_info
*info
= par
->matchinfo
;
206 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
208 if (matchsize
!= IPT_ALIGN(sizeof(struct ipt_ipv4options_info
)))
212 /* Now check the coherence of the data ... */
213 if (((info
->options
& IPT_IPV4OPTION_MATCH_ANY_OPT
) == IPT_IPV4OPTION_MATCH_ANY_OPT
) &&
214 (((info
->options
& IPT_IPV4OPTION_DONT_MATCH_SRR
) == IPT_IPV4OPTION_DONT_MATCH_SRR
) ||
215 ((info
->options
& IPT_IPV4OPTION_DONT_MATCH_RR
) == IPT_IPV4OPTION_DONT_MATCH_RR
) ||
216 ((info
->options
& IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP
) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP
) ||
217 ((info
->options
& IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT
) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT
) ||
218 ((info
->options
& IPT_IPV4OPTION_DONT_MATCH_ANY_OPT
) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT
)))
219 return 0; /* opposites */
220 if (((info
->options
& IPT_IPV4OPTION_DONT_MATCH_ANY_OPT
) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT
) &&
221 (((info
->options
& IPT_IPV4OPTION_MATCH_LSRR
) == IPT_IPV4OPTION_MATCH_LSRR
) ||
222 ((info
->options
& IPT_IPV4OPTION_MATCH_SSRR
) == IPT_IPV4OPTION_MATCH_SSRR
) ||
223 ((info
->options
& IPT_IPV4OPTION_MATCH_RR
) == IPT_IPV4OPTION_MATCH_RR
) ||
224 ((info
->options
& IPT_IPV4OPTION_MATCH_TIMESTAMP
) == IPT_IPV4OPTION_MATCH_TIMESTAMP
) ||
225 ((info
->options
& IPT_IPV4OPTION_MATCH_ROUTER_ALERT
) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT
) ||
226 ((info
->options
& IPT_IPV4OPTION_MATCH_ANY_OPT
) == IPT_IPV4OPTION_MATCH_ANY_OPT
)))
227 return 0; /* opposites */
228 if (((info
->options
& IPT_IPV4OPTION_MATCH_SSRR
) == IPT_IPV4OPTION_MATCH_SSRR
) &&
229 ((info
->options
& IPT_IPV4OPTION_MATCH_LSRR
) == IPT_IPV4OPTION_MATCH_LSRR
))
230 return 0; /* cannot match in the same time loose and strict source routing */
231 if ((((info
->options
& IPT_IPV4OPTION_MATCH_SSRR
) == IPT_IPV4OPTION_MATCH_SSRR
) ||
232 ((info
->options
& IPT_IPV4OPTION_MATCH_LSRR
) == IPT_IPV4OPTION_MATCH_LSRR
)) &&
233 ((info
->options
& IPT_IPV4OPTION_DONT_MATCH_SRR
) == IPT_IPV4OPTION_DONT_MATCH_SRR
))
234 return 0; /* opposites */
235 if (((info
->options
& IPT_IPV4OPTION_MATCH_RR
) == IPT_IPV4OPTION_MATCH_RR
) &&
236 ((info
->options
& IPT_IPV4OPTION_DONT_MATCH_RR
) == IPT_IPV4OPTION_DONT_MATCH_RR
))
237 return 0; /* opposites */
238 if (((info
->options
& IPT_IPV4OPTION_MATCH_TIMESTAMP
) == IPT_IPV4OPTION_MATCH_TIMESTAMP
) &&
239 ((info
->options
& IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP
) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP
))
240 return 0; /* opposites */
241 if (((info
->options
& IPT_IPV4OPTION_MATCH_ROUTER_ALERT
) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT
) &&
242 ((info
->options
& IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT
) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT
))
243 return 0; /* opposites */
245 /* everything looks ok. */
249 static struct ipt_match ipv4options_match
= {
250 .name
= "ipv4options",
252 .matchsize
= sizeof(struct ipt_ipv4options_info
),
253 .checkentry
= checkentry
,
257 static int __init
init(void)
259 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
260 return xt_register_match(&ipv4options_match
);
262 return ipt_register_match(&ipv4options_match
);
266 static void __exit
fini(void)
268 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
269 xt_unregister_match(&ipv4options_match
);
271 ipt_unregister_match(&ipv4options_match
);