update to 2.6.9-rc1
[linux-flexiantxendom0-3.2.10.git] / net / ipv4 / netfilter / ip_conntrack_standalone.c
1 /* This file contains all the functions required for the standalone
2    ip_conntrack module.
3
4    These are not required by the compatibility layer.
5 */
6
7 /* (C) 1999-2001 Paul `Rusty' Russell
8  * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2 as
12  * published by the Free Software Foundation.
13  */
14
15 #include <linux/config.h>
16 #include <linux/types.h>
17 #include <linux/ip.h>
18 #include <linux/netfilter.h>
19 #include <linux/netfilter_ipv4.h>
20 #include <linux/module.h>
21 #include <linux/skbuff.h>
22 #include <linux/proc_fs.h>
23 #include <linux/seq_file.h>
24 #include <linux/percpu.h>
25 #ifdef CONFIG_SYSCTL
26 #include <linux/sysctl.h>
27 #endif
28 #include <net/checksum.h>
29 #include <net/ip.h>
30
31 #define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_conntrack_lock)
32 #define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_conntrack_lock)
33
34 #include <linux/netfilter_ipv4/ip_conntrack.h>
35 #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
36 #include <linux/netfilter_ipv4/ip_conntrack_core.h>
37 #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
38 #include <linux/netfilter_ipv4/listhelp.h>
39
40 #if 0
41 #define DEBUGP printk
42 #else
43 #define DEBUGP(format, args...)
44 #endif
45
46 MODULE_LICENSE("GPL");
47
48 extern atomic_t ip_conntrack_count;
49 DECLARE_PER_CPU(struct ip_conntrack_stat, ip_conntrack_stat);
50
51 static int kill_proto(const struct ip_conntrack *i, void *data)
52 {
53         return (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == 
54                         *((u_int8_t *) data));
55 }
56
57 static unsigned int
58 print_tuple(char *buffer, const struct ip_conntrack_tuple *tuple,
59             struct ip_conntrack_protocol *proto)
60 {
61         int len;
62
63         len = sprintf(buffer, "src=%u.%u.%u.%u dst=%u.%u.%u.%u ",
64                       NIPQUAD(tuple->src.ip), NIPQUAD(tuple->dst.ip));
65
66         len += proto->print_tuple(buffer + len, tuple);
67
68         return len;
69 }
70
71 #ifdef CONFIG_IP_NF_CT_ACCT
72 static unsigned int
73 seq_print_counters(struct seq_file *s, struct ip_conntrack_counter *counter)
74 {
75         return seq_printf(s, "packets=%llu bytes=%llu ",
76                           counter->packets, counter->bytes);
77 }
78 #else
79 #define seq_print_counters(x, y)        0
80 #endif
81
82 static void *ct_seq_start(struct seq_file *s, loff_t *pos)
83 {
84         unsigned int *bucket;
85
86         /* strange seq_file api calls stop even if we fail,
87          * thus we need to grab lock since stop unlocks */
88         READ_LOCK(&ip_conntrack_lock);
89   
90         if (*pos >= ip_conntrack_htable_size)
91                 return NULL;
92
93         bucket = kmalloc(sizeof(unsigned int), GFP_KERNEL);
94         if (!bucket) {
95                 return ERR_PTR(-ENOMEM);
96         }
97   
98         *bucket = *pos;
99         return bucket;
100 }
101   
102 static void *ct_seq_next(struct seq_file *s, void *v, loff_t *pos)
103 {
104         unsigned int *bucket = (unsigned int *) v;
105
106         *pos = ++(*bucket);
107         if (*pos >= ip_conntrack_htable_size) {
108                 kfree(v);
109                 return NULL;
110         }
111         return bucket;
112 }
113   
114 static void ct_seq_stop(struct seq_file *s, void *v)
115 {
116         READ_UNLOCK(&ip_conntrack_lock);
117 }
118
119 /* return 0 on success, 1 in case of error */
120 static int ct_seq_real_show(const struct ip_conntrack_tuple_hash *hash,
121                             struct seq_file *s)
122 {
123         struct ip_conntrack *conntrack = hash->ctrack;
124         struct ip_conntrack_protocol *proto;
125         char buffer[IP_CT_PRINT_BUFLEN];
126
127         MUST_BE_READ_LOCKED(&ip_conntrack_lock);
128
129         IP_NF_ASSERT(conntrack);
130
131         /* we only want to print DIR_ORIGINAL */
132         if (DIRECTION(hash))
133                 return 0;
134
135         proto = __ip_ct_find_proto(conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
136                                .tuple.dst.protonum);
137         IP_NF_ASSERT(proto);
138
139         if (seq_printf(s, "%-8s %u %lu ",
140                       proto->name,
141                       conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum,
142                       timer_pending(&conntrack->timeout)
143                       ? (conntrack->timeout.expires - jiffies)/HZ : 0) != 0)
144                 return 1;
145
146         proto->print_conntrack(buffer, conntrack);
147         if (seq_puts(s, buffer))
148                 return 1;
149   
150         print_tuple(buffer, &conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
151                     proto);
152
153         if (seq_print_counters(s, &conntrack->counters[IP_CT_DIR_ORIGINAL]))
154                 return 1;
155
156         if (!(test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)))
157                 if (seq_printf(s, "[UNREPLIED] "))
158                         return 1;
159
160         print_tuple(buffer, &conntrack->tuplehash[IP_CT_DIR_REPLY].tuple,
161                     proto);
162         if (seq_puts(s, buffer))
163                 return 1;
164
165         if (seq_print_counters(s, &conntrack->counters[IP_CT_DIR_REPLY]))
166                 return 1;
167
168         if (test_bit(IPS_ASSURED_BIT, &conntrack->status))
169                 if (seq_printf(s, "[ASSURED] "))
170                         return 1;
171
172         if (seq_printf(s, "use=%u\n", atomic_read(&conntrack->ct_general.use)))
173                 return 1;
174
175         return 0;
176 }
177
178
179 static int ct_seq_show(struct seq_file *s, void *v)
180 {
181         unsigned int *bucket = (unsigned int *) v;
182
183         if (LIST_FIND(&ip_conntrack_hash[*bucket], ct_seq_real_show,
184                       struct ip_conntrack_tuple_hash *, s)) {
185                 /* buffer was filled and unable to print that tuple */
186                 return 1;
187         }
188         return 0;
189 }
190         
191 static struct seq_operations ct_seq_ops = {
192         .start = ct_seq_start,
193         .next  = ct_seq_next,
194         .stop  = ct_seq_stop,
195         .show  = ct_seq_show
196 };
197   
198 static int ct_open(struct inode *inode, struct file *file)
199 {
200         return seq_open(file, &ct_seq_ops);
201 }
202
203 static struct file_operations ct_file_ops = {
204         .owner   = THIS_MODULE,
205         .open    = ct_open,
206         .read    = seq_read,
207         .llseek  = seq_lseek,
208         .release = seq_release
209 };
210   
211 /* expects */
212 static void *exp_seq_start(struct seq_file *s, loff_t *pos)
213 {
214         struct list_head *e = &ip_conntrack_expect_list;
215         loff_t i;
216
217         /* strange seq_file api calls stop even if we fail,
218          * thus we need to grab lock since stop unlocks */
219         READ_LOCK(&ip_conntrack_lock);
220         READ_LOCK(&ip_conntrack_expect_tuple_lock);
221
222         if (list_empty(e))
223                 return NULL;
224
225         for (i = 0; i <= *pos; i++) {
226                 e = e->next;
227                 if (e == &ip_conntrack_expect_list)
228                         return NULL;
229         }
230         return e;
231 }
232
233 static void *exp_seq_next(struct seq_file *s, void *v, loff_t *pos)
234 {
235         struct list_head *e = v;
236
237         e = e->next;
238
239         if (e == &ip_conntrack_expect_list)
240                 return NULL;
241
242         return e;
243 }
244
245 static void exp_seq_stop(struct seq_file *s, void *v)
246 {
247         READ_UNLOCK(&ip_conntrack_expect_tuple_lock);
248         READ_UNLOCK(&ip_conntrack_lock);
249 }
250
251 static int exp_seq_show(struct seq_file *s, void *v)
252 {
253         struct ip_conntrack_expect *expect = v;
254         char buffer[IP_CT_PRINT_BUFLEN];
255
256         if (expect->expectant->helper->timeout)
257                 seq_printf(s, "%lu ", timer_pending(&expect->timeout)
258                            ? (expect->timeout.expires - jiffies)/HZ : 0);
259         else
260                 seq_printf(s, "- ");
261
262         seq_printf(s, "use=%u proto=%u ", atomic_read(&expect->use),
263                    expect->tuple.dst.protonum);
264
265         print_tuple(buffer, &expect->tuple,
266                     __ip_ct_find_proto(expect->tuple.dst.protonum));
267         return seq_printf(s, "%s\n", buffer);
268 }
269
270 static struct seq_operations exp_seq_ops = {
271         .start = exp_seq_start,
272         .next = exp_seq_next,
273         .stop = exp_seq_stop,
274         .show = exp_seq_show
275 };
276
277 static int exp_open(struct inode *inode, struct file *file)
278 {
279         return seq_open(file, &exp_seq_ops);
280 }
281   
282 static struct file_operations exp_file_ops = {
283         .owner   = THIS_MODULE,
284         .open    = exp_open,
285         .read    = seq_read,
286         .llseek  = seq_lseek,
287         .release = seq_release
288 };
289
290 static void *ct_cpu_seq_start(struct seq_file *seq, loff_t *pos)
291 {
292         int cpu;
293
294         for (cpu = *pos; cpu < NR_CPUS; ++cpu) {
295                 if (!cpu_possible(cpu))
296                         continue;
297                 *pos = cpu;
298                 return &per_cpu(ip_conntrack_stat, cpu);
299         }
300
301         return NULL;
302 }
303
304 static void *ct_cpu_seq_next(struct seq_file *seq, void *v, loff_t *pos)
305 {
306         int cpu;
307
308         for (cpu = *pos + 1; cpu < NR_CPUS; ++cpu) {
309                 if (!cpu_possible(cpu))
310                         continue;
311                 *pos = cpu;
312                 return &per_cpu(ip_conntrack_stat, cpu);
313         }
314
315         return NULL;
316 }
317
318 static void ct_cpu_seq_stop(struct seq_file *seq, void *v)
319 {
320 }
321
322 static int ct_cpu_seq_show(struct seq_file *seq, void *v)
323 {
324         unsigned int nr_conntracks = atomic_read(&ip_conntrack_count);
325         struct ip_conntrack_stat *st = v;
326
327         seq_printf(seq, "%08x  %08x %08x %08x %08x %08x %08x %08x "
328                         "%08x %08x %08x %08x %08x  %08x %08x %08x \n",
329                    nr_conntracks,
330                    st->searched,
331                    st->found,
332                    st->new,
333                    st->invalid,
334                    st->ignore,
335                    st->delete,
336                    st->delete_list,
337                    st->insert,
338                    st->insert_failed,
339                    st->drop,
340                    st->early_drop,
341                    st->icmp_error,
342
343                    st->expect_new,
344                    st->expect_create,
345                    st->expect_delete
346                 );
347         return 0;
348 }
349
350 static struct seq_operations ct_cpu_seq_ops = {
351         .start  = ct_cpu_seq_start,
352         .next   = ct_cpu_seq_next,
353         .stop   = ct_cpu_seq_stop,
354         .show   = ct_cpu_seq_show,
355 };
356
357 static int ct_cpu_seq_open(struct inode *inode, struct file *file)
358 {
359         return seq_open(file, &ct_cpu_seq_ops);
360 }
361
362 static struct file_operations ct_cpu_seq_fops = {
363         .owner   = THIS_MODULE,
364         .open    = ct_cpu_seq_open,
365         .read    = seq_read,
366         .llseek  = seq_lseek,
367         .release = seq_release_private,
368 };
369
370 static unsigned int ip_confirm(unsigned int hooknum,
371                                struct sk_buff **pskb,
372                                const struct net_device *in,
373                                const struct net_device *out,
374                                int (*okfn)(struct sk_buff *))
375 {
376         /* We've seen it coming out the other side: confirm it */
377         return ip_conntrack_confirm(*pskb);
378 }
379
380 static unsigned int ip_conntrack_defrag(unsigned int hooknum,
381                                         struct sk_buff **pskb,
382                                         const struct net_device *in,
383                                         const struct net_device *out,
384                                         int (*okfn)(struct sk_buff *))
385 {
386         /* Previously seen (loopback)?  Ignore.  Do this before
387            fragment check. */
388         if ((*pskb)->nfct)
389                 return NF_ACCEPT;
390
391         /* Gather fragments. */
392         if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
393                 *pskb = ip_ct_gather_frags(*pskb);
394                 if (!*pskb)
395                         return NF_STOLEN;
396         }
397         return NF_ACCEPT;
398 }
399
400 static unsigned int ip_refrag(unsigned int hooknum,
401                               struct sk_buff **pskb,
402                               const struct net_device *in,
403                               const struct net_device *out,
404                               int (*okfn)(struct sk_buff *))
405 {
406         struct rtable *rt = (struct rtable *)(*pskb)->dst;
407
408         /* We've seen it coming out the other side: confirm */
409         if (ip_confirm(hooknum, pskb, in, out, okfn) != NF_ACCEPT)
410                 return NF_DROP;
411
412         /* Local packets are never produced too large for their
413            interface.  We degfragment them at LOCAL_OUT, however,
414            so we have to refragment them here. */
415         if ((*pskb)->len > dst_pmtu(&rt->u.dst) &&
416             !skb_shinfo(*pskb)->tso_size) {
417                 /* No hook can be after us, so this should be OK. */
418                 ip_fragment(*pskb, okfn);
419                 return NF_STOLEN;
420         }
421         return NF_ACCEPT;
422 }
423
424 static unsigned int ip_conntrack_local(unsigned int hooknum,
425                                        struct sk_buff **pskb,
426                                        const struct net_device *in,
427                                        const struct net_device *out,
428                                        int (*okfn)(struct sk_buff *))
429 {
430         /* root is playing with raw sockets. */
431         if ((*pskb)->len < sizeof(struct iphdr)
432             || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) {
433                 if (net_ratelimit())
434                         printk("ipt_hook: happy cracking.\n");
435                 return NF_ACCEPT;
436         }
437         return ip_conntrack_in(hooknum, pskb, in, out, okfn);
438 }
439
440 /* Connection tracking may drop packets, but never alters them, so
441    make it the first hook. */
442 static struct nf_hook_ops ip_conntrack_defrag_ops = {
443         .hook           = ip_conntrack_defrag,
444         .owner          = THIS_MODULE,
445         .pf             = PF_INET,
446         .hooknum        = NF_IP_PRE_ROUTING,
447         .priority       = NF_IP_PRI_CONNTRACK_DEFRAG,
448 };
449
450 static struct nf_hook_ops ip_conntrack_in_ops = {
451         .hook           = ip_conntrack_in,
452         .owner          = THIS_MODULE,
453         .pf             = PF_INET,
454         .hooknum        = NF_IP_PRE_ROUTING,
455         .priority       = NF_IP_PRI_CONNTRACK,
456 };
457
458 static struct nf_hook_ops ip_conntrack_defrag_local_out_ops = {
459         .hook           = ip_conntrack_defrag,
460         .owner          = THIS_MODULE,
461         .pf             = PF_INET,
462         .hooknum        = NF_IP_LOCAL_OUT,
463         .priority       = NF_IP_PRI_CONNTRACK_DEFRAG,
464 };
465
466 static struct nf_hook_ops ip_conntrack_local_out_ops = {
467         .hook           = ip_conntrack_local,
468         .owner          = THIS_MODULE,
469         .pf             = PF_INET,
470         .hooknum        = NF_IP_LOCAL_OUT,
471         .priority       = NF_IP_PRI_CONNTRACK,
472 };
473
474 /* Refragmenter; last chance. */
475 static struct nf_hook_ops ip_conntrack_out_ops = {
476         .hook           = ip_refrag,
477         .owner          = THIS_MODULE,
478         .pf             = PF_INET,
479         .hooknum        = NF_IP_POST_ROUTING,
480         .priority       = NF_IP_PRI_LAST,
481 };
482
483 static struct nf_hook_ops ip_conntrack_local_in_ops = {
484         .hook           = ip_confirm,
485         .owner          = THIS_MODULE,
486         .pf             = PF_INET,
487         .hooknum        = NF_IP_LOCAL_IN,
488         .priority       = NF_IP_PRI_LAST-1,
489 };
490
491 /* Sysctl support */
492
493 #ifdef CONFIG_SYSCTL
494
495 /* From ip_conntrack_core.c */
496 extern int ip_conntrack_max;
497 extern unsigned int ip_conntrack_htable_size;
498
499 /* From ip_conntrack_proto_tcp.c */
500 extern unsigned long ip_ct_tcp_timeout_syn_sent;
501 extern unsigned long ip_ct_tcp_timeout_syn_recv;
502 extern unsigned long ip_ct_tcp_timeout_established;
503 extern unsigned long ip_ct_tcp_timeout_fin_wait;
504 extern unsigned long ip_ct_tcp_timeout_close_wait;
505 extern unsigned long ip_ct_tcp_timeout_last_ack;
506 extern unsigned long ip_ct_tcp_timeout_time_wait;
507 extern unsigned long ip_ct_tcp_timeout_close;
508 extern unsigned long ip_ct_tcp_timeout_max_retrans;
509 extern int ip_ct_tcp_loose;
510 extern int ip_ct_tcp_be_liberal;
511 extern int ip_ct_tcp_max_retrans;
512
513 /* From ip_conntrack_proto_udp.c */
514 extern unsigned long ip_ct_udp_timeout;
515 extern unsigned long ip_ct_udp_timeout_stream;
516
517 /* From ip_conntrack_proto_icmp.c */
518 extern unsigned long ip_ct_icmp_timeout;
519
520 /* From ip_conntrack_proto_icmp.c */
521 extern unsigned long ip_ct_generic_timeout;
522
523 /* Log invalid packets of a given protocol */
524 unsigned int ip_ct_log_invalid = 0;
525 static int log_invalid_proto_min = 0;
526 static int log_invalid_proto_max = 255;
527
528 static struct ctl_table_header *ip_ct_sysctl_header;
529
530 static ctl_table ip_ct_sysctl_table[] = {
531         {
532                 .ctl_name       = NET_IPV4_NF_CONNTRACK_MAX,
533                 .procname       = "ip_conntrack_max",
534                 .data           = &ip_conntrack_max,
535                 .maxlen         = sizeof(int),
536                 .mode           = 0644,
537                 .proc_handler   = &proc_dointvec,
538         },
539         {
540                 .ctl_name       = NET_IPV4_NF_CONNTRACK_BUCKETS,
541                 .procname       = "ip_conntrack_buckets",
542                 .data           = &ip_conntrack_htable_size,
543                 .maxlen         = sizeof(unsigned int),
544                 .mode           = 0444,
545                 .proc_handler   = &proc_dointvec,
546         },
547         {
548                 .ctl_name       = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT,
549                 .procname       = "ip_conntrack_tcp_timeout_syn_sent",
550                 .data           = &ip_ct_tcp_timeout_syn_sent,
551                 .maxlen         = sizeof(unsigned int),
552                 .mode           = 0644,
553                 .proc_handler   = &proc_dointvec_jiffies,
554         },
555         {
556                 .ctl_name       = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_RECV,
557                 .procname       = "ip_conntrack_tcp_timeout_syn_recv",
558                 .data           = &ip_ct_tcp_timeout_syn_recv,
559                 .maxlen         = sizeof(unsigned int),
560                 .mode           = 0644,
561                 .proc_handler   = &proc_dointvec_jiffies,
562         },
563         {
564                 .ctl_name       = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED,
565                 .procname       = "ip_conntrack_tcp_timeout_established",
566                 .data           = &ip_ct_tcp_timeout_established,
567                 .maxlen         = sizeof(unsigned int),
568                 .mode           = 0644,
569                 .proc_handler   = &proc_dointvec_jiffies,
570         },
571         {
572                 .ctl_name       = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_FIN_WAIT,
573                 .procname       = "ip_conntrack_tcp_timeout_fin_wait",
574                 .data           = &ip_ct_tcp_timeout_fin_wait,
575                 .maxlen         = sizeof(unsigned int),
576                 .mode           = 0644,
577                 .proc_handler   = &proc_dointvec_jiffies,
578         },
579         {
580                 .ctl_name       = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE_WAIT,
581                 .procname       = "ip_conntrack_tcp_timeout_close_wait",
582                 .data           = &ip_ct_tcp_timeout_close_wait,
583                 .maxlen         = sizeof(unsigned int),
584                 .mode           = 0644,
585                 .proc_handler   = &proc_dointvec_jiffies,
586         },
587         {
588                 .ctl_name       = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_LAST_ACK,
589                 .procname       = "ip_conntrack_tcp_timeout_last_ack",
590                 .data           = &ip_ct_tcp_timeout_last_ack,
591                 .maxlen         = sizeof(unsigned int),
592                 .mode           = 0644,
593                 .proc_handler   = &proc_dointvec_jiffies,
594         },
595         {
596                 .ctl_name       = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_TIME_WAIT,
597                 .procname       = "ip_conntrack_tcp_timeout_time_wait",
598                 .data           = &ip_ct_tcp_timeout_time_wait,
599                 .maxlen         = sizeof(unsigned int),
600                 .mode           = 0644,
601                 .proc_handler   = &proc_dointvec_jiffies,
602         },
603         {
604                 .ctl_name       = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE,
605                 .procname       = "ip_conntrack_tcp_timeout_close",
606                 .data           = &ip_ct_tcp_timeout_close,
607                 .maxlen         = sizeof(unsigned int),
608                 .mode           = 0644,
609                 .proc_handler   = &proc_dointvec_jiffies,
610         },
611         {
612                 .ctl_name       = NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT,
613                 .procname       = "ip_conntrack_udp_timeout",
614                 .data           = &ip_ct_udp_timeout,
615                 .maxlen         = sizeof(unsigned int),
616                 .mode           = 0644,
617                 .proc_handler   = &proc_dointvec_jiffies,
618         },
619         {
620                 .ctl_name       = NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT_STREAM,
621                 .procname       = "ip_conntrack_udp_timeout_stream",
622                 .data           = &ip_ct_udp_timeout_stream,
623                 .maxlen         = sizeof(unsigned int),
624                 .mode           = 0644,
625                 .proc_handler   = &proc_dointvec_jiffies,
626         },
627         {
628                 .ctl_name       = NET_IPV4_NF_CONNTRACK_ICMP_TIMEOUT,
629                 .procname       = "ip_conntrack_icmp_timeout",
630                 .data           = &ip_ct_icmp_timeout,
631                 .maxlen         = sizeof(unsigned int),
632                 .mode           = 0644,
633                 .proc_handler   = &proc_dointvec_jiffies,
634         },
635         {
636                 .ctl_name       = NET_IPV4_NF_CONNTRACK_GENERIC_TIMEOUT,
637                 .procname       = "ip_conntrack_generic_timeout",
638                 .data           = &ip_ct_generic_timeout,
639                 .maxlen         = sizeof(unsigned int),
640                 .mode           = 0644,
641                 .proc_handler   = &proc_dointvec_jiffies,
642         },
643         {
644                 .ctl_name       = NET_IPV4_NF_CONNTRACK_LOG_INVALID,
645                 .procname       = "ip_conntrack_log_invalid",
646                 .data           = &ip_ct_log_invalid,
647                 .maxlen         = sizeof(unsigned int),
648                 .mode           = 0644,
649                 .proc_handler   = &proc_dointvec_minmax,
650                 .strategy       = &sysctl_intvec,
651                 .extra1         = &log_invalid_proto_min,
652                 .extra2         = &log_invalid_proto_max,
653         },
654         {
655                 .ctl_name       = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_MAX_RETRANS,
656                 .procname       = "ip_conntrack_tcp_timeout_max_retrans",
657                 .data           = &ip_ct_tcp_timeout_max_retrans,
658                 .maxlen         = sizeof(unsigned int),
659                 .mode           = 0644,
660                 .proc_handler   = &proc_dointvec_jiffies,
661         },
662         {
663                 .ctl_name       = NET_IPV4_NF_CONNTRACK_TCP_LOOSE,
664                 .procname       = "ip_conntrack_tcp_loose",
665                 .data           = &ip_ct_tcp_loose,
666                 .maxlen         = sizeof(unsigned int),
667                 .mode           = 0644,
668                 .proc_handler   = &proc_dointvec,
669         },
670         {
671                 .ctl_name       = NET_IPV4_NF_CONNTRACK_TCP_BE_LIBERAL,
672                 .procname       = "ip_conntrack_tcp_be_liberal",
673                 .data           = &ip_ct_tcp_be_liberal,
674                 .maxlen         = sizeof(unsigned int),
675                 .mode           = 0644,
676                 .proc_handler   = &proc_dointvec,
677         },
678         {
679                 .ctl_name       = NET_IPV4_NF_CONNTRACK_TCP_MAX_RETRANS,
680                 .procname       = "ip_conntrack_tcp_max_retrans",
681                 .data           = &ip_ct_tcp_max_retrans,
682                 .maxlen         = sizeof(unsigned int),
683                 .mode           = 0644,
684                 .proc_handler   = &proc_dointvec,
685         },
686         { .ctl_name = 0 }
687 };
688
689 #define NET_IP_CONNTRACK_MAX 2089
690
691 static ctl_table ip_ct_netfilter_table[] = {
692         {
693                 .ctl_name       = NET_IPV4_NETFILTER,
694                 .procname       = "netfilter",
695                 .mode           = 0555,
696                 .child          = ip_ct_sysctl_table,
697         },
698         {
699                 .ctl_name       = NET_IP_CONNTRACK_MAX,
700                 .procname       = "ip_conntrack_max",
701                 .data           = &ip_conntrack_max,
702                 .maxlen         = sizeof(int),
703                 .mode           = 0644,
704                 .proc_handler   = &proc_dointvec
705         },
706         { .ctl_name = 0 }
707 };
708
709 static ctl_table ip_ct_ipv4_table[] = {
710         {
711                 .ctl_name       = NET_IPV4,
712                 .procname       = "ipv4",
713                 .mode           = 0555,
714                 .child          = ip_ct_netfilter_table,
715         },
716         { .ctl_name = 0 }
717 };
718
719 static ctl_table ip_ct_net_table[] = {
720         {
721                 .ctl_name       = CTL_NET,
722                 .procname       = "net",
723                 .mode           = 0555, 
724                 .child          = ip_ct_ipv4_table,
725         },
726         { .ctl_name = 0 }
727 };
728 #endif
729 static int init_or_cleanup(int init)
730 {
731         struct proc_dir_entry *proc, *proc_exp, *proc_stat;
732         int ret = 0;
733
734         if (!init) goto cleanup;
735
736         ret = ip_conntrack_init();
737         if (ret < 0)
738                 goto cleanup_nothing;
739
740         proc = proc_net_create("ip_conntrack", 0440, NULL);
741         if (!proc) goto cleanup_init;
742         proc->proc_fops = &ct_file_ops;
743
744         proc_exp = proc_net_create("ip_conntrack_expect", 0440, NULL);
745         if (!proc_exp) goto cleanup_proc;
746         proc_exp->proc_fops = &exp_file_ops;
747
748         proc_stat = proc_net_fops_create("ip_conntrack_stat", S_IRUGO,
749                                          &ct_cpu_seq_fops);
750         if (!proc_stat)
751                 goto cleanup_proc_exp;
752         proc_stat->owner = THIS_MODULE;
753
754         ret = nf_register_hook(&ip_conntrack_defrag_ops);
755         if (ret < 0) {
756                 printk("ip_conntrack: can't register pre-routing defrag hook.\n");
757                 goto cleanup_proc_stat;
758         }
759         ret = nf_register_hook(&ip_conntrack_defrag_local_out_ops);
760         if (ret < 0) {
761                 printk("ip_conntrack: can't register local_out defrag hook.\n");
762                 goto cleanup_defragops;
763         }
764         ret = nf_register_hook(&ip_conntrack_in_ops);
765         if (ret < 0) {
766                 printk("ip_conntrack: can't register pre-routing hook.\n");
767                 goto cleanup_defraglocalops;
768         }
769         ret = nf_register_hook(&ip_conntrack_local_out_ops);
770         if (ret < 0) {
771                 printk("ip_conntrack: can't register local out hook.\n");
772                 goto cleanup_inops;
773         }
774         ret = nf_register_hook(&ip_conntrack_out_ops);
775         if (ret < 0) {
776                 printk("ip_conntrack: can't register post-routing hook.\n");
777                 goto cleanup_inandlocalops;
778         }
779         ret = nf_register_hook(&ip_conntrack_local_in_ops);
780         if (ret < 0) {
781                 printk("ip_conntrack: can't register local in hook.\n");
782                 goto cleanup_inoutandlocalops;
783         }
784 #ifdef CONFIG_SYSCTL
785         ip_ct_sysctl_header = register_sysctl_table(ip_ct_net_table, 0);
786         if (ip_ct_sysctl_header == NULL) {
787                 printk("ip_conntrack: can't register to sysctl.\n");
788                 goto cleanup;
789         }
790 #endif
791
792         return ret;
793
794  cleanup:
795 #ifdef CONFIG_SYSCTL
796         unregister_sysctl_table(ip_ct_sysctl_header);
797 #endif
798         nf_unregister_hook(&ip_conntrack_local_in_ops);
799  cleanup_inoutandlocalops:
800         nf_unregister_hook(&ip_conntrack_out_ops);
801  cleanup_inandlocalops:
802         nf_unregister_hook(&ip_conntrack_local_out_ops);
803  cleanup_inops:
804         nf_unregister_hook(&ip_conntrack_in_ops);
805  cleanup_defraglocalops:
806         nf_unregister_hook(&ip_conntrack_defrag_local_out_ops);
807  cleanup_defragops:
808         nf_unregister_hook(&ip_conntrack_defrag_ops);
809  cleanup_proc_stat:
810         proc_net_remove("ip_conntrack_stat");
811 cleanup_proc_exp:
812         proc_net_remove("ip_conntrack_exp");
813  cleanup_proc:
814         proc_net_remove("ip_conntrack");
815  cleanup_init:
816         ip_conntrack_cleanup();
817  cleanup_nothing:
818         return ret;
819 }
820
821 /* FIXME: Allow NULL functions and sub in pointers to generic for
822    them. --RR */
823 int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto)
824 {
825         int ret = 0;
826         struct list_head *i;
827
828         WRITE_LOCK(&ip_conntrack_lock);
829         list_for_each(i, &protocol_list) {
830                 if (((struct ip_conntrack_protocol *)i)->proto
831                     == proto->proto) {
832                         ret = -EBUSY;
833                         goto out;
834                 }
835         }
836
837         list_prepend(&protocol_list, proto);
838
839  out:
840         WRITE_UNLOCK(&ip_conntrack_lock);
841         return ret;
842 }
843
844 void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto)
845 {
846         WRITE_LOCK(&ip_conntrack_lock);
847
848         /* ip_ct_find_proto() returns proto_generic in case there is no protocol 
849          * helper. So this should be enough - HW */
850         LIST_DELETE(&protocol_list, proto);
851         WRITE_UNLOCK(&ip_conntrack_lock);
852         
853         /* Somebody could be still looking at the proto in bh. */
854         synchronize_net();
855
856         /* Remove all contrack entries for this protocol */
857         ip_ct_selective_cleanup(kill_proto, &proto->proto);
858 }
859
860 static int __init init(void)
861 {
862         return init_or_cleanup(1);
863 }
864
865 static void __exit fini(void)
866 {
867         init_or_cleanup(0);
868 }
869
870 module_init(init);
871 module_exit(fini);
872
873 /* Some modules need us, but don't depend directly on any symbol.
874    They should call this. */
875 void need_ip_conntrack(void)
876 {
877 }
878
879 EXPORT_SYMBOL(ip_conntrack_protocol_register);
880 EXPORT_SYMBOL(ip_conntrack_protocol_unregister);
881 EXPORT_SYMBOL(invert_tuplepr);
882 EXPORT_SYMBOL(ip_conntrack_alter_reply);
883 EXPORT_SYMBOL(ip_conntrack_destroyed);
884 EXPORT_SYMBOL(ip_conntrack_get);
885 EXPORT_SYMBOL(__ip_conntrack_confirm);
886 EXPORT_SYMBOL(need_ip_conntrack);
887 EXPORT_SYMBOL(ip_conntrack_helper_register);
888 EXPORT_SYMBOL(ip_conntrack_helper_unregister);
889 EXPORT_SYMBOL(ip_ct_selective_cleanup);
890 EXPORT_SYMBOL(ip_ct_refresh_acct);
891 EXPORT_SYMBOL(ip_ct_find_proto);
892 EXPORT_SYMBOL(__ip_ct_find_proto);
893 EXPORT_SYMBOL(ip_ct_find_helper);
894 EXPORT_SYMBOL(ip_conntrack_expect_alloc);
895 EXPORT_SYMBOL(ip_conntrack_expect_related);
896 EXPORT_SYMBOL(ip_conntrack_change_expect);
897 EXPORT_SYMBOL(ip_conntrack_unexpect_related);
898 EXPORT_SYMBOL_GPL(ip_conntrack_expect_find_get);
899 EXPORT_SYMBOL_GPL(ip_conntrack_expect_put);
900 EXPORT_SYMBOL(ip_conntrack_tuple_taken);
901 EXPORT_SYMBOL(ip_ct_gather_frags);
902 EXPORT_SYMBOL(ip_conntrack_htable_size);
903 EXPORT_SYMBOL(ip_conntrack_expect_list);
904 EXPORT_SYMBOL(ip_conntrack_lock);
905 EXPORT_SYMBOL(ip_conntrack_hash);
906 EXPORT_SYMBOL(ip_conntrack_untracked);
907 EXPORT_SYMBOL_GPL(ip_conntrack_find_get);
908 EXPORT_SYMBOL_GPL(ip_conntrack_put);
909 EXPORT_SYMBOL(ip_ct_log_invalid);