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

📄 af_key.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
			if (ext_type == SADB_EXT_ADDRESS_SRC ||			    ext_type == SADB_EXT_ADDRESS_DST ||			    ext_type == SADB_EXT_ADDRESS_PROXY ||			    ext_type == SADB_X_EXT_NAT_T_OA) {				if (verify_address_len(p))					return -EINVAL;			}			if (ext_type == SADB_X_EXT_SEC_CTX) {				if (verify_sec_ctx_len(p))					return -EINVAL;			}			ext_hdrs[ext_type-1] = p;		}		p   += ext_len;		len -= ext_len;	}	return 0;}static uint16_tpfkey_satype2proto(uint8_t satype){	switch (satype) {	case SADB_SATYPE_UNSPEC:		return IPSEC_PROTO_ANY;	case SADB_SATYPE_AH:		return IPPROTO_AH;	case SADB_SATYPE_ESP:		return IPPROTO_ESP;	case SADB_X_SATYPE_IPCOMP:		return IPPROTO_COMP;		break;	default:		return 0;	}	/* NOTREACHED */}static uint8_tpfkey_proto2satype(uint16_t proto){	switch (proto) {	case IPPROTO_AH:		return SADB_SATYPE_AH;	case IPPROTO_ESP:		return SADB_SATYPE_ESP;	case IPPROTO_COMP:		return SADB_X_SATYPE_IPCOMP;		break;	default:		return 0;	}	/* NOTREACHED */}/* BTW, this scheme means that there is no way with PFKEY2 sockets to * say specifically 'just raw sockets' as we encode them as 255. */static uint8_t pfkey_proto_to_xfrm(uint8_t proto){	return (proto == IPSEC_PROTO_ANY ? 0 : proto);}static uint8_t pfkey_proto_from_xfrm(uint8_t proto){	return (proto ? proto : IPSEC_PROTO_ANY);}static int pfkey_sadb_addr2xfrm_addr(struct sadb_address *addr,				     xfrm_address_t *xaddr){	switch (((struct sockaddr*)(addr + 1))->sa_family) {	case AF_INET:		xaddr->a4 =			((struct sockaddr_in *)(addr + 1))->sin_addr.s_addr;		return AF_INET;#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)	case AF_INET6:		memcpy(xaddr->a6,		       &((struct sockaddr_in6 *)(addr + 1))->sin6_addr,		       sizeof(struct in6_addr));		return AF_INET6;#endif	default:		return 0;	}	/* NOTREACHED */}static struct  xfrm_state *pfkey_xfrm_state_lookup(struct sadb_msg *hdr, void **ext_hdrs){	struct sadb_sa *sa;	struct sadb_address *addr;	uint16_t proto;	unsigned short family;	xfrm_address_t *xaddr;	sa = (struct sadb_sa *) ext_hdrs[SADB_EXT_SA-1];	if (sa == NULL)		return NULL;	proto = pfkey_satype2proto(hdr->sadb_msg_satype);	if (proto == 0)		return NULL;	/* sadb_address_len should be checked by caller */	addr = (struct sadb_address *) ext_hdrs[SADB_EXT_ADDRESS_DST-1];	if (addr == NULL)		return NULL;	family = ((struct sockaddr *)(addr + 1))->sa_family;	switch (family) {	case AF_INET:		xaddr = (xfrm_address_t *)&((struct sockaddr_in *)(addr + 1))->sin_addr;		break;#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)	case AF_INET6:		xaddr = (xfrm_address_t *)&((struct sockaddr_in6 *)(addr + 1))->sin6_addr;		break;#endif	default:		xaddr = NULL;	}	if (!xaddr)		return NULL;	return xfrm_state_lookup(xaddr, sa->sadb_sa_spi, proto, family);}#define PFKEY_ALIGN8(a) (1 + (((a) - 1) | (8 - 1)))static intpfkey_sockaddr_size(sa_family_t family){	switch (family) {	case AF_INET:		return PFKEY_ALIGN8(sizeof(struct sockaddr_in));#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)	case AF_INET6:		return PFKEY_ALIGN8(sizeof(struct sockaddr_in6));#endif	default:		return 0;	}	/* NOTREACHED */}static inline int pfkey_mode_from_xfrm(int mode){	switch(mode) {	case XFRM_MODE_TRANSPORT:		return IPSEC_MODE_TRANSPORT;	case XFRM_MODE_TUNNEL:		return IPSEC_MODE_TUNNEL;	case XFRM_MODE_BEET:		return IPSEC_MODE_BEET;	default:		return -1;	}}static inline int pfkey_mode_to_xfrm(int mode){	switch(mode) {	case IPSEC_MODE_ANY:	/*XXX*/	case IPSEC_MODE_TRANSPORT:		return XFRM_MODE_TRANSPORT;	case IPSEC_MODE_TUNNEL:		return XFRM_MODE_TUNNEL;	case IPSEC_MODE_BEET:		return XFRM_MODE_BEET;	default:		return -1;	}}static struct sk_buff *__pfkey_xfrm_state2msg(struct xfrm_state *x,					      int add_keys, int hsc){	struct sk_buff *skb;	struct sadb_msg *hdr;	struct sadb_sa *sa;	struct sadb_lifetime *lifetime;	struct sadb_address *addr;	struct sadb_key *key;	struct sadb_x_sa2 *sa2;	struct sockaddr_in *sin;	struct sadb_x_sec_ctx *sec_ctx;	struct xfrm_sec_ctx *xfrm_ctx;	int ctx_size = 0;#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)	struct sockaddr_in6 *sin6;#endif	int size;	int auth_key_size = 0;	int encrypt_key_size = 0;	int sockaddr_size;	struct xfrm_encap_tmpl *natt = NULL;	int mode;	/* address family check */	sockaddr_size = pfkey_sockaddr_size(x->props.family);	if (!sockaddr_size)		return ERR_PTR(-EINVAL);	/* base, SA, (lifetime (HSC),) address(SD), (address(P),)	   key(AE), (identity(SD),) (sensitivity)> */	size = sizeof(struct sadb_msg) +sizeof(struct sadb_sa) +		sizeof(struct sadb_lifetime) +		((hsc & 1) ? sizeof(struct sadb_lifetime) : 0) +		((hsc & 2) ? sizeof(struct sadb_lifetime) : 0) +			sizeof(struct sadb_address)*2 +				sockaddr_size*2 +					sizeof(struct sadb_x_sa2);	if ((xfrm_ctx = x->security)) {		ctx_size = PFKEY_ALIGN8(xfrm_ctx->ctx_len);		size += sizeof(struct sadb_x_sec_ctx) + ctx_size;	}	/* identity & sensitivity */	if ((x->props.family == AF_INET &&	     x->sel.saddr.a4 != x->props.saddr.a4)#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)	    || (x->props.family == AF_INET6 &&		memcmp (x->sel.saddr.a6, x->props.saddr.a6, sizeof (struct in6_addr)))#endif		)		size += sizeof(struct sadb_address) + sockaddr_size;	if (add_keys) {		if (x->aalg && x->aalg->alg_key_len) {			auth_key_size =				PFKEY_ALIGN8((x->aalg->alg_key_len + 7) / 8);			size += sizeof(struct sadb_key) + auth_key_size;		}		if (x->ealg && x->ealg->alg_key_len) {			encrypt_key_size =				PFKEY_ALIGN8((x->ealg->alg_key_len+7) / 8);			size += sizeof(struct sadb_key) + encrypt_key_size;		}	}	if (x->encap)		natt = x->encap;	if (natt && natt->encap_type) {		size += sizeof(struct sadb_x_nat_t_type);		size += sizeof(struct sadb_x_nat_t_port);		size += sizeof(struct sadb_x_nat_t_port);	}	skb =  alloc_skb(size + 16, GFP_ATOMIC);	if (skb == NULL)		return ERR_PTR(-ENOBUFS);	/* 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 ? */	hdr->sadb_msg_len = size / sizeof(uint64_t);	/* sa */	sa = (struct sadb_sa *)  skb_put(skb, sizeof(struct sadb_sa));	sa->sadb_sa_len = sizeof(struct sadb_sa)/sizeof(uint64_t);	sa->sadb_sa_exttype = SADB_EXT_SA;	sa->sadb_sa_spi = x->id.spi;	sa->sadb_sa_replay = x->props.replay_window;	switch (x->km.state) {	case XFRM_STATE_VALID:		sa->sadb_sa_state = x->km.dying ?			SADB_SASTATE_DYING : SADB_SASTATE_MATURE;		break;	case XFRM_STATE_ACQ:		sa->sadb_sa_state = SADB_SASTATE_LARVAL;		break;	default:		sa->sadb_sa_state = SADB_SASTATE_DEAD;		break;	}	sa->sadb_sa_auth = 0;	if (x->aalg) {		struct xfrm_algo_desc *a = xfrm_aalg_get_byname(x->aalg->alg_name, 0);		sa->sadb_sa_auth = a ? a->desc.sadb_alg_id : 0;	}	sa->sadb_sa_encrypt = 0;	BUG_ON(x->ealg && x->calg);	if (x->ealg) {		struct xfrm_algo_desc *a = xfrm_ealg_get_byname(x->ealg->alg_name, 0);		sa->sadb_sa_encrypt = a ? a->desc.sadb_alg_id : 0;	}	/* KAME compatible: sadb_sa_encrypt is overloaded with calg id */	if (x->calg) {		struct xfrm_algo_desc *a = xfrm_calg_get_byname(x->calg->alg_name, 0);		sa->sadb_sa_encrypt = a ? a->desc.sadb_alg_id : 0;	}	sa->sadb_sa_flags = 0;	if (x->props.flags & XFRM_STATE_NOECN)		sa->sadb_sa_flags |= SADB_SAFLAGS_NOECN;	if (x->props.flags & XFRM_STATE_DECAP_DSCP)		sa->sadb_sa_flags |= SADB_SAFLAGS_DECAP_DSCP;	if (x->props.flags & XFRM_STATE_NOPMTUDISC)		sa->sadb_sa_flags |= SADB_SAFLAGS_NOPMTUDISC;	/* hard time */	if (hsc & 2) {		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(x->lft.hard_packet_limit);		lifetime->sadb_lifetime_bytes = _X2KEY(x->lft.hard_byte_limit);		lifetime->sadb_lifetime_addtime = x->lft.hard_add_expires_seconds;		lifetime->sadb_lifetime_usetime = x->lft.hard_use_expires_seconds;	}	/* soft time */	if (hsc & 1) {		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(x->lft.soft_packet_limit);		lifetime->sadb_lifetime_bytes = _X2KEY(x->lft.soft_byte_limit);		lifetime->sadb_lifetime_addtime = x->lft.soft_add_expires_seconds;		lifetime->sadb_lifetime_usetime = x->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 = x->curlft.packets;	lifetime->sadb_lifetime_bytes = x->curlft.bytes;	lifetime->sadb_lifetime_addtime = x->curlft.add_time;	lifetime->sadb_lifetime_usetime = x->curlft.use_time;	/* 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;	/* "if the ports are non-zero, then the sadb_address_proto field,	   normally zero, MUST be filled in with the transport	   protocol's number." - RFC2367 */	addr->sadb_address_proto = 0;	addr->sadb_address_reserved = 0;	if (x->props.family == AF_INET) {		addr->sadb_address_prefixlen = 32;		sin = (struct sockaddr_in *) (addr + 1);		sin->sin_family = AF_INET;		sin->sin_addr.s_addr = x->props.saddr.a4;		sin->sin_port = 0;		memset(sin->sin_zero, 0, sizeof(sin->sin_zero));	}#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)	else if (x->props.family == AF_INET6) {		addr->sadb_address_prefixlen = 128;		sin6 = (struct sockaddr_in6 *) (addr + 1);		sin6->sin6_family = AF_INET6;		sin6->sin6_port = 0;		sin6->sin6_flowinfo = 0;		memcpy(&sin6->sin6_addr, x->props.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 = 0;	addr->sadb_address_prefixlen = 32; /* XXX */	addr->sadb_address_reserved = 0;	if (x->props.family == AF_INET) {		sin = (struct sockaddr_in *) (addr + 1);		sin->sin_family = AF_INET;		sin->sin_addr.s_addr = x->id.daddr.a4;		sin->sin_port = 0;		memset(sin->sin_zero, 0, sizeof(sin->sin_zero));		if (x->sel.saddr.a4 != x->props.saddr.a4) {			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_PROXY;			addr->sadb_address_proto =				pfkey_proto_from_xfrm(x->sel.proto);			addr->sadb_address_prefixlen = x->sel.prefixlen_s;			addr->sadb_address_reserved = 0;			sin = (struct sockaddr_in *) (addr + 1);			sin->sin_family = AF_INET;			sin->sin_addr.s_addr = x->sel.saddr.a4;			sin->sin_port = x->sel.sport;			memset(sin->sin_zero, 0, sizeof(sin->sin_zero));		}	}#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)	else if (x->props.family == AF_INET6) {		addr->sadb_address_prefixlen = 128;		sin6 = (struct sockaddr_in6 *) (addr + 1);		sin6->sin6_family = AF_INET6;		sin6->sin6_port = 0;		sin6->sin6_flowinfo = 0;		memcpy(&sin6->sin6_addr, x->id.daddr.a6, sizeof(struct in6_addr));		sin6->sin6_scope_id = 0;		if (memcmp (x->sel.saddr.a6, x->props.saddr.a6,			    sizeof(struct in6_addr))) {			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_PROXY;			addr->sadb_address_proto =				pfkey_proto_from_xfrm(x->sel.proto);			addr->sadb_address_prefixlen = x->sel.prefixlen_s;			addr->sadb_address_reserved = 0;			sin6 = (struct sockaddr_in6 *) (addr + 1);			sin6->sin6_family = AF_INET6;			sin6->sin6_port = x->sel.sport;			sin6->sin6_flowinfo = 0;			memcpy(&sin6->sin6_addr, x->sel.saddr.a6,			       sizeof(struct in6_addr));			sin6->sin6_scope_id = 0;		}	}#endif	else		BUG();	/* auth key */	if (add_keys && auth_key_size) {		key = (struct sadb_key *) skb_put(skb,						  sizeof(struct sadb_key)+auth_key_size);		key->sadb_key_len = (sizeof(struct sadb_key) + auth_key_size) /			sizeof(uint64_t);		key->sadb_key_exttype = SADB_EXT_KEY_AUTH;		key->sadb_key_bits = x->aalg->alg_key_len;		key->sadb_key_reserved = 0;		memcpy(key + 1, x->aalg->alg_key, (x->aalg->alg_key_len+7)/8);	}	/* encrypt key */	if (add_keys && encrypt_key_size) {		key = (struct sadb_key *) skb_put(skb,						  sizeof(struct sadb_key)+encrypt_key_size);		key->sadb_key_len = (sizeof(struct sadb_key) +				     encrypt_key_size) / sizeof(uint64_t);		key->sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;		key->sadb_key_bits = x->ealg->alg_key_len;		key->sadb_key_reserved = 0;		memcpy(key + 1, x->ealg->alg_key,		       (x->ealg->alg_key_len+7)/8);	}	/* sa */	sa2 = (struct sadb_x_sa2 *)  skb_put(skb, sizeof(struct sadb_x_sa2));	sa2->sadb_x_sa2_len = sizeof(struct sadb_x_sa2)/sizeof(uint64_t);	sa2->sadb_x_sa2_exttype = SADB_X_EXT_SA2;	if ((mode = pfkey_mode_from_xfrm(x->props.mode)) < 0) {

⌨️ 快捷键说明

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