⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 af_key.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	hdr = (struct sadb_msg *) skb->data;	hdr->sadb_msg_version = PF_KEY_V2;	hdr->sadb_msg_type = event2keytype(c->event);	hdr->sadb_msg_satype = pfkey_proto2satype(x->id.proto);	hdr->sadb_msg_errno = 0;	hdr->sadb_msg_reserved = 0;	hdr->sadb_msg_seq = c->seq;	hdr->sadb_msg_pid = c->pid;	pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL);	return 0;}static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs){	struct xfrm_state *x;	int err;	struct km_event c;	x = pfkey_msg2xfrm_state(hdr, ext_hdrs);	if (IS_ERR(x))		return PTR_ERR(x);	xfrm_state_hold(x);	if (hdr->sadb_msg_type == SADB_ADD)		err = xfrm_state_add(x);	else		err = xfrm_state_update(x);	xfrm_audit_state_add(x, err ? 0 : 1,			     audit_get_loginuid(current->audit_context), 0);	if (err < 0) {		x->km.state = XFRM_STATE_DEAD;		__xfrm_state_put(x);		goto out;	}	if (hdr->sadb_msg_type == SADB_ADD)		c.event = XFRM_MSG_NEWSA;	else		c.event = XFRM_MSG_UPDSA;	c.seq = hdr->sadb_msg_seq;	c.pid = hdr->sadb_msg_pid;	km_state_notify(x, &c);out:	xfrm_state_put(x);	return err;}static int pfkey_delete(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs){	struct xfrm_state *x;	struct km_event c;	int err;	if (!ext_hdrs[SADB_EXT_SA-1] ||	    !present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],				     ext_hdrs[SADB_EXT_ADDRESS_DST-1]))		return -EINVAL;	x = pfkey_xfrm_state_lookup(hdr, ext_hdrs);	if (x == NULL)		return -ESRCH;	if ((err = security_xfrm_state_delete(x)))		goto out;	if (xfrm_state_kern(x)) {		err = -EPERM;		goto out;	}	err = xfrm_state_delete(x);	if (err < 0)		goto out;	c.seq = hdr->sadb_msg_seq;	c.pid = hdr->sadb_msg_pid;	c.event = XFRM_MSG_DELSA;	km_state_notify(x, &c);out:	xfrm_audit_state_delete(x, err ? 0 : 1,			       audit_get_loginuid(current->audit_context), 0);	xfrm_state_put(x);	return err;}static int pfkey_get(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs){	__u8 proto;	struct sk_buff *out_skb;	struct sadb_msg *out_hdr;	struct xfrm_state *x;	if (!ext_hdrs[SADB_EXT_SA-1] ||	    !present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],				     ext_hdrs[SADB_EXT_ADDRESS_DST-1]))		return -EINVAL;	x = pfkey_xfrm_state_lookup(hdr, ext_hdrs);	if (x == NULL)		return -ESRCH;	out_skb = pfkey_xfrm_state2msg(x);	proto = x->id.proto;	xfrm_state_put(x);	if (IS_ERR(out_skb))		return  PTR_ERR(out_skb);	out_hdr = (struct sadb_msg *) out_skb->data;	out_hdr->sadb_msg_version = hdr->sadb_msg_version;	out_hdr->sadb_msg_type = SADB_GET;	out_hdr->sadb_msg_satype = pfkey_proto2satype(proto);	out_hdr->sadb_msg_errno = 0;	out_hdr->sadb_msg_reserved = 0;	out_hdr->sadb_msg_seq = hdr->sadb_msg_seq;	out_hdr->sadb_msg_pid = hdr->sadb_msg_pid;	pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, sk);	return 0;}static struct sk_buff *compose_sadb_supported(struct sadb_msg *orig,					      gfp_t allocation){	struct sk_buff *skb;	struct sadb_msg *hdr;	int len, auth_len, enc_len, i;	auth_len = xfrm_count_auth_supported();	if (auth_len) {		auth_len *= sizeof(struct sadb_alg);		auth_len += sizeof(struct sadb_supported);	}	enc_len = xfrm_count_enc_supported();	if (enc_len) {		enc_len *= sizeof(struct sadb_alg);		enc_len += sizeof(struct sadb_supported);	}	len = enc_len + auth_len + sizeof(struct sadb_msg);	skb = alloc_skb(len + 16, allocation);	if (!skb)		goto out_put_algs;	hdr = (struct sadb_msg *) skb_put(skb, sizeof(*hdr));	pfkey_hdr_dup(hdr, orig);	hdr->sadb_msg_errno = 0;	hdr->sadb_msg_len = len / sizeof(uint64_t);	if (auth_len) {		struct sadb_supported *sp;		struct sadb_alg *ap;		sp = (struct sadb_supported *) skb_put(skb, auth_len);		ap = (struct sadb_alg *) (sp + 1);		sp->sadb_supported_len = auth_len / sizeof(uint64_t);		sp->sadb_supported_exttype = SADB_EXT_SUPPORTED_AUTH;		for (i = 0; ; i++) {			struct xfrm_algo_desc *aalg = xfrm_aalg_get_byidx(i);			if (!aalg)				break;			if (aalg->available)				*ap++ = aalg->desc;		}	}	if (enc_len) {		struct sadb_supported *sp;		struct sadb_alg *ap;		sp = (struct sadb_supported *) skb_put(skb, enc_len);		ap = (struct sadb_alg *) (sp + 1);		sp->sadb_supported_len = enc_len / sizeof(uint64_t);		sp->sadb_supported_exttype = SADB_EXT_SUPPORTED_ENCRYPT;		for (i = 0; ; i++) {			struct xfrm_algo_desc *ealg = xfrm_ealg_get_byidx(i);			if (!ealg)				break;			if (ealg->available)				*ap++ = ealg->desc;		}	}out_put_algs:	return skb;}static int pfkey_register(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs){	struct pfkey_sock *pfk = pfkey_sk(sk);	struct sk_buff *supp_skb;	if (hdr->sadb_msg_satype > SADB_SATYPE_MAX)		return -EINVAL;	if (hdr->sadb_msg_satype != SADB_SATYPE_UNSPEC) {		if (pfk->registered&(1<<hdr->sadb_msg_satype))			return -EEXIST;		pfk->registered |= (1<<hdr->sadb_msg_satype);	}	xfrm_probe_algs();	supp_skb = compose_sadb_supported(hdr, GFP_KERNEL);	if (!supp_skb) {		if (hdr->sadb_msg_satype != SADB_SATYPE_UNSPEC)			pfk->registered &= ~(1<<hdr->sadb_msg_satype);		return -ENOBUFS;	}	pfkey_broadcast(supp_skb, GFP_KERNEL, BROADCAST_REGISTERED, sk);	return 0;}static int key_notify_sa_flush(struct km_event *c){	struct sk_buff *skb;	struct sadb_msg *hdr;	skb = alloc_skb(sizeof(struct sadb_msg) + 16, GFP_ATOMIC);	if (!skb)		return -ENOBUFS;	hdr = (struct sadb_msg *) skb_put(skb, sizeof(struct sadb_msg));	hdr->sadb_msg_satype = pfkey_proto2satype(c->data.proto);	hdr->sadb_msg_type = SADB_FLUSH;	hdr->sadb_msg_seq = c->seq;	hdr->sadb_msg_pid = c->pid;	hdr->sadb_msg_version = PF_KEY_V2;	hdr->sadb_msg_errno = (uint8_t) 0;	hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t));	pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL);	return 0;}static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs){	unsigned proto;	struct km_event c;	struct xfrm_audit audit_info;	int err;	proto = pfkey_satype2proto(hdr->sadb_msg_satype);	if (proto == 0)		return -EINVAL;	audit_info.loginuid = audit_get_loginuid(current->audit_context);	audit_info.secid = 0;	err = xfrm_state_flush(proto, &audit_info);	if (err)		return err;	c.data.proto = proto;	c.seq = hdr->sadb_msg_seq;	c.pid = hdr->sadb_msg_pid;	c.event = XFRM_MSG_FLUSHSA;	km_state_notify(NULL, &c);	return 0;}struct pfkey_dump_data{	struct sk_buff *skb;	struct sadb_msg *hdr;	struct sock *sk;};static int dump_sa(struct xfrm_state *x, int count, void *ptr){	struct pfkey_dump_data *data = ptr;	struct sk_buff *out_skb;	struct sadb_msg *out_hdr;	out_skb = pfkey_xfrm_state2msg(x);	if (IS_ERR(out_skb))		return PTR_ERR(out_skb);	out_hdr = (struct sadb_msg *) out_skb->data;	out_hdr->sadb_msg_version = data->hdr->sadb_msg_version;	out_hdr->sadb_msg_type = SADB_DUMP;	out_hdr->sadb_msg_satype = pfkey_proto2satype(x->id.proto);	out_hdr->sadb_msg_errno = 0;	out_hdr->sadb_msg_reserved = 0;	out_hdr->sadb_msg_seq = count;	out_hdr->sadb_msg_pid = data->hdr->sadb_msg_pid;	pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, data->sk);	return 0;}static int pfkey_dump(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs){	u8 proto;	struct pfkey_dump_data data = { .skb = skb, .hdr = hdr, .sk = sk };	proto = pfkey_satype2proto(hdr->sadb_msg_satype);	if (proto == 0)		return -EINVAL;	return xfrm_state_walk(proto, dump_sa, &data);}static int pfkey_promisc(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs){	struct pfkey_sock *pfk = pfkey_sk(sk);	int satype = hdr->sadb_msg_satype;	if (hdr->sadb_msg_len == (sizeof(*hdr) / sizeof(uint64_t))) {		/* XXX we mangle packet... */		hdr->sadb_msg_errno = 0;		if (satype != 0 && satype != 1)			return -EINVAL;		pfk->promisc = satype;	}	pfkey_broadcast(skb_clone(skb, GFP_KERNEL), GFP_KERNEL, BROADCAST_ALL, NULL);	return 0;}static int check_reqid(struct xfrm_policy *xp, int dir, int count, void *ptr){	int i;	u32 reqid = *(u32*)ptr;	for (i=0; i<xp->xfrm_nr; i++) {		if (xp->xfrm_vec[i].reqid == reqid)			return -EEXIST;	}	return 0;}static u32 gen_reqid(void){	u32 start;	static u32 reqid = IPSEC_MANUAL_REQID_MAX;	start = reqid;	do {		++reqid;		if (reqid == 0)			reqid = IPSEC_MANUAL_REQID_MAX+1;		if (xfrm_policy_walk(XFRM_POLICY_TYPE_MAIN, check_reqid,				     (void*)&reqid) != -EEXIST)			return reqid;	} while (reqid != start);	return 0;}static intparse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq){	struct xfrm_tmpl *t = xp->xfrm_vec + xp->xfrm_nr;	struct sockaddr_in *sin;#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)	struct sockaddr_in6 *sin6;#endif	int mode;	if (xp->xfrm_nr >= XFRM_MAX_DEPTH)		return -ELOOP;	if (rq->sadb_x_ipsecrequest_mode == 0)		return -EINVAL;	t->id.proto = rq->sadb_x_ipsecrequest_proto; /* XXX check proto */	if ((mode = pfkey_mode_to_xfrm(rq->sadb_x_ipsecrequest_mode)) < 0)		return -EINVAL;	t->mode = mode;	if (rq->sadb_x_ipsecrequest_level == IPSEC_LEVEL_USE)		t->optional = 1;	else if (rq->sadb_x_ipsecrequest_level == IPSEC_LEVEL_UNIQUE) {		t->reqid = rq->sadb_x_ipsecrequest_reqid;		if (t->reqid > IPSEC_MANUAL_REQID_MAX)			t->reqid = 0;		if (!t->reqid && !(t->reqid = gen_reqid()))			return -ENOBUFS;	}	/* addresses present only in tunnel mode */	if (t->mode == XFRM_MODE_TUNNEL) {		struct sockaddr *sa;		sa = (struct sockaddr *)(rq+1);		switch(sa->sa_family) {		case AF_INET:			sin = (struct sockaddr_in*)sa;			t->saddr.a4 = sin->sin_addr.s_addr;			sin++;			if (sin->sin_family != AF_INET)				return -EINVAL;			t->id.daddr.a4 = sin->sin_addr.s_addr;			break;#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)		case AF_INET6:			sin6 = (struct sockaddr_in6*)sa;			memcpy(t->saddr.a6, &sin6->sin6_addr, sizeof(struct in6_addr));			sin6++;			if (sin6->sin6_family != AF_INET6)				return -EINVAL;			memcpy(t->id.daddr.a6, &sin6->sin6_addr, sizeof(struct in6_addr));			break;#endif		default:			return -EINVAL;		}		t->encap_family = sa->sa_family;	} else		t->encap_family = xp->family;	/* No way to set this via kame pfkey */	t->aalgos = t->ealgos = t->calgos = ~0;	xp->xfrm_nr++;	return 0;}static intparse_ipsecrequests(struct xfrm_policy *xp, struct sadb_x_policy *pol){	int err;	int len = pol->sadb_x_policy_len*8 - sizeof(struct sadb_x_policy);	struct sadb_x_ipsecrequest *rq = (void*)(pol+1);	while (len >= sizeof(struct sadb_x_ipsecrequest)) {		if ((err = parse_ipsecrequest(xp, rq)) < 0)			return err;		len -= rq->sadb_x_ipsecrequest_len;		rq = (void*)((u8*)rq + rq->sadb_x_ipsecrequest_len);	}	return 0;}static inline int pfkey_xfrm_policy2sec_ctx_size(struct xfrm_policy *xp){  struct xfrm_sec_ctx *xfrm_ctx = xp->security;	if (xfrm_ctx) {		int len = sizeof(struct sadb_x_sec_ctx);		len += xfrm_ctx->ctx_len;		return PFKEY_ALIGN8(len);	}	return 0;}static int pfkey_xfrm_policy2msg_size(struct xfrm_policy *xp){	struct xfrm_tmpl *t;	int sockaddr_size = pfkey_sockaddr_size(xp->family);	int socklen = 0;	int i;	for (i=0; i<xp->xfrm_nr; i++) {		t = xp->xfrm_vec + i;		socklen += (t->encap_family == AF_INET ?			    sizeof(struct sockaddr_in) :			    sizeof(struct sockaddr_in6));	}	return sizeof(struct sadb_msg) +		(sizeof(struct sadb_lifetime) * 3) +		(sizeof(struct sadb_address) * 2) +		(sockaddr_size * 2) +		sizeof(struct sadb_x_policy) +		(xp->xfrm_nr * sizeof(struct sadb_x_ipsecrequest)) +		(socklen * 2) +		pfkey_xfrm_policy2sec_ctx_size(xp);}static struct sk_buff * pfkey_xfrm_policy2msg_prep(struct xfrm_policy *xp)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -