IPsec初始化

版权声明:如有需要,可供转载,但请注明出处:https://blog.csdn.net/City_of_skey/article/details/86586382

目录

1、简介

2、状态初始化

3、策略初始化

4、输入初始化


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);
}

 

你可能感兴趣的:(网络,IPsec,安全)