版权声明:如有需要,可供转载,但请注明出处:https://blog.csdn.net/City_of_skey/article/details/86586382
目录
1、简介
IPsec的初始化主要包括三部分:状态初始化、策略初始化、输入初始化。初始化函数是xfrm_init
void __init xfrm_init(void)
{
register_pernet_subsys(&xfrm_net_ops);
/*输入初始化*/
xfrm_input_init();
}
xfrm_net_ops结构体:
static struct pernet_operations __net_initdata xfrm_net_ops = {
.init = xfrm_net_init,
.exit = xfrm_net_exit,
};
xfrm_net_init函数:
static int __net_init xfrm_net_init(struct net *net)
{
int rv;
rv = xfrm_statistics_init(net);
if (rv < 0)
goto out_statistics;
/*状态初始化*/
rv = xfrm_state_init(net);
if (rv < 0)
goto out_state;
/*策略初始化*/
rv = xfrm_policy_init(net);
if (rv < 0)
goto out_policy;
xfrm_dst_ops_init(net);
rv = xfrm_sysctl_init(net);
if (rv < 0)
goto out_sysctl;
return 0;
out_sysctl:
xfrm_policy_fini(net);
out_policy:
xfrm_state_fini(net);
out_state:
xfrm_statistics_fini(net);
out_statistics:
return rv;
}
2、状态初始化
状态初始化函数是xfrm_state_init,主要的工作是初始化源ip、目的ip、spi三个哈希表,初始化工作队列
int __net_init xfrm_state_init(struct net *net)
{
unsigned int sz;
INIT_LIST_HEAD(&net->xfrm.state_all);
/*哈希表初始默认长度是8*/
sz = sizeof(struct hlist_head) * 8;
/*初始化目的ip、源ip、spi三个哈希表*/
net->xfrm.state_bydst = xfrm_hash_alloc(sz);
if (!net->xfrm.state_bydst)
goto out_bydst;
net->xfrm.state_bysrc = xfrm_hash_alloc(sz);
if (!net->xfrm.state_bysrc)
goto out_bysrc;
net->xfrm.state_byspi = xfrm_hash_alloc(sz);
if (!net->xfrm.state_byspi)
goto out_byspi;
net->xfrm.state_hmask = ((sz / sizeof(struct hlist_head)) - 1);
net->xfrm.state_num = 0;
INIT_WORK(&net->xfrm.state_hash_work, xfrm_hash_resize);
INIT_HLIST_HEAD(&net->xfrm.state_gc_list);
/*初始化工作队列*/
INIT_WORK(&net->xfrm.state_gc_work, xfrm_state_gc_task);
init_waitqueue_head(&net->xfrm.km_waitq);
return 0;
out_byspi:
xfrm_hash_free(net->xfrm.state_bysrc, sz);
out_bysrc:
xfrm_hash_free(net->xfrm.state_bydst, sz);
out_bydst:
return -ENOMEM;
}
3、策略初始化
策略初始化主要做了三件事情
1、给xfrm_dst分配内核cache
2、给输入、输出、转发三个节点,两个方向初始化
3、注册网卡改变通知事件
static int __net_init xfrm_policy_init(struct net *net)
{
unsigned int hmask, sz;
int dir;
if (net_eq(net, &init_net))
/*给xfrm_dst分配一个内核cache*/
xfrm_dst_cache = kmem_cache_create("xfrm_dst_cache",
sizeof(struct xfrm_dst),
0, SLAB_HWCACHE_ALIGN|SLAB_PANIC,
NULL);
hmask = 8 - 1;
sz = (hmask+1) * sizeof(struct hlist_head);
/*给index分配哈希表,初始长度是8*/
net->xfrm.policy_byidx = xfrm_hash_alloc(sz);
if (!net->xfrm.policy_byidx)
goto out_byidx;
net->xfrm.policy_idx_hmask = hmask;
/*输入、输出、转发三个节点初始,两个方向*/
for (dir = 0; dir < XFRM_POLICY_MAX * 2; dir++) {
struct xfrm_policy_hash *htab;
net->xfrm.policy_count[dir] = 0;
INIT_HLIST_HEAD(&net->xfrm.policy_inexact[dir]);
htab = &net->xfrm.policy_bydst[dir];
htab->table = xfrm_hash_alloc(sz);
if (!htab->table)
goto out_bydst;
htab->hmask = hmask;
}
INIT_LIST_HEAD(&net->xfrm.policy_all);
/*初始化策略队列*/
INIT_WORK(&net->xfrm.policy_hash_work, xfrm_hash_resize);
if (net_eq(net, &init_net))
/*注册网卡通知处理事件*/
register_netdevice_notifier(&xfrm_dev_notifier);
return 0;
out_bydst:
for (dir--; dir >= 0; dir--) {
struct xfrm_policy_hash *htab;
htab = &net->xfrm.policy_bydst[dir];
xfrm_hash_free(htab->table, sz);
}
xfrm_hash_free(net->xfrm.policy_byidx, sz);
out_byidx:
return -ENOMEM;
}
xfrm_dev_notifier结构体:
static struct notifier_block xfrm_dev_notifier = {
.notifier_call = xfrm_dev_event,
};
xfrm_dev_event:
static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr)
{
struct net_device *dev = ptr;
switch (event) {
case NETDEV_DOWN:
/*网卡down删除工作*/
__xfrm_garbage_collect(dev_net(dev));
}
return NOTIFY_DONE;
}
4、输入初始化
xfrm_input_init是输入初始化,主要是分配struct sec_patch内核cache,对输入的数据包做层层解密,sk_buff结构体中的sp指针如果是非空表示解密后的数据包。
void __init xfrm_input_init(void)
{
/*分配sec_path内核cache*/
secpath_cachep = kmem_cache_create("secpath_cache",
sizeof(struct sec_path),
0, SLAB_HWCACHE_ALIGN|SLAB_PANIC,
NULL);
}