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

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

1ip_conntrack_defrag:

通常当IP报文被送至L4层处理时,如果该报文是分片报文,那么报文就会先被保存起来,直到所有分片到达后重组成一个完整报文后,再被分发到L4层。当没有启动conntrack时,netfilterHOOK点对报文操作时,并不检查该报文是否分片;但是如果启动conntrack功能,则必须保证进入netfilter HOOK点的报文是一个完整的报文,因此ip_conntrack_defrag一般处于最前端的HOOK,负责将分片报文重组。

/* 若报文分片,则 调用ip_ct_gather_frags 组装报文,如果所有分片均已到达,pskb指向新生成的报文,继续沿着HOOK链进行下一步处理;否则为空,报文被缓存等待下一分片到来*/

if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {

     *pskb = ip_ct_gather_frags(*pskb,

                                hooknum == NF_IP_PRE_ROUTING ?

                      IP_DEFRAG_CONNTRACK_IN :

                      IP_DEFRAG_CONNTRACK_OUT);

     if (!*pskb)

          return NF_STOLEN;

}

return NF_ACCEPT;

ip_ct_gather_frags直接调用ip_defrag处理IP分片报文。对于分片报文的重组主要在ip_fragment.c中完成。

 

 

3, resolve_normal_ct

   resolve_normal_ct在全局连接表中,查找与该报文相应的连接状态,返回的是ip_conntrack的指针,用于描述和记录连接的状态;若该连接尚不存在,则创建相应的结构,并进行初始化,设置连接状态。

   /*1,将数据包的内容转化成相应的tuple,对于和协议相关的部分,如端口,则调用相关协议的处理函数pkt_to_tuple*/

      if (!ip_ct_get_tuple(skb->nh.iph, skb, skb->nh.iph->ihl*4,

                   &tuple,proto))

         return NULL;

   /*2,在全局连接表中查找和tuple相同的hash项,全局连接表以tuple计算出相应的hash值,每一个hash项所保存的元素也是相应的tuple*/

      h = ip_conntrack_find_get(&tuple, NULL);

   /*3,若在全局连接表中无法查到tuple所对应的hash项,即相应的连接状态不存在,系统调用init_conntrack创建并初始化ip_conntrack,并返回其相应的tuple结构指针*/

      if (!h) {

         h = init_conntrack(&tuple, proto, skb);

         if (!h)

              return NULL;

         if (IS_ERR(h))

              return (void *)h;

     }

   /*4,根据全局连接表所获得tuple,获取其对应的ip_conntrack结构*/

      ct = tuplehash_to_ctrack(h);

   /*5,判断连接方向,若是reply方向,设置相应的应答标识和数据包状态标识*/

      if (DIRECTION(h) == IP_CT_DIR_REPLY) {

         *ctinfo = IP_CT_ESTABLISHED + IP_CT_IS_REPLY;

         /* Please set reply bit if this packet OK */

         *set_reply = 1;

     } else {

   /*6, 若是origin方向,根据ip_conntrack中的status,设置相应的应答标识和数据包状态标识*/

         /* Once we've had two way comms, always ESTABLISHED. */

         if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {

              DEBUGP("ip_conntrack_in: normal packet for %p/n",

                     ct);

                 *ctinfo = IP_CT_ESTABLISHED;

         } else if (test_bit(IPS_EXPECTED_BIT, &ct->status)) {

              DEBUGP("ip_conntrack_in: related packet for %p/n",

                     ct);

              *ctinfo = IP_CT_RELATED;

         } else {

              DEBUGP("ip_conntrack_in: new packet for %p/n",

                     ct);

              *ctinfo = IP_CT_NEW;

         }

         *set_reply = 0;

     }

   /*7, 设置skb的对应成员,数据包对应的连接状态结构和数据包连接状态标记*/

      skb->nfct = &ct->ct_general;

     skb->nfctinfo = *ctinfo;