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