【转帖LINUX】netfilter中的conntrack内核阅读笔记(2)

来源:互联网 发布:数据库什么是存储过程 编辑:程序博客网 时间:2024/06/16 17:28


2008-07-07 22:05
初始化

1,ip_conntrack_standalone_init是contrack模块的初始化函数。它主要完成以下内容:

   /*1, 初始化conntrack相关的数据结构,如hash表,ip_conntrack_protocol以及内存管理等*/

ret = ip_conntrack_init();

if (ret < 0)

     return ret;


#ifdef CONFIG_PROC_FS

/* 在/proc目录下创建"ip_conntrack","ip_conntrack_expect"记录连接跟踪信息*/

……

#endif

/*2,为conntrack注册hook点*/

ret = nf_register_hooks(ip_conntrack_ops, ARRAY_SIZE(ip_conntrack_ops));

if (ret < 0) {

     printk("ip_conntrack: can't register hooks./n");

     goto cleanup_proc_stat;

}

#ifdef CONFIG_SYSCTL

/*3,注册sysctrl的操作函数集*/

ip_ct_sysctl_header = register_sysctl_table(ip_ct_net_table, 0);

if (ip_ct_sysctl_header == NULL) {

     printk("ip_conntrack: can't register to sysctl./n");

     ret = -ENOMEM;

     goto cleanup_hooks;

}

#endif

2,ip_conntrack_init:

   /*1,完成hash的初始化,hash桶的大小为内存大小的1/16384 ,在i386中,若内存小于32M,hash桶为256个,若大于1G,桶为8196个。Hash表的大小为桶个数的8倍,用ip_conntrack_hash 指针表示*/

    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;

     …

     ip_conntrack_hash = alloc_hashtable(ip_conntrack_htable_size, &ip_conntrack_vmalloc);

     /*2, conntrack采用catche的内存管理方式*/

     ip_conntrack_cachep = kmem_cache_create("ip_conntrack",

                                             sizeof(struct ip_conntrack), 0,

                                             0, NULL, NULL);

     …

     ip_conntrack_expect_cachep = kmem_cache_create("ip_conntrack_expect",

                       sizeof(struct ip_conntrack_expect),

                       0, 0, NULL, NULL);

     …

/*3,初始化ip_ct_protos数组。conntrack对每种协议数据的处理,都有不同的地方,例如,tuple

中提取的内容,TCP的与ICMP的肯定不同的,因为ICMP连端口的概念也没有,所以,对于每种协议的一些特殊处理的函数,需要进行封装,struct ip_conntrack_protocol 结构就实现了这一封装。ip_ct_protos数组记录了个协议所需的私有数据,在初始化工作中,ip_ct_protos默认为ip_conntrack_generic_protoco,而对TCP、UDP和ICMP协议,定义了ip_conntrack_protocol_tcp、ip_conntrack_protocol_udp和ip_conntrack_protocol_icmp,封装至ip_ct_protos 数组。这样,在以后的数据包处理后,就可以根据包中的协议值,使用ip_ct_protos[协议值],找到注册的协议节点,调用协议对应的处理函数了*/

for (i = 0; i < MAX_IP_CT_PROTO; i++)

     ip_ct_protos[i] = &ip_conntrack_generic_protocol;

/* Sew in builtin protocols. */

ip_ct_protos[IPPROTO_TCP] = &ip_conntrack_protocol_tcp;

ip_ct_protos[IPPROTO_UDP] = &ip_conntrack_protocol_udp;

ip_ct_protos[IPPROTO_ICMP] = &ip_conntrack_protocol_icmp;

/*4,??用于ipt_REJECT,似乎和conntrack记录icmp以及TCP rst错误相关,具体需进一步研究*/

ip_ct_attach = ip_conntrack_attach


/*5,??*/

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);

 

原创粉丝点击