使用连接跟踪结构体nf_conn中用结构体变量ct_general中的变量use, 来标记连接跟踪表的引用计数,当连接跟踪被插入到list中时,引用计数会加1。
在nf_conntrack_alloc的时候连接跟踪引用计数初始化为0;在nf_contrack_in时,连接跟踪信息被插入到unconfirmed_list里,引用计数计数加1,这时引用计数为1;后面在nf_confirm中,如果数据完整且没被篡改,连接跟踪信息则会被插入到连接跟踪链表中,引用计数加1,引用计数为2, 此时连接跟踪表正式更新。综上,引用计数有0,1,2三个值,分别代表连接跟踪的不同状态。
引用计数:0
static struct nf_conn *
__nf_conntrack_alloc(struct net *net,
const struct nf_conntrack_zone *zone,
const struct nf_conntrack_tuple *orig,
const struct nf_conntrack_tuple *repl,
gfp_t gfp, u32 hash)
{
...
/* Because we use RCU lookups, we set ct_general.use to zero before
* this is inserted in any list.
*/
atomic_set(&ct->ct_general.use, 0);
return ct;
}
引用计数:1
init_conntrack(struct net *net, struct nf_conn *tmpl,
const struct nf_conntrack_tuple *tuple,
const struct nf_conntrack_l3proto *l3proto,
const struct nf_conntrack_l4proto *l4proto,
struct sk_buff *skb,
unsigned int dataoff, u32 hash)
{
/* Now it is inserted into the unconfirmed list, bump refcount */
nf_conntrack_get(&ct->ct_general);
nf_ct_add_to_unconfirmed_list(ct);
...
return &ct->tuplehash[IP_CT_DIR_ORIGINAL];
}
引用计数:2
/* Confirm a connection given skb; places it in hash table */
int
__nf_conntrack_confirm(struct sk_buff *skb)
{
...
atomic_inc(&ct->ct_general.use);
ct->status |= IPS_CONFIRMED;
*/
__nf_conntrack_hash_insert(ct, hash, reply_hash);
nf_conntrack_double_unlock(hash, reply_hash);
local_bh_enable();
...
return ret;
}
EXPORT_SYMBOL_GPL(__nf_conntrack_confirm);
从引用计数可以判断连接跟踪表的状态。