de54a352d8b909c209ac3b40386111bc60464565
[openwrt-10.03/.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 @@ CONFIG_IP_NF_FILTER
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 @@ extern void ip_ct_refresh_acct(struct ip
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 @@ if [ "$CONFIG_IP_NF_IPTABLES" != "n" ]; 
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 @@ int ip_conntrack_max = 0;
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 @@ unsigned int ip_conntrack_in(unsigned in
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 @@ int __init ip_conntrack_init(void)
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 @@ static unsigned int ip_confirm(unsigned 
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 @@ static unsigned int ip_conntrack_local(u
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 @@ static int init_or_cleanup(int init)
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 @@ static int init_or_cleanup(int init)
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 @@ EXPORT_SYMBOL(ip_conntrack_htable_size);
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 @@ int __init ip_nat_init(void)
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 @@ match(const struct sk_buff *skb,
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 @@ match(const struct sk_buff *skb,
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 @@ obj-$(CONFIG_IP_NF_IPTABLES) += ip_table
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 @@ obj-$(CONFIG_IP_NF_TARGET_CONNMARK) += i
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 @@ if [ "$CONFIG_IP6_NF_IPTABLES" != "n" ];
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