pfkey.c

来自「eCos操作系统源码」· C语言 代码 · 共 2,135 行 · 第 1/3 页

C
2,135
字号
 * sadb_supported returned into ipsec_supported. * OUT: *	 0: success and return length sent. *	-1: error occured, and set errno. */intpfkey_recv_register(so)	int so;{	pid_t pid = getpid();	struct sadb_msg *newmsg;	int error = -1;	/* receive message */	for (;;) {		if ((newmsg = pfkey_recv(so)) == NULL)			return -1;		if (newmsg->sadb_msg_type == SADB_REGISTER &&		    newmsg->sadb_msg_pid == pid)			break;		free(newmsg);	}	/* check and fix */	newmsg->sadb_msg_len = PFKEY_UNUNIT64(newmsg->sadb_msg_len);	error = pfkey_set_supported(newmsg, newmsg->sadb_msg_len);	free(newmsg);	if (error == 0)		__ipsec_errcode = EIPSEC_NO_ERROR;	return error;}/* * receiving SADB_REGISTER message from the kernel, and copy buffer for * sadb_supported returned into ipsec_supported. * NOTE: sadb_msg_len must be host order. * IN: *	tlen: msg length, it's to makeing sure. * OUT: *	 0: success and return length sent. *	-1: error occured, and set errno. */intpfkey_set_supported(msg, tlen)	struct sadb_msg *msg;	int tlen;{	struct sadb_supported *sup;	caddr_t p;	caddr_t ep;	/* validity */	if (msg->sadb_msg_len != tlen) {		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;		return -1;	}	p = (caddr_t)msg;	ep = p + tlen;	p += sizeof(struct sadb_msg);	while (p < ep) {		sup = (struct sadb_supported *)p;		if (ep < p + sizeof(*sup) ||		    PFKEY_EXTLEN(sup) < sizeof(*sup) ||		    ep < p + sup->sadb_supported_len) {			/* invalid format */			break;		}		switch (sup->sadb_supported_exttype) {		case SADB_EXT_SUPPORTED_AUTH:		case SADB_EXT_SUPPORTED_ENCRYPT:			break;		default:			__ipsec_errcode = EIPSEC_INVAL_SATYPE;			return -1;		}		/* fixed length */		sup->sadb_supported_len = PFKEY_EXTLEN(sup);		/* set supported map */		if (setsupportedmap(sup) != 0)			return -1;		p += sup->sadb_supported_len;	}	if (p != ep) {		__ipsec_errcode = EIPSEC_INVAL_SATYPE;		return -1;	}	__ipsec_errcode = EIPSEC_NO_ERROR;	return 0;}/* * sending SADB_FLUSH message to the kernel. * OUT: *	positive: success and return length sent. *	-1	: error occured, and set errno. */intpfkey_send_flush(so, satype)	int so;	u_int satype;{	int len;	if ((len = pfkey_send_x3(so, SADB_FLUSH, satype)) < 0)		return -1;	return len;}/* * sending SADB_DUMP message to the kernel. * OUT: *	positive: success and return length sent. *	-1	: error occured, and set errno. */intpfkey_send_dump(so, satype)	int so;	u_int satype;{	int len;	if ((len = pfkey_send_x3(so, SADB_DUMP, satype)) < 0)		return -1;	return len;}/* * sending SADB_X_PROMISC message to the kernel. * NOTE that this function handles promisc mode toggle only. * IN: *	flag:	set promisc off if zero, set promisc on if non-zero. * OUT: *	positive: success and return length sent. *	-1	: error occured, and set errno. *	0     : error occured, and set errno. *	others: a pointer to new allocated buffer in which supported *	        algorithms is. */intpfkey_send_promisc_toggle(so, flag)	int so;	int flag;{	int len;	if ((len = pfkey_send_x3(so, SADB_X_PROMISC, (flag ? 1 : 0))) < 0)		return -1;	return len;}/* * sending SADB_X_SPDADD message to the kernel. * OUT: *	positive: success and return length sent. *	-1	: error occured, and set errno. */intpfkey_send_spdadd(so, src, prefs, dst, prefd, proto, policy, policylen, seq)	int so;	struct sockaddr *src, *dst;	u_int prefs, prefd, proto;	caddr_t policy;	int policylen;	u_int32_t seq;{	int len;	if ((len = pfkey_send_x4(so, SADB_X_SPDADD,				src, prefs, dst, prefd, proto,				0, 0,				policy, policylen, seq)) < 0)		return -1;	return len;}/* * sending SADB_X_SPDADD message to the kernel. * OUT: *	positive: success and return length sent. *	-1	: error occured, and set errno. */intpfkey_send_spdadd2(so, src, prefs, dst, prefd, proto, ltime, vtime,		policy, policylen, seq)	int so;	struct sockaddr *src, *dst;	u_int prefs, prefd, proto;	u_int64_t ltime, vtime;	caddr_t policy;	int policylen;	u_int32_t seq;{	int len;	if ((len = pfkey_send_x4(so, SADB_X_SPDADD,				src, prefs, dst, prefd, proto,				ltime, vtime,				policy, policylen, seq)) < 0)		return -1;	return len;}/* * sending SADB_X_SPDUPDATE message to the kernel. * OUT: *	positive: success and return length sent. *	-1	: error occured, and set errno. */intpfkey_send_spdupdate(so, src, prefs, dst, prefd, proto, policy, policylen, seq)	int so;	struct sockaddr *src, *dst;	u_int prefs, prefd, proto;	caddr_t policy;	int policylen;	u_int32_t seq;{	int len;	if ((len = pfkey_send_x4(so, SADB_X_SPDUPDATE,				src, prefs, dst, prefd, proto,				0, 0,				policy, policylen, seq)) < 0)		return -1;	return len;}/* * sending SADB_X_SPDUPDATE message to the kernel. * OUT: *	positive: success and return length sent. *	-1	: error occured, and set errno. */intpfkey_send_spdupdate2(so, src, prefs, dst, prefd, proto, ltime, vtime,		policy, policylen, seq)	int so;	struct sockaddr *src, *dst;	u_int prefs, prefd, proto;	u_int64_t ltime, vtime;	caddr_t policy;	int policylen;	u_int32_t seq;{	int len;	if ((len = pfkey_send_x4(so, SADB_X_SPDUPDATE,				src, prefs, dst, prefd, proto,				ltime, vtime,				policy, policylen, seq)) < 0)		return -1;	return len;}/* * sending SADB_X_SPDDELETE message to the kernel. * OUT: *	positive: success and return length sent. *	-1	: error occured, and set errno. */intpfkey_send_spddelete(so, src, prefs, dst, prefd, proto, policy, policylen, seq)	int so;	struct sockaddr *src, *dst;	u_int prefs, prefd, proto;	caddr_t policy;	int policylen;	u_int32_t seq;{	int len;	if (policylen != sizeof(struct sadb_x_policy)) {		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;		return -1;	}	if ((len = pfkey_send_x4(so, SADB_X_SPDDELETE,				src, prefs, dst, prefd, proto,				0, 0,				policy, policylen, seq)) < 0)		return -1;	return len;}/* * sending SADB_X_SPDDELETE message to the kernel. * OUT: *	positive: success and return length sent. *	-1	: error occured, and set errno. */intpfkey_send_spddelete2(so, spid)	int so;	u_int32_t spid;{	int len;	if ((len = pfkey_send_x5(so, SADB_X_SPDDELETE2, spid)) < 0)		return -1;	return len;}/* * sending SADB_X_SPDGET message to the kernel. * OUT: *	positive: success and return length sent. *	-1	: error occured, and set errno. */intpfkey_send_spdget(so, spid)	int so;	u_int32_t spid;{	int len;	if ((len = pfkey_send_x5(so, SADB_X_SPDGET, spid)) < 0)		return -1;	return len;}/* * sending SADB_X_SPDSETIDX message to the kernel. * OUT: *	positive: success and return length sent. *	-1	: error occured, and set errno. */intpfkey_send_spdsetidx(so, src, prefs, dst, prefd, proto, policy, policylen, seq)	int so;	struct sockaddr *src, *dst;	u_int prefs, prefd, proto;	caddr_t policy;	int policylen;	u_int32_t seq;{	int len;	if (policylen != sizeof(struct sadb_x_policy)) {		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;		return -1;	}	if ((len = pfkey_send_x4(so, SADB_X_SPDSETIDX,				src, prefs, dst, prefd, proto,				0, 0,				policy, policylen, seq)) < 0)		return -1;	return len;}/* * sending SADB_SPDFLUSH message to the kernel. * OUT: *	positive: success and return length sent. *	-1	: error occured, and set errno. */intpfkey_send_spdflush(so)	int so;{	int len;	if ((len = pfkey_send_x3(so, SADB_X_SPDFLUSH, SADB_SATYPE_UNSPEC)) < 0)		return -1;	return len;}/* * sending SADB_SPDDUMP message to the kernel. * OUT: *	positive: success and return length sent. *	-1	: error occured, and set errno. */intpfkey_send_spddump(so)	int so;{	int len;	if ((len = pfkey_send_x3(so, SADB_X_SPDDUMP, SADB_SATYPE_UNSPEC)) < 0)		return -1;	return len;}/* sending SADB_ADD or SADB_UPDATE message to the kernel */static intpfkey_send_x1(so, type, satype, mode, src, dst, spi, reqid, wsize,		keymat, e_type, e_keylen, a_type, a_keylen, flags,		l_alloc, l_bytes, l_addtime, l_usetime, seq)	int so;	u_int type, satype, mode;	struct sockaddr *src, *dst;	u_int32_t spi, reqid;	u_int wsize;	caddr_t keymat;	u_int e_type, e_keylen, a_type, a_keylen, flags;	u_int32_t l_alloc, l_bytes, l_addtime, l_usetime, seq;{	struct sadb_msg *newmsg;	int len;	caddr_t p;	int plen;	caddr_t ep;	/* validity check */	if (src == NULL || dst == NULL) {		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;		return -1;	}	if (src->sa_family != dst->sa_family) {		__ipsec_errcode = EIPSEC_FAMILY_MISMATCH;		return -1;	}	switch (src->sa_family) {	case AF_INET:		plen = sizeof(struct in_addr) << 3;		break;	case AF_INET6:		plen = sizeof(struct in6_addr) << 3;		break;	default:		__ipsec_errcode = EIPSEC_INVAL_FAMILY;		return -1;	}	switch (satype) {	case SADB_SATYPE_ESP:		if (e_type == SADB_EALG_NONE) {			__ipsec_errcode = EIPSEC_NO_ALGS;			return -1;		}		break;	case SADB_SATYPE_AH:		if (e_type != SADB_EALG_NONE) {			__ipsec_errcode = EIPSEC_INVAL_ALGS;			return -1;		}		if (a_type == SADB_AALG_NONE) {			__ipsec_errcode = EIPSEC_NO_ALGS;			return -1;		}		break;	case SADB_X_SATYPE_IPCOMP:		if (e_type == SADB_X_CALG_NONE) {			__ipsec_errcode = EIPSEC_INVAL_ALGS;			return -1;		}		if (a_type != SADB_AALG_NONE) {			__ipsec_errcode = EIPSEC_NO_ALGS;			return -1;		}		break;	default:		__ipsec_errcode = EIPSEC_INVAL_SATYPE;		return -1;	}	/* create new sadb_msg to reply. */	len = sizeof(struct sadb_msg)		+ sizeof(struct sadb_sa)		+ sizeof(struct sadb_x_sa2)		+ sizeof(struct sadb_address)		+ PFKEY_ALIGN8(src->sa_len)		+ sizeof(struct sadb_address)		+ PFKEY_ALIGN8(dst->sa_len)		+ sizeof(struct sadb_lifetime)		+ sizeof(struct sadb_lifetime);	if (e_type != SADB_EALG_NONE)		len += (sizeof(struct sadb_key) + PFKEY_ALIGN8(e_keylen));	if (a_type != SADB_AALG_NONE)		len += (sizeof(struct sadb_key) + PFKEY_ALIGN8(a_keylen));	if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {		__ipsec_set_strerror(strerror(errno));		return -1;	}	ep = ((caddr_t)newmsg) + len;	p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len,	                     satype, seq, getpid());	if (!p) {		free(newmsg);		return -1;	}	p = pfkey_setsadbsa(p, ep, spi, wsize, a_type, e_type, flags);	if (!p) {		free(newmsg);		return -1;	}	p = pfkey_setsadbxsa2(p, ep, mode, reqid);	if (!p) {		free(newmsg);		return -1;	}	p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, plen,	    IPSEC_ULPROTO_ANY);	if (!p) {		free(newmsg);		return -1;	}	p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, plen,	    IPSEC_ULPROTO_ANY);	if (!p) {		free(newmsg);		return -1;	}	if (e_type != SADB_EALG_NONE) {		p = pfkey_setsadbkey(p, ep, SADB_EXT_KEY_ENCRYPT,		                   keymat, e_keylen);		if (!p) {			free(newmsg);			return -1;		}	}	if (a_type != SADB_AALG_NONE) {		p = pfkey_setsadbkey(p, ep, SADB_EXT_KEY_AUTH,		                   keymat + e_keylen, a_keylen);		if (!p) {			free(newmsg);			return -1;		}	}	/* set sadb_lifetime for destination */	p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_HARD,			l_alloc, l_bytes, l_addtime, l_usetime);	if (!p) {		free(newmsg);		return -1;	}	p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_SOFT,			l_alloc, l_bytes, l_addtime, l_usetime);	if (!p || p != ep) {		free(newmsg);		return -1;	}	/* send message */	len = pfkey_send(so, newmsg, len);	free(newmsg);	if (len < 0)		return -1;	__ipsec_errcode = EIPSEC_NO_ERROR;	return len;}/* sending SADB_DELETE or SADB_GET message to the kernel */static intpfkey_send_x2(so, type, satype, mode, src, dst, spi)	int so;	u_int type, satype, mode;	struct sockaddr *src, *dst;	u_int32_t spi;{	struct sadb_msg *newmsg;	int len;	caddr_t p;	int plen;	caddr_t ep;	/* validity check */	if (src == NULL || dst == NULL) {		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;		return -1;	}	if (src->sa_family != dst->sa_family) {		__ipsec_errcode = EIPSEC_FAMILY_MISMATCH;		return -1;	}	switch (src->sa_family) {	case AF_INET:		plen = sizeof(struct in_addr) << 3;		break;	case AF_INET6:		plen = sizeof(struct in6_addr) << 3;		break;	default:		__ipsec_errcode = EIPSEC_INVAL_FAMILY;		return -1;	}	/* create new sadb_msg to reply. */	len = sizeof(struct sadb_msg)		+ sizeof(struct sadb_sa)		+ sizeof(struct sadb_address)		+ PFKEY_ALIGN8(src->sa_len)		+ sizeof(struct sadb_address)		+ PFKEY_ALIGN8(dst->sa_len);	if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {		__ipsec_set_strerror(strerror(errno));		return -1;	}	ep = ((caddr_t)newmsg) + len;	p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len, satype, 0,	    getpid());	if (!p) {		free(newmsg);		return -1;	}	p = pfkey_setsadbsa(p, ep, spi, 0, 0, 0, 0);	if (!p) {		free(newmsg);		return -1;	}	p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, plen,	    IPSEC_ULPROTO_ANY);	if (!p) {		free(newmsg);		return -1;	}	p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, plen,	    IPSEC_ULPROTO_ANY);	if (!p || p != ep) {		free(newmsg);		return -1;	}	/* send message */	len = pfkey_send(so, newmsg, len);	free(newmsg);	if (len < 0)		return -1;	__ipsec_errcode = EIPSEC_NO_ERROR;	return len;}/* * sending SADB_REGISTER, SADB_FLUSH, SADB_DUMP or SADB_X_PROMISC message * to the kernel */static intpfkey_send_x3(so, type, satype)	int so;	u_int type, satype;{	struct sadb_msg *newmsg;	int len;	caddr_t p;	caddr_t ep;	/* validity check */	switch (type) {	case SADB_X_PROMISC:		if (satype != 0 && satype != 1) {			__ipsec_errcode = EIPSEC_INVAL_SATYPE;			return -1;		}		break;	default:		switch (satype) {		case SADB_SATYPE_UNSPEC:		case SADB_SATYPE_AH:		case SADB_SATYPE_ESP:		case SADB_X_SATYPE_IPCOMP:			break;		default:			__ipsec_errcode = EIPSEC_INVAL_SATYPE;			return -1;		}	}	/* create new sadb_msg to send. */	len = sizeof(struct sadb_msg);	if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {		__ipsec_set_strerror(strerror(errno));		return -1;	}	ep = ((caddr_t)newmsg) + len;	p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len, satype, 0,	    getpid());	if (!p || p != ep) {		free(newmsg);		return -1;	}	/* send message */

⌨️ 快捷键说明

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