This commit was manufactured by cvs2svn to create tag
[linux-2.6.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 #ifdef CONFIG_SYSCTL
24 #include <linux/sysctl.h>
25 #endif
26 #include <net/checksum.h>
27 #include <net/ip.h>
28
29 #define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_conntrack_lock)
30 #define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_conntrack_lock)
31
32 #include <linux/netfilter_ipv4/ip_conntrack.h>
33 #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
34 #include <linux/netfilter_ipv4/ip_conntrack_core.h>
35 #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
36 #include <linux/netfilter_ipv4/listhelp.h>
37
38 #if 0
39 #define DEBUGP printk
40 #else
41 #define DEBUGP(format, args...)
42 #endif
43
44 MODULE_LICENSE("GPL");
45
46 static int kill_proto(const struct ip_conntrack *i, void *data)
47 {
48         return (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == 
49                         *((u_int8_t *) data));
50 }
51
52 static unsigned int
53 print_tuple(char *buffer, const struct ip_conntrack_tuple *tuple,
54             struct ip_conntrack_protocol *proto)
55 {
56         int len;
57
58         len = sprintf(buffer, "src=%u.%u.%u.%u dst=%u.%u.%u.%u ",
59                       NIPQUAD(tuple->src.ip), NIPQUAD(tuple->dst.ip));
60
61         len += proto->print_tuple(buffer + len, tuple);
62
63         return len;
64 }
65
66 /* FIXME: Don't print source proto part. --RR */
67 static unsigned int
68 print_expect(char *buffer, const struct ip_conntrack_expect *expect)
69 {
70         unsigned int len;
71
72         if (expect->expectant->helper->timeout)
73                 len = sprintf(buffer, "EXPECTING: %lu ",
74                               timer_pending(&expect->timeout)
75                               ? (expect->timeout.expires - jiffies)/HZ : 0);
76         else
77                 len = sprintf(buffer, "EXPECTING: - ");
78         len += sprintf(buffer + len, "use=%u proto=%u ",
79                       atomic_read(&expect->use), expect->tuple.dst.protonum);
80         len += print_tuple(buffer + len, &expect->tuple,
81                            __ip_ct_find_proto(expect->tuple.dst.protonum));
82         len += sprintf(buffer + len, "\n");
83         return len;
84 }
85
86 static unsigned int
87 print_conntrack(char *buffer, struct ip_conntrack *conntrack)
88 {
89         unsigned int len;
90         struct ip_conntrack_protocol *proto
91                 = __ip_ct_find_proto(conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
92                                .tuple.dst.protonum);
93
94         len = sprintf(buffer, "%-8s %u %lu ",
95                       proto->name,
96                       conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
97                       .tuple.dst.protonum,
98                       timer_pending(&conntrack->timeout)
99                       ? (conntrack->timeout.expires - jiffies)/HZ : 0);
100
101         len += proto->print_conntrack(buffer + len, conntrack);
102         len += print_tuple(buffer + len,
103                            &conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
104                            proto);
105         if (!(test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)))
106                 len += sprintf(buffer + len, "[UNREPLIED] ");
107         len += print_tuple(buffer + len,
108                            &conntrack->tuplehash[IP_CT_DIR_REPLY].tuple,
109                            proto);
110         if (test_bit(IPS_ASSURED_BIT, &conntrack->status))
111                 len += sprintf(buffer + len, "[ASSURED] ");
112         len += sprintf(buffer + len, "use=%u ",
113                        atomic_read(&conntrack->ct_general.use));
114         len += sprintf(buffer + len, "xid=%d ",
115                        conntrack->xid);
116         len += sprintf(buffer + len, "\n");
117
118         return len;
119 }
120
121 /* Returns true when finished. */
122 static inline int
123 conntrack_iterate(const struct ip_conntrack_tuple_hash *hash,
124                   char *buffer, off_t offset, off_t *upto,
125                   unsigned int *len, unsigned int maxlen)
126 {
127         unsigned int newlen;
128         IP_NF_ASSERT(hash->ctrack);
129
130         MUST_BE_READ_LOCKED(&ip_conntrack_lock);
131
132         /* Only count originals */
133         if (DIRECTION(hash))
134                 return 0;
135
136         if ((*upto)++ < offset)
137                 return 0;
138
139         newlen = print_conntrack(buffer + *len, hash->ctrack);
140         if (*len + newlen > maxlen)
141                 return 1;
142         else *len += newlen;
143
144         return 0;
145 }
146
147 static int
148 list_conntracks(char *buffer, char **start, off_t offset, int length)
149 {
150         unsigned int i;
151         unsigned int len = 0;
152         off_t upto = 0;
153         struct list_head *e;
154
155         READ_LOCK(&ip_conntrack_lock);
156         /* Traverse hash; print originals then reply. */
157         for (i = 0; i < ip_conntrack_htable_size; i++) {
158                 if (LIST_FIND(&ip_conntrack_hash[i], conntrack_iterate,
159                               struct ip_conntrack_tuple_hash *,
160                               buffer, offset, &upto, &len, length))
161                         goto finished;
162         }
163
164         /* Now iterate through expecteds. */
165         READ_LOCK(&ip_conntrack_expect_tuple_lock);
166         list_for_each(e, &ip_conntrack_expect_list) {
167                 unsigned int last_len;
168                 struct ip_conntrack_expect *expect
169                         = (struct ip_conntrack_expect *)e;
170                 if (upto++ < offset) continue;
171
172                 last_len = len;
173                 len += print_expect(buffer + len, expect);
174                 if (len > length) {
175                         len = last_len;
176                         goto finished_expects;
177                 }
178         }
179
180  finished_expects:
181         READ_UNLOCK(&ip_conntrack_expect_tuple_lock);
182  finished:
183         READ_UNLOCK(&ip_conntrack_lock);
184
185         /* `start' hack - see fs/proc/generic.c line ~165 */
186         *start = (char *)((unsigned int)upto - offset);
187         return len;
188 }
189
190 static unsigned int ip_confirm(unsigned int hooknum,
191                                struct sk_buff **pskb,
192                                const struct net_device *in,
193                                const struct net_device *out,
194                                int (*okfn)(struct sk_buff *))
195 {
196         /* We've seen it coming out the other side: confirm it */
197         return ip_conntrack_confirm(*pskb);
198 }
199
200 static unsigned int ip_conntrack_defrag(unsigned int hooknum,
201                                         struct sk_buff **pskb,
202                                         const struct net_device *in,
203                                         const struct net_device *out,
204                                         int (*okfn)(struct sk_buff *))
205 {
206         /* Previously seen (loopback)?  Ignore.  Do this before
207            fragment check. */
208         if ((*pskb)->nfct)
209                 return NF_ACCEPT;
210
211         /* Gather fragments. */
212         if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
213                 *pskb = ip_ct_gather_frags(*pskb);
214                 if (!*pskb)
215                         return NF_STOLEN;
216         }
217         return NF_ACCEPT;
218 }
219
220 static unsigned int ip_refrag(unsigned int hooknum,
221                               struct sk_buff **pskb,
222                               const struct net_device *in,
223                               const struct net_device *out,
224                               int (*okfn)(struct sk_buff *))
225 {
226         struct rtable *rt = (struct rtable *)(*pskb)->dst;
227
228         /* We've seen it coming out the other side: confirm */
229         if (ip_confirm(hooknum, pskb, in, out, okfn) != NF_ACCEPT)
230                 return NF_DROP;
231
232         /* Local packets are never produced too large for their
233            interface.  We degfragment them at LOCAL_OUT, however,
234            so we have to refragment them here. */
235         if ((*pskb)->len > dst_pmtu(&rt->u.dst) &&
236             !skb_shinfo(*pskb)->tso_size) {
237                 /* No hook can be after us, so this should be OK. */
238                 ip_fragment(*pskb, okfn);
239                 return NF_STOLEN;
240         }
241         return NF_ACCEPT;
242 }
243
244 static unsigned int ip_conntrack_local(unsigned int hooknum,
245                                        struct sk_buff **pskb,
246                                        const struct net_device *in,
247                                        const struct net_device *out,
248                                        int (*okfn)(struct sk_buff *))
249 {
250         /* root is playing with raw sockets. */
251         if ((*pskb)->len < sizeof(struct iphdr)
252             || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) {
253                 if (net_ratelimit())
254                         printk("ipt_hook: happy cracking.\n");
255                 return NF_ACCEPT;
256         }
257         return ip_conntrack_in(hooknum, pskb, in, out, okfn);
258 }
259
260 /* Connection tracking may drop packets, but never alters them, so
261    make it the first hook. */
262 static struct nf_hook_ops ip_conntrack_defrag_ops = {
263         .hook           = ip_conntrack_defrag,
264         .owner          = THIS_MODULE,
265         .pf             = PF_INET,
266         .hooknum        = NF_IP_PRE_ROUTING,
267         .priority       = NF_IP_PRI_CONNTRACK_DEFRAG,
268 };
269
270 static struct nf_hook_ops ip_conntrack_in_ops = {
271         .hook           = ip_conntrack_in,
272         .owner          = THIS_MODULE,
273         .pf             = PF_INET,
274         .hooknum        = NF_IP_PRE_ROUTING,
275         .priority       = NF_IP_PRI_CONNTRACK,
276 };
277
278 static struct nf_hook_ops ip_conntrack_defrag_local_out_ops = {
279         .hook           = ip_conntrack_defrag,
280         .owner          = THIS_MODULE,
281         .pf             = PF_INET,
282         .hooknum        = NF_IP_LOCAL_OUT,
283         .priority       = NF_IP_PRI_CONNTRACK_DEFRAG,
284 };
285
286 static struct nf_hook_ops ip_conntrack_local_out_ops = {
287         .hook           = ip_conntrack_local,
288         .owner          = THIS_MODULE,
289         .pf             = PF_INET,
290         .hooknum        = NF_IP_LOCAL_OUT,
291         .priority       = NF_IP_PRI_CONNTRACK,
292 };
293
294 /* Refragmenter; last chance. */
295 static struct nf_hook_ops ip_conntrack_out_ops = {
296         .hook           = ip_refrag,
297         .owner          = THIS_MODULE,
298         .pf             = PF_INET,
299         .hooknum        = NF_IP_POST_ROUTING,
300         .priority       = NF_IP_PRI_LAST,
301 };
302
303 static struct nf_hook_ops ip_conntrack_local_in_ops = {
304         .hook           = ip_confirm,
305         .owner          = THIS_MODULE,
306         .pf             = PF_INET,
307         .hooknum        = NF_IP_LOCAL_IN,
308         .priority       = NF_IP_PRI_LAST-1,
309 };
310
311 /* Sysctl support */
312
313 #ifdef CONFIG_SYSCTL
314
315 /* From ip_conntrack_core.c */
316 extern int ip_conntrack_max;
317 extern unsigned int ip_conntrack_htable_size;
318
319 /* From ip_conntrack_proto_tcp.c */
320 extern unsigned long ip_ct_tcp_timeout_syn_sent;
321 extern unsigned long ip_ct_tcp_timeout_syn_recv;
322 extern unsigned long ip_ct_tcp_timeout_established;
323 extern unsigned long ip_ct_tcp_timeout_fin_wait;
324 extern unsigned long ip_ct_tcp_timeout_close_wait;
325 extern unsigned long ip_ct_tcp_timeout_last_ack;
326 extern unsigned long ip_ct_tcp_timeout_time_wait;
327 extern unsigned long ip_ct_tcp_timeout_close;
328
329 /* From ip_conntrack_proto_udp.c */
330 extern unsigned long ip_ct_udp_timeout;
331 extern unsigned long ip_ct_udp_timeout_stream;
332
333 /* From ip_conntrack_proto_icmp.c */
334 extern unsigned long ip_ct_icmp_timeout;
335
336 /* From ip_conntrack_proto_icmp.c */
337 extern unsigned long ip_ct_generic_timeout;
338
339 static struct ctl_table_header *ip_ct_sysctl_header;
340
341 static ctl_table ip_ct_sysctl_table[] = {
342         {
343                 .ctl_name       = NET_IPV4_NF_CONNTRACK_MAX,
344                 .procname       = "ip_conntrack_max",
345                 .data           = &ip_conntrack_max,
346                 .maxlen         = sizeof(int),
347                 .mode           = 0644,
348                 .proc_handler   = &proc_dointvec,
349         },
350         {
351                 .ctl_name       = NET_IPV4_NF_CONNTRACK_BUCKETS,
352                 .procname       = "ip_conntrack_buckets",
353                 .data           = &ip_conntrack_htable_size,
354                 .maxlen         = sizeof(unsigned int),
355                 .mode           = 0444,
356                 .proc_handler   = &proc_dointvec,
357         },
358         {
359                 .ctl_name       = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT,
360                 .procname       = "ip_conntrack_tcp_timeout_syn_sent",
361                 .data           = &ip_ct_tcp_timeout_syn_sent,
362                 .maxlen         = sizeof(unsigned int),
363                 .mode           = 0644,
364                 .proc_handler   = &proc_dointvec_jiffies,
365         },
366         {
367                 .ctl_name       = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_RECV,
368                 .procname       = "ip_conntrack_tcp_timeout_syn_recv",
369                 .data           = &ip_ct_tcp_timeout_syn_recv,
370                 .maxlen         = sizeof(unsigned int),
371                 .mode           = 0644,
372                 .proc_handler   = &proc_dointvec_jiffies,
373         },
374         {
375                 .ctl_name       = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED,
376                 .procname       = "ip_conntrack_tcp_timeout_established",
377                 .data           = &ip_ct_tcp_timeout_established,
378                 .maxlen         = sizeof(unsigned int),
379                 .mode           = 0644,
380                 .proc_handler   = &proc_dointvec_jiffies,
381         },
382         {
383                 .ctl_name       = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_FIN_WAIT,
384                 .procname       = "ip_conntrack_tcp_timeout_fin_wait",
385                 .data           = &ip_ct_tcp_timeout_fin_wait,
386                 .maxlen         = sizeof(unsigned int),
387                 .mode           = 0644,
388                 .proc_handler   = &proc_dointvec_jiffies,
389         },
390         {
391                 .ctl_name       = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE_WAIT,
392                 .procname       = "ip_conntrack_tcp_timeout_close_wait",
393                 .data           = &ip_ct_tcp_timeout_close_wait,
394                 .maxlen         = sizeof(unsigned int),
395                 .mode           = 0644,
396                 .proc_handler   = &proc_dointvec_jiffies,
397         },
398         {
399                 .ctl_name       = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_LAST_ACK,
400                 .procname       = "ip_conntrack_tcp_timeout_last_ack",
401                 .data           = &ip_ct_tcp_timeout_last_ack,
402                 .maxlen         = sizeof(unsigned int),
403                 .mode           = 0644,
404                 .proc_handler   = &proc_dointvec_jiffies,
405         },
406         {
407                 .ctl_name       = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_TIME_WAIT,
408                 .procname       = "ip_conntrack_tcp_timeout_time_wait",
409                 .data           = &ip_ct_tcp_timeout_time_wait,
410                 .maxlen         = sizeof(unsigned int),
411                 .mode           = 0644,
412                 .proc_handler   = &proc_dointvec_jiffies,
413         },
414         {
415                 .ctl_name       = NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE,
416                 .procname       = "ip_conntrack_tcp_timeout_close",
417                 .data           = &ip_ct_tcp_timeout_close,
418                 .maxlen         = sizeof(unsigned int),
419                 .mode           = 0644,
420                 .proc_handler   = &proc_dointvec_jiffies,
421         },
422         {
423                 .ctl_name       = NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT,
424                 .procname       = "ip_conntrack_udp_timeout",
425                 .data           = &ip_ct_udp_timeout,
426                 .maxlen         = sizeof(unsigned int),
427                 .mode           = 0644,
428                 .proc_handler   = &proc_dointvec_jiffies,
429         },
430         {
431                 .ctl_name       = NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT_STREAM,
432                 .procname       = "ip_conntrack_udp_timeout_stream",
433                 .data           = &ip_ct_udp_timeout_stream,
434                 .maxlen         = sizeof(unsigned int),
435                 .mode           = 0644,
436                 .proc_handler   = &proc_dointvec_jiffies,
437         },
438         {
439                 .ctl_name       = NET_IPV4_NF_CONNTRACK_ICMP_TIMEOUT,
440                 .procname       = "ip_conntrack_icmp_timeout",
441                 .data           = &ip_ct_icmp_timeout,
442                 .maxlen         = sizeof(unsigned int),
443                 .mode           = 0644,
444                 .proc_handler   = &proc_dointvec_jiffies,
445         },
446         {
447                 .ctl_name       = NET_IPV4_NF_CONNTRACK_GENERIC_TIMEOUT,
448                 .procname       = "ip_conntrack_generic_timeout",
449                 .data           = &ip_ct_generic_timeout,
450                 .maxlen         = sizeof(unsigned int),
451                 .mode           = 0644,
452                 .proc_handler   = &proc_dointvec_jiffies,
453         },
454         { .ctl_name = 0 }
455 };
456
457 #define NET_IP_CONNTRACK_MAX 2089
458
459 static ctl_table ip_ct_netfilter_table[] = {
460         {
461                 .ctl_name       = NET_IPV4_NETFILTER,
462                 .procname       = "netfilter",
463                 .mode           = 0555,
464                 .child          = ip_ct_sysctl_table,
465         },
466         {
467                 .ctl_name       = NET_IP_CONNTRACK_MAX,
468                 .procname       = "ip_conntrack_max",
469                 .data           = &ip_conntrack_max,
470                 .maxlen         = sizeof(int),
471                 .mode           = 0644,
472                 .proc_handler   = &proc_dointvec
473         },
474         { .ctl_name = 0 }
475 };
476
477 static ctl_table ip_ct_ipv4_table[] = {
478         {
479                 .ctl_name       = NET_IPV4,
480                 .procname       = "ipv4",
481                 .mode           = 0555,
482                 .child          = ip_ct_netfilter_table,
483         },
484         { .ctl_name = 0 }
485 };
486
487 static ctl_table ip_ct_net_table[] = {
488         {
489                 .ctl_name       = CTL_NET,
490                 .procname       = "net",
491                 .mode           = 0555, 
492                 .child          = ip_ct_ipv4_table,
493         },
494         { .ctl_name = 0 }
495 };
496 #endif
497 static int init_or_cleanup(int init)
498 {
499         struct proc_dir_entry *proc;
500         int ret = 0;
501
502         if (!init) goto cleanup;
503
504         ret = ip_conntrack_init();
505         if (ret < 0)
506                 goto cleanup_nothing;
507
508         proc = proc_net_create("ip_conntrack", 0440, list_conntracks);
509         if (!proc) goto cleanup_init;
510         proc->owner = THIS_MODULE;
511
512         ret = nf_register_hook(&ip_conntrack_defrag_ops);
513         if (ret < 0) {
514                 printk("ip_conntrack: can't register pre-routing defrag hook.\n");
515                 goto cleanup_proc;
516         }
517         ret = nf_register_hook(&ip_conntrack_defrag_local_out_ops);
518         if (ret < 0) {
519                 printk("ip_conntrack: can't register local_out defrag hook.\n");
520                 goto cleanup_defragops;
521         }
522         ret = nf_register_hook(&ip_conntrack_in_ops);
523         if (ret < 0) {
524                 printk("ip_conntrack: can't register pre-routing hook.\n");
525                 goto cleanup_defraglocalops;
526         }
527         ret = nf_register_hook(&ip_conntrack_local_out_ops);
528         if (ret < 0) {
529                 printk("ip_conntrack: can't register local out hook.\n");
530                 goto cleanup_inops;
531         }
532         ret = nf_register_hook(&ip_conntrack_out_ops);
533         if (ret < 0) {
534                 printk("ip_conntrack: can't register post-routing hook.\n");
535                 goto cleanup_inandlocalops;
536         }
537         ret = nf_register_hook(&ip_conntrack_local_in_ops);
538         if (ret < 0) {
539                 printk("ip_conntrack: can't register local in hook.\n");
540                 goto cleanup_inoutandlocalops;
541         }
542 #ifdef CONFIG_SYSCTL
543         ip_ct_sysctl_header = register_sysctl_table(ip_ct_net_table, 0);
544         if (ip_ct_sysctl_header == NULL) {
545                 printk("ip_conntrack: can't register to sysctl.\n");
546                 goto cleanup;
547         }
548 #endif
549
550         return ret;
551
552  cleanup:
553 #ifdef CONFIG_SYSCTL
554         unregister_sysctl_table(ip_ct_sysctl_header);
555 #endif
556         nf_unregister_hook(&ip_conntrack_local_in_ops);
557  cleanup_inoutandlocalops:
558         nf_unregister_hook(&ip_conntrack_out_ops);
559  cleanup_inandlocalops:
560         nf_unregister_hook(&ip_conntrack_local_out_ops);
561  cleanup_inops:
562         nf_unregister_hook(&ip_conntrack_in_ops);
563  cleanup_defraglocalops:
564         nf_unregister_hook(&ip_conntrack_defrag_local_out_ops);
565  cleanup_defragops:
566         nf_unregister_hook(&ip_conntrack_defrag_ops);
567  cleanup_proc:
568         proc_net_remove("ip_conntrack");
569  cleanup_init:
570         ip_conntrack_cleanup();
571  cleanup_nothing:
572         return ret;
573 }
574
575 /* FIXME: Allow NULL functions and sub in pointers to generic for
576    them. --RR */
577 int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto)
578 {
579         int ret = 0;
580         struct list_head *i;
581
582         WRITE_LOCK(&ip_conntrack_lock);
583         list_for_each(i, &protocol_list) {
584                 if (((struct ip_conntrack_protocol *)i)->proto
585                     == proto->proto) {
586                         ret = -EBUSY;
587                         goto out;
588                 }
589         }
590
591         list_prepend(&protocol_list, proto);
592
593  out:
594         WRITE_UNLOCK(&ip_conntrack_lock);
595         return ret;
596 }
597
598 void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto)
599 {
600         WRITE_LOCK(&ip_conntrack_lock);
601
602         /* ip_ct_find_proto() returns proto_generic in case there is no protocol 
603          * helper. So this should be enough - HW */
604         LIST_DELETE(&protocol_list, proto);
605         WRITE_UNLOCK(&ip_conntrack_lock);
606         
607         /* Somebody could be still looking at the proto in bh. */
608         synchronize_net();
609
610         /* Remove all contrack entries for this protocol */
611         ip_ct_selective_cleanup(kill_proto, &proto->proto);
612 }
613
614 static int __init init(void)
615 {
616         return init_or_cleanup(1);
617 }
618
619 static void __exit fini(void)
620 {
621         init_or_cleanup(0);
622 }
623
624 module_init(init);
625 module_exit(fini);
626
627 /* Some modules need us, but don't depend directly on any symbol.
628    They should call this. */
629 void need_ip_conntrack(void)
630 {
631 }
632
633 EXPORT_SYMBOL(ip_conntrack_protocol_register);
634 EXPORT_SYMBOL(ip_conntrack_protocol_unregister);
635 EXPORT_SYMBOL(invert_tuplepr);
636 EXPORT_SYMBOL(ip_conntrack_alter_reply);
637 EXPORT_SYMBOL(ip_conntrack_destroyed);
638 EXPORT_SYMBOL(ip_conntrack_get);
639 EXPORT_SYMBOL(need_ip_conntrack);
640 EXPORT_SYMBOL(ip_conntrack_helper_register);
641 EXPORT_SYMBOL(ip_conntrack_helper_unregister);
642 EXPORT_SYMBOL(ip_ct_selective_cleanup);
643 EXPORT_SYMBOL(ip_ct_refresh);
644 EXPORT_SYMBOL(ip_ct_find_proto);
645 EXPORT_SYMBOL(__ip_ct_find_proto);
646 EXPORT_SYMBOL(ip_ct_find_helper);
647 EXPORT_SYMBOL(ip_conntrack_expect_alloc);
648 EXPORT_SYMBOL(ip_conntrack_expect_related);
649 EXPORT_SYMBOL(ip_conntrack_change_expect);
650 EXPORT_SYMBOL(ip_conntrack_unexpect_related);
651 EXPORT_SYMBOL_GPL(ip_conntrack_expect_find_get);
652 EXPORT_SYMBOL_GPL(ip_conntrack_expect_put);
653 EXPORT_SYMBOL(ip_conntrack_tuple_taken);
654 EXPORT_SYMBOL(ip_ct_gather_frags);
655 EXPORT_SYMBOL(ip_conntrack_htable_size);
656 EXPORT_SYMBOL(ip_conntrack_expect_list);
657 EXPORT_SYMBOL(ip_conntrack_lock);
658 EXPORT_SYMBOL(ip_conntrack_hash);
659 EXPORT_SYMBOL(ip_conntrack_untracked);
660 EXPORT_SYMBOL_GPL(ip_conntrack_find_get);
661 EXPORT_SYMBOL_GPL(ip_conntrack_put);