Chinaunix
标题:
nf_nat_move_storage函数的目的是什么?【已解决】
[打印本页]
作者:
jiufei19
时间:
2011-08-13 12:46
标题:
nf_nat_move_storage函数的目的是什么?【已解决】
本帖最后由 jiufei19 于 2011-08-14 14:30 编辑
在继续阅读连接跟踪和NAT的源码时,读到了函数nf_nat_move_storage,该函数的定义如下:
static void nf_nat_move_storage(struct nf_conn *conntrack, void *old)
{
struct nf_conn_nat *new_nat = nf_ct_ext_find(conntrack, NF_CT_EXT_NAT);
struct nf_conn_nat *old_nat = (struct nf_conn_nat *)old;
struct nf_conn *ct = old_nat->ct;
unsigned int srchash;
if (!(ct->status & IPS_NAT_DONE_MASK))
return;
srchash = hash_by_src(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
write_lock_bh(&nf_nat_lock);
hlist_replace_rcu(&old_nat->bysource, &new_nat->bysource);
new_nat->ct = ct;
write_unlock_bh(&nf_nat_lock);
}
其中new_nat和old_nat的关系我很难理解,望各位前辈给予指点,谢谢!
作者:
jiufei19
时间:
2011-08-13 15:39
回复
1#
jiufei19
下面我分析下造成产生对此函数功能不清的问题
1、假定当前netfilter已经添加了nat_extend,但是尚未添加ftp helper_extend
2 、开始准备添加一个ftp helper_extend,于是根据如下源码:
void *__nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp)
{
...
if (!ct->ext)
return nf_ct_ext_create(&ct->ext, id, gfp);
if (nf_ct_ext_exist(ct, id))
return NULL;
...
if (newlen >= ct->ext->real_len) {
...
for (i = 0; i < NF_CT_EXT_NUM; i++) {
if (!nf_ct_ext_exist(ct, i))
continue;
t = rcu_dereference(nf_ct_ext_types
);
if (t && t->move)
t->move(ct, ct->ext + ct->ext->offset[id]);
...
}
...
}
上面红色语句表示实际调用nf_nat_move_storage这个函数,显然上面的id为即将添加的helper_extend的id,而我们知道此时我们正要添加一个helper_extend,于是知道这里的ct->ext->offset[id]应该为0,所以上述红色语句实际应为:
t->move(ct, ct->ext);
于是我们进入了本问题的关键部分,即在nf_nat_move_storage函数中有如下两个语句:
struct nf_conn_nat *new_nat = nf_ct_ext_find(conntrack, NF_CT_EXT_NAT);
struct nf_conn_nat *old_nat = (struct nf_conn_nat *)old;
其中new_nat为实际当前连接跟踪conntrack已经具有的nat_extend的偏移位置;而old_nat就是上面调用move函数是传入的ct->ext,显然这里把ct->ext称为了old_nat,因此就产生了我的疑问了,不晓得这里是要做什么?望前辈指点。
作者:
jiufei19
时间:
2011-08-14 11:13
本帖最后由 jiufei19 于 2011-08-14 13:40 编辑
回复
1#
jiufei19
今天继续尝试解决此问题。由于我提出问题的内核版本为2.6.23,所以为了进行对比,我找到了内核版本2.6.36的同一段程序,发现二者之间在调用t->move函数时有显著不同,下面我列出2.6.36的不同之处:
void *__nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp)
{
...
old = ct->ext;
...
new = __krealloc(old, newlen, gfp);
...
if (new != old) {
for (i = 0; i < NF_CT_EXT_NUM; i++) {
if (!__nf_ct_ext_exist(old, i))
continue;
...
if (t && t->move)
t->move((void *)new + new->offset
,
(void *)old + old->offset
);
...
}
}
...
}
由上面代码可见,2.6.36和2.6.23的关键不同是红色部分的内容,在2.6.23中,使用了offset[id],而这里是offset【i】。前面我的疑问中分析了,如果offset的下标索引为id的话,那么在此处上下文下该offset【id】实际为0值,导致后面的调用很难理解,似乎2.6.23代码有错。而如果如2.6.36所示,则此处的offset【i】就不是0了,于是old->offset
就是原来的nat_extend的偏移,那么new->offset【i】就是在添加helper_extend后原来nat_extend的偏移了,现在的问题是new->offset【i】和old->offset【i】之间的关系是什么?进一步new和old之间的关系又是什么?我不太理解,因此就导致了对nf_nat_move_storage函数也不理解的问题。
望斑竹和各位前辈解惑!
作者:
jiufei19
时间:
2011-08-14 14:34
回复
3#
jiufei19
问题基本解决了,看来nf_nat_move_storage函数的目的就是让新分配的new所代表的nf_ct_ext,以及后面紧跟的nat_extend和helper_extend去替换原来的old。不过这里又引入了另外一个我之前曾经发帖问过的问题,即为啥只有对nat_extend才设置对应的nf_nat_move_storage函数,而对helper_extend而言,就不需要这样的类似move函数了呢?
欢迎光临 Chinaunix (http://bbs.chinaunix.net/)
Powered by Discuz! X3.2