赞
踩
原标题:Linux网络子系统安全性模块详细分析之文件xfrm_state.c
2.4.4.6 核心代码注释
该文件中xfrm_state_find( )函数涉及的原理较多,此处对其进行简要的注释。
struct xfrm_state * xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr, const struct flowi *fl, struct xfrm_tmpl *tmpl, struct xfrm_policy *pol, int *err, unsigned short family)
{
static xfrm_address_t saddr_wildcard = { };
struct net *net = xp_net(pol);
unsigned int h, h_wildcard;
struct hlist_node *entry;
struct xfrm_state *x, *x0, *to_put;
int acquire_in_progress = 0;
int error = 0;
struct xfrm_state *best = NULL;
u32 mark = pol->mark.v & pol->mark.m;
unsigned short encap_family = tmpl->encap_family;
to_put = NULL;
/*SA操作前要进行加锁*/
spin_lock_bh(&xfrm_state_lock);
/*计算出目的地址Hash值,然后进行遍历Hash表,比较协议簇、序列号、地址、SPI等字段,如果均相等再进一步查找*/
h = xfrm_dst_hash(net, daddr, saddr, tmpl->reqid, encap_family);
hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) {
if (x->props.family == encap_family && x->props.reqid == tmpl->reqid && (mark & x->mark.m) == x->mark.v && !(x->props.flags & XFRM_STATE_WILDRECV) && xfrm_state_addr_check(x, daddr, saddr, encap_family) && tmpl->mode == x->props.mode && tmpl->id.proto == x->id.proto && (tmpl->id.spi == x->id.spi || !tmpl->id.spi))
/*根据SA的状态以及选择子进一步查找SA*/
xfrm_state_look_at(pol, x, fl, encap_family, &best, &acquire_in_progress, &error);
}
if (best)
goto found;
/*将源地址置空再进行查找*/
h_wildcard = xfrm_dst_hash(net, daddr, &saddr_wildcard, tmpl->reqid, encap_family);
hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h_wildcard, bydst) {
if (x->props.family == encap_family &&
x->props.reqid == tmpl->reqid &&
(mark & x->mark.m) == x->mark.v &&
!(x->props.flags & XFRM_STATE_WILDRECV) &&
xfrm_state_addr_check(x, daddr, saddr, encap_family) &&
tmpl->mode == x->props.mode &&
tmpl->id.proto == x->id.proto &&
(tmpl->id.spi == x->id.spi || !tmpl->id.spi))
xfrm_state_look_at(pol, x, fl, encap_family,
&best, &acquire_in_progress, &error);
}
found:
x = best;
/*没找到SA、没错误、也没ACQ标志*/
if (!x && !error && !acquire_in_progress) {
/*根据地址、SPI、协议进行查找*/
if (tmpl->id.spi && (x0 = __xfrm_state_lookup(net, mark, daddr, tmpl->id.spi,
tmpl->id.proto, encap_family)) != NULL) {
/*如果找到则说明SPI被使用,释放些SA*/
to_put = x0;
error = -EEXIST;
goto out;
}
/*此时重新分配一个SA,并对其进行初始化*/
x = xfrm_state_alloc(net);
xfrm_init_tempstate(x, fl, tmpl, daddr, saddr, family);
memcpy(&x->mark, &pol->mark, sizeof(x->mark));
/*调用安全钩子函数分配ACQ状态的SA*/
error = security_xfrm_state_alloc_acquire(x, pol->security, fl->flowi_secid);
if (error) {
x->km.state = XFRM_STATE_DEAD;
to_put = x;
x = NULL;
goto out;
}
/*将新状态发送给用户空间程序, 在其中调用pfkey_acquire()函数让用户空间进程进行IKE协商生成新SA*/
if (km_query(x, tmpl, pol) == 0) {
/*SA状态设置为ACQ,并回到相关的链表和Hash表中*/
x->km.state = XFRM_STATE_ACQ;
list_add(&x->km.all, &net->xfrm.state_all);
hlist_add_head(&x->bydst, net->xfrm.state_bydst+h);
h = xfrm_src_hash(net, daddr, saddr, encap_family);
hlist_add_head(&x->bysrc, net->xfrm.state_bysrc+h);
if (x->id.spi) {
h = xfrm_spi_hash(net, &x->id.daddr, x->id.spi, x->id.proto, encap_family);
hlist_add_head(&x->byspi, net->xfrm.state_byspi+h);
}
/*设置生命期,定时器等*/
x->lft.hard_add_expires_seconds = net->xfrm.sysctl_acq_expires;
tasklet_hrtimer_start(&x->mtimer, ktime_set(net->xfrm.sysctl_acq_expires, 0), HRTIMER_MODE_REL);
net->xfrm.state_num++;
xfrm_hash_grow_check(net, x->bydst.next != NULL);
} else {
x->km.state = XFRM_STATE_DEAD;
to_put = x;
x = NULL;
error = -ESRCH;
}
}
out:
…
return x;
责任编辑:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。