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

📄 af_key.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
{	struct sk_buff *skb;	int size;	size = pfkey_xfrm_policy2msg_size(xp);	skb =  alloc_skb(size + 16, GFP_ATOMIC);	if (skb == NULL)		return ERR_PTR(-ENOBUFS);	return skb;}static int pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, int dir){	struct sadb_msg *hdr;	struct sadb_address *addr;	struct sadb_lifetime *lifetime;	struct sadb_x_policy *pol;	struct sockaddr_in   *sin;	struct sadb_x_sec_ctx *sec_ctx;	struct xfrm_sec_ctx *xfrm_ctx;#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)	struct sockaddr_in6  *sin6;#endif	int i;	int size;	int sockaddr_size = pfkey_sockaddr_size(xp->family);	int socklen = (xp->family == AF_INET ?		       sizeof(struct sockaddr_in) :		       sizeof(struct sockaddr_in6));	size = pfkey_xfrm_policy2msg_size(xp);	/* call should fill header later */	hdr = (struct sadb_msg *) skb_put(skb, sizeof(struct sadb_msg));	memset(hdr, 0, size);	/* XXX do we need this ? */	/* src address */	addr = (struct sadb_address*) skb_put(skb,					      sizeof(struct sadb_address)+sockaddr_size);	addr->sadb_address_len =		(sizeof(struct sadb_address)+sockaddr_size)/			sizeof(uint64_t);	addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC;	addr->sadb_address_proto = pfkey_proto_from_xfrm(xp->selector.proto);	addr->sadb_address_prefixlen = xp->selector.prefixlen_s;	addr->sadb_address_reserved = 0;	/* src address */	if (xp->family == AF_INET) {		sin = (struct sockaddr_in *) (addr + 1);		sin->sin_family = AF_INET;		sin->sin_addr.s_addr = xp->selector.saddr.a4;		sin->sin_port = xp->selector.sport;		memset(sin->sin_zero, 0, sizeof(sin->sin_zero));	}#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)	else if (xp->family == AF_INET6) {		sin6 = (struct sockaddr_in6 *) (addr + 1);		sin6->sin6_family = AF_INET6;		sin6->sin6_port = xp->selector.sport;		sin6->sin6_flowinfo = 0;		memcpy(&sin6->sin6_addr, xp->selector.saddr.a6,		       sizeof(struct in6_addr));		sin6->sin6_scope_id = 0;	}#endif	else		BUG();	/* dst address */	addr = (struct sadb_address*) skb_put(skb,					      sizeof(struct sadb_address)+sockaddr_size);	addr->sadb_address_len =		(sizeof(struct sadb_address)+sockaddr_size)/			sizeof(uint64_t);	addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST;	addr->sadb_address_proto = pfkey_proto_from_xfrm(xp->selector.proto);	addr->sadb_address_prefixlen = xp->selector.prefixlen_d;	addr->sadb_address_reserved = 0;	if (xp->family == AF_INET) {		sin = (struct sockaddr_in *) (addr + 1);		sin->sin_family = AF_INET;		sin->sin_addr.s_addr = xp->selector.daddr.a4;		sin->sin_port = xp->selector.dport;		memset(sin->sin_zero, 0, sizeof(sin->sin_zero));	}#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)	else if (xp->family == AF_INET6) {		sin6 = (struct sockaddr_in6 *) (addr + 1);		sin6->sin6_family = AF_INET6;		sin6->sin6_port = xp->selector.dport;		sin6->sin6_flowinfo = 0;		memcpy(&sin6->sin6_addr, xp->selector.daddr.a6,		       sizeof(struct in6_addr));		sin6->sin6_scope_id = 0;	}#endif	else		BUG();	/* hard time */	lifetime = (struct sadb_lifetime *)  skb_put(skb,						     sizeof(struct sadb_lifetime));	lifetime->sadb_lifetime_len =		sizeof(struct sadb_lifetime)/sizeof(uint64_t);	lifetime->sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;	lifetime->sadb_lifetime_allocations =  _X2KEY(xp->lft.hard_packet_limit);	lifetime->sadb_lifetime_bytes = _X2KEY(xp->lft.hard_byte_limit);	lifetime->sadb_lifetime_addtime = xp->lft.hard_add_expires_seconds;	lifetime->sadb_lifetime_usetime = xp->lft.hard_use_expires_seconds;	/* soft time */	lifetime = (struct sadb_lifetime *)  skb_put(skb,						     sizeof(struct sadb_lifetime));	lifetime->sadb_lifetime_len =		sizeof(struct sadb_lifetime)/sizeof(uint64_t);	lifetime->sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;	lifetime->sadb_lifetime_allocations =  _X2KEY(xp->lft.soft_packet_limit);	lifetime->sadb_lifetime_bytes = _X2KEY(xp->lft.soft_byte_limit);	lifetime->sadb_lifetime_addtime = xp->lft.soft_add_expires_seconds;	lifetime->sadb_lifetime_usetime = xp->lft.soft_use_expires_seconds;	/* current time */	lifetime = (struct sadb_lifetime *)  skb_put(skb,						     sizeof(struct sadb_lifetime));	lifetime->sadb_lifetime_len =		sizeof(struct sadb_lifetime)/sizeof(uint64_t);	lifetime->sadb_lifetime_exttype = SADB_EXT_LIFETIME_CURRENT;	lifetime->sadb_lifetime_allocations = xp->curlft.packets;	lifetime->sadb_lifetime_bytes = xp->curlft.bytes;	lifetime->sadb_lifetime_addtime = xp->curlft.add_time;	lifetime->sadb_lifetime_usetime = xp->curlft.use_time;	pol = (struct sadb_x_policy *)  skb_put(skb, sizeof(struct sadb_x_policy));	pol->sadb_x_policy_len = sizeof(struct sadb_x_policy)/sizeof(uint64_t);	pol->sadb_x_policy_exttype = SADB_X_EXT_POLICY;	pol->sadb_x_policy_type = IPSEC_POLICY_DISCARD;	if (xp->action == XFRM_POLICY_ALLOW) {		if (xp->xfrm_nr)			pol->sadb_x_policy_type = IPSEC_POLICY_IPSEC;		else			pol->sadb_x_policy_type = IPSEC_POLICY_NONE;	}	pol->sadb_x_policy_dir = dir+1;	pol->sadb_x_policy_id = xp->index;	pol->sadb_x_policy_priority = xp->priority;	for (i=0; i<xp->xfrm_nr; i++) {		struct sadb_x_ipsecrequest *rq;		struct xfrm_tmpl *t = xp->xfrm_vec + i;		int req_size;		int mode;		req_size = sizeof(struct sadb_x_ipsecrequest);		if (t->mode == XFRM_MODE_TUNNEL)			req_size += ((t->encap_family == AF_INET ?				     sizeof(struct sockaddr_in) :				     sizeof(struct sockaddr_in6)) * 2);		else			size -= 2*socklen;		rq = (void*)skb_put(skb, req_size);		pol->sadb_x_policy_len += req_size/8;		memset(rq, 0, sizeof(*rq));		rq->sadb_x_ipsecrequest_len = req_size;		rq->sadb_x_ipsecrequest_proto = t->id.proto;		if ((mode = pfkey_mode_from_xfrm(t->mode)) < 0)			return -EINVAL;		rq->sadb_x_ipsecrequest_mode = mode;		rq->sadb_x_ipsecrequest_level = IPSEC_LEVEL_REQUIRE;		if (t->reqid)			rq->sadb_x_ipsecrequest_level = IPSEC_LEVEL_UNIQUE;		if (t->optional)			rq->sadb_x_ipsecrequest_level = IPSEC_LEVEL_USE;		rq->sadb_x_ipsecrequest_reqid = t->reqid;		if (t->mode == XFRM_MODE_TUNNEL) {			switch (t->encap_family) {			case AF_INET:				sin = (void*)(rq+1);				sin->sin_family = AF_INET;				sin->sin_addr.s_addr = t->saddr.a4;				sin->sin_port = 0;				memset(sin->sin_zero, 0, sizeof(sin->sin_zero));				sin++;				sin->sin_family = AF_INET;				sin->sin_addr.s_addr = t->id.daddr.a4;				sin->sin_port = 0;				memset(sin->sin_zero, 0, sizeof(sin->sin_zero));				break;#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)			case AF_INET6:				sin6 = (void*)(rq+1);				sin6->sin6_family = AF_INET6;				sin6->sin6_port = 0;				sin6->sin6_flowinfo = 0;				memcpy(&sin6->sin6_addr, t->saddr.a6,				       sizeof(struct in6_addr));				sin6->sin6_scope_id = 0;				sin6++;				sin6->sin6_family = AF_INET6;				sin6->sin6_port = 0;				sin6->sin6_flowinfo = 0;				memcpy(&sin6->sin6_addr, t->id.daddr.a6,				       sizeof(struct in6_addr));				sin6->sin6_scope_id = 0;				break;#endif			default:				break;			}		}	}	/* security context */	if ((xfrm_ctx = xp->security)) {		int ctx_size = pfkey_xfrm_policy2sec_ctx_size(xp);		sec_ctx = (struct sadb_x_sec_ctx *) skb_put(skb, ctx_size);		sec_ctx->sadb_x_sec_len = ctx_size / sizeof(uint64_t);		sec_ctx->sadb_x_sec_exttype = SADB_X_EXT_SEC_CTX;		sec_ctx->sadb_x_ctx_doi = xfrm_ctx->ctx_doi;		sec_ctx->sadb_x_ctx_alg = xfrm_ctx->ctx_alg;		sec_ctx->sadb_x_ctx_len = xfrm_ctx->ctx_len;		memcpy(sec_ctx + 1, xfrm_ctx->ctx_str,		       xfrm_ctx->ctx_len);	}	hdr->sadb_msg_len = size / sizeof(uint64_t);	hdr->sadb_msg_reserved = atomic_read(&xp->refcnt);	return 0;}static int key_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *c){	struct sk_buff *out_skb;	struct sadb_msg *out_hdr;	int err;	out_skb = pfkey_xfrm_policy2msg_prep(xp);	if (IS_ERR(out_skb)) {		err = PTR_ERR(out_skb);		goto out;	}	err = pfkey_xfrm_policy2msg(out_skb, xp, dir);	if (err < 0)		return err;	out_hdr = (struct sadb_msg *) out_skb->data;	out_hdr->sadb_msg_version = PF_KEY_V2;	if (c->data.byid && c->event == XFRM_MSG_DELPOLICY)		out_hdr->sadb_msg_type = SADB_X_SPDDELETE2;	else		out_hdr->sadb_msg_type = event2poltype(c->event);	out_hdr->sadb_msg_errno = 0;	out_hdr->sadb_msg_seq = c->seq;	out_hdr->sadb_msg_pid = c->pid;	pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ALL, NULL);out:	return 0;}static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs){	int err = 0;	struct sadb_lifetime *lifetime;	struct sadb_address *sa;	struct sadb_x_policy *pol;	struct xfrm_policy *xp;	struct km_event c;	struct sadb_x_sec_ctx *sec_ctx;	if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],				     ext_hdrs[SADB_EXT_ADDRESS_DST-1]) ||	    !ext_hdrs[SADB_X_EXT_POLICY-1])		return -EINVAL;	pol = ext_hdrs[SADB_X_EXT_POLICY-1];	if (pol->sadb_x_policy_type > IPSEC_POLICY_IPSEC)		return -EINVAL;	if (!pol->sadb_x_policy_dir || pol->sadb_x_policy_dir >= IPSEC_DIR_MAX)		return -EINVAL;	xp = xfrm_policy_alloc(GFP_KERNEL);	if (xp == NULL)		return -ENOBUFS;	xp->action = (pol->sadb_x_policy_type == IPSEC_POLICY_DISCARD ?		      XFRM_POLICY_BLOCK : XFRM_POLICY_ALLOW);	xp->priority = pol->sadb_x_policy_priority;	sa = ext_hdrs[SADB_EXT_ADDRESS_SRC-1],	xp->family = pfkey_sadb_addr2xfrm_addr(sa, &xp->selector.saddr);	if (!xp->family) {		err = -EINVAL;		goto out;	}	xp->selector.family = xp->family;	xp->selector.prefixlen_s = sa->sadb_address_prefixlen;	xp->selector.proto = pfkey_proto_to_xfrm(sa->sadb_address_proto);	xp->selector.sport = ((struct sockaddr_in *)(sa+1))->sin_port;	if (xp->selector.sport)		xp->selector.sport_mask = htons(0xffff);	sa = ext_hdrs[SADB_EXT_ADDRESS_DST-1],	pfkey_sadb_addr2xfrm_addr(sa, &xp->selector.daddr);	xp->selector.prefixlen_d = sa->sadb_address_prefixlen;	/* Amusing, we set this twice.  KAME apps appear to set same value	 * in both addresses.	 */	xp->selector.proto = pfkey_proto_to_xfrm(sa->sadb_address_proto);	xp->selector.dport = ((struct sockaddr_in *)(sa+1))->sin_port;	if (xp->selector.dport)		xp->selector.dport_mask = htons(0xffff);	sec_ctx = (struct sadb_x_sec_ctx *) ext_hdrs[SADB_X_EXT_SEC_CTX-1];	if (sec_ctx != NULL) {		struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx);		if (!uctx) {			err = -ENOBUFS;			goto out;		}		err = security_xfrm_policy_alloc(xp, uctx);		kfree(uctx);		if (err)			goto out;	}	xp->lft.soft_byte_limit = XFRM_INF;	xp->lft.hard_byte_limit = XFRM_INF;	xp->lft.soft_packet_limit = XFRM_INF;	xp->lft.hard_packet_limit = XFRM_INF;	if ((lifetime = ext_hdrs[SADB_EXT_LIFETIME_HARD-1]) != NULL) {		xp->lft.hard_packet_limit = _KEY2X(lifetime->sadb_lifetime_allocations);		xp->lft.hard_byte_limit = _KEY2X(lifetime->sadb_lifetime_bytes);		xp->lft.hard_add_expires_seconds = lifetime->sadb_lifetime_addtime;		xp->lft.hard_use_expires_seconds = lifetime->sadb_lifetime_usetime;	}	if ((lifetime = ext_hdrs[SADB_EXT_LIFETIME_SOFT-1]) != NULL) {		xp->lft.soft_packet_limit = _KEY2X(lifetime->sadb_lifetime_allocations);		xp->lft.soft_byte_limit = _KEY2X(lifetime->sadb_lifetime_bytes);		xp->lft.soft_add_expires_seconds = lifetime->sadb_lifetime_addtime;		xp->lft.soft_use_expires_seconds = lifetime->sadb_lifetime_usetime;	}	xp->xfrm_nr = 0;	if (pol->sadb_x_policy_type == IPSEC_POLICY_IPSEC &&	    (err = parse_ipsecrequests(xp, pol)) < 0)		goto out;	err = xfrm_policy_insert(pol->sadb_x_policy_dir-1, xp,				 hdr->sadb_msg_type != SADB_X_SPDUPDATE);	xfrm_audit_policy_add(xp, err ? 0 : 1,			     audit_get_loginuid(current->audit_context), 0);	if (err)		goto out;	if (hdr->sadb_msg_type == SADB_X_SPDUPDATE)		c.event = XFRM_MSG_UPDPOLICY;	else		c.event = XFRM_MSG_NEWPOLICY;	c.seq = hdr->sadb_msg_seq;	c.pid = hdr->sadb_msg_pid;	km_policy_notify(xp, pol->sadb_x_policy_dir-1, &c);	xfrm_pol_put(xp);	return 0;out:	security_xfrm_policy_free(xp);	kfree(xp);	return err;}static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs){	int err;	struct sadb_address *sa;	struct sadb_x_policy *pol;	struct xfrm_policy *xp, tmp;	struct xfrm_selector sel;	struct km_event c;	struct sadb_x_sec_ctx *sec_ctx;	if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],				     ext_hdrs[SADB_EXT_ADDRESS_DST-1]) ||	    !ext_hdrs[SADB_X_EXT_POLICY-1])		return -EINVAL;	pol = ext_hdrs[SADB_X_EXT_POLICY-1];	if (!pol->sadb_x_policy_dir || pol->sadb_x_policy_dir >= IPSEC_DIR_MAX)		return -EINVAL;	memset(&sel, 0, sizeof(sel));	sa = ext_hdrs[SADB_EXT_ADDRESS_SRC-1],	sel.family = pfkey_sadb_addr2xfrm_addr(sa, &sel.saddr);	sel.prefixlen_s = sa->sadb_address_prefixlen;	sel.proto = pfkey_proto_to_xfrm(sa->sadb_address_proto);	sel.sport = ((struct sockaddr_in *)(sa+1))->sin_port;	if (sel.sport)		sel.sport_mask = htons(0xffff);	sa = ext_hdrs[SADB_EXT_ADDRESS_DST-1],	pfkey_sadb_addr2xfrm_addr(sa, &sel.daddr);	sel.prefixlen_d = sa->sadb_address_prefixlen;	sel.proto = pfkey_proto_to_xfrm(sa->sadb_address_proto);	sel.dport = ((struct sockaddr_in *)(sa+1))->sin_port;	if (sel.dport)		sel.dport_mask = htons(0xffff);	sec_ctx = (struct sadb_x_sec_ctx *) ext_hdrs[SADB_X_EXT_SEC_CTX-1];	memset(&tmp, 0, sizeof(struct xfrm_policy));	if (sec_ctx != NULL) {		struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx);		if (!uctx)			return -ENOMEM;		err = security_xfrm_policy_alloc(&tmp, uctx);		kfree(uctx);		if (err)			return err;	}	xp = xfrm_policy_bysel_ctx(XFRM_POLICY_TYPE_MAIN, pol->sadb_x_policy_dir-1,				   &sel, tmp.security, 1, &err);	security_xfrm_policy_free(&tmp);	if (xp == NULL)		return -ENOENT;	xfrm_audit_policy_delete(xp, err ? 0 : 1,				audit_get_loginuid(current->audit_context), 0);	if (err)		goto out;	c.seq = hdr->sadb_msg_seq;	c.pid = hdr->sadb_msg_pid;	c.event = XFRM_MSG_DELPOLICY;	km_policy_notify(xp, pol->sadb_x_policy_dir-1, &c);out:	xfrm_pol_put(xp);	return err;}static int key_pol_get_resp(struct sock *sk, struct xfrm_policy *xp, struct sadb_msg *hdr, int dir){	int err;	struct sk_buff *out_skb;	struct sadb_msg *out_hdr;	err = 0;	out_skb = pfkey_xfrm_policy2msg_prep(xp);	if (IS_ERR(out_skb)) {		err =  PTR_ERR(out_skb);		goto out;	}	err = pfkey_xfrm_policy2msg(out_skb, xp, dir);	if (err < 0)		goto out;	out_hdr = (struct sadb_msg *) out_skb->data;	out_hdr->sadb_msg_version = hdr->sadb_msg_version;	out_hdr->sadb_msg_type = hdr->sadb_msg_type;	out_hdr->sadb_msg_

⌨️ 快捷键说明

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