quhr 发表于 2011-12-21 08:43

Linux内核中的IPSEC实现(1)

本文档的Copyleft归yfydz所有,使用GPL发布,可以自由拷贝,转载,转载时请保持文档的完整性,严禁用于任何商业用途。<br>

msn: <a href="mailto:yfydz_no1@hotmail.com" target="_blank">yfydz_no1@hotmail.com</a><br>
来源:<a href="http://yfydz.cublog.cn/" target="_blank">http://yfydz.cublog.cn</a>
<div><br>
1. 前言</div>
<div><br>
在Linux2.6内核中自带了IPSEC的实现,这样就不用象2.4那样打补丁来实现了。该实现包括以下几个部分:
PF_KEY类型套接口,
用来提供和用户层空间进行PF_KEY通信,代码在net/key目录下,前面已经介绍过;安全联盟SA和安全策略SP管理,是使用xfrm库来实现的,
代码在net/xfrm/目录下定义;ESP,AH等协议实现,在net/ipv4(6)下定义;加密认证算法库,在crypto目录下定义,这些算法都
是标准代码了。本系列文章主要描述XFRM库的实现以及在IPV4下相关协议的处理部分, IPV6的忽略。</div>
<div><br>
本文Linux内核代码版本为2.6.19.2。xfrm是内核中变化比较大的部分,每个版本中都有不小的差异,
同时也说明了该模块的不成熟性。</div>
<div>在net/xfrm目录下的各文件大致功能说明如下:</div>
<div>xfrm_state.c: xfrm状态管理<br>
xfrm_policy.c: xfrm策略管理<br>
xfrm_algo.c: 算法管理<br>
xfrm_hash.c: HASH计算函数<br>
xfrm_input.c: 安全路径(sec_path)处理,用于进入的ipsec包<br>
xfrm_user.c:&nbsp; netlink接口的SA和SP管理</div>
<div>在net/ipv4目录下的和ipsec相关各文件大致功能说明如下:</div>
<div>ah4.c: IPV4的AH协议处理<br>
esp4.c: IPV4的ESP协议处理<br>
ipcomp.c: IP压缩协议处理<br>
xfrm4_input: 接收的IPV4的IPSEC包处理<br>
xfrm4_output: 发出的IPV4的IPSEC包处理<br>
xfrm4_state: IPV4的SA处理<br>
xfrm4_policy: IPV4的策略处理<br>
xfrm4_tunnel: IPV4的通道处理<br>
xfrm4_mode_transport: 传输模式<br>
xfrm4_mode_tunnel: 通道模式<br>
xfrm4_mode_beet: BEET模式</div>
<div><br>
2. 数据结构</div>
<div><br>
内核SA的定义用xfrm_state结构定义,SP用xfrm_policy结构定义,在include/net/xfrm.h中定义。</div>
<div><br>
2.1 状态(SA)</div>
<div><br>
xfrm_state状态结构用来描述SA在内核中的具体实现:</div>
<div>struct xfrm_state<br>
{<br>
&nbsp;<br>
// 每个状态结构挂接到三个HASH链表中<br>
&nbsp;struct hlist_node&nbsp;bydst; //
按目的地址HASH<br>
&nbsp;struct hlist_node&nbsp;bysrc; //
按源地址HASH<br>
&nbsp;struct hlist_node&nbsp;byspi; //
按SPI值HASH</div>
<div>
&nbsp;atomic_t&nbsp;&nbsp;refcnt;
// 所有使用计数<br>
&nbsp;spinlock_t&nbsp;&nbsp;lock;&nbsp;&nbsp;
// 状态锁</div>
<div>&nbsp;struct
xfrm_id&nbsp;&nbsp;id; // ID结构,
即目的地址,SPI,协议三元组<br>
&nbsp;struct xfrm_selector&nbsp;sel; //
状态选择子</div>
<div>
&nbsp;u32&nbsp;&nbsp;&nbsp;genid;
// 状态的标志值, 防止发生碰撞</div>
<div>&nbsp;<br>
&nbsp;struct {<br>
&nbsp;&nbsp;u8&nbsp;&nbsp;state;<br>

&nbsp;&nbsp;u8&nbsp;&nbsp;dying;<br>

&nbsp;&nbsp;u32&nbsp;&nbsp;seq;<br>

&nbsp;} km;&nbsp; // KEY回调管理处理结构参数</div>
<div>&nbsp;<br>
&nbsp;struct {<br>
&nbsp;&nbsp;u32&nbsp;&nbsp;reqid;
// 请求ID<br>
&nbsp;&nbsp;u8&nbsp;&nbsp;mode;&nbsp;
// 模式: 传输/通道<br>
&nbsp;&nbsp;u8&nbsp;&nbsp;replay_window;
// 回放窗口<br>
&nbsp;&nbsp;u8&nbsp;&nbsp;aalgo,
ealgo, calgo; // 认证,加密,压缩算法ID值<br>
&nbsp;&nbsp;u8&nbsp;&nbsp;flags;
// 一些标准<br>
&nbsp;&nbsp;u16&nbsp;&nbsp;family;
// 协议族<br>
&nbsp;&nbsp;xfrm_address_t&nbsp;saddr;&nbsp;
// 源地址<br>
&nbsp;&nbsp;int&nbsp;&nbsp;header_len;&nbsp;
// 添加的协议头长度<br>
&nbsp;&nbsp;int&nbsp;&nbsp;trailer_len;
//<br>
&nbsp;} props; // SA相关参数结构</div>
<div>&nbsp;struct xfrm_lifetime_cfg lft; //
生存时间配置</div>
<div>&nbsp;<br>
&nbsp;struct xfrm_algo&nbsp;*aalg; //
hash算法<br>
&nbsp;struct xfrm_algo&nbsp;*ealg; //
加密算法<br>
&nbsp;struct xfrm_algo&nbsp;*calg; //
压缩算法</div>
<div>&nbsp;<br>
&nbsp;struct xfrm_encap_tmpl&nbsp;*encap;
// NAT-T封装信息</div>
<div>&nbsp;<br>
&nbsp;xfrm_address_t&nbsp;*coaddr;</div>
<div>&nbsp;<br>
&nbsp;struct
xfrm_state&nbsp;*tunnel;&nbsp; // 通道,
实际是另一个SA</div>
<div>&nbsp;<br>
&nbsp;atomic_t&nbsp;&nbsp;tunnel_users;
// 通道的使用数</div>
<div>&nbsp;<br>
&nbsp;struct xfrm_replay_state replay; //
回放检测结构,包含各种序列号掩码等信息</div>
<div>&nbsp;<br>
&nbsp;struct xfrm_replay_state preplay; //
上次的回放记录值</div>
<div>&nbsp;<br>
&nbsp;u32&nbsp;&nbsp;&nbsp;xflags;
// 标志</div>
<div>&nbsp;<br>
&nbsp;u32&nbsp;&nbsp;&nbsp;replay_maxage;
// 回放最大时间间隔<br>
&nbsp;u32&nbsp;&nbsp;&nbsp;replay_maxdiff;
// 回放最大差值</div>
<div>&nbsp;<br>
&nbsp;struct timer_list&nbsp;rtimer; //
回放检测定时器</div>
<div>&nbsp;<br>
&nbsp;struct xfrm_stats&nbsp;stats; //
统计值</div>
<div>&nbsp;struct xfrm_lifetime_cur curlft; //
当前时间计数器<br>
&nbsp;struct
timer_list&nbsp;timer;&nbsp; // SA定时器</div>
<div>&nbsp;<br>
&nbsp;u64&nbsp;&nbsp;&nbsp;lastused;
// 上次使用时间</div>
<div>&nbsp;<br>
&nbsp;struct
xfrm_type&nbsp;*type;&nbsp; // 协议,
ESP/AH/IPCOMP<br>
&nbsp;struct
xfrm_mode&nbsp;*mode;&nbsp; // 模式,
通道或传输</div>
<div>&nbsp;<br>
&nbsp;struct xfrm_sec_ctx&nbsp;*security;
// 安全上下文, 加密时使用</div>
<div>&nbsp;<br>
&nbsp;void&nbsp;&nbsp;&nbsp;*data;
// 内部数据<br>
};</div>
<div>&nbsp;</div>
<div>2.2 安全策略(SP)</div>
<div><br>
xfrm_policy结构用于描述SP在内核内部的具体实现:</div>
<div>struct xfrm_policy<br>
{<br>
&nbsp;struct xfrm_policy&nbsp;*next; //
下一个策略<br>
&nbsp;struct hlist_node&nbsp;bydst; //
按目的地址HASH的链表<br>
&nbsp;struct hlist_node&nbsp;byidx; //
按索引号HASH的链表</div>
<div>&nbsp;<br>
&nbsp;rwlock_t&nbsp;&nbsp;lock;&nbsp;
// 策略结构锁<br>
&nbsp;atomic_t&nbsp;&nbsp;refcnt;
// 引用次数<br>
&nbsp;struct timer_list&nbsp;timer; //
策略定时器</div>
<div>
&nbsp;u8&nbsp;&nbsp;&nbsp;type;&nbsp;&nbsp;&nbsp;&nbsp;
// 类型<br>
&nbsp;u32&nbsp;&nbsp;&nbsp;priority;
// 策略优先级<br>
&nbsp;u32&nbsp;&nbsp;&nbsp;index;&nbsp;&nbsp;&nbsp;
// 策略索引号<br>
&nbsp;struct xfrm_selector&nbsp;selector;
// 选择子<br>
&nbsp;struct xfrm_lifetime_cfg
lft;&nbsp;&nbsp;&nbsp;&nbsp;
// 策略生命期<br>
&nbsp;struct xfrm_lifetime_cur
curlft;&nbsp; // 当前的生命期数据<br>
&nbsp;struct
dst_entry&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
*bundles;&nbsp; // 路由链表<br>
&nbsp;__u16&nbsp;&nbsp;&nbsp;family;&nbsp;&nbsp;
// 协议族<br>
&nbsp;__u8&nbsp;&nbsp;&nbsp;action;&nbsp;&nbsp;
// 策略动作, 接受/加密/阻塞...<br>
&nbsp;__u8&nbsp;&nbsp;&nbsp;flags;&nbsp;&nbsp;&nbsp;
// 标志<br>
&nbsp;__u8&nbsp;&nbsp;&nbsp;dead;&nbsp;&nbsp;&nbsp;&nbsp;
// 策略死亡标志<br>
&nbsp;__u8&nbsp;&nbsp;&nbsp;xfrm_nr;&nbsp;
// 使用的xfrm_vec的数量<br>
&nbsp;struct xfrm_sec_ctx&nbsp;*security;
// 安全上下文<br>
&nbsp;struct
xfrm_tmpl&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;xfrm_vec; // 状态模板<br>
};</div>
<div><br>
xfrm模板结构, 用于状态和策略的查询:</div>
<div>struct xfrm_tmpl<br>
{<br>
<br>
// SA三元组, 目的地址, 协议, SOI<br>
&nbsp;struct
xfrm_id&nbsp;&nbsp;id;</div>
<div><br>
// 源地址<br>
&nbsp;xfrm_address_t&nbsp;&nbsp;saddr;</div>
<div>// 请求ID<br>
&nbsp;__u32&nbsp;&nbsp;&nbsp;reqid;</div>
<div><br>
&nbsp;__u8&nbsp;&nbsp;&nbsp;mode;</div>
<div><br>
&nbsp;__u8&nbsp;&nbsp;&nbsp;share;</div>
<div><br>
&nbsp;__u8&nbsp;&nbsp;&nbsp;optional;</div>
<div><br>
&nbsp;__u32&nbsp;&nbsp;&nbsp;aalgos;<br>

&nbsp;__u32&nbsp;&nbsp;&nbsp;ealgos;<br>

&nbsp;__u32&nbsp;&nbsp;&nbsp;calgos;<br>

};</div>
<div>&nbsp;</div>
<div>2.3 协议结构</div>
<div>对ESP, AH, IPCOMP等协议的描述是通过xfrm_type结构来描述的,
多个协议的封装就是靠多个协议结构形成的链表来实现:</div>
<div>struct xfrm_type<br>
{<br>
&nbsp;char&nbsp;&nbsp;&nbsp;*description;
// 描述字符串<br>
&nbsp;struct
module&nbsp;&nbsp;*owner; // 协议模块<br>
&nbsp;__u8&nbsp;&nbsp;&nbsp;proto;&nbsp;
// 协议值<br>
&nbsp;__u8&nbsp;&nbsp;&nbsp;flags;&nbsp;
// 标志<br>
#define XFRM_TYPE_NON_FRAGMENT&nbsp;1<br>
// 初始化状态<br>
&nbsp;int&nbsp;&nbsp;&nbsp;(*init_state)(struct
xfrm_state *x);<br>
// 析构函数<br>
&nbsp;void&nbsp;&nbsp;&nbsp;(*destructor)(struct
xfrm_state *);<br>
// 数据输入函数<br>
&nbsp;int&nbsp;&nbsp;&nbsp;(*input)(struct
xfrm_state *, struct sk_buff *skb);<br>
// 数据输出函数<br>
&nbsp;int&nbsp;&nbsp;&nbsp;(*output)(struct
xfrm_state *, struct sk_buff *pskb);<br>
// 拒绝函数<br>
&nbsp;int&nbsp;&nbsp;&nbsp;(*reject)(struct
xfrm_state *, struct sk_buff *, struct flowi *);<br>
// 头部偏移<br>
&nbsp;int&nbsp;&nbsp;&nbsp;(*hdr_offset)(struct
xfrm_state *, struct sk_buff *, u8 **);<br>
// 本地地址<br>
&nbsp;xfrm_address_t&nbsp;&nbsp;*(*local_addr)(struct
xfrm_state *, xfrm_address_t *);<br>
// 远程地址<br>
&nbsp;xfrm_address_t&nbsp;&nbsp;*(*remote_addr)(struct
xfrm_state *, xfrm_address_t *);<br>
&nbsp;<br>
// 最大数据报长度<br>
&nbsp;u32&nbsp;&nbsp;&nbsp;(*get_max_size)(struct
xfrm_state *, int size);<br>
};</div>
<div>具体的协议结构定义如下, 通常只定义初始化,析构,输入和输出四个成员函数:<br>
AH协议定义<br>
<br>
static struct xfrm_type ah_type =<br>
{<br>
&nbsp;.description&nbsp;= "AH4",<br>
&nbsp;.owner&nbsp;&nbsp;=
THIS_MODULE,<br>
&nbsp;.proto&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;= IPPROTO_AH,<br>
&nbsp;.init_state&nbsp;=
ah_init_state,<br>
&nbsp;.destructor&nbsp;= ah_destroy,<br>
&nbsp;.input&nbsp;&nbsp;=
ah_input,<br>
&nbsp;.output&nbsp;&nbsp;=
ah_output<br>
};</div>
<div>ESP协议定义:<br>
<br>
static struct xfrm_type esp_type =<br>
{<br>
&nbsp;.description&nbsp;= "ESP4",<br>
&nbsp;.owner&nbsp;&nbsp;=
THIS_MODULE,<br>
&nbsp;.proto&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;= IPPROTO_ESP,<br>
&nbsp;.init_state&nbsp;=
esp_init_state,<br>
&nbsp;.destructor&nbsp;= esp_destroy,<br>
&nbsp;.get_max_size&nbsp;=
esp4_get_max_size,<br>
&nbsp;.input&nbsp;&nbsp;=
esp_input,<br>
&nbsp;.output&nbsp;&nbsp;=
esp_output<br>
};</div>
<div>IP压缩协议定义:<br>
<br>
static struct xfrm_type ipcomp_type = {<br>
&nbsp;.description&nbsp;= "IPCOMP4",<br>
&nbsp;.owner&nbsp;&nbsp;=
THIS_MODULE,<br>
&nbsp;.proto&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;= IPPROTO_COMP,<br>
&nbsp;.init_state&nbsp;=
ipcomp_init_state,<br>
&nbsp;.destructor&nbsp;=
ipcomp_destroy,<br>
&nbsp;.input&nbsp;&nbsp;=
ipcomp_input,<br>
&nbsp;.output&nbsp;&nbsp;=
ipcomp_output<br>
};</div>
<div>IPIP协议定义:<br>
<br>
static struct xfrm_type ipip_type = {<br>
&nbsp;.description&nbsp;= "IPIP",<br>
&nbsp;.owner&nbsp;&nbsp;=
THIS_MODULE,<br>
&nbsp;.proto&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;= IPPROTO_IPIP,<br>
&nbsp;.init_state&nbsp;=
ipip_init_state,<br>
&nbsp;.destructor&nbsp;=
ipip_destroy,<br>
&nbsp;.input&nbsp;&nbsp;=
ipip_xfrm_rcv,<br>
&nbsp;.output&nbsp;&nbsp;=
ipip_output<br>
};</div>
<div>2.4 模式结构</div>
<div><br>
模式结构用于描述IPSEC连接描述, 可为通道模式或传输模式两种:</div>
<div>struct xfrm_mode {<br>
// 数据输入函数<br>
&nbsp;int (*input)(struct xfrm_state *x, struct sk_buff
*skb);<br>
// 数据输出函数<br>
&nbsp;int (*output)(struct xfrm_state *x,struct sk_buff
*skb);<br>
// 模块指针<br>
&nbsp;struct module *owner;<br>
// 封装<br>
&nbsp;unsigned int encap;<br>
};</div>
<div>通道模式结构定义:<br>
<br>
static struct xfrm_mode xfrm4_tunnel_mode = {<br>
&nbsp;.input = xfrm4_tunnel_input,<br>
&nbsp;.output = xfrm4_tunnel_output,<br>
&nbsp;.owner = THIS_MODULE,<br>
&nbsp;.encap = XFRM_MODE_TUNNEL,<br>
};</div>
<div>传输模式结构定义:<br>
<br>
static struct xfrm_mode xfrm4_transport_mode = {<br>
&nbsp;.input = xfrm4_transport_input,<br>
&nbsp;.output = xfrm4_transport_output,<br>
&nbsp;.owner = THIS_MODULE,<br>
&nbsp;.encap = XFRM_MODE_TRANSPORT,<br>
};</div>
<div>beet模式, 不知道在哪用<br>
<br>
static struct xfrm_mode xfrm4_beet_mode = {<br>
&nbsp;.input = xfrm4_beet_input,<br>
&nbsp;.output = xfrm4_beet_output,<br>
&nbsp;.owner = THIS_MODULE,<br>
&nbsp;.encap = XFRM_MODE_BEET,<br>
};</div>
<div><br>
2.5 策略的相关协议处理结构</div>
<div><br>
以下结构用于描述具体协议族下的的策略处理:</div>
<div>struct xfrm_policy_afinfo {<br>
// 协议族<br>
&nbsp;unsigned
short&nbsp;&nbsp;family;<br>
// 协议类型<br>
&nbsp;struct
xfrm_type&nbsp;*type_map;<br>
// 模式<br>
&nbsp;struct
xfrm_mode&nbsp;*mode_map;<br>
// 目的操作结构<br>
&nbsp;struct
dst_ops&nbsp;&nbsp;*dst_ops;<br>
// 垃圾搜集<br>
&nbsp;void&nbsp;&nbsp;&nbsp;(*garbage_collect)(void);<br>

// 路由选择<br>
&nbsp;int&nbsp;&nbsp;&nbsp;(*dst_lookup)(struct
xfrm_dst **dst, struct flowi *fl);<br>
// 获取源地址<br>
&nbsp;int&nbsp;&nbsp;&nbsp;(*get_saddr)(xfrm_address_t
*saddr, xfrm_address_t *daddr);<br>
// 查找路由项<br>
&nbsp;struct
dst_entry&nbsp;*(*find_bundle)(struct flowi *fl, struct
xfrm_policy *policy);<br>
// 创建新路由项<br>
&nbsp;int&nbsp;&nbsp;&nbsp;(*bundle_create)(struct
xfrm_policy *policy,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
struct xfrm_state **xfrm,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
int nx,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
struct flowi *fl,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
struct dst_entry **dst_p);<br>
// 解码会话<br>
&nbsp;void&nbsp;&nbsp;&nbsp;(*decode_session)(struct
sk_buff *skb,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
struct flowi *fl);<br>
};</div>
<div><br>
IPV4的策略协议相关处理结构定义如下:</div>
<div><br>
static struct xfrm_policy_afinfo xfrm4_policy_afinfo = {<br>
&nbsp;.family =
&nbsp;&nbsp;AF_INET,<br>
&nbsp;.dst_ops
=&nbsp;&nbsp;&amp;xfrm4_dst_ops,<br>

&nbsp;.dst_lookup
=&nbsp;&nbsp;xfrm4_dst_lookup,<br>
&nbsp;.get_saddr
=&nbsp;&nbsp;xfrm4_get_saddr,<br>
&nbsp;.find_bundle =
&nbsp;&nbsp;__xfrm4_find_bundle,<br>
&nbsp;.bundle_create
=&nbsp;__xfrm4_bundle_create,<br>
&nbsp;.decode_session
=&nbsp;_decode_session4,</div>
<div><br>
2.5 状态的相关协议处理结构</div>
<div>以下结构用于描述具体协议族下的的状态处理:</div>
<div>struct xfrm_state_afinfo {<br>
// 协议族<br>
&nbsp;unsigned
short&nbsp;&nbsp;family;<br>
// 初始化标志<br>
&nbsp;int&nbsp;&nbsp;&nbsp;(*init_flags)(struct
xfrm_state *x);<br>
// 初始化模板选择<br>
&nbsp;void&nbsp;&nbsp;&nbsp;(*init_tempsel)(struct
xfrm_state *x, struct flowi *fl,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct
xfrm_tmpl *tmpl,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;xfrm_address_t
*daddr, xfrm_address_t *saddr);<br>
// 模板排序<br>
&nbsp;int&nbsp;&nbsp;&nbsp;(*tmpl_sort)(struct
xfrm_tmpl **dst, struct xfrm_tmpl **src, int n);<br>
// 状态排序<br>
&nbsp;int&nbsp;&nbsp;&nbsp;(*state_sort)(struct
xfrm_state **dst, struct xfrm_state **src, int n);<br>
};</div>
<div>IPV4的状态相关协议处理结构</div>
<div>static struct xfrm_state_afinfo xfrm4_state_afinfo = {<br>
&nbsp;.family&nbsp;&nbsp;&nbsp;=
AF_INET,<br>
&nbsp;.init_flags&nbsp;&nbsp;=
xfrm4_init_flags,<br>
&nbsp;.init_tempsel&nbsp;&nbsp;=
__xfrm4_init_tempsel,<br>
};</div>
<div><br>
2.6 回调通知信息结构</div>
<div>struct xfrm_mgr<br>
{<br>
&nbsp;struct list_head&nbsp;list;<br>
&nbsp;char&nbsp;&nbsp;&nbsp;*id;<br>

// 状态通知<br>
&nbsp;int&nbsp;&nbsp;&nbsp;(*notify)(struct
xfrm_state *x, struct km_event *c);<br>
// 获取, 如获取SA<br>
&nbsp;int&nbsp;&nbsp;&nbsp;(*acquire)(struct
xfrm_state *x, struct xfrm_tmpl *, struct xfrm_policy *xp, int
dir);<br>
// 编译策略<br>
&nbsp;struct
xfrm_policy&nbsp;*(*compile_policy)(struct sock *sk,
int opt, u8 *data, int len, int *dir);<br>
// 映射<br>
&nbsp;int&nbsp;&nbsp;&nbsp;(*new_mapping)(struct
xfrm_state *x, xfrm_address_t *ipaddr, u16 sport);<br>
// 策略通知<br>
&nbsp;int&nbsp;&nbsp;&nbsp;(*notify_policy)(struct
xfrm_policy *x, int dir, struct km_event *c);<br>
// 报告<br>
&nbsp;int&nbsp;&nbsp;&nbsp;(*report)(u8
proto, struct xfrm_selector *sel, xfrm_address_t *addr);<br>
};</div>
<div><br>
在net/key/pf_key.c中定义了pkeyv2_mgr结构:</div>
<div>static struct xfrm_mgr pfkeyv2_mgr =<br>
{<br>
&nbsp;.id&nbsp;&nbsp;=
"pfkeyv2",<br>
&nbsp;.notify&nbsp;&nbsp;=
pfkey_send_notify,<br>
&nbsp;.acquire&nbsp;=
pfkey_send_acquire,<br>
&nbsp;.compile_policy&nbsp;=
pfkey_compile_policy,<br>
&nbsp;.new_mapping&nbsp;=
pfkey_send_new_mapping,<br>
&nbsp;.notify_policy&nbsp;=
pfkey_send_policy_notify,<br>
};</div>
<div><br>
3. 初始化</div>
<div><br>
<br>
// xfrm初始化函数包括状态, 策略和输入处理的三初始化函数<br>
// xfrm是不支持模块方式的<br>
void __init xfrm_init(void)<br>
{<br>
&nbsp;xfrm_state_init();<br>
&nbsp;xfrm_policy_init();<br>
&nbsp;xfrm_input_init();<br>
}</div>
<div><br>
3.1 xfrm状态初始化</div>
<div><br>
void __init xfrm_state_init(void)<br>
{<br>
&nbsp;unsigned int sz;<br>
// 初始HASH表不大, 每个HASH中初始化为8个链表, 但随着状态数量的增加<br>
// 会动态增加HASH表数量<br>
&nbsp;sz = sizeof(struct hlist_head) * 8;</div>
<div>// 建立3组HASH, 分别按SA的源地址, 目的地址和SPI值<br>
&nbsp;xfrm_state_bydst = xfrm_hash_alloc(sz);<br>
&nbsp;xfrm_state_bysrc = xfrm_hash_alloc(sz);<br>
&nbsp;xfrm_state_byspi = xfrm_hash_alloc(sz);<br>
&nbsp;if (!xfrm_state_bydst || !xfrm_state_bysrc ||
!xfrm_state_byspi)<br>
&nbsp;&nbsp;panic("XFRM: Cannot allocate
bydst/bysrc/byspi hashes.");</div>
<div>// xfrm_state_hmask初始值为=7, 计算出的HASH值与该值与来得到链表号<br>
&nbsp;xfrm_state_hmask = ((sz / sizeof(struct
hlist_head)) - 1);<br>
// 初始化工作队列work_queue, 完成对状态垃圾的搜集和释放<br>
&nbsp;INIT_WORK(&amp;xfrm_state_gc_work,
xfrm_state_gc_task, NULL);<br>
}</div>
<div><br>
3.2 策略初始化</div>
<div><br>
static void __init xfrm_policy_init(void)<br>
{<br>
&nbsp;unsigned int hmask, sz;<br>
&nbsp;int dir;</div>
<div>// 建立一个内核cache, 用于分配xfrm_dst结构()<br>
&nbsp;xfrm_dst_cache =
kmem_cache_create("xfrm_dst_cache",<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
sizeof(struct xfrm_dst),<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
0, SLAB_HWCACHE_ALIGN|SLAB_PANIC,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
NULL, NULL);<br>
// 分配状态HASH表, 初始是8个HASH链表,以后随着策略数量的增加<br>
// 会动态增加HASH表的数量<br>
&nbsp;hmask = 8 - 1;<br>
&nbsp;sz = (hmask+1) * sizeof(struct hlist_head);<br>
// 该HASH表是按策略的index参数进行索引的<br>
&nbsp;xfrm_policy_byidx = xfrm_hash_alloc(sz);<br>
&nbsp;xfrm_idx_hmask = hmask;<br>
&nbsp;if (!xfrm_policy_byidx)<br>
&nbsp;&nbsp;panic("XFRM: failed to allocate
byidx hash\n");</div>
<div>// 输入, 输出, 转发三个处理点, 双向<br>
&nbsp;for (dir = 0; dir &lt;
XFRM_POLICY_MAX * 2; dir++) {<br>
&nbsp;&nbsp;struct xfrm_policy_hash
*htab;</div>
<div>// 初始化inexact链表头, inexact处理选择子相关长度不是标准值的一些特别策略<br>
&nbsp;&nbsp;INIT_HLIST_HEAD(&amp;xfrm_policy_inexact);</div>
<div>// 分配按地址HASH的HASH表<br>
&nbsp;&nbsp;htab =
&amp;xfrm_policy_bydst;<br>
&nbsp;&nbsp;htab-&gt;table =
xfrm_hash_alloc(sz);<br>
&nbsp;&nbsp;htab-&gt;hmask =
hmask;<br>
&nbsp;&nbsp;if
(!htab-&gt;table)<br>
&nbsp;&nbsp;&nbsp;panic("XFRM:
failed to allocate bydst hash\n");<br>
&nbsp;}<br>
// 初始化策略垃圾搜集的工作队列, 完成对策略垃圾的搜集和释放<br>
&nbsp;INIT_WORK(&amp;xfrm_policy_gc_work,
xfrm_policy_gc_task, NULL);<br>
// 登记网卡通知<br>
&nbsp;register_netdevice_notifier(&amp;xfrm_dev_notifier);<br>

}</div>
<div>xfrm的网卡通知回调结构<br>
static struct notifier_block xfrm_dev_notifier = {<br>
&nbsp;xfrm_dev_event,<br>
&nbsp;NULL,<br>
&nbsp;0<br>
};</div>
<div>// 网卡通知回调函数<br>
static int xfrm_dev_event(struct notifier_block *this, unsigned
long event, void *ptr)<br>
{<br>
&nbsp;switch (event) {<br>
// 如果网卡down掉的话, 清除相关的所有的xfrm路由项<br>
&nbsp;case NETDEV_DOWN:<br>
&nbsp;&nbsp;xfrm_flush_bundles();<br>
&nbsp;}<br>
&nbsp;return NOTIFY_DONE;<br>
}</div>
<div>// 清除相关的所有的xfrm路由项<br>
static int xfrm_flush_bundles(void)<br>
{<br>
// 将不用的路由项删除<br>
&nbsp;xfrm_prune_bundles(stale_bundle);<br>
&nbsp;return 0;<br>
}</div>
<div>&nbsp;</div>
<div>3.3 输入初始化</div>
<div><br>
void __init xfrm_input_init(void)<br>
{<br>
// 建立一个内核cache, 用于分配sec_path结构(安全路径)<br>
&nbsp;secpath_cachep =
kmem_cache_create("secpath_cache",<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
sizeof(struct sec_path),<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
0, SLAB_HWCACHE_ALIGN|SLAB_PANIC,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
NULL, NULL);<br>
}</div>
<div>struct sec_path结构是对输入的加密包进行层层解包的处理, 在sk_buff中有该结构的指针sp,
如果sp非空表示这是个IPSEC解密后的包。</div>
<div>&nbsp;</div>
<div>...... 待续 ......</div>
页: [1]
查看完整版本: Linux内核中的IPSEC实现(1)