| 
          int __init ip_conntrack_init(void){
 unsigned int i;
 int ret;
 
 /* Idea from tcp.c: use 1/16384 of memory. On i386: 32MB
 * machine has 256 buckets. >= 1GB machines have 8192 buckets. */
 if (!ip_conntrack_htable_size) {
 ip_conntrack_htable_size
 = (((num_physpages << PAGE_SHIFT) / 16384)
 / sizeof(struct list_head));
 if (num_physpages > (1024 * 1024 * 1024 / PAGE_SIZE))
 ip_conntrack_htable_size = 8192;
 if (ip_conntrack_htable_size < 16)
 ip_conntrack_htable_size = 16;
 }
 ip_conntrack_max = 8 * ip_conntrack_htable_size;
 
 printk("ip_conntrack version %s (%u buckets, %d max)"
 " - %Zd bytes per conntrack\n", IP_CONNTRACK_VERSION,
 ip_conntrack_htable_size, ip_conntrack_max,
 sizeof(struct ip_conntrack));
 
 ret = nf_register_sockopt(&so_getorigdst);
 if (ret != 0) {
 printk(KERN_ERR "Unable to register netfilter socket option\n");
 return ret;
 }
 
 ip_conntrack_hash = alloc_hashtable(ip_conntrack_htable_size,
 &ip_conntrack_vmalloc);
 if (!ip_conntrack_hash) {
 printk(KERN_ERR "Unable to create ip_conntrack_hash\n");
 goto err_unreg_sockopt;
 }
 ip_conntrack_cachep = kmem_cache_create("ip_conntrack",
 sizeof(struct ip_conntrack), 0,
 0, NULL, NULL);
 if (!ip_conntrack_cachep) {
 printk(KERN_ERR "Unable to create ip_conntrack slab cache\n");
 goto err_free_hash;
 }
 
 ip_conntrack_expect_cachep = kmem_cache_create("ip_conntrack_expect",
 sizeof(struct ip_conntrack_expect),
 0, 0, NULL, NULL);
 if (!ip_conntrack_expect_cachep) {
 printk(KERN_ERR "Unable to create ip_expect slab cache\n");
 goto err_free_conntrack_slab;
 }
 
 /* Don't NEED lock here, but good form anyway. */
 write_lock_bh(&ip_conntrack_lock);
 for (i = 0; i < MAX_IP_CT_PROTO; i++)
 rcu_assign_pointer(ip_ct_protos[i], &ip_conntrack_generic_protocol);
 /* Sew in builtin protocols. */
 rcu_assign_pointer(ip_ct_protos[IPPROTO_TCP], &ip_conntrack_protocol_tcp);
 rcu_assign_pointer(ip_ct_protos[IPPROTO_UDP], &ip_conntrack_protocol_udp);
 rcu_assign_pointer(ip_ct_protos[IPPROTO_ICMP], &ip_conntrack_protocol_icmp);
 write_unlock_bh(&ip_conntrack_lock);
 
 /* For use by ipt_REJECT */
 rcu_assign_pointer(ip_ct_attach, ip_conntrack_attach);
 
 /* Set up fake conntrack:
 - to never be deleted, not in any hashes */
 atomic_set(&ip_conntrack_untracked.ct_general.use, 1);
 /* - and look it like as a confirmed connection */
 set_bit(IPS_CONFIRMED_BIT, &ip_conntrack_untracked.status);
 
 return ret;
 
 err_free_conntrack_slab:
 kmem_cache_destroy(ip_conntrack_cachep);
 err_free_hash:
 free_conntrack_hash(ip_conntrack_hash, ip_conntrack_vmalloc,
 ip_conntrack_htable_size);
 err_unreg_sockopt:
 nf_unregister_sockopt(&so_getorigdst);
 
 return -ENOMEM;
 }
 
 |