最后一要注意的问题,就是对于每一条连接,寻找链表在hash表的入口,也就是如计算hash值。我们关心的是一条连接,连接是由“请求”和“应答”的数据包组成,数据包会被转化成tuple,所以,hash值就是根据tuple,通过一定的hash算法实现,这样,整个hash表如下图所示:
如图,小结一下:
n 整个hash表用ip_conntrack_hash指针数组来描述,它包含了ip_conntrack_htable_size个元素,用户态可以在模块插入时传递,默认是根据内存大小计算出来的;
n 整个连接跟踪表的大小使用全局变量ip_conntrack_max描述,与hash表的关系是ip_conntrack_max=8*ip_conntrack_htable_size;
n hash链表的每一个节点是一个structip_conntrack_tuple_hash结构,它有两个成员,一个是list,一个是tuple;
n Netfilter将每一个数据包转换成tuple,再根据tuple计算出hash值,这样,就可以使用ip_conntrack_hash[hash_id]找到hash表中链表的入口,并组织链表;
n 找到hash表中链表入口后,如果链表中不存在此“tuple”,则是一个新连接,就把tuple插入到链表的合适位置;
n 图中两个节点tuple[ORIGINAL]和tuple[REPLY],虽然是分开的,在两个链表当中,但是如前所述,它们同时又被封装在ip_conntrack结构的tuplehash数组中,这在图中,并没有标注出来;
n 链表的组织采用的是双向链表,上图中没有完整表示出来;
当然,具体的实现要稍微麻烦一点,主要体现在一些复杂的应用层协议上来,例如主动模式下的FTP协议,服务器在连接建立后,会主动打开高端口与客户端进行通讯,这样,由于端口变换了,我们前面说的连接表的实现就会遇到麻烦。Netfilter为这些协议提供了一个巧秒的解决办法,我们在本章中,先分析连接跟踪的基本实现,然后再来分析Netfilter对这些特殊的协议的支持的实现。netfilter
[color=Red]3.连接跟踪的初始化[/color]
3.1初始化函数
ip_conntrack_standalone.c是连接跟踪的主要模块:
static int __init init(void)
{
return init_or_cleanup(1);
}
初始化函数进一步调用init_or_cleanup()进行模块的初始化,它主要完成hash表的初始化等三个方面的工作:
static int init_or_cleanup(int init)
{
/*初始化连接跟踪的一些变量、数据结构,如初始化连接跟踪表的大小,Hash表的大小等*/
ret = ip_conntrack_init();
if (ret < 0)
goto cleanup_nothing;
/*创建proc 文件系统的对应节点*/
#ifdef CONFIG_PROC_FS
……
#endif
/*为连接跟踪注册Hook */
ret = nf_register_hook(&ip_conntrack_defrag_ops);
if (ret < 0) {
printk("ip_conntrack: can't register pre-routing defrag hook.\n");
goto cleanup_proc_stat;
}
……
}
本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-31885-3.html
哦对了