Linux内核中PF_KEY协议族的实现(4)
<div align="center"><font size="5">Linux内核中PF_KEY协议族的实现(4)</font></div><div><br>本文档的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>
<div> </div>
<div>6. 通知回调处理</div>
<div><br>6.1 初始化</div>
<div>在pf_key的初始化函数中定义了通知回调结构pfkeyv2_mgr:</div>
<div> err = xfrm_register_km(&pfkeyv2_mgr);</div>
<div>该结构定义如下:</div>
<div>static struct xfrm_mgr pfkeyv2_mgr =<br>{<br> .id = "pfkeyv2",<br> .notify = pfkey_send_notify,<br> .acquire = pfkey_send_acquire,<br> .compile_policy = pfkey_compile_policy,<br> .new_mapping = pfkey_send_new_mapping,<br> .notify_policy = pfkey_send_policy_notify,<br>};</div>
<div><br>6.2 登记</div>
<div>/* net/xfrm/xfrm_state.c */<br>// 就是把xfrm_mgr结构挂接到xfrm_km_list链表<br>int xfrm_register_km(struct xfrm_mgr *km)<br>{<br> write_lock_bh(&xfrm_km_lock);<br>// 将结构挂接到xfrm_km_list链表<br> list_add_tail(&km->list, &xfrm_km_list);<br> write_unlock_bh(&xfrm_km_lock);<br> return 0;<br>}<br>EXPORT_SYMBOL(xfrm_register_km);</div>
<div><br>6.3 发送通知</div>
<div>在pf_key中调用以下两个函数来调用通知回调函数, 分别针对安全策略操作和SA操作:</div>
<div>// 安全策略通知回调<br>void km_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c)<br>{<br> struct xfrm_mgr *km;</div>
<div> read_lock(&xfrm_km_lock);<br>// 状态的通知回调函数为notify_policy<br> list_for_each_entry(km, &xfrm_km_list, list)<br> if (km->notify_policy)<br> km->notify_policy(xp, dir, c);<br> read_unlock(&xfrm_km_lock);<br>}</div>
<div>// SA状态通知回调<br>void km_state_notify(struct xfrm_state *x, struct km_event *c)<br>{<br> struct xfrm_mgr *km;<br> read_lock(&xfrm_km_lock);<br>// 状态的通知回调函数为notify<br> list_for_each_entry(km, &xfrm_km_list, list)<br> if (km->notify)<br> km->notify(x, c);<br> read_unlock(&xfrm_km_lock);<br>}</div>
<div><br>调用这些通知函数前要填写事件的相关参数, 如:</div>
<div>static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)<br>{<br> unsigned proto;<br> struct km_event c;</div>
<div> proto = pfkey_satype2proto(hdr->sadb_msg_satype);<br> if (proto == 0)<br> return -EINVAL;</div>
<div> xfrm_state_flush(proto);<br>// 填写事件参数<br>// 协议<br> c.data.proto = proto;<br>// 序列号<br> c.seq = hdr->sadb_msg_seq;<br>// sock对方(用户空间进程)的pid<br> c.pid = hdr->sadb_msg_pid;<br>// 事件<br> c.event = XFRM_MSG_FLUSHSA;<br> km_state_notify(NULL, &c);</div>
<div> return 0;<br>}</div>
<div><br>6.4 pf_key通知回调函数</div>
<div>6.4.1 发送SA消息时的通知回调</div>
<div>// 状态通知回调, 在SA操作后调用<br>static int pfkey_send_notify(struct xfrm_state *x, struct km_event *c)<br>{<br>// 根据事件类型来发送相关通知<br> switch (c->event) {<br> case XFRM_MSG_EXPIRE:<br>// SA到期的通知, SA消息类型为SADB_EXPIRE,只是进行了登记的PF_KEY socket可以收到<br> return key_notify_sa_expire(x, c);<br> case XFRM_MSG_DELSA:<br> case XFRM_MSG_NEWSA:<br> case XFRM_MSG_UPDSA:<br>// SA的通知, SA消息类型为分别为SADB_DELETE, SADB_ADD和SADB_UPDATE, <br>// 所有PF_KEY socket都可以收到<br> return key_notify_sa(x, c);<br> case XFRM_MSG_FLUSHSA:<br>// 删除全部SA的通知, SA消息类型为分别为SADB_FLUSH, 所有PF_KEY socket都可以收到<br> return key_notify_sa_flush(c);<br> case XFRM_MSG_NEWAE: /* not yet supported */<br> break;<br> default:<br> printk("pfkey: Unknown SA event %d\n", c->event);<br> break;<br> }</div>
<div> return 0;<br>}</div>
<div><br>6.4.2 发送ACQUIRE</div>
<div><br>关于ACQUIRE的作用, 摘一段UNP vol.1, r3中的话:</div>
<div>chapter19.5:</div>
<div>"When the kernel needs to communicate with a peer and policy says
that an SA is required but one is not available, the kernel sends an
SADB_ACQUIRE message to key management sockets that have registered the
SA type required, containing a proposal extension describing the
kernel's proposed algorithms and key lengths. The proposal may be a
combination of what is supported by the system and preconfigured policy
that limits what is permitted for this communication. The proposal is a
list of algorithms, key lengths, and lifetimes, in order of preference.
When a key management daemon receives an SADB_ACQUIRE message, it
performs the acts required to choose a key that fits one of the kernel's
proposed combinations, and installs this key in the kernel. "</div>
<div> </div>
<div>static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *xp, int dir)<br>{<br> struct sk_buff *skb;<br> struct sadb_msg *hdr;<br> struct sadb_address *addr;<br> struct sadb_x_policy *pol;<br> struct sockaddr_in *sin;<br>#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)<br> struct sockaddr_in6 *sin6;<br>#endif<br> int sockaddr_size;<br> int size;<br> struct sadb_x_sec_ctx *sec_ctx;<br> struct xfrm_sec_ctx *xfrm_ctx;<br> int ctx_size = 0;<br> <br> sockaddr_size = pfkey_sockaddr_size(x->props.family);<br> if (!sockaddr_size)<br> return -EINVAL;<br>// 消息长度包括SA基本头, 两个SA地址, 两个网络地址和策略<br> size = sizeof(struct sadb_msg) +<br> (sizeof(struct sadb_address) * 2) +<br> (sockaddr_size * 2) +<br> sizeof(struct sadb_x_policy);</div>
<div>// 还添加AH或ESP中所有算法描述的长度<br> if (x->id.proto == IPPROTO_AH)<br> size += count_ah_combs(t);<br> else if (x->id.proto == IPPROTO_ESP)<br> size += count_esp_combs(t);</div>
<div> if ((xfrm_ctx = x->security)) {<br> ctx_size = PFKEY_ALIGN8(xfrm_ctx->ctx_len);<br> size += sizeof(struct sadb_x_sec_ctx) + ctx_size;<br> }</div>
<div>// 分配skb<br> skb = alloc_skb(size + 16, GFP_ATOMIC);<br> if (skb == NULL)<br> return -ENOMEM;<br>// 先填基本SA消息头信息 <br> hdr = (struct sadb_msg *) skb_put(skb, sizeof(struct sadb_msg));<br> hdr->sadb_msg_version = PF_KEY_V2;<br> hdr->sadb_msg_type = SADB_ACQUIRE;<br> hdr->sadb_msg_satype = pfkey_proto2satype(x->id.proto);<br> hdr->sadb_msg_len = size / sizeof(uint64_t);<br> hdr->sadb_msg_errno = 0;<br> hdr->sadb_msg_reserved = 0;<br> hdr->sadb_msg_seq = x->km.seq = get_acqseq();<br> hdr->sadb_msg_pid = 0;</div>
<div> /* src address */<br>// 填充SA源地址信息<br> addr = (struct sadb_address*) skb_put(skb, <br> sizeof(struct sadb_address)+sockaddr_size);<br> addr->sadb_address_len = <br> (sizeof(struct sadb_address)+sockaddr_size)/<br> sizeof(uint64_t);<br> addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC;<br> addr->sadb_address_proto = 0;<br> addr->sadb_address_reserved = 0;<br> if (x->props.family == AF_INET) {<br>// IPV4地址<br> addr->sadb_address_prefixlen = 32;</div>
<div> sin = (struct sockaddr_in *) (addr + 1);<br> sin->sin_family = AF_INET;<br> sin->sin_addr.s_addr = x->props.saddr.a4;<br> sin->sin_port = 0;<br> memset(sin->sin_zero, 0, sizeof(sin->sin_zero));<br> }<br>#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)<br> else if (x->props.family == AF_INET6) {<br>// IPV6地址<br> addr->sadb_address_prefixlen = 128;</div>
<div> sin6 = (struct sockaddr_in6 *) (addr + 1);<br> sin6->sin6_family = AF_INET6;<br> sin6->sin6_port = 0;<br> sin6->sin6_flowinfo = 0;<br> memcpy(&sin6->sin6_addr,<br> x->props.saddr.a6, sizeof(struct in6_addr));<br> sin6->sin6_scope_id = 0;<br> }<br>#endif<br> else<br> BUG();<br> <br> /* dst address */<br>// 填充SA目的地址信息<br> addr = (struct sadb_address*) skb_put(skb, <br> sizeof(struct sadb_address)+sockaddr_size);<br> addr->sadb_address_len =<br> (sizeof(struct sadb_address)+sockaddr_size)/<br> sizeof(uint64_t);<br> addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST;<br> addr->sadb_address_proto = 0;<br> addr->sadb_address_reserved = 0;<br> if (x->props.family == AF_INET) {<br> addr->sadb_address_prefixlen = 32; </div>
<div> sin = (struct sockaddr_in *) (addr + 1);<br> sin->sin_family = AF_INET;<br> sin->sin_addr.s_addr = x->id.daddr.a4;<br> sin->sin_port = 0;<br> memset(sin->sin_zero, 0, sizeof(sin->sin_zero));<br> }<br>#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)<br> else if (x->props.family == AF_INET6) {<br> addr->sadb_address_prefixlen = 128; </div>
<div> sin6 = (struct sockaddr_in6 *) (addr + 1);<br> sin6->sin6_family = AF_INET6;<br> sin6->sin6_port = 0;<br> sin6->sin6_flowinfo = 0;<br> memcpy(&sin6->sin6_addr,<br> x->id.daddr.a6, sizeof(struct in6_addr));<br> sin6->sin6_scope_id = 0;<br> }<br>#endif<br> else<br> BUG();</div>
<div>// 填充策略信息<br> pol = (struct sadb_x_policy *) skb_put(skb, sizeof(struct sadb_x_policy));<br> pol->sadb_x_policy_len = sizeof(struct sadb_x_policy)/sizeof(uint64_t);<br> pol->sadb_x_policy_exttype = SADB_X_EXT_POLICY;<br> pol->sadb_x_policy_type = IPSEC_POLICY_IPSEC;<br> pol->sadb_x_policy_dir = dir+1;<br> pol->sadb_x_policy_id = xp->index;</div>
<div> /* Set sadb_comb's. */<br>// 填充AH或ESP的可用算法信息<br> if (x->id.proto == IPPROTO_AH)<br> dump_ah_combs(skb, t);<br> else if (x->id.proto == IPPROTO_ESP)<br> dump_esp_combs(skb, t);</div>
<div> /* security context */<br> if (xfrm_ctx) {<br>// 填充安全上下文信息<br> sec_ctx = (struct sadb_x_sec_ctx *) skb_put(skb,<br> sizeof(struct sadb_x_sec_ctx) + ctx_size);<br> sec_ctx->sadb_x_sec_len =<br> (sizeof(struct sadb_x_sec_ctx) + ctx_size) / sizeof(uint64_t);<br> sec_ctx->sadb_x_sec_exttype = SADB_X_EXT_SEC_CTX;<br> sec_ctx->sadb_x_ctx_doi = xfrm_ctx->ctx_doi;<br> sec_ctx->sadb_x_ctx_alg = xfrm_ctx->ctx_alg;<br> sec_ctx->sadb_x_ctx_len = xfrm_ctx->ctx_len;<br> memcpy(sec_ctx + 1, xfrm_ctx->ctx_str,<br> xfrm_ctx->ctx_len);<br> }<br>// 广播到进行了登记的PF_KEY套接口<br> return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_REGISTERED, NULL);<br>}</div>
<div><br>6.4.3 编译策略</div>
<div>// 将sadb_x_policy(标准接口格式)编译为xfrm_policy(内核具体实现格式)<br>static struct xfrm_policy *pfkey_compile_policy(struct sock *sk, int opt,<br> u8 *data, int len, int *dir)<br>{<br> struct xfrm_policy *xp;<br> struct sadb_x_policy *pol = (struct sadb_x_policy*)data;<br> struct sadb_x_sec_ctx *sec_ctx;</div>
<div>// 选项opt必须是IP_IPSEC_POLICY, 否则出错<br> switch (sk->sk_family) {<br> case AF_INET:<br> if (opt != IP_IPSEC_POLICY) {<br> *dir = -EOPNOTSUPP;<br> return NULL;<br> }<br> break;<br>#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)<br> case AF_INET6:<br> if (opt != IPV6_IPSEC_POLICY) {<br> *dir = -EOPNOTSUPP;<br> return NULL;<br> }<br> break;<br>#endif<br> default:<br> *dir = -EINVAL;<br> return NULL;<br> }</div>
<div> *dir = -EINVAL;</div>
<div> if (len < sizeof(struct sadb_x_policy) ||<br> pol->sadb_x_policy_len*8 > len ||<br> pol->sadb_x_policy_type > IPSEC_POLICY_BYPASS ||<br> (!pol->sadb_x_policy_dir || pol->sadb_x_policy_dir > IPSEC_DIR_OUTBOUND))<br> return NULL;<br>// 分配策略空间<br> xp = xfrm_policy_alloc(GFP_ATOMIC);<br> if (xp == NULL) {<br> *dir = -ENOBUFS;<br> return NULL;<br> }</div>
<div>// 填写策略动作<br> xp->action = (pol->sadb_x_policy_type == IPSEC_POLICY_DISCARD ?<br> XFRM_POLICY_BLOCK : XFRM_POLICY_ALLOW);</div>
<div>// 填写策略有效期参数<br> xp->lft.soft_byte_limit = XFRM_INF;<br> xp->lft.hard_byte_limit = XFRM_INF;<br> xp->lft.soft_packet_limit = XFRM_INF;<br> xp->lft.hard_packet_limit = XFRM_INF;<br> xp->family = sk->sk_family;</div>
<div> xp->xfrm_nr = 0;<br>// 解析ipsec请求<br> if (pol->sadb_x_policy_type == IPSEC_POLICY_IPSEC &&<br> (*dir = parse_ipsecrequests(xp, pol)) < 0)<br> goto out;</div>
<div> /* security context too */<br> if (len >= (pol->sadb_x_policy_len*8 +<br> sizeof(struct sadb_x_sec_ctx))) {<br>// 转换安全上下文<br> char *p = (char *)pol;<br> struct xfrm_user_sec_ctx *uctx;</div>
<div> p += pol->sadb_x_policy_len*8;<br> sec_ctx = (struct sadb_x_sec_ctx *)p;<br> if (len < pol->sadb_x_policy_len*8 +<br> sec_ctx->sadb_x_sec_len) {<br> *dir = -EINVAL;<br> goto out;<br> }<br> if ((*dir = verify_sec_ctx_len(p)))<br> goto out;<br> uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx);<br> *dir = security_xfrm_policy_alloc(xp, uctx);<br> kfree(uctx);</div>
<div> if (*dir)<br> goto out;<br> }</div>
<div> *dir = pol->sadb_x_policy_dir-1;<br> return xp;</div>
<div>out:<br> security_xfrm_policy_free(xp);<br> kfree(xp);<br> return NULL;<br>}</div>
<div>6.4.4 NAT穿越映射</div>
<div>// 发送新映射(NAT穿越)SA消息, 包含SA头, SA, 转换前地址,端口, 转换后的地址端口<br>static int pfkey_send_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport)<br>{<br> struct sk_buff *skb;<br> struct sadb_msg *hdr;<br> struct sadb_sa *sa;<br> struct sadb_address *addr;<br> struct sadb_x_nat_t_port *n_port;<br> struct sockaddr_in *sin;<br>#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)<br> struct sockaddr_in6 *sin6;<br>#endif<br> int sockaddr_size;<br> int size;<br> __u8 satype = (x->id.proto == IPPROTO_ESP ? SADB_SATYPE_ESP : 0);<br> struct xfrm_encap_tmpl *natt = NULL;</div>
<div>// 协议的地址长度<br> sockaddr_size = pfkey_sockaddr_size(x->props.family);<br> if (!sockaddr_size)<br> return -EINVAL;</div>
<div> if (!satype)<br> return -EINVAL;</div>
<div> if (!x->encap)<br> return -EINVAL;</div>
<div>// NAT转换结构<br> natt = x->encap;</div>
<div> /* Build an SADB_X_NAT_T_NEW_MAPPING message:<br> *<br> * HDR | SA | ADDRESS_SRC (old addr) | NAT_T_SPORT (old port) |<br> * ADDRESS_DST (new addr) | NAT_T_DPORT (new port)<br> */<br>// 消息总长: SA消息头+SA+两个SA地址+两个协议地址+2个NAT端口 <br> size = sizeof(struct sadb_msg) +<br> sizeof(struct sadb_sa) +<br> (sizeof(struct sadb_address) * 2) +<br> (sockaddr_size * 2) +<br> (sizeof(struct sadb_x_nat_t_port) * 2);<br>// 分配skb <br> skb = alloc_skb(size + 16, GFP_ATOMIC);<br> if (skb == NULL)<br> return -ENOMEM;</div>
<div>// 填写SA头 <br> hdr = (struct sadb_msg *) skb_put(skb, sizeof(struct sadb_msg));<br> hdr->sadb_msg_version = PF_KEY_V2;<br> hdr->sadb_msg_type = SADB_X_NAT_T_NEW_MAPPING;<br> hdr->sadb_msg_satype = satype;<br> hdr->sadb_msg_len = size / sizeof(uint64_t);<br> hdr->sadb_msg_errno = 0;<br> hdr->sadb_msg_reserved = 0;<br> hdr->sadb_msg_seq = x->km.seq = get_acqseq();<br> hdr->sadb_msg_pid = 0;</div>
<div> /* SA */<br>// 填写SA结构<br> sa = (struct sadb_sa *) skb_put(skb, sizeof(struct sadb_sa));<br> sa->sadb_sa_len = sizeof(struct sadb_sa)/sizeof(uint64_t);<br> sa->sadb_sa_exttype = SADB_EXT_SA;<br> sa->sadb_sa_spi = x->id.spi;<br> sa->sadb_sa_replay = 0;<br> sa->sadb_sa_state = 0;<br> sa->sadb_sa_auth = 0;<br> sa->sadb_sa_encrypt = 0;<br> sa->sadb_sa_flags = 0;</div>
<div> /* ADDRESS_SRC (old addr) */<br>// 转换前SA地址参数<br> addr = (struct sadb_address*)<br> skb_put(skb, sizeof(struct sadb_address)+sockaddr_size);<br> addr->sadb_address_len = <br> (sizeof(struct sadb_address)+sockaddr_size)/<br> sizeof(uint64_t);<br> addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC;<br> addr->sadb_address_proto = 0;<br> addr->sadb_address_reserved = 0;<br> if (x->props.family == AF_INET) {<br>// 填写转换前IPV4协议地址具体参数<br> addr->sadb_address_prefixlen = 32;</div>
<div> sin = (struct sockaddr_in *) (addr + 1);<br> sin->sin_family = AF_INET;<br> sin->sin_addr.s_addr = x->props.saddr.a4;<br> sin->sin_port = 0;<br> memset(sin->sin_zero, 0, sizeof(sin->sin_zero));<br> }<br>#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)<br> else if (x->props.family == AF_INET6) {<br>// 填写转换前IPV6协议地址具体参数<br> addr->sadb_address_prefixlen = 128;</div>
<div> sin6 = (struct sockaddr_in6 *) (addr + 1);<br> sin6->sin6_family = AF_INET6;<br> sin6->sin6_port = 0;<br> sin6->sin6_flowinfo = 0;<br> memcpy(&sin6->sin6_addr,<br> x->props.saddr.a6, sizeof(struct in6_addr));<br> sin6->sin6_scope_id = 0;<br> }<br>#endif<br> else<br> BUG();</div>
<div> /* NAT_T_SPORT (old port) */<br>// 填写转换前端口参数<br> n_port = (struct sadb_x_nat_t_port*) skb_put(skb, sizeof (*n_port));<br> n_port->sadb_x_nat_t_port_len = sizeof(*n_port)/sizeof(uint64_t);<br> n_port->sadb_x_nat_t_port_exttype = SADB_X_EXT_NAT_T_SPORT;<br> n_port->sadb_x_nat_t_port_port = natt->encap_sport;<br> n_port->sadb_x_nat_t_port_reserved = 0;</div>
<div> /* ADDRESS_DST (new addr) */<br>// 填写转换后地址属性参数<br> addr = (struct sadb_address*)<br> skb_put(skb, sizeof(struct sadb_address)+sockaddr_size);<br> addr->sadb_address_len = <br> (sizeof(struct sadb_address)+sockaddr_size)/<br> sizeof(uint64_t);<br> addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST;<br> addr->sadb_address_proto = 0;<br> addr->sadb_address_reserved = 0;<br> if (x->props.family == AF_INET) {<br>// 填写转换后IPV4协议地址具体参数<br> addr->sadb_address_prefixlen = 32;</div>
<div> sin = (struct sockaddr_in *) (addr + 1);<br> sin->sin_family = AF_INET;<br> sin->sin_addr.s_addr = ipaddr->a4;<br> sin->sin_port = 0;<br> memset(sin->sin_zero, 0, sizeof(sin->sin_zero));<br> }<br>#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)<br> else if (x->props.family == AF_INET6) {<br>// 填写转换后IPV6协议地址具体参数<br> addr->sadb_address_prefixlen = 128;</div>
<div> sin6 = (struct sockaddr_in6 *) (addr + 1);<br> sin6->sin6_family = AF_INET6;<br> sin6->sin6_port = 0;<br> sin6->sin6_flowinfo = 0;<br> memcpy(&sin6->sin6_addr, &ipaddr->a6, sizeof(struct in6_addr));<br> sin6->sin6_scope_id = 0;<br> }<br>#endif<br> else<br> BUG();</div>
<div> /* NAT_T_DPORT (new port) */<br>// 填写转换前端口参数<br> n_port = (struct sadb_x_nat_t_port*) skb_put(skb, sizeof (*n_port));<br> n_port->sadb_x_nat_t_port_len = sizeof(*n_port)/sizeof(uint64_t);<br> n_port->sadb_x_nat_t_port_exttype = SADB_X_EXT_NAT_T_DPORT;<br> n_port->sadb_x_nat_t_port_port = sport;<br> n_port->sadb_x_nat_t_port_reserved = 0;<br>// 发送给进行登记了的PF_KEY套接口<br> return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_REGISTERED, NULL);<br>}</div>
<div><br>6.4.5 发送策略的通知</div>
<div><br>// 策略通知回调, 在安全策略操作后调用<br>static int pfkey_send_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c)<br>{<br> if (xp && xp->type != XFRM_POLICY_TYPE_MAIN)<br> return 0;</div>
<div> switch (c->event) {<br> case XFRM_MSG_POLEXPIRE:<br>// 策略到期通知, 空函数<br> return key_notify_policy_expire(xp, c);<br> case XFRM_MSG_DELPOLICY:<br> case XFRM_MSG_NEWPOLICY:<br> case XFRM_MSG_UPDPOLICY:<br>// 策略的通知, SA消息类型为分别为SADB_X_SPDDELETE, SADB_X_SPDADD, SADB_X_SPDUPDATE等, <br>// 所有PF_KEY socket都可以收到<br> return key_notify_policy(xp, dir, c);<br> case XFRM_MSG_FLUSHPOLICY:<br> if (c->data.type != XFRM_POLICY_TYPE_MAIN)<br> break;<br>// 策略的通知, SA消息类型为分别为SADB_X_FLUSH, 所有PF_KEY socket都可以收到<br> return key_notify_policy_flush(c);<br> default:<br> printk("pfkey: Unknown policy event %d\n", c->event);<br> break;<br> }</div>
<div> return 0;<br>}</div>
<div><br>在pf_key.c中只用到了6.4.1和6.4.5的这两个函数.</div>
<div><br>...... 待续 ......</div>
页:
[1]