日期:2014-05-16 浏览次数:20695 次
6. 通知回调处理 6.1 初始化 在pf_key的初始化函数中定义了通知回调结构pfkeyv2_mgr: err = xfrm_register_km(&pfkeyv2_mgr); 该结构定义如下: static struct xfrm_mgr pfkeyv2_mgr = { .id = "pfkeyv2", .notify = pfkey_send_notify, .acquire = pfkey_send_acquire, .compile_policy = pfkey_compile_policy, .new_mapping = pfkey_send_new_mapping, .notify_policy = pfkey_send_policy_notify, }; 6.2 登记 /* net/xfrm/xfrm_state.c */ // 就是把xfrm_mgr结构挂接到xfrm_km_list链表 int xfrm_register_km(struct xfrm_mgr *km) { write_lock_bh(&xfrm_km_lock); // 将结构挂接到xfrm_km_list链表 list_add_tail(&km->list, &xfrm_km_list); write_unlock_bh(&xfrm_km_lock); return 0; } EXPORT_SYMBOL(xfrm_register_km); 6.3 发送通知 在pf_key中调用以下两个函数来调用通知回调函数, 分别针对安全策略操作和SA操作: // 安全策略通知回调 void km_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c) { struct xfrm_mgr *km; read_lock(&xfrm_km_lock); // 状态的通知回调函数为notify_policy list_for_each_entry(km, &xfrm_km_list, list) if (km->notify_policy) km->notify_policy(xp, dir, c); read_unlock(&xfrm_km_lock); } // SA状态通知回调 void km_state_notify(struct xfrm_state *x, struct km_event *c) { struct xfrm_mgr *km; read_lock(&xfrm_km_lock); // 状态的通知回调函数为notify list_for_each_entry(km, &xfrm_km_list, list) if (km->notify) km->notify(x, c); read_unlock(&xfrm_km_lock); } 调用这些通知函数前要填写事件的相关参数, 如: static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs) { unsigned proto; struct km_event c; proto = pfkey_satype2proto(hdr->sadb_msg_satype); if (proto == 0) return -EINVAL; xfrm_state_flush(proto); // 填写事件参数 // 协议 c.data.proto = proto; // 序列号 c.seq = hdr->sadb_msg_seq; // sock对方(用户空间进程)的pid c.pid = hdr->sadb_msg_pid; // 事件 c.event = XFRM_MSG_FLUSHSA; km_state_notify(NULL, &c); return 0; } 6.4 pf_key通知回调函数 6.4.1 发送SA消息时的通知回调 // 状态通知回调, 在SA操作后调用 static int pfkey_send_notify(struct xfrm_state *x, struct km_event *c) { // 根据事件类型来发送相关通知 switch (c->event) { case XFRM_MSG_EXPIRE: // SA到期的通知, SA消息类型为SADB_EXPIRE,只是进行了登记的PF_KEY socket可以收到 return key_notify_sa_expire(x, c); case XFRM_MSG_DELSA: case XFRM_MSG_NEWSA: case XFRM_MSG_UPDSA: // SA的通知, SA消息类型为分别为SADB_DELETE, SADB_ADD和SADB_UPDATE, // 所有PF_KEY socket都可以收到 return key_notify_sa(x, c); case XFRM_MSG_FLUSHSA: // 删除全部SA的通知, SA消息类型为分别为SADB_FLUSH, 所有PF_KEY socket都可以收到 return key_notify_sa_flush(c); case XFRM_MSG_NEWAE: /* not yet supported */ break; default: printk("pfkey: Unknown SA event %d\n", c->event); break; } return 0; } 6.4.2 发送ACQUIRE 关于ACQUIRE的作用, 摘一段UNP vol.1, r3中的话: chapter19.5: "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. " static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *xp, int dir) { struct sk_buff *skb; struct sadb_msg *hdr; struct sadb_address *addr; struct sadb_x_policy *pol; struct sockaddr_in *sin; #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) struct sockaddr_in6 *sin6; #endif int sockaddr_size; int size; struct sadb_x_sec_ctx *sec_ctx; struct xfrm_sec_ctx *xfrm_ctx; int ctx_size = 0;