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

来源:互联网 发布:数据库什么是存储过程 编辑:程序博客网 时间:2024/06/16 19:42
2008-07-07 22:09

3,init_conntrack

init_conntrack用于创建一个新的ip_conntrack,并对其进行初始化。

/*1,每一个连接包含两个tupleoriginalreplyip_ct_invert_tuple 根据传入的original tuple获取其reply tuple,其最终将调用所属协议的invert_tuple 完成处理*/

   if (!ip_ct_invert_tuple(&repl_tuple, tuple, protocol)) {

     DEBUGP("Can't invert tuple./n");

     return NULL;

}

/*2,cache中为conntrack分配内存,并进行通用的初始化,如初始化tuplehashtimeout和ct_general;如果当前连接数已达上限,则调用early_drop释放tuple所在hash链上的未应答项*/

   conntrack = ip_conntrack_alloc(tuple, &repl_tuple);

/*3,调用所属协议的new函数,根据报文数据,初始化conntrack,和协议相关的私有处理,将放到对具体协议tcp分析时讨论*/

   if (!protocol->new(conntrack, skb)) {

     ip_conntrack_free(conntrack);

     return NULL;

}

/*4,expecthelper均和动态协议相关,将在分析ftp协议时做重点介绍*/

   exp = find_expectation(tuple);

if (exp) {

    

} else {

     conntrack->helper = __ip_conntrack_helper_find(&repl_tuple);

     CONNTRACK_STAT_INC(new);

}

write_unlock_bh(&ip_conntrack_lock);

if (exp) {

    

}

/*5,original tuple放到unconfirmed链上??*/   list_add(&conntrack->tuplehash[IP_CT_DIR_ORIGINAL].list, &unconfirmed);

 

4tuplehash_to_ctrack:

tuplehash_to_ctrack这个函数主要用来将全局连接表中获取的hashtuple转换成相应的ip_conntrack结构。它使用了container_of这个宏来完成处理的。container_of通过结构中某个成员的指针,来获取结构的指针。它的实现非常有趣:

/*1,将结构体强制在0地址展开,从而获取其member的偏移量*/

   #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

/*2,根据member的指针ptr,减去其相对偏移量,即获得了其宿主结构conntrack的指针*/

   #define container_of(ptr, type, member) ({            /

        const typeof( ((type *)0)->member ) *__mptr = (ptr); /

        (type *)( (char *)__mptr - offsetof(type,member) );})

5,TCP

Ip层可以承载多种协议,不同的协议,在建立相应连接的状态表时,所需的信息和对信息的处理也是不同的,以下我们将以tcp协议为例阐述具体协议的处理过程。

首先,在ip_conntrack_in的步骤3中,当我们确定了具体承载的协议后,需要调用相关的error函数,对报文的有效性进行验证,该函数为ip_conntrack_protocol_tcp.c中的tcp_error函数,该函数主要检查了tcp报文头的完整性,校验和的正确性以及flag的有效性。

ip_conntrack_in步骤4的处理过程中,首先通过ip_ct_get_tupleresolve_normal_ct step1)函数调用tcp_pkt_to_tuple将报文中的相关信息转化成一个tcp连接所需的tuple。之后根据这个tuple查找全局连接表,获取相应的状态表(resolve_normal_ct step2);对于新建连接则调用tcp_new建立并初始化状态表(init_conntrack)。FilterTcp的连接建立状态表的过程分为两类;一种filter知道连接的建立过程,它从连接的第一个syn报文开始,就记录连接的状态;另一种是filter不知道连接何时建立的,filter开始记录连接的状态时,连接早已建立成功,filter不知道连接的过去,例如filter发生重启,丢失了所有原有的连接状态信息。针对后一种情况,系统通过全局变量ip_ct_tcp_loose来确定是否支持,对此种情况后续章节会有专门的介绍。tcp_new针对此两种情况分别进行了设置。

ip_conntrack_in步骤5,最终调用tcp_packet对报文进行处理,并更新相应的连接状态。在这里最为重要的是通过tcp_in_window来判别报文的有效性。在介绍该函数之前,先来了解一些tcp filter的知识。

原创粉丝点击