ipsec.c

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

C
2,682
字号
			ipseclog((LOG_ERR, "ipsec4_getpolicybysock: "			      "Invalid policy for PCB %d\n", currsp->policy));			*error = EINVAL;			return NULL;		}		/* NOTREACHED */	}	/* when non-privilieged socket */	/* look for a policy in SPD */	kernsp = key_allocsp(&currsp->spidx, dir);	/* SP found */	if (kernsp != NULL) {		KEYDEBUG(KEYDEBUG_IPSEC_STAMP,			printf("DP ipsec4_getpolicybysock called "			       "to allocate SP:%p\n", kernsp));		*error = 0;		ipsec_fillpcbcache(pcbsp, m, kernsp, dir);		return kernsp;	}	/* no SP found */	switch (currsp->policy) {	case IPSEC_POLICY_BYPASS:		ipseclog((LOG_ERR, "ipsec4_getpolicybysock: "		       "Illegal policy for non-priviliged defined %d\n",			currsp->policy));		*error = EINVAL;		return NULL;	case IPSEC_POLICY_ENTRUST:		if (ip4_def_policy.policy != IPSEC_POLICY_DISCARD		 && ip4_def_policy.policy != IPSEC_POLICY_NONE) {			ipseclog((LOG_INFO,			    "fixed system default policy: %d->%d\n",			    ip4_def_policy.policy, IPSEC_POLICY_NONE));			ip4_def_policy.policy = IPSEC_POLICY_NONE;		}		ip4_def_policy.refcnt++;		*error = 0;		ipsec_fillpcbcache(pcbsp, m, &ip4_def_policy, dir);		return &ip4_def_policy;	case IPSEC_POLICY_IPSEC:		currsp->refcnt++;		*error = 0;		ipsec_fillpcbcache(pcbsp, m, currsp, dir);		return currsp;	default:		ipseclog((LOG_ERR, "ipsec4_getpolicybysock: "		   "Invalid policy for PCB %d\n", currsp->policy));		*error = EINVAL;		return NULL;	}	/* NOTREACHED */}/* * For FORWADING packet or OUTBOUND without a socket. Searching SPD for packet, * and return a pointer to SP. * OUT:	positive: a pointer to the entry for security policy leaf matched. *	NULL:	no apropreate SP found, the following value is set to error. *		0	: bypass *		EACCES	: discard packet. *		ENOENT	: ipsec_acquire() in progress, maybe. *		others	: error occured. */struct secpolicy *ipsec4_getpolicybyaddr(m, dir, flag, error)	struct mbuf *m;	u_int dir;	int flag;	int *error;{	struct secpolicy *sp = NULL;	/* sanity check */	if (m == NULL || error == NULL)		panic("ipsec4_getpolicybyaddr: NULL pointer was passed.\n");    {	struct secpolicyindex spidx;	bzero(&spidx, sizeof(spidx));	/* make a index to look for a policy */	*error = ipsec_setspidx_mbuf(&spidx, dir, AF_INET, m,	    (flag & IP_FORWARDING) ? 0 : 1);	if (*error != 0)		return NULL;	sp = key_allocsp(&spidx, dir);    }	/* SP found */	if (sp != NULL) {		KEYDEBUG(KEYDEBUG_IPSEC_STAMP,			printf("DP ipsec4_getpolicybyaddr called "			       "to allocate SP:%p\n", sp));		*error = 0;		return sp;	}	/* no SP found */	if (ip4_def_policy.policy != IPSEC_POLICY_DISCARD	 && ip4_def_policy.policy != IPSEC_POLICY_NONE) {		ipseclog((LOG_INFO, "fixed system default policy:%d->%d\n",			ip4_def_policy.policy,			IPSEC_POLICY_NONE));		ip4_def_policy.policy = IPSEC_POLICY_NONE;	}	ip4_def_policy.refcnt++;	*error = 0;	return &ip4_def_policy;}#ifdef INET6/* * For OUTBOUND packet having a socket. Searching SPD for packet, * and return a pointer to SP. * OUT:	NULL:	no apropreate SP found, the following value is set to error. *		0	: bypass *		EACCES	: discard packet. *		ENOENT	: ipsec_acquire() in progress, maybe. *		others	: error occured. *	others:	a pointer to SP */struct secpolicy *ipsec6_getpolicybysock(m, dir, so, error)	struct mbuf *m;	u_int dir;	struct socket *so;	int *error;{	struct inpcbpolicy *pcbsp = NULL;	struct secpolicy *currsp = NULL;	/* policy on socket */	struct secpolicy *kernsp = NULL;	/* policy on kernel */	/* sanity check */	if (m == NULL || so == NULL || error == NULL)		panic("ipsec6_getpolicybysock: NULL pointer was passed.\n");#ifdef DIAGNOSTIC	if (so->so_proto->pr_domain->dom_family != AF_INET6)		panic("ipsec6_getpolicybysock: socket domain != inet6\n");#endif	pcbsp = sotoin6pcb(so)->in6p_sp;	/* if we have a cached entry, and if it is still valid, use it. */	ipsec6stat.spdcachelookup++;	currsp = ipsec_checkpcbcache(m, pcbsp, dir);	if (currsp) {		*error = 0;		return currsp;	}	ipsec6stat.spdcachemiss++;	/* set spidx in pcb */	/* XXX why is it necessary to do this? */	ipsec6_setspidx_in6pcb(m, sotoin6pcb(so));	/* sanity check */	if (pcbsp == NULL)		panic("ipsec6_getpolicybysock: pcbsp is NULL.\n");	switch (dir) {	case IPSEC_DIR_INBOUND:		currsp = pcbsp->sp_in;		break;	case IPSEC_DIR_OUTBOUND:		currsp = pcbsp->sp_out;		break;	default:		panic("ipsec6_getpolicybysock: illegal direction.\n");	}	/* sanity check */	if (currsp == NULL)		panic("ipsec6_getpolicybysock: currsp is NULL.\n");	/* when privilieged socket */	if (pcbsp->priv) {		switch (currsp->policy) {		case IPSEC_POLICY_BYPASS:			currsp->refcnt++;			*error = 0;			ipsec_fillpcbcache(pcbsp, m, currsp, dir);			return currsp;		case IPSEC_POLICY_ENTRUST:			/* look for a policy in SPD */			kernsp = key_allocsp(&currsp->spidx, dir);			/* SP found */			if (kernsp != NULL) {				KEYDEBUG(KEYDEBUG_IPSEC_STAMP,					printf("DP ipsec6_getpolicybysock called "					       "to allocate SP:%p\n", kernsp));				*error = 0;				ipsec_fillpcbcache(pcbsp, m, kernsp, dir);				return kernsp;			}			/* no SP found */			if (ip6_def_policy.policy != IPSEC_POLICY_DISCARD			 && ip6_def_policy.policy != IPSEC_POLICY_NONE) {				ipseclog((LOG_INFO,				    "fixed system default policy: %d->%d\n",				    ip6_def_policy.policy, IPSEC_POLICY_NONE));				ip6_def_policy.policy = IPSEC_POLICY_NONE;			}			ip6_def_policy.refcnt++;			*error = 0;			ipsec_fillpcbcache(pcbsp, m, &ip6_def_policy, dir);			return &ip6_def_policy;					case IPSEC_POLICY_IPSEC:			currsp->refcnt++;			*error = 0;			ipsec_fillpcbcache(pcbsp, m, currsp, dir);			return currsp;		default:			ipseclog((LOG_ERR, "ipsec6_getpolicybysock: "			    "Invalid policy for PCB %d\n", currsp->policy));			*error = EINVAL;			return NULL;		}		/* NOTREACHED */	}	/* when non-privilieged socket */	/* look for a policy in SPD */	kernsp = key_allocsp(&currsp->spidx, dir);	/* SP found */	if (kernsp != NULL) {		KEYDEBUG(KEYDEBUG_IPSEC_STAMP,			printf("DP ipsec6_getpolicybysock called "			       "to allocate SP:%p\n", kernsp));		*error = 0;		ipsec_fillpcbcache(pcbsp, m, kernsp, dir);		return kernsp;	}	/* no SP found */	switch (currsp->policy) {	case IPSEC_POLICY_BYPASS:		ipseclog((LOG_ERR, "ipsec6_getpolicybysock: "		    "Illegal policy for non-priviliged defined %d\n",		    currsp->policy));		*error = EINVAL;		return NULL;	case IPSEC_POLICY_ENTRUST:		if (ip6_def_policy.policy != IPSEC_POLICY_DISCARD		 && ip6_def_policy.policy != IPSEC_POLICY_NONE) {			ipseclog((LOG_INFO,			    "fixed system default policy: %d->%d\n",			    ip6_def_policy.policy, IPSEC_POLICY_NONE));			ip6_def_policy.policy = IPSEC_POLICY_NONE;		}		ip6_def_policy.refcnt++;		*error = 0;		ipsec_fillpcbcache(pcbsp, m, &ip6_def_policy, dir);		return &ip6_def_policy;	case IPSEC_POLICY_IPSEC:		currsp->refcnt++;		*error = 0;		ipsec_fillpcbcache(pcbsp, m, currsp, dir);		return currsp;	default:		ipseclog((LOG_ERR,		    "ipsec6_policybysock: Invalid policy for PCB %d\n",		    currsp->policy));		*error = EINVAL;		return NULL;	}	/* NOTREACHED */}/* * For FORWADING packet or OUTBOUND without a socket. Searching SPD for packet, * and return a pointer to SP. * `flag' means that packet is to be forwarded whether or not. *	flag = 1: forwad * OUT:	positive: a pointer to the entry for security policy leaf matched. *	NULL:	no apropreate SP found, the following value is set to error. *		0	: bypass *		EACCES	: discard packet. *		ENOENT	: ipsec_acquire() in progress, maybe. *		others	: error occured. */#ifndef IP_FORWARDING#define IP_FORWARDING 1#endifstruct secpolicy *ipsec6_getpolicybyaddr(m, dir, flag, error)	struct mbuf *m;	u_int dir;	int flag;	int *error;{	struct secpolicy *sp = NULL;	/* sanity check */	if (m == NULL || error == NULL)		panic("ipsec6_getpolicybyaddr: NULL pointer was passed.\n");	/* get a policy entry matched with the packet */    {	struct secpolicyindex spidx;	bzero(&spidx, sizeof(spidx));	/* make a index to look for a policy */	*error = ipsec_setspidx_mbuf(&spidx, dir, AF_INET6, m,	    (flag & IP_FORWARDING) ? 0 : 1);	if (*error != 0)		return NULL;	sp = key_allocsp(&spidx, dir);    }	/* SP found */	if (sp != NULL) {		KEYDEBUG(KEYDEBUG_IPSEC_STAMP,			printf("DP ipsec6_getpolicybyaddr called "			       "to allocate SP:%p\n", sp));		*error = 0;		return sp;	}	/* no SP found */	if (ip6_def_policy.policy != IPSEC_POLICY_DISCARD	 && ip6_def_policy.policy != IPSEC_POLICY_NONE) {		ipseclog((LOG_INFO, "fixed system default policy: %d->%d\n",		    ip6_def_policy.policy, IPSEC_POLICY_NONE));		ip6_def_policy.policy = IPSEC_POLICY_NONE;	}	ip6_def_policy.refcnt++;	*error = 0;	return &ip6_def_policy;}#endif /* INET6 *//* * set IP address into spidx from mbuf. * When Forwarding packet and ICMP echo reply, this function is used. * * IN:	get the followings from mbuf. *	protocol family, src, dst, next protocol * OUT: *	0:	success. *	other:	failure, and set errno. */intipsec_setspidx_mbuf(spidx, dir, family, m, needport)	struct secpolicyindex *spidx;	u_int dir, family;	struct mbuf *m;	int needport;{	int error;	/* sanity check */	if (spidx == NULL || m == NULL)		panic("ipsec_setspidx_mbuf: NULL pointer was passed.\n");	bzero(spidx, sizeof(*spidx));	error = ipsec_setspidx(m, spidx, needport);	if (error)		goto bad;	spidx->dir = dir;	return 0;    bad:	/* XXX initialize */	bzero(spidx, sizeof(*spidx));	return EINVAL;}static intipsec4_setspidx_inpcb(m, pcb)	struct mbuf *m;	struct inpcb *pcb;{	struct secpolicyindex *spidx;	int error;	/* sanity check */	if (pcb == NULL)		panic("ipsec4_setspidx_inpcb: no PCB found.\n");	if (pcb->inp_sp == NULL)		panic("ipsec4_setspidx_inpcb: no inp_sp found.\n");	if (pcb->inp_sp->sp_out == NULL || pcb->inp_sp->sp_in == NULL)		panic("ipsec4_setspidx_inpcb: no sp_in/out found.\n");	bzero(&pcb->inp_sp->sp_in->spidx, sizeof(*spidx));	bzero(&pcb->inp_sp->sp_out->spidx, sizeof(*spidx));	spidx = &pcb->inp_sp->sp_in->spidx;	error = ipsec_setspidx(m, spidx, 1);	if (error)		goto bad;	spidx->dir = IPSEC_DIR_INBOUND;	spidx = &pcb->inp_sp->sp_out->spidx;	error = ipsec_setspidx(m, spidx, 1);	if (error)		goto bad;	spidx->dir = IPSEC_DIR_OUTBOUND;	return 0;bad:	bzero(&pcb->inp_sp->sp_in->spidx, sizeof(*spidx));	bzero(&pcb->inp_sp->sp_out->spidx, sizeof(*spidx));	return error;}#ifdef INET6static intipsec6_setspidx_in6pcb(m, pcb)	struct mbuf *m;	struct in6pcb *pcb;{	struct secpolicyindex *spidx;	int error;	/* sanity check */	if (pcb == NULL)		panic("ipsec6_setspidx_in6pcb: no PCB found.\n");	if (pcb->in6p_sp == NULL)		panic("ipsec6_setspidx_in6pcb: no in6p_sp found.\n");	if (pcb->in6p_sp->sp_out == NULL || pcb->in6p_sp->sp_in == NULL)		panic("ipsec6_setspidx_in6pcb: no sp_in/out found.\n");	bzero(&pcb->in6p_sp->sp_in->spidx, sizeof(*spidx));	bzero(&pcb->in6p_sp->sp_out->spidx, sizeof(*spidx));	spidx = &pcb->in6p_sp->sp_in->spidx;	error = ipsec_setspidx(m, spidx, 1);	if (error)		goto bad;	spidx->dir = IPSEC_DIR_INBOUND;	spidx = &pcb->in6p_sp->sp_out->spidx;	error = ipsec_setspidx(m, spidx, 1);	if (error)		goto bad;	spidx->dir = IPSEC_DIR_OUTBOUND;	return 0;bad:	bzero(&pcb->in6p_sp->sp_in->spidx, sizeof(*spidx));	bzero(&pcb->in6p_sp->sp_out->spidx, sizeof(*spidx));	return error;}#endif/* * configure security policy index (src/dst/proto/sport/dport) * by looking at the content of mbuf. * the caller is responsible for error recovery (like clearing up spidx). */static intipsec_setspidx(m, spidx, needport)	struct mbuf *m;	struct secpolicyindex *spidx;	int needport;{	struct ip *ip = NULL;	struct ip ipbuf;	u_int v;	struct mbuf *n;	int len;	int error;	if (m == NULL)		panic("ipsec_setspidx: m == 0 passed.\n");	bzero(spidx, sizeof(*spidx));	/*	 * validate m->m_pkthdr.len.  we see incorrect length if we	 * mistakenly call this function with inconsistent mbuf chain	 * (like 4.4BSD tcp/udp processing).  XXX should we panic here?	 */	len = 0;	for (n = m; n; n = n->m_next)		len += n->m_len;	if (m->m_pkthdr.len != len) {		KEYDEBUG(KEYDEBUG_IPSEC_DUMP,			printf("ipsec_setspidx: "			       "total of m_len(%d) != pkthdr.len(%d), "			       "ignored.\n",				len, m->m_pkthdr.len));		return EINVAL;	}	if (m->m_pkthdr.len < sizeof(struct ip)) {		KEYDEBUG(KEYDEBUG_IPSEC_DUMP,			printf("ipsec_setspidx: "			    "pkthdr.len(%d) < sizeof(struct ip), ignored.\n",			    m->m_pkthdr.len));		return EINVAL;	}	if (m->m_len >= sizeof(*ip))		ip = mtod(m, struct ip *);	else {		m_copydata(m, 0, sizeof(ipbuf), (caddr_t)&ipbuf);		ip = &ipbuf;	}#ifdef _IP_VHL	v = _IP_VHL_V(ip->ip_vhl);#else	v = ip->ip_v;#endif	switch (v) {	case 4:		error = ipsec4_setspidx_ipaddr(m, spidx);		if (error)			return error;		ipsec4_get_ulp(m, spidx, needport);

⌨️ 快捷键说明

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