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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章