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

📄 af_key.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		kfree_skb(skb);		return ERR_PTR(-EINVAL);	}	sa2->sadb_x_sa2_mode = mode;	sa2->sadb_x_sa2_reserved1 = 0;	sa2->sadb_x_sa2_reserved2 = 0;	sa2->sadb_x_sa2_sequence = 0;	sa2->sadb_x_sa2_reqid = x->props.reqid;	if (natt && natt->encap_type) {		struct sadb_x_nat_t_type *n_type;		struct sadb_x_nat_t_port *n_port;		/* type */		n_type = (struct sadb_x_nat_t_type*) skb_put(skb, sizeof(*n_type));		n_type->sadb_x_nat_t_type_len = sizeof(*n_type)/sizeof(uint64_t);		n_type->sadb_x_nat_t_type_exttype = SADB_X_EXT_NAT_T_TYPE;		n_type->sadb_x_nat_t_type_type = natt->encap_type;		n_type->sadb_x_nat_t_type_reserved[0] = 0;		n_type->sadb_x_nat_t_type_reserved[1] = 0;		n_type->sadb_x_nat_t_type_reserved[2] = 0;		/* source port */		n_port = (struct sadb_x_nat_t_port*) skb_put(skb, sizeof (*n_port));		n_port->sadb_x_nat_t_port_len = sizeof(*n_port)/sizeof(uint64_t);		n_port->sadb_x_nat_t_port_exttype = SADB_X_EXT_NAT_T_SPORT;		n_port->sadb_x_nat_t_port_port = natt->encap_sport;		n_port->sadb_x_nat_t_port_reserved = 0;		/* dest port */		n_port = (struct sadb_x_nat_t_port*) skb_put(skb, sizeof (*n_port));		n_port->sadb_x_nat_t_port_len = sizeof(*n_port)/sizeof(uint64_t);		n_port->sadb_x_nat_t_port_exttype = SADB_X_EXT_NAT_T_DPORT;		n_port->sadb_x_nat_t_port_port = natt->encap_dport;		n_port->sadb_x_nat_t_port_reserved = 0;	}	/* security context */	if (xfrm_ctx) {		sec_ctx = (struct sadb_x_sec_ctx *) skb_put(skb,				sizeof(struct sadb_x_sec_ctx) + ctx_size);		sec_ctx->sadb_x_sec_len =		  (sizeof(struct sadb_x_sec_ctx) + 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);	}	return skb;}static inline struct sk_buff *pfkey_xfrm_state2msg(struct xfrm_state *x){	struct sk_buff *skb;	skb = __pfkey_xfrm_state2msg(x, 1, 3);	return skb;}static inline struct sk_buff *pfkey_xfrm_state2msg_expire(struct xfrm_state *x,							  int hsc){	return __pfkey_xfrm_state2msg(x, 0, hsc);}static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr,						void **ext_hdrs){	struct xfrm_state *x;	struct sadb_lifetime *lifetime;	struct sadb_sa *sa;	struct sadb_key *key;	struct sadb_x_sec_ctx *sec_ctx;	uint16_t proto;	int err;	sa = (struct sadb_sa *) ext_hdrs[SADB_EXT_SA-1];	if (!sa ||	    !present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],				     ext_hdrs[SADB_EXT_ADDRESS_DST-1]))		return ERR_PTR(-EINVAL);	if (hdr->sadb_msg_satype == SADB_SATYPE_ESP &&	    !ext_hdrs[SADB_EXT_KEY_ENCRYPT-1])		return ERR_PTR(-EINVAL);	if (hdr->sadb_msg_satype == SADB_SATYPE_AH &&	    !ext_hdrs[SADB_EXT_KEY_AUTH-1])		return ERR_PTR(-EINVAL);	if (!!ext_hdrs[SADB_EXT_LIFETIME_HARD-1] !=	    !!ext_hdrs[SADB_EXT_LIFETIME_SOFT-1])		return ERR_PTR(-EINVAL);	proto = pfkey_satype2proto(hdr->sadb_msg_satype);	if (proto == 0)		return ERR_PTR(-EINVAL);	/* default error is no buffer space */	err = -ENOBUFS;	/* RFC2367:   Only SADB_SASTATE_MATURE SAs may be submitted in an SADB_ADD message.   SADB_SASTATE_LARVAL SAs are created by SADB_GETSPI and it is not   sensible to add a new SA in the DYING or SADB_SASTATE_DEAD state.   Therefore, the sadb_sa_state field of all submitted SAs MUST be   SADB_SASTATE_MATURE and the kernel MUST return an error if this is   not true.	   However, KAME setkey always uses SADB_SASTATE_LARVAL.	   Hence, we have to _ignore_ sadb_sa_state, which is also reasonable.	 */	if (sa->sadb_sa_auth > SADB_AALG_MAX ||	    (hdr->sadb_msg_satype == SADB_X_SATYPE_IPCOMP &&	     sa->sadb_sa_encrypt > SADB_X_CALG_MAX) ||	    sa->sadb_sa_encrypt > SADB_EALG_MAX)		return ERR_PTR(-EINVAL);	key = (struct sadb_key*) ext_hdrs[SADB_EXT_KEY_AUTH-1];	if (key != NULL &&	    sa->sadb_sa_auth != SADB_X_AALG_NULL &&	    ((key->sadb_key_bits+7) / 8 == 0 ||	     (key->sadb_key_bits+7) / 8 > key->sadb_key_len * sizeof(uint64_t)))		return ERR_PTR(-EINVAL);	key = ext_hdrs[SADB_EXT_KEY_ENCRYPT-1];	if (key != NULL &&	    sa->sadb_sa_encrypt != SADB_EALG_NULL &&	    ((key->sadb_key_bits+7) / 8 == 0 ||	     (key->sadb_key_bits+7) / 8 > key->sadb_key_len * sizeof(uint64_t)))		return ERR_PTR(-EINVAL);	x = xfrm_state_alloc();	if (x == NULL)		return ERR_PTR(-ENOBUFS);	x->id.proto = proto;	x->id.spi = sa->sadb_sa_spi;	x->props.replay_window = sa->sadb_sa_replay;	if (sa->sadb_sa_flags & SADB_SAFLAGS_NOECN)		x->props.flags |= XFRM_STATE_NOECN;	if (sa->sadb_sa_flags & SADB_SAFLAGS_DECAP_DSCP)		x->props.flags |= XFRM_STATE_DECAP_DSCP;	if (sa->sadb_sa_flags & SADB_SAFLAGS_NOPMTUDISC)		x->props.flags |= XFRM_STATE_NOPMTUDISC;	lifetime = (struct sadb_lifetime*) ext_hdrs[SADB_EXT_LIFETIME_HARD-1];	if (lifetime != NULL) {		x->lft.hard_packet_limit = _KEY2X(lifetime->sadb_lifetime_allocations);		x->lft.hard_byte_limit = _KEY2X(lifetime->sadb_lifetime_bytes);		x->lft.hard_add_expires_seconds = lifetime->sadb_lifetime_addtime;		x->lft.hard_use_expires_seconds = lifetime->sadb_lifetime_usetime;	}	lifetime = (struct sadb_lifetime*) ext_hdrs[SADB_EXT_LIFETIME_SOFT-1];	if (lifetime != NULL) {		x->lft.soft_packet_limit = _KEY2X(lifetime->sadb_lifetime_allocations);		x->lft.soft_byte_limit = _KEY2X(lifetime->sadb_lifetime_bytes);		x->lft.soft_add_expires_seconds = lifetime->sadb_lifetime_addtime;		x->lft.soft_use_expires_seconds = lifetime->sadb_lifetime_usetime;	}	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)			goto out;		err = security_xfrm_state_alloc(x, uctx);		kfree(uctx);		if (err)			goto out;	}	key = (struct sadb_key*) ext_hdrs[SADB_EXT_KEY_AUTH-1];	if (sa->sadb_sa_auth) {		int keysize = 0;		struct xfrm_algo_desc *a = xfrm_aalg_get_byid(sa->sadb_sa_auth);		if (!a) {			err = -ENOSYS;			goto out;		}		if (key)			keysize = (key->sadb_key_bits + 7) / 8;		x->aalg = kmalloc(sizeof(*x->aalg) + keysize, GFP_KERNEL);		if (!x->aalg)			goto out;		strcpy(x->aalg->alg_name, a->name);		x->aalg->alg_key_len = 0;		if (key) {			x->aalg->alg_key_len = key->sadb_key_bits;			memcpy(x->aalg->alg_key, key+1, keysize);		}		x->props.aalgo = sa->sadb_sa_auth;		/* x->algo.flags = sa->sadb_sa_flags; */	}	if (sa->sadb_sa_encrypt) {		if (hdr->sadb_msg_satype == SADB_X_SATYPE_IPCOMP) {			struct xfrm_algo_desc *a = xfrm_calg_get_byid(sa->sadb_sa_encrypt);			if (!a) {				err = -ENOSYS;				goto out;			}			x->calg = kmalloc(sizeof(*x->calg), GFP_KERNEL);			if (!x->calg)				goto out;			strcpy(x->calg->alg_name, a->name);			x->props.calgo = sa->sadb_sa_encrypt;		} else {			int keysize = 0;			struct xfrm_algo_desc *a = xfrm_ealg_get_byid(sa->sadb_sa_encrypt);			if (!a) {				err = -ENOSYS;				goto out;			}			key = (struct sadb_key*) ext_hdrs[SADB_EXT_KEY_ENCRYPT-1];			if (key)				keysize = (key->sadb_key_bits + 7) / 8;			x->ealg = kmalloc(sizeof(*x->ealg) + keysize, GFP_KERNEL);			if (!x->ealg)				goto out;			strcpy(x->ealg->alg_name, a->name);			x->ealg->alg_key_len = 0;			if (key) {				x->ealg->alg_key_len = key->sadb_key_bits;				memcpy(x->ealg->alg_key, key+1, keysize);			}			x->props.ealgo = sa->sadb_sa_encrypt;		}	}	/* x->algo.flags = sa->sadb_sa_flags; */	x->props.family = pfkey_sadb_addr2xfrm_addr((struct sadb_address *) ext_hdrs[SADB_EXT_ADDRESS_SRC-1],						    &x->props.saddr);	if (!x->props.family) {		err = -EAFNOSUPPORT;		goto out;	}	pfkey_sadb_addr2xfrm_addr((struct sadb_address *) ext_hdrs[SADB_EXT_ADDRESS_DST-1],				  &x->id.daddr);	if (ext_hdrs[SADB_X_EXT_SA2-1]) {		struct sadb_x_sa2 *sa2 = (void*)ext_hdrs[SADB_X_EXT_SA2-1];		int mode = pfkey_mode_to_xfrm(sa2->sadb_x_sa2_mode);		if (mode < 0) {			err = -EINVAL;			goto out;		}		x->props.mode = mode;		x->props.reqid = sa2->sadb_x_sa2_reqid;	}	if (ext_hdrs[SADB_EXT_ADDRESS_PROXY-1]) {		struct sadb_address *addr = ext_hdrs[SADB_EXT_ADDRESS_PROXY-1];		/* Nobody uses this, but we try. */		x->sel.family = pfkey_sadb_addr2xfrm_addr(addr, &x->sel.saddr);		x->sel.prefixlen_s = addr->sadb_address_prefixlen;	}	if (!x->sel.family)		x->sel.family = x->props.family;	if (ext_hdrs[SADB_X_EXT_NAT_T_TYPE-1]) {		struct sadb_x_nat_t_type* n_type;		struct xfrm_encap_tmpl *natt;		x->encap = kmalloc(sizeof(*x->encap), GFP_KERNEL);		if (!x->encap)			goto out;		natt = x->encap;		n_type = ext_hdrs[SADB_X_EXT_NAT_T_TYPE-1];		natt->encap_type = n_type->sadb_x_nat_t_type_type;		if (ext_hdrs[SADB_X_EXT_NAT_T_SPORT-1]) {			struct sadb_x_nat_t_port* n_port =				ext_hdrs[SADB_X_EXT_NAT_T_SPORT-1];			natt->encap_sport = n_port->sadb_x_nat_t_port_port;		}		if (ext_hdrs[SADB_X_EXT_NAT_T_DPORT-1]) {			struct sadb_x_nat_t_port* n_port =				ext_hdrs[SADB_X_EXT_NAT_T_DPORT-1];			natt->encap_dport = n_port->sadb_x_nat_t_port_port;		}	}	err = xfrm_init_state(x);	if (err)		goto out;	x->km.seq = hdr->sadb_msg_seq;	return x;out:	x->km.state = XFRM_STATE_DEAD;	xfrm_state_put(x);	return ERR_PTR(err);}static int pfkey_reserved(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs){	return -EOPNOTSUPP;}static int pfkey_getspi(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs){	struct sk_buff *resp_skb;	struct sadb_x_sa2 *sa2;	struct sadb_address *saddr, *daddr;	struct sadb_msg *out_hdr;	struct sadb_spirange *range;	struct xfrm_state *x = NULL;	int mode;	int err;	u32 min_spi, max_spi;	u32 reqid;	u8 proto;	unsigned short family;	xfrm_address_t *xsaddr = NULL, *xdaddr = NULL;	if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],				     ext_hdrs[SADB_EXT_ADDRESS_DST-1]))		return -EINVAL;	proto = pfkey_satype2proto(hdr->sadb_msg_satype);	if (proto == 0)		return -EINVAL;	if ((sa2 = ext_hdrs[SADB_X_EXT_SA2-1]) != NULL) {		mode = pfkey_mode_to_xfrm(sa2->sadb_x_sa2_mode);		if (mode < 0)			return -EINVAL;		reqid = sa2->sadb_x_sa2_reqid;	} else {		mode = 0;		reqid = 0;	}	saddr = ext_hdrs[SADB_EXT_ADDRESS_SRC-1];	daddr = ext_hdrs[SADB_EXT_ADDRESS_DST-1];	family = ((struct sockaddr *)(saddr + 1))->sa_family;	switch (family) {	case AF_INET:		xdaddr = (xfrm_address_t *)&((struct sockaddr_in *)(daddr + 1))->sin_addr.s_addr;		xsaddr = (xfrm_address_t *)&((struct sockaddr_in *)(saddr + 1))->sin_addr.s_addr;		break;#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)	case AF_INET6:		xdaddr = (xfrm_address_t *)&((struct sockaddr_in6 *)(daddr + 1))->sin6_addr;		xsaddr = (xfrm_address_t *)&((struct sockaddr_in6 *)(saddr + 1))->sin6_addr;		break;#endif	}	if (hdr->sadb_msg_seq) {		x = xfrm_find_acq_byseq(hdr->sadb_msg_seq);		if (x && xfrm_addr_cmp(&x->id.daddr, xdaddr, family)) {			xfrm_state_put(x);			x = NULL;		}	}	if (!x)		x = xfrm_find_acq(mode, reqid, proto, xdaddr, xsaddr, 1, family);	if (x == NULL)		return -ENOENT;	min_spi = 0x100;	max_spi = 0x0fffffff;	range = ext_hdrs[SADB_EXT_SPIRANGE-1];	if (range) {		min_spi = range->sadb_spirange_min;		max_spi = range->sadb_spirange_max;	}	err = xfrm_alloc_spi(x, min_spi, max_spi);	resp_skb = err ? ERR_PTR(err) : pfkey_xfrm_state2msg(x);	if (IS_ERR(resp_skb)) {		xfrm_state_put(x);		return  PTR_ERR(resp_skb);	}	out_hdr = (struct sadb_msg *) resp_skb->data;	out_hdr->sadb_msg_version = hdr->sadb_msg_version;	out_hdr->sadb_msg_type = SADB_GETSPI;	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;	xfrm_state_put(x);	pfkey_broadcast(resp_skb, GFP_KERNEL, BROADCAST_ONE, sk);	return 0;}static int pfkey_acquire(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs){	struct xfrm_state *x;	if (hdr->sadb_msg_len != sizeof(struct sadb_msg)/8)		return -EOPNOTSUPP;	if (hdr->sadb_msg_seq == 0 || hdr->sadb_msg_errno == 0)		return 0;	x = xfrm_find_acq_byseq(hdr->sadb_msg_seq);	if (x == NULL)		return 0;	spin_lock_bh(&x->lock);	if (x->km.state == XFRM_STATE_ACQ) {		x->km.state = XFRM_STATE_ERROR;		wake_up(&km_waitq);	}	spin_unlock_bh(&x->lock);	xfrm_state_put(x);	return 0;}static inline int event2poltype(int event){	switch (event) {	case XFRM_MSG_DELPOLICY:		return SADB_X_SPDDELETE;	case XFRM_MSG_NEWPOLICY:		return SADB_X_SPDADD;	case XFRM_MSG_UPDPOLICY:		return SADB_X_SPDUPDATE;	case XFRM_MSG_POLEXPIRE:	//	return SADB_X_SPDEXPIRE;	default:		printk("pfkey: Unknown policy event %d\n", event);		break;	}	return 0;}static inline int event2keytype(int event){	switch (event) {	case XFRM_MSG_DELSA:		return SADB_DELETE;	case XFRM_MSG_NEWSA:		return SADB_ADD;	case XFRM_MSG_UPDSA:		return SADB_UPDATE;	case XFRM_MSG_EXPIRE:		return SADB_EXPIRE;	default:		printk("pfkey: Unknown SA event %d\n", event);		break;	}	return 0;}/* ADD/UPD/DEL */static int key_notify_sa(struct xfrm_state *x, struct km_event *c){	struct sk_buff *skb;	struct sadb_msg *hdr;	skb = pfkey_xfrm_state2msg(x);	if (IS_ERR(skb))		return PTR_ERR(skb);

⌨️ 快捷键说明

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