netfilternfconntrack模块实现分析.docx

上传人:b****6 文档编号:8888642 上传时间:2023-05-15 格式:DOCX 页数:46 大小:161.07KB
下载 相关 举报
netfilternfconntrack模块实现分析.docx_第1页
第1页 / 共46页
netfilternfconntrack模块实现分析.docx_第2页
第2页 / 共46页
netfilternfconntrack模块实现分析.docx_第3页
第3页 / 共46页
netfilternfconntrack模块实现分析.docx_第4页
第4页 / 共46页
netfilternfconntrack模块实现分析.docx_第5页
第5页 / 共46页
netfilternfconntrack模块实现分析.docx_第6页
第6页 / 共46页
netfilternfconntrack模块实现分析.docx_第7页
第7页 / 共46页
netfilternfconntrack模块实现分析.docx_第8页
第8页 / 共46页
netfilternfconntrack模块实现分析.docx_第9页
第9页 / 共46页
netfilternfconntrack模块实现分析.docx_第10页
第10页 / 共46页
netfilternfconntrack模块实现分析.docx_第11页
第11页 / 共46页
netfilternfconntrack模块实现分析.docx_第12页
第12页 / 共46页
netfilternfconntrack模块实现分析.docx_第13页
第13页 / 共46页
netfilternfconntrack模块实现分析.docx_第14页
第14页 / 共46页
netfilternfconntrack模块实现分析.docx_第15页
第15页 / 共46页
netfilternfconntrack模块实现分析.docx_第16页
第16页 / 共46页
netfilternfconntrack模块实现分析.docx_第17页
第17页 / 共46页
netfilternfconntrack模块实现分析.docx_第18页
第18页 / 共46页
netfilternfconntrack模块实现分析.docx_第19页
第19页 / 共46页
netfilternfconntrack模块实现分析.docx_第20页
第20页 / 共46页
亲,该文档总共46页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

netfilternfconntrack模块实现分析.docx

《netfilternfconntrack模块实现分析.docx》由会员分享,可在线阅读,更多相关《netfilternfconntrack模块实现分析.docx(46页珍藏版)》请在冰点文库上搜索。

netfilternfconntrack模块实现分析.docx

netfilternfconntrack模块实现分析

netfilter-nf-conntrack-模块实现分析

一.连接记录的存储

 

相关函数:

staticinlinestructnf_conn*nf_ct_tuplehash_to_ctrack(conststructnf_conntrack_tuple_hash*hash)

staticinlinestructnf_conn*nf_ct_get(conststructsk_buff*skb,enumip_conntrack_info*ctinfo)

 

nf_conntrack中tuple存储如上图所示。

在structnf_conntrack_tuple_hash中,成员hnode链接入ct->hash[]->first中的。

实际的记录在保存在structnf_conntrack_tuple中。

1.记录的访问:

hlist_nulls_for_each_entry_rcu

c:

\source\s?

defs=hlist_nulls_for_each_entry_rcu

103#definehlist_nulls_for_each_entry_rcu(tpos,pos,head,member)\

104for(pos=rcu_dereference((head)->first);\

105(!

is_a_nulls(pos))&&\

106({tpos=hlist_nulls_entry(pos,typeof(*tpos),member);1;});\

107pos=rcu_dereference(pos->next))

108

参见/net/netfilter/nf_conntrack_core.c__nf_conntrack_find函数;

structnf_conntrack_tuple_hash*h;

structhlist_nulls_node*n;

hlist_nulls_for_each_entry_rcu(h,n,&net->ct.hash[hash],hnnode)

2.记录的添加

84staticinlinevoidhlist_nulls_add_head_rcu(structhlist_nulls_node*n,

85structhlist_nulls_head*h)

86{

87structhlist_nulls_node*first=h->first;

88

89n->next=first;

90n->pprev=&h->first;

91rcu_assign_pointer(h->first,n);

92if(!

is_a_nulls(first))

93first->pprev=&n->next;

94}

参见/net/netfilter/nf_conntrack_core.c:

313staticvoid__nf_conntrack_hash_insert(structnf_conn*ct,

314unsignedinthash,

315unsignedintrepl_hash)

316{

317structnet*net=nf_ct_net(ct);

318

319hlist_nulls_add_head_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode,

320&net->ct.hash[hash]);

321hlist_nulls_add_head_rcu(&ct->tuplehash[IP_CT_DIR_REPLY].hnnode,

322&net->ct.hash[repl_hash]);

323}

3.记录的删除

59staticinlinevoidhlist_nulls_del_rcu(structhlist_nulls_node*n)

60{

61__hlist_nulls_del(n);

62n->pprev=LIST_POISON2;

63}

59staticinlinevoid__hlist_nulls_del(structhlist_nulls_node*n)

60{

61structhlist_nulls_node*next=n->next;

62structhlist_nulls_node**pprev=n->pprev;

63*pprev=next;

64if(!

is_a_nulls(next))

65next->pprev=pprev;

66}

二.nf_conntrack模块的初始化

/net/netfilter/nf_conntrack_standalone.c

510staticint__initnf_conntrack_standalone_init(void)

511{

512returnregister_pernet_subsys(&nf_conntrack_net_ops);

513}

 

473staticintnf_conntrack_net_init(structnet*net)

474{

475intret;

476

477ret=nf_conntrack_init(net);

478if(ret<0)

479gotoout_init;

480ret=nf_conntrack_standalone_init_proc(net);

481if(ret<0)

482gotoout_proc;

483net->ct.sysctl_checksum=1;

484net->ct.sysctl_log_invalid=0;

485ret=nf_conntrack_standalone_init_sysctl(net);

486if(ret<0)

487gotoout_sysctl;

488return0;

489

447-------:

/net/netfilter/nf_conntrack_core.c#nf_conntrack_init

1275intnf_conntrack_init(structnet*net)

1276{

1277intret;

1278

1279if(net_eq(net,&init_net)){

1280ret=nf_conntrack_init_init_net();

1281if(ret<0)

1282gotoout_init_net;

1283}

1284ret=nf_conntrack_init_net(net);

1285if(ret<0)

1286gotoout_net;

1287

1288if(net_eq(net,&init_net)){

1289/*ForusebyREJECTtarget*/

1290rcu_assign_pointer(ip_ct_attach,nf_conntrack_attach);

1291rcu_assign_pointer(nf_ct_destroy,destroy_conntrack);

1292}

1293return0;

1294

-----------------------/net/netfilter/nf_conntrack_core.c#nf_conntrack_init_net

 

1223staticintnf_conntrack_init_net(structnet*net)

1224{

1225intret;

1226

1227atomic_set(&net->ct.count,0);

1228INIT_HLIST_NULLS_HEAD(&net->ct.unconfirmed,0);

1229net->ct.stat=alloc_percpu(structip_conntrack_stat);

1234ret=nf_conntrack_ecache_init(net);

1237net->ct.hash=nf_ct_alloc_hashtable(&nf_conntrack_htable_size,

1238&net->ct.hash_vmalloc,1);

1244ret=nf_conntrack_expect_init(net);

1247ret=nf_conntrack_acct_init(net);

1253#ifdefCONFIG_NET_NS

1254nf_conntrack_untracked.ct_net=&init_net;

1255#endif

1256atomic_set(&nf_conntrack_untracked.ct_general.use,1);

1257/*-andlookitlikeasaconfirmedconnection*/

1258set_bit(IPS_CONFIRMED_BIT,&nf_conntrack_untracked.status);

1259

1260return0;

 

这个函数所做的主要工作就是初始化net中的net->ct中的成员。

初始化hash表大小,初始化expect链表大小,初始化acct扩展模块。

最后nf_conntrack_untracked.ct_net=&init_net,再设置它的status位为IPS_CONFIRMED_BIT;

三.conntrack的扩展

/include/net/netfilter/nf_conntrack_extend.h

     66 structnf_ct_ext_type

     67 {

     68 /*Destroysrelationships(canbeNULL).*/

     69 void(*destroy)(structnf_conn*ct);

     70 /*Calledwhenrealloacted(canbeNULL).

     71 Contentshasalreadybeenmoved.*/

     72 void(*move)(void*new,void*old);

     73 

     74 enumnf_ct_ext_idid;

     75 

     76 unsignedintflags;

     77 

     78 /*Lengthandminalignment.*/

     79 u8len;

     80 u8align;

     81 /*initialsizeofnf_ct_ext.*/

     82 u8alloc_size;

     83 };

 

目前conntrack扩展有acct,helper,nat三种。

它存储在*nf_ct_ext_types[NF_CT_EXT_NUM]全局数组中。

以nf_conntrack_acct为例:

/net/netfilter/nf_conntrack_acct.c

初始化

     59 staticstructnf_ct_ext_typeacct_extend__read_mostly={

     60 .len=sizeof(structnf_conn_counter[IP_CT_DIR_MAX]),

     61 .align=__alignof__(structnf_conn_counter[IP_CT_DIR_MAX]),获得对齐方式

     62 .id=NF_CT_EXT_ACCT,

     63 };

structnf_conn_counter为计数用:

     17 structnf_conn_counter{

     18 u_int64_tpackets;

     19 u_int64_tbytes;

     20 };

.len=sizeof(structnf_conn_counter[IP_CT_DIR_MAX]),代表为连接的两个方向都要分配,进行计数。

1.扩展的注册

/net/netfilter/nf_conntrack_acct.c

    110 intnf_conntrack_acct_init(structnet*net)

    111 {

    112 intret;

    113 

    114 net->ct.sysctl_acct=nf_ct_acct;

    115 

    116 if(net_eq(net,&init_net)){

    123 ret=nf_ct_extend_register(&acct_extend);

    124 if(ret<0){

    125 printk(KERN_ERR"nf_conntrack_acct:

Unabletoregisterextension\n");

    126 gotoout_extend_register;

    127 }

    128 }

    129 

    130 ret=nf_conntrack_acct_init_sysctl(net);

    131 if(ret<0)

    132 gotoout_sysctl;

    133 

    134 return0;

nf_conntrack_acct_init:

114:

     25 staticintnf_ct_acct__read_mostly=NF_CT_ACCT_DEFAULT;

nf_conntrack_acct_init:

123:

nf_ct_extend_register

/net/netfilter/nf_conntrack_extend.c

    159 /*ThisMUSTbecalledinprocesscontext.*/

    160 intnf_ct_extend_register(structnf_ct_ext_type*type)

    161 {

    162 intret=0;

    163 

    164 mutex_lock(&nf_ct_ext_type_mutex);

    165 if(nf_ct_ext_types[type->id]){

    166 ret=-EBUSY;

    167 gotoout;

    168 }

    169 

    170 /*Thisensuresthatnf_ct_ext_create()canallocateenougharea

    171 beforeupdatingalloc_size*/

    172 type->alloc_size=ALIGN(sizeof(structnf_ct_ext),type->align)

    173 +type->len;

    174 rcu_assign_pointer(nf_ct_ext_types[type->id],type);

    175 update_alloc_size(type);

    176 out:

    177 mutex_unlock(&nf_ct_ext_type_mutex);

    178 returnret;

    179 }

第172行对nf_ct_ext的size进行对齐,再加上type->len再赋值给type->alloc_size.即它的大小为2*nf_conn_counter+1*nf_ct_ext;然后再将type保存到nf_ext_types数组中。

对照

可以发现,structnf_ct_ext_type仅仅只是保存了structnf_ct_ext所必要的一些信息而已。

至于为何要对齐,是因为扩展不只是一种,它们的数组结构也不一样,对齐方式都不一样,所以得保存自己的对齐方式,再对齐。

2.添加一个acct扩展

nf_ct_acct_ext_add:

/include/net/netfilter/nf_conntrack_acct.h

     28 staticinline

     29 structnf_conn_counter*nf_ct_acct_ext_add(structnf_conn*ct,gfp_tgfp)

     30 {

     31 structnet*net=nf_ct_net(ct);

     32 structnf_conn_counter*acct;

     33 

     34 if(!

net->ct.sysctl_acct)

     35 returnNULL;

     36 

     37 acct=nf_ct_ext_add(ct,NF_CT_EXT_ACCT,gfp);

     38 if(!

acct)

     39 pr_debug("failedtoaddaccountingextensionarea");

     40 

     41 

     42 returnacct;

     43 };

/include/net/netfilter/nf_conntrack_extend.h#61

     61 #definenf_ct_ext_add(ct,id,gfp)\

     62 ((id##_TYPE*)__nf_ct_ext_add((ct),(id),(gfp)))

/net/netfilter/nf_conntrack_extend.c

函数会判断ct->ext是否为NULL,若为NULL则证明这是第一个,所以调用nf_ct_ext_create(),

它分配一个扩展的size并且返回它的起始地址;

对于扩展的管理是先来的放前面。

所以nf_ct_ext:

:

offset[id]会是添加id对应的扩展之前

nf_ct_ext的对齐后的连同以前添加的扩展数据在内的长度。

     45 staticvoid*

     46 nf_ct_ext_create(structnf_ct_ext**ext,enumnf_ct_ext_idid,gfp_tgfp)

     47 {

     48 unsignedintoff,len;

     49 structnf_ct_ext_type*t;

     50 

     51 rcu_read_lock();

     52 t=rcu_dereference(nf_ct_ext_types[id]);

     53 BUG_ON(t==NULL);

     54 off=ALIGN(sizeof(structnf_ct_ext),t->align);

     55 len=off+t->len;

     56 rcu_read_unlock();

     57 

     58 *ext=kzalloc(t->alloc_size,gfp);

     59 if(!

*ext)

     60 returnNULL;

     61 

     62 INIT_RCU_HEAD(&(*ext)->rcu);

     63 (*ext)->offset[id]=off;

     64 (*ext)->len=len;

     65 

     66 return(void*)(*ext)+off;

     67 }

3.查找一个扩展

/include/net/netfilter/nf_conntrack_extend.h#nf_ct_ext_find

     38 #definenf_ct_ext_find(ext,id)\

     39 ((id##_TYPE*)__nf_ct_ext_find((ext),(id)))

对于acct就强制转换成NF_CT_EXT_ACCT_TYPE

又:

     14 #defineNF_CT_EXT_HELPER_TYPEstructnf_conn_help

     15 #defineNF_CT_EXT_NAT_TYPEstructnf_conn_nat

     16 #defineNF_CT_EXT_ACCT_TYPEstructnf_conn_counter

所以转换成了structnf_conn_counter类型。

     31 staticinlinevoid*__nf_ct_ext_find(conststructnf_conn*ct,u8id)

     32 {

     33 if(!

nf_ct_ext_exist(ct,id))

     34 returnNULL;

     35 

     36 return(void*)ct->ext+ct->ext->offset[id];

     37 }

根据offset取出值。

四.conntrack的具体实现

以PF_INET为例:

/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c

373staticint__initnf_conntrack_l3proto_ipv4_init(void)

374{

375intret=0;

376

377need_conntrack();

378nf_defrag_ipv4_enable();

379

380ret=nf_register_sockopt(&so_getorigdst);

386ret=nf_conntrack_l4proto_register(&nf_conntrack_l4proto_t

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 考试认证 > 其它考试

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2