netfilter: add support for raw table and NOTRACK target (#5504)
[openwrt/openwrt.git] / target / linux / generic-2.4 / patches / 628-netfilter_raw.patch
1 --- a/Documentation/Configure.help
2 +++ b/Documentation/Configure.help
3 @@ -3057,6 +3057,34 @@
4 If you want to compile it as a module, say M here and read
5 <file:Documentation/modules.txt>. If unsure, say `N'.
6
7 +raw table support (required for NOTRACK/TRACE)
8 +CONFIG_IP_NF_RAW
9 + This option adds a `raw' table to iptables. This table is the very
10 + first in the netfilter framework and hooks in at the PREROUTING
11 + and OUTPUT chains.
12 +
13 + If you want to compile it as a module, say M here and read
14 + <file:Documentation/modules.txt>. If unsure, say `N'.
15 +
16 +NOTRACK target support
17 +CONFIG_IP_NF_TARGET_NOTRACK
18 + The NOTRACK target allows a select rule to specify
19 + which packets *not* to enter the conntrack/NAT
20 + subsystem with all the consequences (no ICMP error tracking,
21 + no protocol helpers for the selected packets).
22 +
23 + If you want to compile it as a module, say M here and read
24 + <file:Documentation/modules.txt>. If unsure, say `N'.
25 +
26 +raw table support (required for TRACE)
27 +CONFIG_IP6_NF_RAW
28 + This option adds a `raw' table to ip6tables. This table is the very
29 + first in the netfilter framework and hooks in at the PREROUTING
30 + and OUTPUT chains.
31 +
32 + If you want to compile it as a module, say M here and read
33 + <file:Documentation/modules.txt>. If unsure, say `N'.
34 +
35 REJECT target support
36 CONFIG_IP_NF_TARGET_REJECT
37 The REJECT target allows a filtering rule to specify that an ICMP
38 --- a/include/linux/netfilter_ipv4/ip_conntrack.h
39 +++ b/include/linux/netfilter_ipv4/ip_conntrack.h
40 @@ -286,6 +286,9 @@
41 /* Call me when a conntrack is destroyed. */
42 extern void (*ip_conntrack_destroyed)(struct ip_conntrack *conntrack);
43
44 +/* Fake conntrack entry for untracked connections */
45 +extern struct ip_conntrack ip_conntrack_untracked;
46 +
47 /* Returns new sk_buff, or NULL */
48 struct sk_buff *
49 ip_ct_gather_frags(struct sk_buff *skb, u_int32_t user);
50 --- a/include/linux/netfilter_ipv4/ipt_conntrack.h
51 +++ b/include/linux/netfilter_ipv4/ipt_conntrack.h
52 @@ -10,6 +10,7 @@
53
54 #define IPT_CONNTRACK_STATE_SNAT (1 << (IP_CT_NUMBER + 1))
55 #define IPT_CONNTRACK_STATE_DNAT (1 << (IP_CT_NUMBER + 2))
56 +#define IPT_CONNTRACK_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 3))
57
58 /* flags, invflags: */
59 #define IPT_CONNTRACK_STATE 0x01
60 --- a/include/linux/netfilter_ipv4/ipt_state.h
61 +++ b/include/linux/netfilter_ipv4/ipt_state.h
62 @@ -4,6 +4,8 @@
63 #define IPT_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1))
64 #define IPT_STATE_INVALID (1 << 0)
65
66 +#define IPT_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 1))
67 +
68 struct ipt_state_info
69 {
70 unsigned int statemask;
71 --- a/include/linux/netfilter_ipv4.h
72 +++ b/include/linux/netfilter_ipv4.h
73 @@ -51,6 +51,8 @@
74
75 enum nf_ip_hook_priorities {
76 NF_IP_PRI_FIRST = INT_MIN,
77 + NF_IP_PRI_CONNTRACK_DEFRAG = -400,
78 + NF_IP_PRI_RAW = -300,
79 NF_IP_PRI_CONNTRACK = -200,
80 NF_IP_PRI_MANGLE = -150,
81 NF_IP_PRI_NAT_DST = -100,
82 --- a/net/ipv4/netfilter/Config.in
83 +++ b/net/ipv4/netfilter/Config.in
84 @@ -153,6 +153,15 @@
85 dep_tristate ' TTL target support' CONFIG_IP_NF_TARGET_TTL $CONFIG_IP_NF_IPTABLES
86 dep_tristate ' ULOG target support' CONFIG_IP_NF_TARGET_ULOG $CONFIG_IP_NF_IPTABLES
87 dep_tristate ' TCPMSS target support' CONFIG_IP_NF_TARGET_TCPMSS $CONFIG_IP_NF_IPTABLES
88 + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
89 + tristate ' raw table support (required for NOTRACK/TRACE)' CONFIG_IP_NF_RAW $CONFIG_IP_NF_IPTABLES
90 + fi
91 + if [ "$CONFIG_IP_NF_RAW" != "n" ]; then
92 + if [ "$CONFIG_IP_NF_CONNTRACK" != "n" ]; then
93 + dep_tristate ' NOTRACK target support' CONFIG_IP_NF_TARGET_NOTRACK $CONFIG_IP_NF_RAW
94 + fi
95 + # Marker for TRACE target
96 + fi
97 fi
98
99 tristate 'ARP tables support' CONFIG_IP_NF_ARPTABLES
100 --- a/net/ipv4/netfilter/ip_conntrack_core.c
101 +++ b/net/ipv4/netfilter/ip_conntrack_core.c
102 @@ -64,6 +64,7 @@
103 static atomic_t ip_conntrack_count = ATOMIC_INIT(0);
104 struct list_head *ip_conntrack_hash;
105 static kmem_cache_t *ip_conntrack_cachep;
106 +struct ip_conntrack ip_conntrack_untracked;
107 static LIST_HEAD(unconfirmed);
108
109 extern struct ip_conntrack_protocol ip_conntrack_generic_protocol;
110 @@ -834,6 +835,15 @@
111 int set_reply;
112 int ret;
113
114 + /* Never happen */
115 + if ((*pskb)->nh.iph->frag_off & htons(IP_OFFSET)) {
116 + if (net_ratelimit()) {
117 + printk(KERN_ERR "ip_conntrack_in: Frag of proto %u (hook=%u)\n",
118 + (*pskb)->nh.iph->protocol, hooknum);
119 + }
120 + return NF_DROP;
121 + }
122 +
123 /* FIXME: Do this right please. --RR */
124 (*pskb)->nfcache |= NFC_UNKNOWN;
125
126 @@ -1489,6 +1499,18 @@
127
128 /* For use by ipt_REJECT */
129 ip_ct_attach = ip_conntrack_attach;
130 +
131 + /* Set up fake conntrack:
132 + - to never be deleted, not in any hashes */
133 + atomic_set(&ip_conntrack_untracked.ct_general.use, 1);
134 + /* - and look it like as a confirmed connection */
135 + set_bit(IPS_CONFIRMED_BIT, &ip_conntrack_untracked.status);
136 + /* - and prepare the ctinfo field for REJECT/NAT. */
137 + ip_conntrack_untracked.infos[IP_CT_NEW].master =
138 + ip_conntrack_untracked.infos[IP_CT_RELATED].master =
139 + ip_conntrack_untracked.infos[IP_CT_RELATED + IP_CT_IS_REPLY].master =
140 + &ip_conntrack_untracked.ct_general;
141 +
142 return ret;
143
144 err_free_hash:
145 --- a/net/ipv4/netfilter/ip_conntrack_standalone.c
146 +++ b/net/ipv4/netfilter/ip_conntrack_standalone.c
147 @@ -218,6 +218,29 @@
148 return ip_conntrack_confirm(*pskb);
149 }
150
151 +static unsigned int ip_conntrack_defrag(unsigned int hooknum,
152 + struct sk_buff **pskb,
153 + const struct net_device *in,
154 + const struct net_device *out,
155 + int (*okfn)(struct sk_buff *))
156 +{
157 + /* Previously seen (loopback)? Ignore. Do this before
158 + fragment check. */
159 + if ((*pskb)->nfct)
160 + return NF_ACCEPT;
161 +
162 + /* Gather fragments. */
163 + if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
164 + *pskb = ip_ct_gather_frags(*pskb,
165 + hooknum == NF_IP_PRE_ROUTING ?
166 + IP_DEFRAG_CONNTRACK_IN :
167 + IP_DEFRAG_CONNTRACK_OUT);
168 + if (!*pskb)
169 + return NF_STOLEN;
170 + }
171 + return NF_ACCEPT;
172 +}
173 +
174 static unsigned int ip_refrag(unsigned int hooknum,
175 struct sk_buff **pskb,
176 const struct net_device *in,
177 @@ -259,9 +282,15 @@
178
179 /* Connection tracking may drop packets, but never alters them, so
180 make it the first hook. */
181 +static struct nf_hook_ops ip_conntrack_defrag_ops
182 += { { NULL, NULL }, ip_conntrack_defrag, PF_INET, NF_IP_PRE_ROUTING,
183 + NF_IP_PRI_CONNTRACK_DEFRAG };
184 static struct nf_hook_ops ip_conntrack_in_ops
185 = { { NULL, NULL }, ip_conntrack_in, PF_INET, NF_IP_PRE_ROUTING,
186 NF_IP_PRI_CONNTRACK };
187 +static struct nf_hook_ops ip_conntrack_defrag_local_out_ops
188 += { { NULL, NULL }, ip_conntrack_defrag, PF_INET, NF_IP_LOCAL_OUT,
189 + NF_IP_PRI_CONNTRACK_DEFRAG };
190 static struct nf_hook_ops ip_conntrack_local_out_ops
191 = { { NULL, NULL }, ip_conntrack_local, PF_INET, NF_IP_LOCAL_OUT,
192 NF_IP_PRI_CONNTRACK };
193 @@ -382,10 +411,20 @@
194 if (!proc) goto cleanup_init;
195 proc->owner = THIS_MODULE;
196
197 + ret = nf_register_hook(&ip_conntrack_defrag_ops);
198 + if (ret < 0) {
199 + printk("ip_conntrack: can't register pre-routing defrag hook.\n");
200 + goto cleanup_proc;
201 + }
202 + ret = nf_register_hook(&ip_conntrack_defrag_local_out_ops);
203 + if (ret < 0) {
204 + printk("ip_conntrack: can't register local_out defrag hook.\n");
205 + goto cleanup_defragops;
206 + }
207 ret = nf_register_hook(&ip_conntrack_in_ops);
208 if (ret < 0) {
209 printk("ip_conntrack: can't register pre-routing hook.\n");
210 - goto cleanup_proc;
211 + goto cleanup_defraglocalops;
212 }
213 ret = nf_register_hook(&ip_conntrack_local_out_ops);
214 if (ret < 0) {
215 @@ -423,6 +462,10 @@
216 nf_unregister_hook(&ip_conntrack_local_out_ops);
217 cleanup_inops:
218 nf_unregister_hook(&ip_conntrack_in_ops);
219 + cleanup_defraglocalops:
220 + nf_unregister_hook(&ip_conntrack_defrag_local_out_ops);
221 + cleanup_defragops:
222 + nf_unregister_hook(&ip_conntrack_defrag_ops);
223 cleanup_proc:
224 proc_net_remove("ip_conntrack");
225 cleanup_init:
226 @@ -512,5 +555,6 @@
227 EXPORT_SYMBOL(ip_conntrack_expect_list);
228 EXPORT_SYMBOL(ip_conntrack_lock);
229 EXPORT_SYMBOL(ip_conntrack_hash);
230 +EXPORT_SYMBOL(ip_conntrack_untracked);
231 EXPORT_SYMBOL_GPL(ip_conntrack_find_get);
232 EXPORT_SYMBOL_GPL(ip_conntrack_put);
233 --- a/net/ipv4/netfilter/ip_nat_core.c
234 +++ b/net/ipv4/netfilter/ip_nat_core.c
235 @@ -1023,6 +1023,10 @@
236 /* FIXME: Man, this is a hack. <SIGH> */
237 IP_NF_ASSERT(ip_conntrack_destroyed == NULL);
238 ip_conntrack_destroyed = &ip_nat_cleanup_conntrack;
239 +
240 + /* Initialize fake conntrack so that NAT will skip it */
241 + ip_conntrack_untracked.nat.info.initialized |=
242 + (1 << IP_NAT_MANIP_SRC) | (1 << IP_NAT_MANIP_DST);
243
244 return 0;
245 }
246 --- /dev/null
247 +++ b/net/ipv4/netfilter/iptable_raw.c
248 @@ -0,0 +1,149 @@
249 +/*
250 + * 'raw' table, which is the very first hooked in at PRE_ROUTING and LOCAL_OUT .
251 + *
252 + * Copyright (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
253 + */
254 +#include <linux/module.h>
255 +#include <linux/netfilter_ipv4/ip_tables.h>
256 +
257 +#define RAW_VALID_HOOKS ((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT))
258 +
259 +/* Standard entry. */
260 +struct ipt_standard
261 +{
262 + struct ipt_entry entry;
263 + struct ipt_standard_target target;
264 +};
265 +
266 +struct ipt_error_target
267 +{
268 + struct ipt_entry_target target;
269 + char errorname[IPT_FUNCTION_MAXNAMELEN];
270 +};
271 +
272 +struct ipt_error
273 +{
274 + struct ipt_entry entry;
275 + struct ipt_error_target target;
276 +};
277 +
278 +static struct
279 +{
280 + struct ipt_replace repl;
281 + struct ipt_standard entries[2];
282 + struct ipt_error term;
283 +} initial_table __initdata
284 += { { "raw", RAW_VALID_HOOKS, 3,
285 + sizeof(struct ipt_standard) * 2 + sizeof(struct ipt_error),
286 + { [NF_IP_PRE_ROUTING] 0,
287 + [NF_IP_LOCAL_OUT] sizeof(struct ipt_standard) },
288 + { [NF_IP_PRE_ROUTING] 0,
289 + [NF_IP_LOCAL_OUT] sizeof(struct ipt_standard) },
290 + 0, NULL, { } },
291 + {
292 + /* PRE_ROUTING */
293 + { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
294 + 0,
295 + sizeof(struct ipt_entry),
296 + sizeof(struct ipt_standard),
297 + 0, { 0, 0 }, { } },
298 + { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
299 + -NF_ACCEPT - 1 } },
300 + /* LOCAL_OUT */
301 + { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
302 + 0,
303 + sizeof(struct ipt_entry),
304 + sizeof(struct ipt_standard),
305 + 0, { 0, 0 }, { } },
306 + { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
307 + -NF_ACCEPT - 1 } }
308 + },
309 + /* ERROR */
310 + { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
311 + 0,
312 + sizeof(struct ipt_entry),
313 + sizeof(struct ipt_error),
314 + 0, { 0, 0 }, { } },
315 + { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
316 + { } },
317 + "ERROR"
318 + }
319 + }
320 +};
321 +
322 +static struct ipt_table packet_raw = {
323 + .name = "raw",
324 + .table = &initial_table.repl,
325 + .valid_hooks = RAW_VALID_HOOKS,
326 + .lock = RW_LOCK_UNLOCKED,
327 + .me = THIS_MODULE
328 +};
329 +
330 +/* The work comes in here from netfilter.c. */
331 +static unsigned int
332 +ipt_hook(unsigned int hook,
333 + struct sk_buff **pskb,
334 + const struct net_device *in,
335 + const struct net_device *out,
336 + int (*okfn)(struct sk_buff *))
337 +{
338 + return ipt_do_table(pskb, hook, in, out, &packet_raw, NULL);
339 +}
340 +
341 +/* 'raw' is the very first table. */
342 +static struct nf_hook_ops ipt_ops[] = {
343 + {
344 + .hook = ipt_hook,
345 + .pf = PF_INET,
346 + .hooknum = NF_IP_PRE_ROUTING,
347 + .priority = NF_IP_PRI_RAW
348 + },
349 + {
350 + .hook = ipt_hook,
351 + .pf = PF_INET,
352 + .hooknum = NF_IP_LOCAL_OUT,
353 + .priority = NF_IP_PRI_RAW
354 + },
355 +};
356 +
357 +static int __init init(void)
358 +{
359 + int ret;
360 +
361 + /* Register table */
362 + ret = ipt_register_table(&packet_raw);
363 + if (ret < 0)
364 + return ret;
365 +
366 + /* Register hooks */
367 + ret = nf_register_hook(&ipt_ops[0]);
368 + if (ret < 0)
369 + goto cleanup_table;
370 +
371 + ret = nf_register_hook(&ipt_ops[1]);
372 + if (ret < 0)
373 + goto cleanup_hook0;
374 +
375 + return ret;
376 +
377 + cleanup_hook0:
378 + nf_unregister_hook(&ipt_ops[0]);
379 + cleanup_table:
380 + ipt_unregister_table(&packet_raw);
381 +
382 + return ret;
383 +}
384 +
385 +static void __exit fini(void)
386 +{
387 + unsigned int i;
388 +
389 + for (i = 0; i < sizeof(ipt_ops)/sizeof(struct nf_hook_ops); i++)
390 + nf_unregister_hook(&ipt_ops[i]);
391 +
392 + ipt_unregister_table(&packet_raw);
393 +}
394 +
395 +module_init(init);
396 +module_exit(fini);
397 +MODULE_LICENSE("GPL");
398 --- a/net/ipv4/netfilter/ipt_conntrack.c
399 +++ b/net/ipv4/netfilter/ipt_conntrack.c
400 @@ -27,11 +27,13 @@
401
402 #define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg))
403
404 - if (ct)
405 - statebit = IPT_CONNTRACK_STATE_BIT(ctinfo);
406 - else
407 - statebit = IPT_CONNTRACK_STATE_INVALID;
408 -
409 + if (skb->nfct == &ip_conntrack_untracked.infos[IP_CT_NEW])
410 + statebit = IPT_CONNTRACK_STATE_UNTRACKED;
411 + else if (ct)
412 + statebit = IPT_CONNTRACK_STATE_BIT(ctinfo);
413 + else
414 + statebit = IPT_CONNTRACK_STATE_INVALID;
415 +
416 if(sinfo->flags & IPT_CONNTRACK_STATE) {
417 if (ct) {
418 if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip !=
419 --- /dev/null
420 +++ b/net/ipv4/netfilter/ipt_NOTRACK.c
421 @@ -0,0 +1,75 @@
422 +/* This is a module which is used for setting up fake conntracks
423 + * on packets so that they are not seen by the conntrack/NAT code.
424 + */
425 +#include <linux/module.h>
426 +#include <linux/skbuff.h>
427 +
428 +#include <linux/netfilter_ipv4/ip_tables.h>
429 +#include <linux/netfilter_ipv4/ip_conntrack.h>
430 +
431 +static unsigned int
432 +target(struct sk_buff **pskb,
433 + unsigned int hooknum,
434 + const struct net_device *in,
435 + const struct net_device *out,
436 + const void *targinfo,
437 + void *userinfo)
438 +{
439 + /* Previously seen (loopback)? Ignore. */
440 + if ((*pskb)->nfct != NULL)
441 + return IPT_CONTINUE;
442 +
443 + /* Attach fake conntrack entry.
444 + If there is a real ct entry correspondig to this packet,
445 + it'll hang aroun till timing out. We don't deal with it
446 + for performance reasons. JK */
447 + (*pskb)->nfct = &ip_conntrack_untracked.infos[IP_CT_NEW];
448 + nf_conntrack_get((*pskb)->nfct);
449 +
450 + return IPT_CONTINUE;
451 +}
452 +
453 +static int
454 +checkentry(const char *tablename,
455 + const struct ipt_entry *e,
456 + void *targinfo,
457 + unsigned int targinfosize,
458 + unsigned int hook_mask)
459 +{
460 + if (targinfosize != 0) {
461 + printk(KERN_WARNING "NOTRACK: targinfosize %u != 0\n",
462 + targinfosize);
463 + return 0;
464 + }
465 +
466 + if (strcmp(tablename, "raw") != 0) {
467 + printk(KERN_WARNING "NOTRACK: can only be called from \"raw\" table, not \"%s\"\n", tablename);
468 + return 0;
469 + }
470 +
471 + return 1;
472 +}
473 +
474 +static struct ipt_target ipt_notrack_reg = {
475 + .name = "NOTRACK",
476 + .target = target,
477 + .checkentry = checkentry,
478 + .me = THIS_MODULE
479 +};
480 +
481 +static int __init init(void)
482 +{
483 + if (ipt_register_target(&ipt_notrack_reg))
484 + return -EINVAL;
485 +
486 + return 0;
487 +}
488 +
489 +static void __exit fini(void)
490 +{
491 + ipt_unregister_target(&ipt_notrack_reg);
492 +}
493 +
494 +module_init(init);
495 +module_exit(fini);
496 +MODULE_LICENSE("GPL");
497 --- a/net/ipv4/netfilter/ipt_state.c
498 +++ b/net/ipv4/netfilter/ipt_state.c
499 @@ -21,7 +21,9 @@
500 enum ip_conntrack_info ctinfo;
501 unsigned int statebit;
502
503 - if (!ip_conntrack_get((struct sk_buff *)skb, &ctinfo))
504 + if (skb->nfct == &ip_conntrack_untracked.infos[IP_CT_NEW])
505 + statebit = IPT_STATE_UNTRACKED;
506 + else if (!ip_conntrack_get((struct sk_buff *)skb, &ctinfo))
507 statebit = IPT_STATE_INVALID;
508 else
509 statebit = IPT_STATE_BIT(ctinfo);
510 --- a/net/ipv4/netfilter/Makefile
511 +++ b/net/ipv4/netfilter/Makefile
512 @@ -77,6 +77,7 @@
513 obj-$(CONFIG_IP_NF_FILTER) += iptable_filter.o
514 obj-$(CONFIG_IP_NF_MANGLE) += iptable_mangle.o
515 obj-$(CONFIG_IP_NF_NAT) += iptable_nat.o
516 +obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o
517
518 # matches
519 obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
520 @@ -131,6 +132,7 @@
521 obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
522 obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
523 obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
524 +obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o
525
526 # generic ARP tables
527 obj-$(CONFIG_IP_NF_ARPTABLES) += arp_tables.o
528 --- a/net/ipv6/netfilter/Config.in
529 +++ b/net/ipv6/netfilter/Config.in
530 @@ -79,6 +79,10 @@
531 dep_tristate ' IMQ target support' CONFIG_IP6_NF_TARGET_IMQ $CONFIG_IP6_NF_MANGLE
532 fi
533 #dep_tristate ' LOG target support' CONFIG_IP6_NF_TARGET_LOG $CONFIG_IP6_NF_IPTABLES
534 + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
535 + tristate ' raw table support (required for TRACE)' CONFIG_IP6_NF_RAW $CONFIG_IP6_NF_IPTABLES
536 + fi
537 + # Marker for TRACE target
538 fi
539
540 endmenu
541 --- /dev/null
542 +++ b/net/ipv6/netfilter/ip6table_raw.c
543 @@ -0,0 +1,154 @@
544 +/*
545 + * IPv6 raw table, a port of the IPv4 raw table to IPv6
546 + *
547 + * Copyright (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
548 + */
549 +#include <linux/module.h>
550 +#include <linux/netfilter_ipv6/ip6_tables.h>
551 +
552 +#define RAW_VALID_HOOKS ((1 << NF_IP6_PRE_ROUTING) | (1 << NF_IP6_LOCAL_OUT))
553 +
554 +#if 0
555 +#define DEBUGP(x, args...) printk(KERN_DEBUG x, ## args)
556 +#else
557 +#define DEBUGP(x, args...)
558 +#endif
559 +
560 +/* Standard entry. */
561 +struct ip6t_standard
562 +{
563 + struct ip6t_entry entry;
564 + struct ip6t_standard_target target;
565 +};
566 +
567 +struct ip6t_error_target
568 +{
569 + struct ip6t_entry_target target;
570 + char errorname[IP6T_FUNCTION_MAXNAMELEN];
571 +};
572 +
573 +struct ip6t_error
574 +{
575 + struct ip6t_entry entry;
576 + struct ip6t_error_target target;
577 +};
578 +
579 +static struct
580 +{
581 + struct ip6t_replace repl;
582 + struct ip6t_standard entries[2];
583 + struct ip6t_error term;
584 +} initial_table __initdata
585 += { { "raw", RAW_VALID_HOOKS, 3,
586 + sizeof(struct ip6t_standard) * 2 + sizeof(struct ip6t_error),
587 + { [NF_IP6_PRE_ROUTING] 0,
588 + [NF_IP6_LOCAL_OUT] sizeof(struct ip6t_standard) },
589 + { [NF_IP6_PRE_ROUTING] 0,
590 + [NF_IP6_LOCAL_OUT] sizeof(struct ip6t_standard) },
591 + 0, NULL, { } },
592 + {
593 + /* PRE_ROUTING */
594 + { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
595 + 0,
596 + sizeof(struct ip6t_entry),
597 + sizeof(struct ip6t_standard),
598 + 0, { 0, 0 }, { } },
599 + { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
600 + -NF_ACCEPT - 1 } },
601 + /* LOCAL_OUT */
602 + { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
603 + 0,
604 + sizeof(struct ip6t_entry),
605 + sizeof(struct ip6t_standard),
606 + 0, { 0, 0 }, { } },
607 + { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
608 + -NF_ACCEPT - 1 } },
609 + },
610 + /* ERROR */
611 + { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
612 + 0,
613 + sizeof(struct ip6t_entry),
614 + sizeof(struct ip6t_error),
615 + 0, { 0, 0 }, { } },
616 + { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
617 + { } },
618 + "ERROR"
619 + }
620 + }
621 +};
622 +
623 +static struct ip6t_table packet_raw = {
624 + .name = "raw",
625 + .table = &initial_table.repl,
626 + .valid_hooks = RAW_VALID_HOOKS,
627 + .lock = RW_LOCK_UNLOCKED,
628 + .me = THIS_MODULE
629 +};
630 +
631 +/* The work comes in here from netfilter.c. */
632 +static unsigned int
633 +ip6t_hook(unsigned int hook,
634 + struct sk_buff **pskb,
635 + const struct net_device *in,
636 + const struct net_device *out,
637 + int (*okfn)(struct sk_buff *))
638 +{
639 + return ip6t_do_table(pskb, hook, in, out, &packet_raw, NULL);
640 +}
641 +
642 +static struct nf_hook_ops ip6t_ops[] = {
643 + {
644 + .hook = ip6t_hook,
645 + .pf = PF_INET6,
646 + .hooknum = NF_IP6_PRE_ROUTING,
647 + .priority = NF_IP6_PRI_FIRST
648 + },
649 + {
650 + .hook = ip6t_hook,
651 + .pf = PF_INET6,
652 + .hooknum = NF_IP6_LOCAL_OUT,
653 + .priority = NF_IP6_PRI_FIRST
654 + },
655 +};
656 +
657 +static int __init init(void)
658 +{
659 + int ret;
660 +
661 + /* Register table */
662 + ret = ip6t_register_table(&packet_raw);
663 + if (ret < 0)
664 + return ret;
665 +
666 + /* Register hooks */
667 + ret = nf_register_hook(&ip6t_ops[0]);
668 + if (ret < 0)
669 + goto cleanup_table;
670 +
671 + ret = nf_register_hook(&ip6t_ops[1]);
672 + if (ret < 0)
673 + goto cleanup_hook0;
674 +
675 + return ret;
676 +
677 + cleanup_hook0:
678 + nf_unregister_hook(&ip6t_ops[0]);
679 + cleanup_table:
680 + ip6t_unregister_table(&packet_raw);
681 +
682 + return ret;
683 +}
684 +
685 +static void __exit fini(void)
686 +{
687 + unsigned int i;
688 +
689 + for (i = 0; i < sizeof(ip6t_ops)/sizeof(struct nf_hook_ops); i++)
690 + nf_unregister_hook(&ip6t_ops[i]);
691 +
692 + ip6t_unregister_table(&packet_raw);
693 +}
694 +
695 +module_init(init);
696 +module_exit(fini);
697 +MODULE_LICENSE("GPL");
698 --- a/net/ipv6/netfilter/Makefile
699 +++ b/net/ipv6/netfilter/Makefile
700 @@ -32,6 +32,7 @@
701 obj-$(CONFIG_IP6_NF_TARGET_IMQ) += ip6t_IMQ.o
702 obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
703 obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
704 +obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
705 obj-$(CONFIG_IP6_NF_MATCH_RANDOM) += ip6t_random.o
706 obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
707 obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o