Chinaunix首页 | 论坛 | 博客
  • 博客访问: 457393
  • 博文数量: 64
  • 博客积分: 3271
  • 博客等级: 中校
  • 技术积分: 727
  • 用 户 组: 普通用户
  • 注册时间: 2009-07-30 18:42
文章分类

全部博文(64)

文章存档

2013年(1)

2011年(19)

2010年(42)

2009年(2)

分类: LINUX

2010-04-17 14:08:24

@auther

 

                       nat源码追踪

.第一个数据包

1)到达PREROUTING

nf_conntrack_in

ct->[].

                   src:C_L:xx

                   dst:G_W:80

ct->[].

                 src: G_W:80

                 dst: C_L:xx

同时*ctinfo 设置为new

==========nf_conntrack_in调用结束。

 

然后进入nf_nat_in

nf_nat_in

调用

    ret = (, , , , );

maniptype=

因为case :

    所以调用 ret = (, , , , ct);

再由ret = (, , , , ->.);执行target.会执行

进而:

return (ct, &mr->[0], );

之后

    int = !(ct-> & );

1

之后调用:

    (&curr_tuple,

                                        &ct->[].);

取出         curr_tuple:

                   src:C_L:xx

                   dst:G_W:80

 

 

之后进入:

    (&, &curr_tuple, , ct, );

  此函数中,执行:

    /* 2) Select the least-used / combination in the given

       range. */

    * = *;

    (, , ct, );

用于在range中选择一个最少使用的ip由于maintype=DST,所以

= &->..;

最后* = ->;完成对dst.u3.ip的改变。

find_best返回后,new_tuple=        

                        src:C_L:xx

                        dst:S_L:80

 

;回到后,会执行:

    if (!(&, &curr_tuple)) {

                    struct ;

                    /* Alter conntrack table so will recognize replies. */

                    (&reply, &);

                    (ct, &reply);

                    /* Non-atomic: we own this at the moment. */

                    if ( == )

                                   ct-> |= ;

                    else

                                   ct-> |= ;

    }

因为new_tupleget_unique_tuple中已然改变,所以会进入if分支。invert之后,reply.dir=REPLY 

然后进入(ct, &reply)会执行:

ct->[]. = *;

reply=

      src:S_L:80

      dst:C_L:xx

 

   注意,这个reply是在做了DNAT而没有做NAT的期望reply..

到此:

ct->tuplehash[IP_CT_DIR_ORIGNAL].tuple=

                                         src:C_L:xx

                                                                   dst:G_W:80

ct->tuplehash[IP_CT_DIR_REPLY].tuple=

                                   src:S_L:80

                                   dst:C_L:xx

之后由于have_to_hash1,所以,进入

    /* Place in source hash if this is the first time. */

    if () {

                    unsigned int ;

                    = (&ct->[].);

                    (&);

                    /* nf_conntrack_alter_reply might re-allocate exntension aera */

                    nat = (ct);

                    nat->ct = ct;

                    hlist_add_head_rcu(&nat->,

                                                     &net->.[]);

                    (&);

    }

对源地址端口进行hash,然后添加到net->ipv4.nat_bysource.

然后执行:

    if ( == )

                    (, &ct->);

至此完成对tuplednat,并且设置了ct->status。并且设置了

 

然后一层层返回到nf_nat_fn进入

                return (ct, ctinfo, , );

这个函数的主要目的就是把数据改变写到skb里面。

先找出dir,mtype

    enum = ();

    unsigned long ;

    enum = ();

当然,dir=ORIGNAL,mtype=DST.所以:

                    statusbit = ;

所以进入:

if (ct-> & statusbit) {

                    struct ;

                    /* We are aiming to look like inverse of other direction. */

                   (&target, &ct->[!dir].);

                    if (!(target.., , 0, &target, ))

                                   return ;

    }

 

ct->[!dir].进行invert,dir=ORIG,

 target =invert(ct->tuplehash[REPLY].tuple)=

                                         src:C_L:xx

                                                                   dst:S_L:80

然后又:

                    -> = target->..;

    }

进入else分支:

 ip的目标地址换成了target->dst.u3.ipS_L

于是数据包的目标地址,目标ip都替换;内容如下:

                                     src:C_L:xx

                                                               dst:S_L:80

 

小结:

      ctinfo  

      ct->status  , ,

      ct->tuplehash[IP_CT_DIR_ORIGNAL].tuple=

                                        src:C_L:xx

                                         dst:G_W:80

      ct->tuplehash[IP_CT_DIR_REPLY].tuple=

                                      src:S_L:80

                                     dst:C_L:xx

 

hlist_add_head_rcu(&nat->, &net->.[]);

 

 

2)去往G_L

  由于目的地址为S_L:80,所以当数据包传递给上层时,会被路由到G_L所在端口。

然后进入挂钩点:

,

于图1.进入,,再进入,

 

 

nf_nat_out:

 

同样进入:

ret = (, , , , );

于是:

enum = ();

0,maniptype=,

同样,由于连接状态没有改变:

               case : 现样由于src未曾初始化,所以进入:

                                                  ret = (, , , , ct);

进入ret = (, , , , ->.);

进而调用SNATtarget;

进入
               return (ct, &mr->[0], );
 

然后进入了nf_nat_setup_info;

    int = !(ct-> & );

由于之前设置了,所以

得到have_to_hash=0;

    (&curr_tuple,

                                        &ct->[].);

curr_tuple=:

           src: C_L:xx

           dst: S_L:80

然后:

                (&, &curr_tuple, , ct, );

----- -- - >

进而调用:

    (, , ct, );

    if ( == )

                    = &->..;

     * = ->;

 range->minip=G_W;

执行之后

 new_tuple:

        src:G_W:xx

        dst:S_L:80

 

所以,回到中,

if (!(&, &curr_tuple)) {
               struct  ;
               /* Alter conntrack table so will recognize replies. */
               (&reply, &);
               (ct, &reply);
               /* Non-atomic: we own this at the moment. */
               if ( == )
                       ct-> |= ;
               else
                       ct-> |= ;
       }

 

reply=:

   src:S_L:80

   dst:G_W:xx

设置ct-> |= ;表示这个为SNAT

最后

                    (, &ct->);

回到nf_nat_fn  进入

    return (ct, ctinfo, , );

    enum = ();

     enum = ();

dirORIG,mtypeSRC

所以:

    if ( == )

                    statusbit = ;

ct->status设置了

进入执行,替换数据包的源。 & statusbit)

然后结束执行。

钩子执行完毕。

于是进入

 

ipv4_confirm

 

调用

return ();

     if ( && != &) {

                     if (!() && !())

                                    = ();

然后,在__nf_conntrack_confirm中:

    hlist_nulls_del_rcu(&ct->[].);

    hash = (&ct->[].);

    repl_hash = (&ct->[].);

 

    (ct, hash, repl_hash);

skb中保存的ct->tuplehash分别添加到net->ct.hash,完成confirmed;

    (, &ct->);

小结:

      ctinfo  

      ct->status  , , 

      ct->tuplehash[IP_CT_DIR_ORIGNAL].tuple=

                                        src:C_L:xx

                                                                   dst:G_W:80

      ct->tuplehash[IP_CT_DIR_REPLY].tuple=

                                        src:S_L:80

                                                                  dst:G_W:xx

阅读(1873) | 评论(0) | 转发(0) |
0

上一篇:SNAT。。

下一篇:bridge源码流程

给主人留下些什么吧!~~