FreeBSD/sys/netipsec/key.c
/*
 * create secpolicy structure from sadb_x_policy structure.
 * NOTE: `state', `secpolicyindex' in secpolicy structure are not set,
 * so must be set properly later.
 */
create secpolicy structure from sadb_x_policy structure.
NOTE: `state', `secpolicyindex' in secpolicy structure are not set,
so must be set properly later.
create secpolicy structure from sadb_x_policy structure . NOTE : ` state ' ` secpolicyindex ' in secpolicy structure are not set so must be set properly later .
struct secpolicy *
key_msg2sp(struct sadb_x_policy *xpl0, size_t len, int *error)
{
	struct secpolicy *newsp;
	IPSEC_ASSERT(xpl0 != NULL, ("null xpl0"));
	IPSEC_ASSERT(len >= sizeof(*xpl0), ("policy too short: %zu", len));
	if (len != PFKEY_EXTLEN(xpl0)) {
		ipseclog((LOG_DEBUG, "%s: Invalid msg length.\n", __func__));
		*error = EINVAL;
		return NULL;
	}
	if ((newsp = KEY_NEWSP()) == NULL) {
		*error = ENOBUFS;
		return NULL;
	}
	newsp->spidx.dir = xpl0->sadb_x_policy_dir;
	newsp->policy = xpl0->sadb_x_policy_type;
	newsp->priority = xpl0->sadb_x_policy_priority;
	switch (xpl0->sadb_x_policy_type) {
	case IPSEC_POLICY_DISCARD:
	case IPSEC_POLICY_NONE:
	case IPSEC_POLICY_ENTRUST:
	case IPSEC_POLICY_BYPASS:
		newsp->req = NULL;
		break;
	case IPSEC_POLICY_IPSEC:
	    {
		int tlen;
		struct sadb_x_ipsecrequest *xisr;
		struct ipsecrequest **p_isr = &newsp->req;
		if (PFKEY_EXTLEN(xpl0) < sizeof(*xpl0)) {
			ipseclog((LOG_DEBUG, "%s: Invalid msg length.\n",
				__func__));
			KEY_FREESP(&newsp);
			*error = EINVAL;
			return NULL;
		}
		tlen = PFKEY_EXTLEN(xpl0) - sizeof(*xpl0);
		xisr = (struct sadb_x_ipsecrequest *)(xpl0 + 1);
		while (tlen > 0) {
			if (xisr->sadb_x_ipsecrequest_len < sizeof(*xisr)) {
				ipseclog((LOG_DEBUG, "%s: invalid ipsecrequest "
					"length.\n", __func__));
				KEY_FREESP(&newsp);
				*error = EINVAL;
				return NULL;
			}
			*p_isr = ipsec_newisr();
			if ((*p_isr) == NULL) {
				ipseclog((LOG_DEBUG,
				    "%s: No more memory.\n", __func__));
				KEY_FREESP(&newsp);
				*error = ENOBUFS;
				return NULL;
			}
			switch (xisr->sadb_x_ipsecrequest_proto) {
			case IPPROTO_ESP:
			case IPPROTO_AH:
			case IPPROTO_IPCOMP:
				break;
			default:
				ipseclog((LOG_DEBUG,
				    "%s: invalid proto type=%u\n", __func__,
				    xisr->sadb_x_ipsecrequest_proto));
				KEY_FREESP(&newsp);
				*error = EPROTONOSUPPORT;
				return NULL;
			}
			(*p_isr)->saidx.proto = xisr->sadb_x_ipsecrequest_proto;
			switch (xisr->sadb_x_ipsecrequest_mode) {
			case IPSEC_MODE_TRANSPORT:
			case IPSEC_MODE_TUNNEL:
				break;
			case IPSEC_MODE_ANY:
			default:
				ipseclog((LOG_DEBUG,
				    "%s: invalid mode=%u\n", __func__,
				    xisr->sadb_x_ipsecrequest_mode));
				KEY_FREESP(&newsp);
				*error = EINVAL;
				return NULL;
			}
			(*p_isr)->saidx.mode = xisr->sadb_x_ipsecrequest_mode;
			switch (xisr->sadb_x_ipsecrequest_level) {
			case IPSEC_LEVEL_DEFAULT:
			case IPSEC_LEVEL_USE:
			case IPSEC_LEVEL_REQUIRE:
				break;
			case IPSEC_LEVEL_UNIQUE:
				if (xisr->sadb_x_ipsecrequest_reqid
						> IPSEC_MANUAL_REQID_MAX) {
					ipseclog((LOG_DEBUG,
					    "%s: reqid=%d range "
					    "violation, updated by kernel.\n",
					    __func__,
					    xisr->sadb_x_ipsecrequest_reqid));
					xisr->sadb_x_ipsecrequest_reqid = 0;
				}
				if (xisr->sadb_x_ipsecrequest_reqid == 0) {
					u_int32_t reqid;
					if ((reqid = key_newreqid()) == 0) {
						KEY_FREESP(&newsp);
						*error = ENOBUFS;
						return NULL;
					}
					(*p_isr)->saidx.reqid = reqid;
					xisr->sadb_x_ipsecrequest_reqid = reqid;
				} else {
					(*p_isr)->saidx.reqid =
						xisr->sadb_x_ipsecrequest_reqid;
				}
				break;
			default:
				ipseclog((LOG_DEBUG, "%s: invalid level=%u\n",
					__func__,
					xisr->sadb_x_ipsecrequest_level));
				KEY_FREESP(&newsp);
				*error = EINVAL;
				return NULL;
			}
			(*p_isr)->level = xisr->sadb_x_ipsecrequest_level;
			if (xisr->sadb_x_ipsecrequest_len > sizeof(*xisr)) {
				struct sockaddr *paddr;
				paddr = (struct sockaddr *)(xisr + 1);
				if (paddr->sa_len
				    > sizeof((*p_isr)->saidx.src)) {
					ipseclog((LOG_DEBUG, "%s: invalid "
						"request address length.\n",
						__func__));
					KEY_FREESP(&newsp);
					*error = EINVAL;
					return NULL;
				}
				bcopy(paddr, &(*p_isr)->saidx.src,
					paddr->sa_len);
				paddr = (struct sockaddr *)((caddr_t)paddr
							+ paddr->sa_len);
				if (paddr->sa_len
				    > sizeof((*p_isr)->saidx.dst)) {
					ipseclog((LOG_DEBUG, "%s: invalid "
						"request address length.\n",
						__func__));
					KEY_FREESP(&newsp);
					*error = EINVAL;
					return NULL;
				}
				bcopy(paddr, &(*p_isr)->saidx.dst,
					paddr->sa_len);
			}
			(*p_isr)->sp = newsp;
			p_isr = &(*p_isr)->next;
			tlen -= xisr->sadb_x_ipsecrequest_len;
			if (tlen < 0) {
				ipseclog((LOG_DEBUG, "%s: becoming tlen < 0.\n",
					__func__));
				KEY_FREESP(&newsp);
				*error = EINVAL;
				return NULL;
			}
			xisr = (struct sadb_x_ipsecrequest *)((caddr_t)xisr
			                 + xisr->sadb_x_ipsecrequest_len);
		}
	    }
		break;
	default:
		ipseclog((LOG_DEBUG, "%s: invalid policy type.\n", __func__));
		KEY_FREESP(&newsp);
		*error = EINVAL;
		return NULL;
	}
	*error = 0;
	return newsp;
}
struct secpolicy * key_msg2sp ( struct sadb_x_policy * xpl0 , size_t len , int * error ) { struct secpolicy * newsp ; IPSEC_ASSERT ( xpl0 != NULL , ( " " ) ) ; IPSEC_ASSERT ( len >= sizeof ( * xpl0 ) , ( " " , len ) ) ; if ( len != PFKEY_EXTLEN ( xpl0 ) ) { ipseclog ( ( LOG_DEBUG , " \n " , __func__ ) ) ; * error = EINVAL ; return NULL ; } if ( ( newsp = KEY_NEWSP ( ) ) == NULL ) { * error = ENOBUFS ; return NULL ; } newsp -> spidx . dir = xpl0 -> sadb_x_policy_dir ; newsp -> policy = xpl0 -> sadb_x_policy_type ; newsp -> priority = xpl0 -> sadb_x_policy_priority ; switch ( xpl0 -> sadb_x_policy_type ) { case IPSEC_POLICY_DISCARD : case IPSEC_POLICY_NONE : case IPSEC_POLICY_ENTRUST : case IPSEC_POLICY_BYPASS : newsp -> req = NULL ; break ; case IPSEC_POLICY_IPSEC : { int tlen ; struct sadb_x_ipsecrequest * xisr ; struct ipsecrequest * * p_isr = & newsp -> req ; if ( PFKEY_EXTLEN ( xpl0 ) < sizeof ( * xpl0 ) ) { ipseclog ( ( LOG_DEBUG , " \n " , __func__ ) ) ; KEY_FREESP ( & newsp ) ; * error = EINVAL ; return NULL ; } tlen = PFKEY_EXTLEN ( xpl0 ) - sizeof ( * xpl0 ) ; xisr = ( struct sadb_x_ipsecrequest * ) ( xpl0 + 1 ) ; while ( tlen > 0 ) { if ( xisr -> sadb_x_ipsecrequest_len < sizeof ( * xisr ) ) { ipseclog ( ( LOG_DEBUG , " " " \n " , __func__ ) ) ; KEY_FREESP ( & newsp ) ; * error = EINVAL ; return NULL ; } * p_isr = ipsec_newisr ( ) ; if ( ( * p_isr ) == NULL ) { ipseclog ( ( LOG_DEBUG , " \n " , __func__ ) ) ; KEY_FREESP ( & newsp ) ; * error = ENOBUFS ; return NULL ; } switch ( xisr -> sadb_x_ipsecrequest_proto ) { case IPPROTO_ESP : case IPPROTO_AH : case IPPROTO_IPCOMP : break ; default : ipseclog ( ( LOG_DEBUG , " \n " , __func__ , xisr -> sadb_x_ipsecrequest_proto ) ) ; KEY_FREESP ( & newsp ) ; * error = EPROTONOSUPPORT ; return NULL ; } ( * p_isr ) -> saidx . proto = xisr -> sadb_x_ipsecrequest_proto ; switch ( xisr -> sadb_x_ipsecrequest_mode ) { case IPSEC_MODE_TRANSPORT : case IPSEC_MODE_TUNNEL : break ; case IPSEC_MODE_ANY : default : ipseclog ( ( LOG_DEBUG , " \n " , __func__ , xisr -> sadb_x_ipsecrequest_mode ) ) ; KEY_FREESP ( & newsp ) ; * error = EINVAL ; return NULL ; } ( * p_isr ) -> saidx . mode = xisr -> sadb_x_ipsecrequest_mode ; switch ( xisr -> sadb_x_ipsecrequest_level ) { case IPSEC_LEVEL_DEFAULT : case IPSEC_LEVEL_USE : case IPSEC_LEVEL_REQUIRE : break ; case IPSEC_LEVEL_UNIQUE : if ( xisr -> sadb_x_ipsecrequest_reqid > IPSEC_MANUAL_REQID_MAX ) { ipseclog ( ( LOG_DEBUG , " " " \n " , __func__ , xisr -> sadb_x_ipsecrequest_reqid ) ) ; xisr -> sadb_x_ipsecrequest_reqid = 0 ; } if ( xisr -> sadb_x_ipsecrequest_reqid == 0 ) { u_int32_t reqid ; if ( ( reqid = key_newreqid ( ) ) == 0 ) { KEY_FREESP ( & newsp ) ; * error = ENOBUFS ; return NULL ; } ( * p_isr ) -> saidx . reqid = reqid ; xisr -> sadb_x_ipsecrequest_reqid = reqid ; } else { ( * p_isr ) -> saidx . reqid = xisr -> sadb_x_ipsecrequest_reqid ; } break ; default : ipseclog ( ( LOG_DEBUG , " \n " , __func__ , xisr -> sadb_x_ipsecrequest_level ) ) ; KEY_FREESP ( & newsp ) ; * error = EINVAL ; return NULL ; } ( * p_isr ) -> level = xisr -> sadb_x_ipsecrequest_level ; if ( xisr -> sadb_x_ipsecrequest_len > sizeof ( * xisr ) ) { struct sockaddr * paddr ; paddr = ( struct sockaddr * ) ( xisr + 1 ) ; if ( paddr -> sa_len > sizeof ( ( * p_isr ) -> saidx . src ) ) { ipseclog ( ( LOG_DEBUG , " " " \n " , __func__ ) ) ; KEY_FREESP ( & newsp ) ; * error = EINVAL ; return NULL ; } bcopy ( paddr , & ( * p_isr ) -> saidx . src , paddr -> sa_len ) ; paddr = ( struct sockaddr * ) ( ( caddr_t ) paddr + paddr -> sa_len ) ; if ( paddr -> sa_len > sizeof ( ( * p_isr ) -> saidx . dst ) ) { ipseclog ( ( LOG_DEBUG , " " " \n " , __func__ ) ) ; KEY_FREESP ( & newsp ) ; * error = EINVAL ; return NULL ; } bcopy ( paddr , & ( * p_isr ) -> saidx . dst , paddr -> sa_len ) ; } ( * p_isr ) -> sp = newsp ; p_isr = & ( * p_isr ) -> next ; tlen -= xisr -> sadb_x_ipsecrequest_len ; if ( tlen < 0 ) { ipseclog ( ( LOG_DEBUG , " \n " , __func__ ) ) ; KEY_FREESP ( & newsp ) ; * error = EINVAL ; return NULL ; } xisr = ( struct sadb_x_ipsecrequest * ) ( ( caddr_t ) xisr + xisr -> sadb_x_ipsecrequest_len ) ; } } break ; default : ipseclog ( ( LOG_DEBUG , " \n " , __func__ ) ) ; KEY_FREESP ( & newsp ) ; * error = EINVAL ; return NULL ; } * error = 0 ; return newsp ; }
create secpolicy structure from sadb_x_policy structure.
create secpolicy structure from sadb_x_policy structure .
/* check policy */ /* validity check */ /* length check */ /* allocate request buffer */ /* NB: data structure is zero'd */ /* set values */ /* validity check */ /*
				 * If range violation of reqid, kernel will
				 * update it, don't refuse it.
				 */ /* allocate new reqid id if reqid is zero. */ /* set it for manual keying. */ /* set IP addresses if there */ /* validity check */ /* validity check */ /* initialization for the next. */ /* validity check */