File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ipsec-tools / src / libipsec / pfkey.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jun 15 16:37:11 2014 UTC (10 years, 2 months ago) by misho
Branches: ipsec-tools, MAIN
CVS tags: v0_8_2p2, v0_8_1p0, v0_8_1, HEAD
ipsec-tools 0.8.1

    1: /*	$NetBSD: pfkey.c,v 1.21.2.1 2011/11/14 13:25:06 tteras Exp $	*/
    2: 
    3: /*	$KAME: pfkey.c,v 1.47 2003/10/02 19:52:12 itojun Exp $	*/
    4: 
    5: /*
    6:  * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
    7:  * All rights reserved.
    8:  *
    9:  * Redistribution and use in source and binary forms, with or without
   10:  * modification, are permitted provided that the following conditions
   11:  * are met:
   12:  * 1. Redistributions of source code must retain the above copyright
   13:  *    notice, this list of conditions and the following disclaimer.
   14:  * 2. Redistributions in binary form must reproduce the above copyright
   15:  *    notice, this list of conditions and the following disclaimer in the
   16:  *    documentation and/or other materials provided with the distribution.
   17:  * 3. Neither the name of the project nor the names of its contributors
   18:  *    may be used to endorse or promote products derived from this software
   19:  *    without specific prior written permission.
   20:  *
   21:  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
   22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
   25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   31:  * SUCH DAMAGE.
   32:  */
   33: 
   34: #ifdef HAVE_CONFIG_H
   35: #include "config.h"
   36: #endif
   37: 
   38: #include <sys/types.h>
   39: #include <sys/param.h>
   40: #include <sys/socket.h>
   41: #include <net/pfkeyv2.h>
   42: #include <netinet/in.h>
   43: #include PATH_IPSEC_H
   44: 
   45: #include <stdlib.h>
   46: #include <unistd.h>
   47: #include <string.h>
   48: #include <errno.h>
   49: #include <stdio.h>
   50: 
   51: #include "ipsec_strerror.h"
   52: #include "libpfkey.h"
   53: 
   54: #define CALLOC(size, cast) (cast)calloc(1, (size))
   55: 
   56: static int findsupportedmap __P((int));
   57: static int setsupportedmap __P((struct sadb_supported *));
   58: static struct sadb_alg *findsupportedalg __P((u_int, u_int));
   59: static int pfkey_send_x1 __P((struct pfkey_send_sa_args *));
   60: static int pfkey_send_x2 __P((int, u_int, u_int, u_int,
   61: 	struct sockaddr *, struct sockaddr *, u_int32_t));
   62: static int pfkey_send_x3 __P((int, u_int, u_int));
   63: static int pfkey_send_x4 __P((int, u_int, struct sockaddr *, u_int,
   64: 	struct sockaddr *, u_int, u_int, u_int64_t, u_int64_t,
   65: 	char *, int, u_int32_t));
   66: static int pfkey_send_x5 __P((int, u_int, u_int32_t));
   67: 
   68: static caddr_t pfkey_setsadbmsg __P((caddr_t, caddr_t, u_int, u_int,
   69: 	u_int, u_int32_t, pid_t));
   70: static caddr_t pfkey_setsadbsa __P((caddr_t, caddr_t, u_int32_t, u_int,
   71: 	u_int, u_int, u_int32_t));
   72: static caddr_t pfkey_setsadbaddr __P((caddr_t, caddr_t, u_int,
   73: 	struct sockaddr *, u_int, u_int));
   74: 
   75: #ifdef SADB_X_EXT_KMADDRESS
   76: static caddr_t pfkey_setsadbkmaddr __P((caddr_t, caddr_t, struct sockaddr *,
   77: 	struct sockaddr *));
   78: #endif
   79: 
   80: static caddr_t pfkey_setsadbkey __P((caddr_t, caddr_t, u_int, caddr_t, u_int));
   81: static caddr_t pfkey_setsadblifetime __P((caddr_t, caddr_t, u_int, u_int32_t,
   82: 	u_int32_t, u_int32_t, u_int32_t));
   83: static caddr_t pfkey_setsadbxsa2 __P((caddr_t, caddr_t, u_int32_t, u_int32_t));
   84: 
   85: #ifdef SADB_X_EXT_NAT_T_TYPE
   86: static caddr_t pfkey_set_natt_type __P((caddr_t, caddr_t, u_int, u_int8_t));
   87: static caddr_t pfkey_set_natt_port __P((caddr_t, caddr_t, u_int, u_int16_t));
   88: #endif
   89: #ifdef SADB_X_EXT_NAT_T_FRAG
   90: static caddr_t pfkey_set_natt_frag __P((caddr_t, caddr_t, u_int, u_int16_t));
   91: #endif
   92: 
   93: #ifdef SADB_X_EXT_SEC_CTX
   94: static caddr_t pfkey_setsecctx __P((caddr_t, caddr_t, u_int, u_int8_t, u_int8_t,
   95: 				    caddr_t, u_int16_t));
   96: #endif
   97: 
   98: int libipsec_opt = 0
   99: #ifdef SADB_X_EXT_NAT_T_TYPE
  100: 	| LIBIPSEC_OPT_NATT
  101: #endif
  102: #ifdef SADB_X_EXT_NAT_T_FRAG
  103: 	| LIBIPSEC_OPT_FRAG
  104: #endif
  105: #ifdef SADB_X_EXT_NAT_T_SEC_CTX
  106: 	| LIBIPSEC_OPT_SEC_CTX
  107: #endif
  108: 	;
  109: 
  110: /*
  111:  * make and search supported algorithm structure.
  112:  */
  113: static struct sadb_supported *ipsec_supported[] = { NULL, NULL, NULL, 
  114: #ifdef SADB_X_SATYPE_TCPSIGNATURE
  115:     NULL,
  116: #endif
  117: };
  118: 
  119: static int supported_map[] = {
  120: 	SADB_SATYPE_AH,
  121: 	SADB_SATYPE_ESP,
  122: 	SADB_X_SATYPE_IPCOMP,
  123: #ifdef SADB_X_SATYPE_TCPSIGNATURE
  124: 	SADB_X_SATYPE_TCPSIGNATURE,
  125: #endif
  126: };
  127: 
  128: static int
  129: findsupportedmap(satype)
  130: 	int satype;
  131: {
  132: 	int i;
  133: 
  134: 	for (i = 0; i < sizeof(supported_map)/sizeof(supported_map[0]); i++)
  135: 		if (supported_map[i] == satype)
  136: 			return i;
  137: 	return -1;
  138: }
  139: 
  140: static struct sadb_alg *
  141: findsupportedalg(satype, alg_id)
  142: 	u_int satype, alg_id;
  143: {
  144: 	int algno;
  145: 	int tlen;
  146: 	caddr_t p;
  147: 
  148: 	/* validity check */
  149: 	algno = findsupportedmap((int)satype);
  150: 	if (algno == -1) {
  151: 		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
  152: 		return NULL;
  153: 	}
  154: 	if (ipsec_supported[algno] == NULL) {
  155: 		__ipsec_errcode = EIPSEC_DO_GET_SUPP_LIST;
  156: 		return NULL;
  157: 	}
  158: 
  159: 	tlen = ipsec_supported[algno]->sadb_supported_len
  160: 		- sizeof(struct sadb_supported);
  161: 	p = (void *)(ipsec_supported[algno] + 1);
  162: 	while (tlen > 0) {
  163: 		if (tlen < sizeof(struct sadb_alg)) {
  164: 			/* invalid format */
  165: 			break;
  166: 		}
  167: 		if (((struct sadb_alg *)(void *)p)->sadb_alg_id == alg_id)
  168: 			return (void *)p;
  169: 
  170: 		tlen -= sizeof(struct sadb_alg);
  171: 		p += sizeof(struct sadb_alg);
  172: 	}
  173: 
  174: 	__ipsec_errcode = EIPSEC_NOT_SUPPORTED;
  175: 	return NULL;
  176: }
  177: 
  178: static int
  179: setsupportedmap(sup)
  180: 	struct sadb_supported *sup;
  181: {
  182: 	struct sadb_supported **ipsup;
  183: 
  184: 	switch (sup->sadb_supported_exttype) {
  185: 	case SADB_EXT_SUPPORTED_AUTH:
  186: 		ipsup = &ipsec_supported[findsupportedmap(SADB_SATYPE_AH)];
  187: 		break;
  188: 	case SADB_EXT_SUPPORTED_ENCRYPT:
  189: 		ipsup = &ipsec_supported[findsupportedmap(SADB_SATYPE_ESP)];
  190: 		break;
  191: 	default:
  192: 		__ipsec_errcode = EIPSEC_INVAL_SATYPE;
  193: 		return -1;
  194: 	}
  195: 
  196: 	if (*ipsup)
  197: 		free(*ipsup);
  198: 
  199: 	*ipsup = malloc((size_t)sup->sadb_supported_len);
  200: 	if (!*ipsup) {
  201: 		__ipsec_set_strerror(strerror(errno));
  202: 		return -1;
  203: 	}
  204: 	memcpy(*ipsup, sup, (size_t)sup->sadb_supported_len);
  205: 
  206: 	return 0;
  207: }
  208: 
  209: /*
  210:  * check key length against algorithm specified.
  211:  * This function is called with SADB_EXT_SUPPORTED_{AUTH,ENCRYPT} as the
  212:  * augument, and only calls to ipsec_check_keylen2();
  213:  * keylen is the unit of bit.
  214:  * OUT:
  215:  *	-1: invalid.
  216:  *	 0: valid.
  217:  */
  218: int
  219: ipsec_check_keylen(supported, alg_id, keylen)
  220: 	u_int supported;
  221: 	u_int alg_id;
  222: 	u_int keylen;
  223: {
  224: 	u_int satype;
  225: 
  226: 	/* validity check */
  227: 	switch (supported) {
  228: 	case SADB_EXT_SUPPORTED_AUTH:
  229: 		satype = SADB_SATYPE_AH;
  230: 		break;
  231: 	case SADB_EXT_SUPPORTED_ENCRYPT:
  232: 		satype = SADB_SATYPE_ESP;
  233: 		break;
  234: 	default:
  235: 		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
  236: 		return -1;
  237: 	}
  238: 
  239: 	return ipsec_check_keylen2(satype, alg_id, keylen);
  240: }
  241: 
  242: /*
  243:  * check key length against algorithm specified.
  244:  * satype is one of satype defined at pfkeyv2.h.
  245:  * keylen is the unit of bit.
  246:  * OUT:
  247:  *	-1: invalid.
  248:  *	 0: valid.
  249:  */
  250: int
  251: ipsec_check_keylen2(satype, alg_id, keylen)
  252: 	u_int satype;
  253: 	u_int alg_id;
  254: 	u_int keylen;
  255: {
  256: 	struct sadb_alg *alg;
  257: 
  258: 	alg = findsupportedalg(satype, alg_id);
  259: 	if (!alg)
  260: 		return -1;
  261: 
  262: 	if (keylen < alg->sadb_alg_minbits || keylen > alg->sadb_alg_maxbits) {
  263: 		fprintf(stderr, "%d %d %d\n", keylen, alg->sadb_alg_minbits,
  264: 			alg->sadb_alg_maxbits);
  265: 		__ipsec_errcode = EIPSEC_INVAL_KEYLEN;
  266: 		return -1;
  267: 	}
  268: 
  269: 	__ipsec_errcode = EIPSEC_NO_ERROR;
  270: 	return 0;
  271: }
  272: 
  273: /*
  274:  * get max/min key length against algorithm specified.
  275:  * satype is one of satype defined at pfkeyv2.h.
  276:  * keylen is the unit of bit.
  277:  * OUT:
  278:  *	-1: invalid.
  279:  *	 0: valid.
  280:  */
  281: int
  282: ipsec_get_keylen(supported, alg_id, alg0)
  283: 	u_int supported, alg_id;
  284: 	struct sadb_alg *alg0;
  285: {
  286: 	struct sadb_alg *alg;
  287: 	u_int satype;
  288: 
  289: 	/* validity check */
  290: 	if (!alg0) {
  291: 		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
  292: 		return -1;
  293: 	}
  294: 
  295: 	switch (supported) {
  296: 	case SADB_EXT_SUPPORTED_AUTH:
  297: 		satype = SADB_SATYPE_AH;
  298: 		break;
  299: 	case SADB_EXT_SUPPORTED_ENCRYPT:
  300: 		satype = SADB_SATYPE_ESP;
  301: 		break;
  302: 	default:
  303: 		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
  304: 		return -1;
  305: 	}
  306: 
  307: 	alg = findsupportedalg(satype, alg_id);
  308: 	if (!alg)
  309: 		return -1;
  310: 
  311: 	memcpy(alg0, alg, sizeof(*alg0));
  312: 
  313: 	__ipsec_errcode = EIPSEC_NO_ERROR;
  314: 	return 0;
  315: }
  316: 
  317: /*
  318:  * set the rate for SOFT lifetime against HARD one.
  319:  * If rate is more than 100 or equal to zero, then set to 100.
  320:  */
  321: static u_int soft_lifetime_allocations_rate = PFKEY_SOFT_LIFETIME_RATE;
  322: static u_int soft_lifetime_bytes_rate = PFKEY_SOFT_LIFETIME_RATE;
  323: static u_int soft_lifetime_addtime_rate = PFKEY_SOFT_LIFETIME_RATE;
  324: static u_int soft_lifetime_usetime_rate = PFKEY_SOFT_LIFETIME_RATE;
  325: 
  326: u_int
  327: pfkey_set_softrate(type, rate)
  328: 	u_int type, rate;
  329: {
  330: 	__ipsec_errcode = EIPSEC_NO_ERROR;
  331: 
  332: 	if (rate > 100 || rate == 0)
  333: 		rate = 100;
  334: 
  335: 	switch (type) {
  336: 	case SADB_X_LIFETIME_ALLOCATIONS:
  337: 		soft_lifetime_allocations_rate = rate;
  338: 		return 0;
  339: 	case SADB_X_LIFETIME_BYTES:
  340: 		soft_lifetime_bytes_rate = rate;
  341: 		return 0;
  342: 	case SADB_X_LIFETIME_ADDTIME:
  343: 		soft_lifetime_addtime_rate = rate;
  344: 		return 0;
  345: 	case SADB_X_LIFETIME_USETIME:
  346: 		soft_lifetime_usetime_rate = rate;
  347: 		return 0;
  348: 	}
  349: 
  350: 	__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
  351: 	return 1;
  352: }
  353: 
  354: /*
  355:  * get current rate for SOFT lifetime against HARD one.
  356:  * ATTENTION: ~0 is returned if invalid type was passed.
  357:  */
  358: u_int
  359: pfkey_get_softrate(type)
  360: 	u_int type;
  361: {
  362: 	switch (type) {
  363: 	case SADB_X_LIFETIME_ALLOCATIONS:
  364: 		return soft_lifetime_allocations_rate;
  365: 	case SADB_X_LIFETIME_BYTES:
  366: 		return soft_lifetime_bytes_rate;
  367: 	case SADB_X_LIFETIME_ADDTIME:
  368: 		return soft_lifetime_addtime_rate;
  369: 	case SADB_X_LIFETIME_USETIME:
  370: 		return soft_lifetime_usetime_rate;
  371: 	}
  372: 
  373: 	return (u_int)~0;
  374: }
  375: 
  376: /*
  377:  * sending SADB_GETSPI message to the kernel.
  378:  * OUT:
  379:  *	positive: success and return length sent.
  380:  *	-1	: error occured, and set errno.
  381:  */
  382: int
  383: pfkey_send_getspi_nat(int so, u_int satype, u_int mode, struct sockaddr *src,
  384:     struct sockaddr *dst, u_int8_t natt_type, u_int16_t sport,
  385:     u_int16_t dport, u_int32_t min, u_int32_t max, u_int32_t reqid,
  386:     u_int32_t seq)
  387: {
  388: 	struct sadb_msg *newmsg;
  389: 	caddr_t ep;
  390: 	int len;
  391: 	int need_spirange = 0;
  392: 	caddr_t p;
  393: 	int plen;
  394: 
  395: 	/* validity check */
  396: 	if (src == NULL || dst == NULL) {
  397: 		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
  398: 		return -1;
  399: 	}
  400: 	if (src->sa_family != dst->sa_family) {
  401: 		__ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
  402: 		return -1;
  403: 	}
  404: 	if (min > max || (min > 0 && min <= 255)) {
  405: 		__ipsec_errcode = EIPSEC_INVAL_SPI;
  406: 		return -1;
  407: 	}
  408: 	switch (src->sa_family) {
  409: 	case AF_INET:
  410: 		plen = sizeof(struct in_addr) << 3;
  411: 		break;
  412: 	case AF_INET6:
  413: 		plen = sizeof(struct in6_addr) << 3;
  414: 		break;
  415: 	default:
  416: 		__ipsec_errcode = EIPSEC_INVAL_FAMILY;
  417: 		return -1;
  418: 	}
  419: 
  420: 	/* create new sadb_msg to send. */
  421: 	len = sizeof(struct sadb_msg)
  422: 		+ sizeof(struct sadb_x_sa2)
  423: 		+ sizeof(struct sadb_address)
  424: 		+ PFKEY_ALIGN8(sysdep_sa_len(src))
  425: 		+ sizeof(struct sadb_address)
  426: 		+ PFKEY_ALIGN8(sysdep_sa_len(dst));
  427: 
  428: 	if (min > 255 && max < (u_int)~0) {
  429: 		need_spirange++;
  430: 		len += sizeof(struct sadb_spirange);
  431: 	}
  432: 
  433: #ifdef SADB_X_EXT_NAT_T_TYPE
  434: 	if(natt_type||sport||dport){
  435: 		len += sizeof(struct sadb_x_nat_t_type);
  436: 		len += sizeof(struct sadb_x_nat_t_port);
  437: 		len += sizeof(struct sadb_x_nat_t_port);
  438: 	}
  439: #endif
  440: 
  441: 	if ((newmsg = CALLOC((size_t)len, struct sadb_msg *)) == NULL) {
  442: 		__ipsec_set_strerror(strerror(errno));
  443: 		return -1;
  444: 	}
  445: 	ep = ((caddr_t)(void *)newmsg) + len;
  446: 
  447: 	p = pfkey_setsadbmsg((void *)newmsg, ep, SADB_GETSPI,
  448: 	    (u_int)len, satype, seq, getpid());
  449: 	if (!p) {
  450: 		free(newmsg);
  451: 		return -1;
  452: 	}
  453: 
  454: 	p = pfkey_setsadbxsa2(p, ep, mode, reqid);
  455: 	if (!p) {
  456: 		free(newmsg);
  457: 		return -1;
  458: 	}
  459: 
  460: 	/* set sadb_address for source */
  461: 	p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, (u_int)plen,
  462: 	    IPSEC_ULPROTO_ANY);
  463: 	if (!p) {
  464: 		free(newmsg);
  465: 		return -1;
  466: 	}
  467: 
  468: 	/* set sadb_address for destination */
  469: 	p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, (u_int)plen,
  470: 	    IPSEC_ULPROTO_ANY);
  471: 	if (!p) {
  472: 		free(newmsg);
  473: 		return -1;
  474: 	}
  475: 
  476: #ifdef SADB_X_EXT_NAT_T_TYPE
  477: 	/* Add nat-t messages */
  478: 	if (natt_type) {
  479: 		p = pfkey_set_natt_type(p, ep, SADB_X_EXT_NAT_T_TYPE, 
  480: 					natt_type);
  481: 		if (!p) {
  482: 			free(newmsg);
  483: 			return -1;
  484: 		}
  485: 
  486: 		p = pfkey_set_natt_port(p, ep, SADB_X_EXT_NAT_T_SPORT,
  487: 					sport);
  488: 		if (!p) {
  489: 			free(newmsg);
  490: 			return -1;
  491: 		}
  492: 
  493: 		p = pfkey_set_natt_port(p, ep, SADB_X_EXT_NAT_T_DPORT,
  494: 					dport);
  495: 		if (!p) {
  496: 			free(newmsg);
  497: 			return -1;
  498: 		}
  499: 	}
  500: #endif
  501: 
  502: 	/* proccessing spi range */
  503: 	if (need_spirange) {
  504: 		struct sadb_spirange spirange;
  505: 
  506: 		if (p + sizeof(spirange) > ep) {
  507: 			free(newmsg);
  508: 			return -1;
  509: 		}
  510: 
  511: 		memset(&spirange, 0, sizeof(spirange));
  512: 		spirange.sadb_spirange_len = PFKEY_UNIT64(sizeof(spirange));
  513: 		spirange.sadb_spirange_exttype = SADB_EXT_SPIRANGE;
  514: 		spirange.sadb_spirange_min = min;
  515: 		spirange.sadb_spirange_max = max;
  516: 
  517: 		memcpy(p, &spirange, sizeof(spirange));
  518: 
  519: 		p += sizeof(spirange);
  520: 	}
  521: 	if (p != ep) {
  522: 		free(newmsg);
  523: 		return -1;
  524: 	}
  525: 
  526: 	/* send message */
  527: 	len = pfkey_send(so, newmsg, len);
  528: 	free(newmsg);
  529: 
  530: 	if (len < 0)
  531: 		return -1;
  532: 
  533: 	__ipsec_errcode = EIPSEC_NO_ERROR;
  534: 	return len;
  535: }
  536: 
  537: int
  538: pfkey_send_getspi(int so, u_int satype, u_int mode, struct sockaddr *src,
  539:     struct sockaddr *dst, u_int32_t min, u_int32_t max, u_int32_t reqid,
  540:     u_int32_t seq)
  541: {
  542: 	return pfkey_send_getspi_nat(so, satype, mode, src, dst, 0, 0, 0,
  543: 		min, max, reqid, seq);
  544: }
  545: 
  546: /*
  547:  * sending SADB_UPDATE message to the kernel.
  548:  * The length of key material is a_keylen + e_keylen.
  549:  * OUT:
  550:  *	positive: success and return length sent.
  551:  *	-1	: error occured, and set errno.
  552:  */
  553: int
  554: pfkey_send_update2(struct pfkey_send_sa_args *sa_parms)
  555: {
  556: 	int len;
  557: 
  558: 	sa_parms->type = SADB_UPDATE;
  559: 	if ((len = pfkey_send_x1(sa_parms)) < 0)
  560: 		return -1;
  561: 
  562: 	return len;
  563: }
  564: 
  565: /*
  566:  * sending SADB_ADD message to the kernel.
  567:  * The length of key material is a_keylen + e_keylen.
  568:  * OUT:
  569:  *	positive: success and return length sent.
  570:  *	-1	: error occured, and set errno.
  571:  */
  572: int
  573: pfkey_send_add2(struct pfkey_send_sa_args *sa_parms)
  574: {
  575: 	int len;
  576: 	
  577: 	sa_parms->type = SADB_ADD;
  578: 	if ((len = pfkey_send_x1(sa_parms)) < 0)
  579: 		return -1;
  580: 
  581: 	return len;
  582: }
  583: 
  584: /*
  585:  * sending SADB_DELETE message to the kernel.
  586:  * OUT:
  587:  *	positive: success and return length sent.
  588:  *	-1	: error occured, and set errno.
  589:  */
  590: int
  591: pfkey_send_delete(int so, u_int satype, u_int mode, struct sockaddr *src,
  592:     struct sockaddr *dst, u_int32_t spi)
  593: {
  594: 	int len;
  595: 	if ((len = pfkey_send_x2(so, SADB_DELETE, satype, mode, src, dst, spi)) < 0)
  596: 		return -1;
  597: 
  598: 	return len;
  599: }
  600: 
  601: /*
  602:  * sending SADB_DELETE without spi to the kernel.  This is
  603:  * the "delete all" request (an extension also present in
  604:  * Solaris).
  605:  *
  606:  * OUT:
  607:  *	positive: success and return length sent
  608:  *	-1	: error occured, and set errno
  609:  */
  610: /*ARGSUSED*/
  611: int
  612: pfkey_send_delete_all(int so, u_int satype, u_int mode, struct sockaddr *src,
  613:     struct sockaddr *dst)
  614: {
  615: 	struct sadb_msg *newmsg;
  616: 	int len;
  617: 	caddr_t p;
  618: 	int plen;
  619: 	caddr_t ep;
  620: 
  621: 	/* validity check */
  622: 	if (src == NULL || dst == NULL) {
  623: 		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
  624: 		return -1;
  625: 	}
  626: 	if (src->sa_family != dst->sa_family) {
  627: 		__ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
  628: 		return -1;
  629: 	}
  630: 	switch (src->sa_family) {
  631: 	case AF_INET:
  632: 		plen = sizeof(struct in_addr) << 3;
  633: 		break;
  634: 	case AF_INET6:
  635: 		plen = sizeof(struct in6_addr) << 3;
  636: 		break;
  637: 	default:
  638: 		__ipsec_errcode = EIPSEC_INVAL_FAMILY;
  639: 		return -1;
  640: 	}
  641: 
  642: 	/* create new sadb_msg to reply. */
  643: 	len = sizeof(struct sadb_msg)
  644: 		+ sizeof(struct sadb_address)
  645: 		+ PFKEY_ALIGN8(sysdep_sa_len(src))
  646: 		+ sizeof(struct sadb_address)
  647: 		+ PFKEY_ALIGN8(sysdep_sa_len(dst));
  648: 
  649: 	if ((newmsg = CALLOC((size_t)len, struct sadb_msg *)) == NULL) {
  650: 		__ipsec_set_strerror(strerror(errno));
  651: 		return -1;
  652: 	}
  653: 	ep = ((caddr_t)(void *)newmsg) + len;
  654: 
  655: 	p = pfkey_setsadbmsg((void *)newmsg, ep, SADB_DELETE, (u_int)len, 
  656: 	    satype, 0, getpid());
  657: 	if (!p) {
  658: 		free(newmsg);
  659: 		return -1;
  660: 	}
  661: 	p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, (u_int)plen,
  662: 	    IPSEC_ULPROTO_ANY);
  663: 	if (!p) {
  664: 		free(newmsg);
  665: 		return -1;
  666: 	}
  667: 	p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, (u_int)plen,
  668: 	    IPSEC_ULPROTO_ANY);
  669: 	if (!p || p != ep) {
  670: 		free(newmsg);
  671: 		return -1;
  672: 	}
  673: 
  674: 	/* send message */
  675: 	len = pfkey_send(so, newmsg, len);
  676: 	free(newmsg);
  677: 
  678: 	if (len < 0)
  679: 		return -1;
  680: 
  681: 	__ipsec_errcode = EIPSEC_NO_ERROR;
  682: 	return len;
  683: }
  684: 
  685: /*
  686:  * sending SADB_GET message to the kernel.
  687:  * OUT:
  688:  *	positive: success and return length sent.
  689:  *	-1	: error occured, and set errno.
  690:  */
  691: int
  692: pfkey_send_get(int so, u_int satype, u_int mode, struct sockaddr *src,
  693:     struct sockaddr *dst, u_int32_t spi)
  694: {
  695: 	int len;
  696: 	if ((len = pfkey_send_x2(so, SADB_GET, satype, mode, src, dst, spi)) < 0)
  697: 		return -1;
  698: 
  699: 	return len;
  700: }
  701: 
  702: /*
  703:  * sending SADB_REGISTER message to the kernel.
  704:  * OUT:
  705:  *	positive: success and return length sent.
  706:  *	-1	: error occured, and set errno.
  707:  */
  708: int
  709: pfkey_send_register(int so, u_int satype)
  710: {
  711: 	int len, algno;
  712: 
  713: 	if (satype == PF_UNSPEC) {
  714: 		for (algno = 0;
  715: 		     algno < sizeof(supported_map)/sizeof(supported_map[0]);
  716: 		     algno++) {
  717: 			if (ipsec_supported[algno]) {
  718: 				free(ipsec_supported[algno]);
  719: 				ipsec_supported[algno] = NULL;
  720: 			}
  721: 		}
  722: 	} else {
  723: 		algno = findsupportedmap((int)satype);
  724: 		if (algno == -1) {
  725: 			__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
  726: 			return -1;
  727: 		}
  728: 
  729: 		if (ipsec_supported[algno]) {
  730: 			free(ipsec_supported[algno]);
  731: 			ipsec_supported[algno] = NULL;
  732: 		}
  733: 	}
  734: 
  735: 	if ((len = pfkey_send_x3(so, SADB_REGISTER, satype)) < 0)
  736: 		return -1;
  737: 
  738: 	return len;
  739: }
  740: 
  741: /*
  742:  * receiving SADB_REGISTER message from the kernel, and copy buffer for
  743:  * sadb_supported returned into ipsec_supported.
  744:  * OUT:
  745:  *	 0: success and return length sent.
  746:  *	-1: error occured, and set errno.
  747:  */
  748: int
  749: pfkey_recv_register(int so)
  750: {
  751: 	pid_t pid = getpid();
  752: 	struct sadb_msg *newmsg;
  753: 	int error = -1;
  754: 
  755: 	/* receive message */
  756: 	for (;;) {
  757: 		if ((newmsg = pfkey_recv(so)) == NULL)
  758: 			return -1;
  759: 		if (newmsg->sadb_msg_type == SADB_REGISTER &&
  760: 		    newmsg->sadb_msg_pid == pid)
  761: 			break;
  762: 		free(newmsg);
  763: 	}
  764: 
  765: 	/* check and fix */
  766: 	newmsg->sadb_msg_len = PFKEY_UNUNIT64(newmsg->sadb_msg_len);
  767: 
  768: 	error = pfkey_set_supported(newmsg, newmsg->sadb_msg_len);
  769: 	free(newmsg);
  770: 
  771: 	if (error == 0)
  772: 		__ipsec_errcode = EIPSEC_NO_ERROR;
  773: 
  774: 	return error;
  775: }
  776: 
  777: /*
  778:  * receiving SADB_REGISTER message from the kernel, and copy buffer for
  779:  * sadb_supported returned into ipsec_supported.
  780:  * NOTE: sadb_msg_len must be host order.
  781:  * IN:
  782:  *	tlen: msg length, it's to makeing sure.
  783:  * OUT:
  784:  *	 0: success and return length sent.
  785:  *	-1: error occured, and set errno.
  786:  */
  787: int
  788: pfkey_set_supported(struct sadb_msg *msg, int tlen)
  789: {
  790: 	struct sadb_supported *sup;
  791: 	caddr_t p;
  792: 	caddr_t ep;
  793: 
  794: 	/* validity */
  795: 	if (msg->sadb_msg_len != tlen) {
  796: 		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
  797: 		return -1;
  798: 	}
  799: 
  800: 	p = (void *)msg;
  801: 	ep = p + tlen;
  802: 
  803: 	p += sizeof(struct sadb_msg);
  804: 
  805: 	while (p < ep) {
  806: 		sup = (void *)p;
  807: 		if (ep < p + sizeof(*sup) ||
  808: 		    PFKEY_EXTLEN(sup) < sizeof(*sup) ||
  809: 		    ep < p + sup->sadb_supported_len) {
  810: 			/* invalid format */
  811: 			break;
  812: 		}
  813: 
  814: 		switch (sup->sadb_supported_exttype) {
  815: 		case SADB_EXT_SUPPORTED_AUTH:
  816: 		case SADB_EXT_SUPPORTED_ENCRYPT:
  817: 			break;
  818: 		default:
  819: 			__ipsec_errcode = EIPSEC_INVAL_SATYPE;
  820: 			return -1;
  821: 		}
  822: 
  823: 		/* fixed length */
  824: 		sup->sadb_supported_len = PFKEY_EXTLEN(sup);
  825: 
  826: 		/* set supported map */
  827: 		if (setsupportedmap(sup) != 0)
  828: 			return -1;
  829: 
  830: 		p += sup->sadb_supported_len;
  831: 	}
  832: 
  833: 	if (p != ep) {
  834: 		__ipsec_errcode = EIPSEC_INVAL_SATYPE;
  835: 		return -1;
  836: 	}
  837: 
  838: 	__ipsec_errcode = EIPSEC_NO_ERROR;
  839: 
  840: 	return 0;
  841: }
  842: 
  843: /*
  844:  * sending SADB_FLUSH message to the kernel.
  845:  * OUT:
  846:  *	positive: success and return length sent.
  847:  *	-1	: error occured, and set errno.
  848:  */
  849: int
  850: pfkey_send_flush(int so, u_int satype)
  851: {
  852: 	int len;
  853: 
  854: 	if ((len = pfkey_send_x3(so, SADB_FLUSH, satype)) < 0)
  855: 		return -1;
  856: 
  857: 	return len;
  858: }
  859: 
  860: /*
  861:  * sending SADB_DUMP message to the kernel.
  862:  * OUT:
  863:  *	positive: success and return length sent.
  864:  *	-1	: error occured, and set errno.
  865:  */
  866: int
  867: pfkey_send_dump(int so, u_int satype)
  868: {
  869: 	int len;
  870: 
  871: 	if ((len = pfkey_send_x3(so, SADB_DUMP, satype)) < 0)
  872: 		return -1;
  873: 
  874: 	return len;
  875: }
  876: 
  877: /*
  878:  * sending SADB_X_PROMISC message to the kernel.
  879:  * NOTE that this function handles promisc mode toggle only.
  880:  * IN:
  881:  *	flag:	set promisc off if zero, set promisc on if non-zero.
  882:  * OUT:
  883:  *	positive: success and return length sent.
  884:  *	-1	: error occured, and set errno.
  885:  *	0     : error occured, and set errno.
  886:  *	others: a pointer to new allocated buffer in which supported
  887:  *	        algorithms is.
  888:  */
  889: int
  890: pfkey_send_promisc_toggle(int so, int flag)
  891: {
  892: 	int len;
  893: 
  894: 	if ((len = pfkey_send_x3(so, SADB_X_PROMISC, 
  895: 	    (u_int)(flag ? 1 : 0))) < 0)
  896: 		return -1;
  897: 
  898: 	return len;
  899: }
  900: 
  901: /*
  902:  * sending SADB_X_SPDADD message to the kernel.
  903:  * OUT:
  904:  *	positive: success and return length sent.
  905:  *	-1	: error occured, and set errno.
  906:  */
  907: int
  908: pfkey_send_spdadd(int so, struct sockaddr *src, u_int prefs,
  909:     struct sockaddr *dst, u_int prefd, u_int proto, caddr_t policy,
  910:     int policylen, u_int32_t seq)
  911: {
  912: 	int len;
  913: 
  914: 	if ((len = pfkey_send_x4(so, SADB_X_SPDADD,
  915: 				src, prefs, dst, prefd, proto,
  916: 				(u_int64_t)0, (u_int64_t)0,
  917: 				policy, policylen, seq)) < 0)
  918: 		return -1;
  919: 
  920: 	return len;
  921: }
  922: 
  923: /*
  924:  * sending SADB_X_SPDADD message to the kernel.
  925:  * OUT:
  926:  *	positive: success and return length sent.
  927:  *	-1	: error occured, and set errno.
  928:  */
  929: int
  930: pfkey_send_spdadd2(int so, struct sockaddr *src, u_int prefs,
  931:     struct sockaddr *dst, u_int prefd, u_int proto, u_int64_t ltime,
  932:     u_int64_t vtime, caddr_t policy, int policylen, u_int32_t seq)
  933: {
  934: 	int len;
  935: 
  936: 	if ((len = pfkey_send_x4(so, SADB_X_SPDADD,
  937: 				src, prefs, dst, prefd, proto,
  938: 				ltime, vtime,
  939: 				policy, policylen, seq)) < 0)
  940: 		return -1;
  941: 
  942: 	return len;
  943: }
  944: 
  945: /*
  946:  * sending SADB_X_SPDUPDATE message to the kernel.
  947:  * OUT:
  948:  *	positive: success and return length sent.
  949:  *	-1	: error occured, and set errno.
  950:  */
  951: int
  952: pfkey_send_spdupdate(int so, struct sockaddr *src, u_int prefs,
  953:     struct sockaddr *dst, u_int prefd, u_int proto, caddr_t policy,
  954:     int policylen, u_int32_t seq)
  955: {
  956: 	int len;
  957: 
  958: 	if ((len = pfkey_send_x4(so, SADB_X_SPDUPDATE,
  959: 				src, prefs, dst, prefd, proto,
  960: 				(u_int64_t)0, (u_int64_t)0,
  961: 				policy, policylen, seq)) < 0)
  962: 		return -1;
  963: 
  964: 	return len;
  965: }
  966: 
  967: /*
  968:  * sending SADB_X_SPDUPDATE message to the kernel.
  969:  * OUT:
  970:  *	positive: success and return length sent.
  971:  *	-1	: error occured, and set errno.
  972:  */
  973: int
  974: pfkey_send_spdupdate2(int so, struct sockaddr *src, u_int prefs,
  975:     struct sockaddr *dst, u_int prefd, u_int proto, u_int64_t ltime,
  976:     u_int64_t vtime, caddr_t policy, int policylen, u_int32_t seq)
  977: {
  978: 	int len;
  979: 
  980: 	if ((len = pfkey_send_x4(so, SADB_X_SPDUPDATE,
  981: 				src, prefs, dst, prefd, proto,
  982: 				ltime, vtime,
  983: 				policy, policylen, seq)) < 0)
  984: 		return -1;
  985: 
  986: 	return len;
  987: }
  988: 
  989: /*
  990:  * sending SADB_X_SPDDELETE message to the kernel.
  991:  * OUT:
  992:  *	positive: success and return length sent.
  993:  *	-1	: error occured, and set errno.
  994:  */
  995: int
  996: pfkey_send_spddelete(int so, struct sockaddr *src, u_int prefs,
  997:     struct sockaddr *dst, u_int prefd, u_int proto, caddr_t policy,
  998:     int policylen, u_int32_t seq)
  999: {
 1000: 	int len;
 1001: 
 1002: 	if (policylen != sizeof(struct sadb_x_policy)) {
 1003: 		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
 1004: 		return -1;
 1005: 	}
 1006: 
 1007: 	if ((len = pfkey_send_x4(so, SADB_X_SPDDELETE,
 1008: 				src, prefs, dst, prefd, proto,
 1009: 				(u_int64_t)0, (u_int64_t)0,
 1010: 				policy, policylen, seq)) < 0)
 1011: 		return -1;
 1012: 
 1013: 	return len;
 1014: }
 1015: 
 1016: /*
 1017:  * sending SADB_X_SPDDELETE message to the kernel.
 1018:  * OUT:
 1019:  *	positive: success and return length sent.
 1020:  *	-1	: error occured, and set errno.
 1021:  */
 1022: int
 1023: pfkey_send_spddelete2(int so, u_int32_t spid)
 1024: {
 1025: 	int len;
 1026: 
 1027: 	if ((len = pfkey_send_x5(so, SADB_X_SPDDELETE2, spid)) < 0)
 1028: 		return -1;
 1029: 
 1030: 	return len;
 1031: }
 1032: 
 1033: /*
 1034:  * sending SADB_X_SPDGET message to the kernel.
 1035:  * OUT:
 1036:  *	positive: success and return length sent.
 1037:  *	-1	: error occured, and set errno.
 1038:  */
 1039: int
 1040: pfkey_send_spdget(int so, u_int32_t spid)
 1041: {
 1042: 	int len;
 1043: 
 1044: 	if ((len = pfkey_send_x5(so, SADB_X_SPDGET, spid)) < 0)
 1045: 		return -1;
 1046: 
 1047: 	return len;
 1048: }
 1049: 
 1050: /*
 1051:  * sending SADB_X_SPDSETIDX message to the kernel.
 1052:  * OUT:
 1053:  *	positive: success and return length sent.
 1054:  *	-1	: error occured, and set errno.
 1055:  */
 1056: int
 1057: pfkey_send_spdsetidx(int so, struct sockaddr *src, u_int prefs,
 1058:     struct sockaddr *dst, u_int prefd, u_int proto, caddr_t policy,
 1059:     int policylen, u_int32_t seq)
 1060: {
 1061: 	int len;
 1062: 
 1063: 	if (policylen != sizeof(struct sadb_x_policy)) {
 1064: 		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
 1065: 		return -1;
 1066: 	}
 1067: 
 1068: 	if ((len = pfkey_send_x4(so, SADB_X_SPDSETIDX,
 1069: 				src, prefs, dst, prefd, proto,
 1070: 				(u_int64_t)0, (u_int64_t)0,
 1071: 				policy, policylen, seq)) < 0)
 1072: 		return -1;
 1073: 
 1074: 	return len;
 1075: }
 1076: 
 1077: /*
 1078:  * sending SADB_SPDFLUSH message to the kernel.
 1079:  * OUT:
 1080:  *	positive: success and return length sent.
 1081:  *	-1	: error occured, and set errno.
 1082:  */
 1083: int
 1084: pfkey_send_spdflush(int so)
 1085: {
 1086: 	int len;
 1087: 
 1088: 	if ((len = pfkey_send_x3(so, SADB_X_SPDFLUSH, SADB_SATYPE_UNSPEC)) < 0)
 1089: 		return -1;
 1090: 
 1091: 	return len;
 1092: }
 1093: 
 1094: /*
 1095:  * sending SADB_SPDDUMP message to the kernel.
 1096:  * OUT:
 1097:  *	positive: success and return length sent.
 1098:  *	-1	: error occured, and set errno.
 1099:  */
 1100: int
 1101: pfkey_send_spddump(int so)
 1102: {
 1103: 	int len;
 1104: 
 1105: 	if ((len = pfkey_send_x3(so, SADB_X_SPDDUMP, SADB_SATYPE_UNSPEC)) < 0)
 1106: 		return -1;
 1107: 
 1108: 	return len;
 1109: }
 1110: 
 1111: 
 1112: #ifdef SADB_X_MIGRATE
 1113: /*
 1114:  * sending SADB_X_MIGRATE message to the kernel.
 1115:  * OUT:
 1116:  *	positive: success and return length sent.
 1117:  *	-1	: error occured, and set errno.
 1118:  */
 1119: int
 1120: pfkey_send_migrate(int so, struct sockaddr *local, struct sockaddr *remote,
 1121:     struct sockaddr *src, u_int prefs, struct sockaddr *dst, u_int prefd,
 1122:     u_int proto, caddr_t policy, int policylen, u_int32_t seq)
 1123: {
 1124: 	struct sadb_msg *newmsg;
 1125: 	int len;
 1126: 	caddr_t p;
 1127: 	int plen;
 1128: 	caddr_t ep;
 1129: 
 1130: 	/* validity check */
 1131: 	if (src == NULL || dst == NULL) {
 1132: 		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
 1133: 		return -1;
 1134: 	}
 1135: 	if (src->sa_family != dst->sa_family) {
 1136: 		__ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
 1137: 		return -1;
 1138: 	}
 1139: 
 1140: 	if (local == NULL || remote == NULL) {
 1141: 		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
 1142: 		return -1;
 1143: 	}
 1144: #ifdef SADB_X_EXT_KMADDRESS
 1145: 	if (local->sa_family != remote->sa_family) {
 1146: 		__ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
 1147: 		return -1;
 1148: 	}
 1149: #endif
 1150: 
 1151: 	switch (src->sa_family) {
 1152: 	case AF_INET:
 1153: 		plen = sizeof(struct in_addr) << 3;
 1154: 		break;
 1155: 	case AF_INET6:
 1156: 		plen = sizeof(struct in6_addr) << 3;
 1157: 		break;
 1158: 	default:
 1159: 		__ipsec_errcode = EIPSEC_INVAL_FAMILY;
 1160: 		return -1;
 1161: 	}
 1162: 	if (prefs > plen || prefd > plen) {
 1163: 		__ipsec_errcode = EIPSEC_INVAL_PREFIXLEN;
 1164: 		return -1;
 1165: 	}
 1166: 
 1167: 	/* create new sadb_msg to reply. */
 1168: 	len = sizeof(struct sadb_msg)
 1169: #ifdef SADB_X_EXT_KMADDRESS
 1170: 		+ sizeof(struct sadb_x_kmaddress)
 1171: 		+ PFKEY_ALIGN8(2*sysdep_sa_len(local))
 1172: #endif
 1173: 		+ sizeof(struct sadb_address)
 1174: 		+ PFKEY_ALIGN8(sysdep_sa_len(src))
 1175: 		+ sizeof(struct sadb_address)
 1176: 		+ PFKEY_ALIGN8(sysdep_sa_len(dst))
 1177: 		+ policylen;
 1178: 
 1179: 	if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {
 1180: 		__ipsec_set_strerror(strerror(errno));
 1181: 		return -1;
 1182: 	}
 1183: 	ep = ((caddr_t)newmsg) + len;
 1184: 
 1185: 	p = pfkey_setsadbmsg((caddr_t)newmsg, ep, SADB_X_MIGRATE, (u_int)len,
 1186: 	    SADB_SATYPE_UNSPEC, seq, getpid());
 1187: 	if (!p) {
 1188: 		free(newmsg);
 1189: 		return -1;
 1190: 	}
 1191: #ifdef SADB_X_EXT_KMADDRESS
 1192: 	p = pfkey_setsadbkmaddr(p, ep, local, remote);
 1193: 	if (!p) {
 1194: 		free(newmsg);
 1195: 		return -1;
 1196: 	}
 1197: #endif
 1198: 	p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, prefs, proto);
 1199: 	if (!p) {
 1200: 		free(newmsg);
 1201: 		return -1;
 1202: 	}
 1203: 	p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, prefd, proto);
 1204: 	if (!p || p + policylen != ep) {
 1205: 		free(newmsg);
 1206: 		return -1;
 1207: 	}
 1208: 	memcpy(p, policy, policylen);
 1209: 
 1210: 	/* send message */
 1211: 	len = pfkey_send(so, newmsg, len);
 1212: 	free(newmsg);
 1213: 
 1214: 	if (len < 0)
 1215: 		return -1;
 1216: 
 1217: 	__ipsec_errcode = EIPSEC_NO_ERROR;
 1218: 	return len;
 1219: }
 1220: #endif
 1221: 
 1222: 
 1223: /* sending SADB_ADD or SADB_UPDATE message to the kernel */
 1224: static int
 1225: pfkey_send_x1(struct pfkey_send_sa_args *sa_parms)
 1226: {
 1227: 	struct sadb_msg *newmsg;
 1228: 	int len;
 1229: 	caddr_t p;
 1230: 	int plen;
 1231: 	caddr_t ep;
 1232: 
 1233: 	/* validity check */
 1234: 	if (sa_parms->src == NULL || sa_parms->dst == NULL) {
 1235: 		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
 1236: 		return -1;
 1237: 	}
 1238: 	if (sa_parms->src->sa_family != sa_parms->dst->sa_family) {
 1239: 		__ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
 1240: 		return -1;
 1241: 	}
 1242: 	switch (sa_parms->src->sa_family) {
 1243: 	case AF_INET:
 1244: 		plen = sizeof(struct in_addr) << 3;
 1245: 		break;
 1246: 	case AF_INET6:
 1247: 		plen = sizeof(struct in6_addr) << 3;
 1248: 		break;
 1249: 	default:
 1250: 		__ipsec_errcode = EIPSEC_INVAL_FAMILY;
 1251: 		return -1;
 1252: 	}
 1253: 
 1254: 	switch (sa_parms->satype) {
 1255: 	case SADB_SATYPE_ESP:
 1256: 		if (sa_parms->e_type == SADB_EALG_NONE) {
 1257: 			__ipsec_errcode = EIPSEC_NO_ALGS;
 1258: 			return -1;
 1259: 		}
 1260: 		break;
 1261: 	case SADB_SATYPE_AH:
 1262: 		if (sa_parms->e_type != SADB_EALG_NONE) {
 1263: 			__ipsec_errcode = EIPSEC_INVAL_ALGS;
 1264: 			return -1;
 1265: 		}
 1266: 		if (sa_parms->a_type == SADB_AALG_NONE) {
 1267: 			__ipsec_errcode = EIPSEC_NO_ALGS;
 1268: 			return -1;
 1269: 		}
 1270: 		break;
 1271: 	case SADB_X_SATYPE_IPCOMP:
 1272: 		if (sa_parms->e_type == SADB_X_CALG_NONE) {
 1273: 			__ipsec_errcode = EIPSEC_INVAL_ALGS;
 1274: 			return -1;
 1275: 		}
 1276: 		if (sa_parms->a_type != SADB_AALG_NONE) {
 1277: 			__ipsec_errcode = EIPSEC_NO_ALGS;
 1278: 			return -1;
 1279: 		}
 1280: 		break;
 1281: #ifdef SADB_X_AALG_TCP_MD5
 1282: 	case SADB_X_SATYPE_TCPSIGNATURE:
 1283: 		if (sa_parms->e_type != SADB_EALG_NONE) {
 1284: 			__ipsec_errcode = EIPSEC_INVAL_ALGS;
 1285: 			return -1;
 1286: 		}
 1287: 		if (sa_parms->a_type != SADB_X_AALG_TCP_MD5) {
 1288: 			__ipsec_errcode = EIPSEC_INVAL_ALGS;
 1289: 			return -1;
 1290: 		}
 1291: 		break;
 1292: #endif
 1293: 	default:
 1294: 		__ipsec_errcode = EIPSEC_INVAL_SATYPE;
 1295: 		return -1;
 1296: 	}
 1297: 
 1298: 	/* create new sadb_msg to reply. */
 1299: 	len = sizeof(struct sadb_msg)
 1300: 		+ sizeof(struct sadb_sa)
 1301: 		+ sizeof(struct sadb_x_sa2)
 1302: 		+ sizeof(struct sadb_address)
 1303: 		+ PFKEY_ALIGN8(sysdep_sa_len(sa_parms->src))
 1304: 		+ sizeof(struct sadb_address)
 1305: 		+ PFKEY_ALIGN8(sysdep_sa_len(sa_parms->dst))
 1306: 		+ sizeof(struct sadb_lifetime)
 1307: 		+ sizeof(struct sadb_lifetime);
 1308: 
 1309: 	if (sa_parms->e_type != SADB_EALG_NONE && 
 1310: 	    sa_parms->satype != SADB_X_SATYPE_IPCOMP)
 1311: 		len += (sizeof(struct sadb_key) + 
 1312: 			PFKEY_ALIGN8(sa_parms->e_keylen));
 1313: 	if (sa_parms->a_type != SADB_AALG_NONE)
 1314: 		len += (sizeof(struct sadb_key) + 
 1315: 			PFKEY_ALIGN8(sa_parms->a_keylen));
 1316: 
 1317: #ifdef SADB_X_EXT_SEC_CTX
 1318: 	if (sa_parms->ctxstr != NULL)
 1319: 		len += (sizeof(struct sadb_x_sec_ctx)
 1320: 		    + PFKEY_ALIGN8(sa_parms->ctxstrlen));
 1321: #endif
 1322: 
 1323: #ifdef SADB_X_EXT_NAT_T_TYPE
 1324: 	/* add nat-t packets */
 1325: 	if (sa_parms->l_natt_type) {
 1326: 		switch(sa_parms->satype) {
 1327: 		case SADB_SATYPE_ESP:
 1328: 		case SADB_X_SATYPE_IPCOMP:
 1329: 			break;
 1330: 		default:
 1331: 			__ipsec_errcode = EIPSEC_NO_ALGS;
 1332: 			return -1;
 1333: 		}
 1334: 
 1335: 		len += sizeof(struct sadb_x_nat_t_type);
 1336: 		len += sizeof(struct sadb_x_nat_t_port);
 1337: 		len += sizeof(struct sadb_x_nat_t_port);
 1338: 		if (sa_parms->l_natt_oa)
 1339: 			len += sizeof(struct sadb_address) +
 1340: 			  PFKEY_ALIGN8(sysdep_sa_len(sa_parms->l_natt_oa));
 1341: #ifdef SADB_X_EXT_NAT_T_FRAG
 1342: 		if (sa_parms->l_natt_frag)
 1343: 			len += sizeof(struct sadb_x_nat_t_frag);
 1344: #endif
 1345: 	}
 1346: #endif
 1347: 
 1348: 	if ((newmsg = CALLOC((size_t)len, struct sadb_msg *)) == NULL) {
 1349: 		__ipsec_set_strerror(strerror(errno));
 1350: 		return -1;
 1351: 	}
 1352: 	ep = ((caddr_t)(void *)newmsg) + len;
 1353: 
 1354: 	p = pfkey_setsadbmsg((void *)newmsg, ep, sa_parms->type, (u_int)len,
 1355: 	                     sa_parms->satype, sa_parms->seq, getpid());
 1356: 	if (!p) {
 1357: 		free(newmsg);
 1358: 		return -1;
 1359: 	}
 1360: 	p = pfkey_setsadbsa(p, ep, sa_parms->spi, sa_parms->wsize, 
 1361: 			    sa_parms->a_type, sa_parms->e_type, 
 1362: 			    sa_parms->flags);
 1363: 	if (!p) {
 1364: 		free(newmsg);
 1365: 		return -1;
 1366: 	}
 1367: 	p = pfkey_setsadbxsa2(p, ep, sa_parms->mode, sa_parms->reqid);
 1368: 	if (!p) {
 1369: 		free(newmsg);
 1370: 		return -1;
 1371: 	}
 1372: 	p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, sa_parms->src, 
 1373: 			      (u_int)plen, IPSEC_ULPROTO_ANY);
 1374: 	if (!p) {
 1375: 		free(newmsg);
 1376: 		return -1;
 1377: 	}
 1378: 	p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, sa_parms->dst, 
 1379: 			      (u_int)plen, IPSEC_ULPROTO_ANY);
 1380: 	if (!p) {
 1381: 		free(newmsg);
 1382: 		return -1;
 1383: 	}
 1384: 
 1385: 	if (sa_parms->e_type != SADB_EALG_NONE && 
 1386: 	    sa_parms->satype != SADB_X_SATYPE_IPCOMP) {
 1387: 		p = pfkey_setsadbkey(p, ep, SADB_EXT_KEY_ENCRYPT,
 1388: 		                   sa_parms->keymat, sa_parms->e_keylen);
 1389: 		if (!p) {
 1390: 			free(newmsg);
 1391: 			return -1;
 1392: 		}
 1393: 	}
 1394: 	if (sa_parms->a_type != SADB_AALG_NONE) {
 1395: 		p = pfkey_setsadbkey(p, ep, SADB_EXT_KEY_AUTH,
 1396: 				     sa_parms->keymat + sa_parms->e_keylen, 
 1397: 				     sa_parms->a_keylen);
 1398: 		if (!p) {
 1399: 			free(newmsg);
 1400: 			return -1;
 1401: 		}
 1402: 	}
 1403: 
 1404: 	/* set sadb_lifetime for destination */
 1405: 	p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_HARD,
 1406: 			sa_parms->l_alloc, sa_parms->l_bytes, 
 1407: 			sa_parms->l_addtime, sa_parms->l_usetime);
 1408: 	if (!p) {
 1409: 		free(newmsg);
 1410: 		return -1;
 1411: 	}
 1412: 	p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_SOFT,
 1413: 				  sa_parms->l_alloc, sa_parms->l_bytes, 
 1414: 				  sa_parms->l_addtime, sa_parms->l_usetime);
 1415: 	if (!p) {
 1416: 		free(newmsg);
 1417: 		return -1;
 1418: 	}
 1419: #ifdef SADB_X_EXT_SEC_CTX
 1420: 	if (sa_parms->ctxstr != NULL) {
 1421: 		p = pfkey_setsecctx(p, ep, SADB_X_EXT_SEC_CTX, sa_parms->ctxdoi,
 1422: 				    sa_parms->ctxalg, sa_parms->ctxstr, 
 1423: 				    sa_parms->ctxstrlen);
 1424: 		if (!p) {
 1425: 			free(newmsg);
 1426: 			return -1;
 1427: 		}
 1428: 	}
 1429: #endif
 1430: 
 1431: #ifdef SADB_X_EXT_NAT_T_TYPE
 1432: 	/* Add nat-t messages */
 1433: 	if (sa_parms->l_natt_type) {
 1434: 		p = pfkey_set_natt_type(p, ep, SADB_X_EXT_NAT_T_TYPE, 
 1435: 					sa_parms->l_natt_type);
 1436: 		if (!p) {
 1437: 			free(newmsg);
 1438: 			return -1;
 1439: 		}
 1440: 
 1441: 		p = pfkey_set_natt_port(p, ep, SADB_X_EXT_NAT_T_SPORT,
 1442: 					sa_parms->l_natt_sport);
 1443: 		if (!p) {
 1444: 			free(newmsg);
 1445: 			return -1;
 1446: 		}
 1447: 
 1448: 		p = pfkey_set_natt_port(p, ep, SADB_X_EXT_NAT_T_DPORT,
 1449: 					sa_parms->l_natt_dport);
 1450: 		if (!p) {
 1451: 			free(newmsg);
 1452: 			return -1;
 1453: 		}
 1454: 
 1455: 		if (sa_parms->l_natt_oa) {
 1456: 			p = pfkey_setsadbaddr(p, ep, SADB_X_EXT_NAT_T_OA,
 1457: 					      sa_parms->l_natt_oa,
 1458: 					      (u_int)PFKEY_ALIGN8(sysdep_sa_len(sa_parms->l_natt_oa)),
 1459: 					      IPSEC_ULPROTO_ANY);
 1460: 			if (!p) {
 1461: 				free(newmsg);
 1462: 				return -1;
 1463: 			}
 1464: 		}
 1465: 
 1466: #ifdef SADB_X_EXT_NAT_T_FRAG
 1467: 		if (sa_parms->l_natt_frag) {
 1468: 			p = pfkey_set_natt_frag(p, ep, SADB_X_EXT_NAT_T_FRAG,
 1469: 					sa_parms->l_natt_frag);
 1470: 			if (!p) {
 1471: 				free(newmsg);
 1472: 				return -1;
 1473: 			}
 1474: 		}
 1475: #endif
 1476: 	}
 1477: #endif
 1478: 
 1479: 	if (p != ep) {
 1480: 		free(newmsg);
 1481: 		return -1;
 1482: 	}
 1483: 
 1484: 	/* send message */
 1485: 	len = pfkey_send(sa_parms->so, newmsg, len);
 1486: 	free(newmsg);
 1487: 
 1488: 	if (len < 0)
 1489: 		return -1;
 1490: 
 1491: 	__ipsec_errcode = EIPSEC_NO_ERROR;
 1492: 	return len;
 1493: }
 1494: 
 1495: /* sending SADB_DELETE or SADB_GET message to the kernel */
 1496: /*ARGSUSED*/
 1497: static int
 1498: pfkey_send_x2(int so, u_int type, u_int satype, u_int mode,
 1499:     struct sockaddr *src, struct sockaddr *dst, u_int32_t spi)
 1500: {
 1501: 	struct sadb_msg *newmsg;
 1502: 	int len;
 1503: 	caddr_t p;
 1504: 	int plen;
 1505: 	caddr_t ep;
 1506: 
 1507: 	/* validity check */
 1508: 	if (src == NULL || dst == NULL) {
 1509: 		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
 1510: 		return -1;
 1511: 	}
 1512: 	if (src->sa_family != dst->sa_family) {
 1513: 		__ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
 1514: 		return -1;
 1515: 	}
 1516: 	switch (src->sa_family) {
 1517: 	case AF_INET:
 1518: 		plen = sizeof(struct in_addr) << 3;
 1519: 		break;
 1520: 	case AF_INET6:
 1521: 		plen = sizeof(struct in6_addr) << 3;
 1522: 		break;
 1523: 	default:
 1524: 		__ipsec_errcode = EIPSEC_INVAL_FAMILY;
 1525: 		return -1;
 1526: 	}
 1527: 
 1528: 	/* create new sadb_msg to reply. */
 1529: 	len = sizeof(struct sadb_msg)
 1530: 		+ sizeof(struct sadb_sa)
 1531: 		+ sizeof(struct sadb_address)
 1532: 		+ PFKEY_ALIGN8(sysdep_sa_len(src))
 1533: 		+ sizeof(struct sadb_address)
 1534: 		+ PFKEY_ALIGN8(sysdep_sa_len(dst));
 1535: 
 1536: 	if ((newmsg = CALLOC((size_t)len, struct sadb_msg *)) == NULL) {
 1537: 		__ipsec_set_strerror(strerror(errno));
 1538: 		return -1;
 1539: 	}
 1540: 	ep = ((caddr_t)(void *)newmsg) + len;
 1541: 
 1542: 	p = pfkey_setsadbmsg((void *)newmsg, ep, type, (u_int)len, satype, 0,
 1543: 	    getpid());
 1544: 	if (!p) {
 1545: 		free(newmsg);
 1546: 		return -1;
 1547: 	}
 1548: 	p = pfkey_setsadbsa(p, ep, spi, 0, 0, 0, 0);
 1549: 	if (!p) {
 1550: 		free(newmsg);
 1551: 		return -1;
 1552: 	}
 1553: 	p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, (u_int)plen,
 1554: 	    IPSEC_ULPROTO_ANY);
 1555: 	if (!p) {
 1556: 		free(newmsg);
 1557: 		return -1;
 1558: 	}
 1559: 	p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, (u_int)plen,
 1560: 	    IPSEC_ULPROTO_ANY);
 1561: 	if (!p || p != ep) {
 1562: 		free(newmsg);
 1563: 		return -1;
 1564: 	}
 1565: 
 1566: 	/* send message */
 1567: 	len = pfkey_send(so, newmsg, len);
 1568: 	free(newmsg);
 1569: 
 1570: 	if (len < 0)
 1571: 		return -1;
 1572: 
 1573: 	__ipsec_errcode = EIPSEC_NO_ERROR;
 1574: 	return len;
 1575: }
 1576: 
 1577: /*
 1578:  * sending SADB_REGISTER, SADB_FLUSH, SADB_DUMP or SADB_X_PROMISC message
 1579:  * to the kernel
 1580:  */
 1581: static int
 1582: pfkey_send_x3(int so, u_int type, u_int satype)
 1583: {
 1584: 	struct sadb_msg *newmsg;
 1585: 	int len;
 1586: 	caddr_t p;
 1587: 	caddr_t ep;
 1588: 
 1589: 	/* validity check */
 1590: 	switch (type) {
 1591: 	case SADB_X_PROMISC:
 1592: 		if (satype != 0 && satype != 1) {
 1593: 			__ipsec_errcode = EIPSEC_INVAL_SATYPE;
 1594: 			return -1;
 1595: 		}
 1596: 		break;
 1597: 	default:
 1598: 		switch (satype) {
 1599: 		case SADB_SATYPE_UNSPEC:
 1600: 		case SADB_SATYPE_AH:
 1601: 		case SADB_SATYPE_ESP:
 1602: 		case SADB_X_SATYPE_IPCOMP:
 1603: #ifdef SADB_X_SATYPE_TCPSIGNATURE
 1604: 		case SADB_X_SATYPE_TCPSIGNATURE:
 1605: #endif
 1606: 			break;
 1607: 		default:
 1608: 			__ipsec_errcode = EIPSEC_INVAL_SATYPE;
 1609: 			return -1;
 1610: 		}
 1611: 	}
 1612: 
 1613: 	/* create new sadb_msg to send. */
 1614: 	len = sizeof(struct sadb_msg);
 1615: 
 1616: 	if ((newmsg = CALLOC((size_t)len, struct sadb_msg *)) == NULL) {
 1617: 		__ipsec_set_strerror(strerror(errno));
 1618: 		return -1;
 1619: 	}
 1620: 	ep = ((caddr_t)(void *)newmsg) + len;
 1621: 
 1622: 	p = pfkey_setsadbmsg((void *)newmsg, ep, type, (u_int)len, satype, 0,
 1623: 	    getpid());
 1624: 	if (!p || p != ep) {
 1625: 		free(newmsg);
 1626: 		return -1;
 1627: 	}
 1628: 
 1629: 	/* send message */
 1630: 	len = pfkey_send(so, newmsg, len);
 1631: 	free(newmsg);
 1632: 
 1633: 	if (len < 0)
 1634: 		return -1;
 1635: 
 1636: 	__ipsec_errcode = EIPSEC_NO_ERROR;
 1637: 	return len;
 1638: }
 1639: 
 1640: /* sending SADB_X_SPDADD message to the kernel */
 1641: static int
 1642: pfkey_send_x4(int so, u_int type, struct sockaddr *src, u_int prefs,
 1643:     struct sockaddr *dst, u_int prefd, u_int proto, u_int64_t ltime,
 1644:     u_int64_t vtime, char *policy, int policylen, u_int32_t seq)
 1645: {
 1646: 	struct sadb_msg *newmsg;
 1647: 	int len;
 1648: 	caddr_t p;
 1649: 	int plen;
 1650: 	caddr_t ep;
 1651: 
 1652: 	/* validity check */
 1653: 	if (src == NULL || dst == NULL) {
 1654: 		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
 1655: 		return -1;
 1656: 	}
 1657: 	if (src->sa_family != dst->sa_family) {
 1658: 		__ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
 1659: 		return -1;
 1660: 	}
 1661: 
 1662: 	switch (src->sa_family) {
 1663: 	case AF_INET:
 1664: 		plen = sizeof(struct in_addr) << 3;
 1665: 		break;
 1666: 	case AF_INET6:
 1667: 		plen = sizeof(struct in6_addr) << 3;
 1668: 		break;
 1669: 	default:
 1670: 		__ipsec_errcode = EIPSEC_INVAL_FAMILY;
 1671: 		return -1;
 1672: 	}
 1673: 	if (prefs > plen || prefd > plen) {
 1674: 		__ipsec_errcode = EIPSEC_INVAL_PREFIXLEN;
 1675: 		return -1;
 1676: 	}
 1677: 
 1678: 	/* create new sadb_msg to reply. */
 1679: 	len = sizeof(struct sadb_msg)
 1680: 		+ sizeof(struct sadb_address)
 1681: 		+ PFKEY_ALIGN8(sysdep_sa_len(src))
 1682: 		+ sizeof(struct sadb_address)
 1683: 		+ PFKEY_ALIGN8(sysdep_sa_len(src))
 1684: 		+ sizeof(struct sadb_lifetime)
 1685: 		+ policylen;
 1686: 
 1687: 	if ((newmsg = CALLOC((size_t)len, struct sadb_msg *)) == NULL) {
 1688: 		__ipsec_set_strerror(strerror(errno));
 1689: 		return -1;
 1690: 	}
 1691: 	ep = ((caddr_t)(void *)newmsg) + len;
 1692: 
 1693: 	p = pfkey_setsadbmsg((void *)newmsg, ep, type, (u_int)len,
 1694: 	    SADB_SATYPE_UNSPEC, seq, getpid());
 1695: 	if (!p) {
 1696: 		free(newmsg);
 1697: 		return -1;
 1698: 	}
 1699: 	p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, prefs, proto);
 1700: 	if (!p) {
 1701: 		free(newmsg);
 1702: 		return -1;
 1703: 	}
 1704: 	p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, prefd, proto);
 1705: 	if (!p) {
 1706: 		free(newmsg);
 1707: 		return -1;
 1708: 	}
 1709: 	p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_HARD,
 1710: 			0, 0, (u_int)ltime, (u_int)vtime);
 1711: 	if (!p || p + policylen != ep) {
 1712: 		free(newmsg);
 1713: 		return -1;
 1714: 	}
 1715: 	memcpy(p, policy, (size_t)policylen);
 1716: 
 1717: 	/* send message */
 1718: 	len = pfkey_send(so, newmsg, len);
 1719: 	free(newmsg);
 1720: 
 1721: 	if (len < 0)
 1722: 		return -1;
 1723: 
 1724: 	__ipsec_errcode = EIPSEC_NO_ERROR;
 1725: 	return len;
 1726: }
 1727: 
 1728: /* sending SADB_X_SPDGET or SADB_X_SPDDELETE message to the kernel */
 1729: static int
 1730: pfkey_send_x5(int so, u_int type, u_int32_t spid)
 1731: {
 1732: 	struct sadb_msg *newmsg;
 1733: 	struct sadb_x_policy xpl;
 1734: 	int len;
 1735: 	caddr_t p;
 1736: 	caddr_t ep;
 1737: 
 1738: 	/* create new sadb_msg to reply. */
 1739: 	len = sizeof(struct sadb_msg)
 1740: 		+ sizeof(xpl);
 1741: 
 1742: 	if ((newmsg = CALLOC((size_t)len, struct sadb_msg *)) == NULL) {
 1743: 		__ipsec_set_strerror(strerror(errno));
 1744: 		return -1;
 1745: 	}
 1746: 	ep = ((caddr_t)(void *)newmsg) + len;
 1747: 
 1748: 	p = pfkey_setsadbmsg((void *)newmsg, ep, type, (u_int)len,
 1749: 	    SADB_SATYPE_UNSPEC, 0, getpid());
 1750: 	if (!p) {
 1751: 		free(newmsg);
 1752: 		return -1;
 1753: 	}
 1754: 
 1755: 	if (p + sizeof(xpl) != ep) {
 1756: 		free(newmsg);
 1757: 		return -1;
 1758: 	}
 1759: 	memset(&xpl, 0, sizeof(xpl));
 1760: 	xpl.sadb_x_policy_len = PFKEY_UNIT64(sizeof(xpl));
 1761: 	xpl.sadb_x_policy_exttype = SADB_X_EXT_POLICY;
 1762: 	xpl.sadb_x_policy_id = spid;
 1763: 	memcpy(p, &xpl, sizeof(xpl));
 1764: 
 1765: 	/* send message */
 1766: 	len = pfkey_send(so, newmsg, len);
 1767: 	free(newmsg);
 1768: 
 1769: 	if (len < 0)
 1770: 		return -1;
 1771: 
 1772: 	__ipsec_errcode = EIPSEC_NO_ERROR;
 1773: 	return len;
 1774: }
 1775: 
 1776: /*
 1777:  * open a socket.
 1778:  * OUT:
 1779:  *	-1: fail.
 1780:  *	others : success and return value of socket.
 1781:  */
 1782: int
 1783: pfkey_open(void)
 1784: {
 1785: 	int so;
 1786: 	int bufsiz_current, bufsiz_wanted;
 1787: 	int ret;
 1788: 	socklen_t len;
 1789: 
 1790: 	if ((so = socket(PF_KEY, SOCK_RAW, PF_KEY_V2)) < 0) {
 1791: 		__ipsec_set_strerror(strerror(errno));
 1792: 		return -1;
 1793: 	}
 1794: 
 1795: 	/*
 1796: 	 * This is a temporary workaround for KAME PR 154.
 1797: 	 * Don't really care even if it fails.
 1798: 	 */
 1799: 	/* Try to have 128k. If we have more, do not lower it. */
 1800: 	bufsiz_wanted = 128 * 1024;
 1801: 	len = sizeof(bufsiz_current);
 1802: 	ret = getsockopt(so, SOL_SOCKET, SO_SNDBUF,
 1803: 		&bufsiz_current, &len);
 1804: 	if ((ret < 0) || (bufsiz_current < bufsiz_wanted))
 1805: 		(void)setsockopt(so, SOL_SOCKET, SO_SNDBUF,
 1806: 			&bufsiz_wanted, sizeof(bufsiz_wanted));
 1807: 
 1808: 	/* Try to have have at least 2MB. If we have more, do not lower it. */
 1809: 	bufsiz_wanted = 2 * 1024 * 1024;
 1810: 	len = sizeof(bufsiz_current);
 1811: 	ret = getsockopt(so, SOL_SOCKET, SO_RCVBUF,
 1812: 		&bufsiz_current, &len);
 1813: 	if (ret < 0)
 1814: 		bufsiz_current = 128 * 1024;
 1815: 
 1816: 	for (; bufsiz_wanted > bufsiz_current; bufsiz_wanted /= 2) {
 1817: 		if (setsockopt(so, SOL_SOCKET, SO_RCVBUF,
 1818: 				&bufsiz_wanted, sizeof(bufsiz_wanted)) == 0)
 1819: 			break;
 1820: 	}
 1821: 
 1822: 	__ipsec_errcode = EIPSEC_NO_ERROR;
 1823: 	return so;
 1824: }
 1825: 
 1826: int
 1827: pfkey_set_buffer_size(int so, int size)
 1828: {
 1829: 	int newsize;
 1830: 	int actual_bufsiz;
 1831: 	socklen_t sizebufsiz;
 1832: 	int desired_bufsiz;
 1833: 
 1834: 	/*
 1835: 	 * on linux you may need to allow the kernel to allocate
 1836: 	 * more buffer space by increasing:
 1837: 	 * /proc/sys/net/core/rmem_max and wmem_max
 1838: 	 */
 1839: 	if (size > 0) {
 1840: 		actual_bufsiz = 0;
 1841: 		sizebufsiz = sizeof(actual_bufsiz);
 1842: 		desired_bufsiz = size * 1024;
 1843: 		if ((getsockopt(so, SOL_SOCKET, SO_RCVBUF,
 1844: 				&actual_bufsiz, &sizebufsiz) < 0)
 1845: 		    || (actual_bufsiz < desired_bufsiz)) {
 1846: 			if (setsockopt(so, SOL_SOCKET, SO_RCVBUF,
 1847: 				       &desired_bufsiz, sizeof(desired_bufsiz)) < 0) {
 1848: 				__ipsec_set_strerror(strerror(errno));
 1849: 				return -1;
 1850: 			}
 1851: 		}
 1852: 	}
 1853: 
 1854: 	/* return actual buffer size */
 1855: 	actual_bufsiz = 0;
 1856: 	sizebufsiz = sizeof(actual_bufsiz);
 1857: 	getsockopt(so, SOL_SOCKET, SO_RCVBUF,
 1858: 		   &actual_bufsiz, &sizebufsiz);
 1859: 	return actual_bufsiz / 1024;
 1860: }
 1861: 
 1862: /*
 1863:  * close a socket.
 1864:  * OUT:
 1865:  *	 0: success.
 1866:  *	-1: fail.
 1867:  */
 1868: void
 1869: pfkey_close(int so)
 1870: {
 1871: 	(void)close(so);
 1872: 
 1873: 	__ipsec_errcode = EIPSEC_NO_ERROR;
 1874: 	return;
 1875: }
 1876: 
 1877: /*
 1878:  * receive sadb_msg data, and return pointer to new buffer allocated.
 1879:  * Must free this buffer later.
 1880:  * OUT:
 1881:  *	NULL	: error occured.
 1882:  *	others	: a pointer to sadb_msg structure.
 1883:  *
 1884:  * XXX should be rewritten to pass length explicitly
 1885:  */
 1886: struct sadb_msg *
 1887: pfkey_recv(int so)
 1888: {
 1889: 	struct sadb_msg buf, *newmsg;
 1890: 	int len, reallen;
 1891: 
 1892: 	while ((len = recv(so, (void *)&buf, sizeof(buf), MSG_PEEK)) < 0) {
 1893: 		if (errno == EINTR)
 1894: 			continue;
 1895: 		__ipsec_set_strerror(strerror(errno));
 1896: 		return NULL;
 1897: 	}
 1898: 
 1899: 	if (len < sizeof(buf)) {
 1900: 		recv(so, (void *)&buf, sizeof(buf), 0);
 1901: 		__ipsec_errcode = EIPSEC_MAX;
 1902: 		return NULL;
 1903: 	}
 1904: 
 1905: 	/* read real message */
 1906: 	reallen = PFKEY_UNUNIT64(buf.sadb_msg_len);
 1907: 	if ((newmsg = CALLOC((size_t)reallen, struct sadb_msg *)) == 0) {
 1908: 		__ipsec_set_strerror(strerror(errno));
 1909: 		return NULL;
 1910: 	}
 1911: 
 1912: 	while ((len = recv(so, (void *)newmsg, (socklen_t)reallen, 0)) < 0) {
 1913: 		if (errno == EINTR)
 1914: 			continue;
 1915: 		__ipsec_set_strerror(strerror(errno));
 1916: 		free(newmsg);
 1917: 		return NULL;
 1918: 	}
 1919: 
 1920: 	if (len != reallen) {
 1921: 		__ipsec_errcode = EIPSEC_SYSTEM_ERROR;
 1922: 		free(newmsg);
 1923: 		return NULL;
 1924: 	}
 1925: 
 1926: 	/* don't trust what the kernel says, validate! */
 1927: 	if (PFKEY_UNUNIT64(newmsg->sadb_msg_len) != len) {
 1928: 		__ipsec_errcode = EIPSEC_SYSTEM_ERROR;
 1929: 		free(newmsg);
 1930: 		return NULL;
 1931: 	}
 1932: 
 1933: 	__ipsec_errcode = EIPSEC_NO_ERROR;
 1934: 	return newmsg;
 1935: }
 1936: 
 1937: /*
 1938:  * send message to a socket.
 1939:  * OUT:
 1940:  *	 others: success and return length sent.
 1941:  *	-1     : fail.
 1942:  */
 1943: int
 1944: pfkey_send(int so, struct sadb_msg *msg, int len)
 1945: {
 1946: 	if ((len = send(so, (void *)msg, (socklen_t)len, 0)) < 0) {
 1947: 		__ipsec_set_strerror(strerror(errno));
 1948: 		return -1;
 1949: 	}
 1950: 
 1951: 	__ipsec_errcode = EIPSEC_NO_ERROR;
 1952: 	return len;
 1953: }
 1954: 
 1955: /*
 1956:  * %%% Utilities
 1957:  * NOTE: These functions are derived from netkey/key.c in KAME.
 1958:  */
 1959: /*
 1960:  * set the pointer to each header in this message buffer.
 1961:  * IN:	msg: pointer to message buffer.
 1962:  *	mhp: pointer to the buffer initialized like below:
 1963:  *		caddr_t mhp[SADB_EXT_MAX + 1];
 1964:  * OUT:	-1: invalid.
 1965:  *	 0: valid.
 1966:  *
 1967:  * XXX should be rewritten to obtain length explicitly
 1968:  */
 1969: int
 1970: pfkey_align(struct sadb_msg *msg, caddr_t *mhp)
 1971: {
 1972: 	struct sadb_ext *ext;
 1973: 	int i;
 1974: 	caddr_t p;
 1975: 	caddr_t ep;	/* XXX should be passed from upper layer */
 1976: 
 1977: 	/* validity check */
 1978: 	if (msg == NULL || mhp == NULL) {
 1979: 		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
 1980: 		return -1;
 1981: 	}
 1982: 
 1983: 	/* initialize */
 1984: 	for (i = 0; i < SADB_EXT_MAX + 1; i++)
 1985: 		mhp[i] = NULL;
 1986: 
 1987: 	mhp[0] = (void *)msg;
 1988: 
 1989: 	/* initialize */
 1990: 	p = (void *) msg;
 1991: 	ep = p + PFKEY_UNUNIT64(msg->sadb_msg_len);
 1992: 
 1993: 	/* skip base header */
 1994: 	p += sizeof(struct sadb_msg);
 1995: 
 1996: 	while (p < ep) {
 1997: 		ext = (void *)p;
 1998: 		if (ep < p + sizeof(*ext) || PFKEY_EXTLEN(ext) < sizeof(*ext) ||
 1999: 		    ep < p + PFKEY_EXTLEN(ext)) {
 2000: 			/* invalid format */
 2001: 			break;
 2002: 		}
 2003: 
 2004: 		/* duplicate check */
 2005: 		/* XXX Are there duplication either KEY_AUTH or KEY_ENCRYPT ?*/
 2006: 		if (mhp[ext->sadb_ext_type] != NULL) {
 2007: 			__ipsec_errcode = EIPSEC_INVAL_EXTTYPE;
 2008: 			return -1;
 2009: 		}
 2010: 
 2011: 		/* set pointer */
 2012: 		switch (ext->sadb_ext_type) {
 2013: 		case SADB_EXT_SA:
 2014: 		case SADB_EXT_LIFETIME_CURRENT:
 2015: 		case SADB_EXT_LIFETIME_HARD:
 2016: 		case SADB_EXT_LIFETIME_SOFT:
 2017: 		case SADB_EXT_ADDRESS_SRC:
 2018: 		case SADB_EXT_ADDRESS_DST:
 2019: 		case SADB_EXT_ADDRESS_PROXY:
 2020: 		case SADB_EXT_KEY_AUTH:
 2021: 			/* XXX should to be check weak keys. */
 2022: 		case SADB_EXT_KEY_ENCRYPT:
 2023: 			/* XXX should to be check weak keys. */
 2024: 		case SADB_EXT_IDENTITY_SRC:
 2025: 		case SADB_EXT_IDENTITY_DST:
 2026: 		case SADB_EXT_SENSITIVITY:
 2027: 		case SADB_EXT_PROPOSAL:
 2028: 		case SADB_EXT_SUPPORTED_AUTH:
 2029: 		case SADB_EXT_SUPPORTED_ENCRYPT:
 2030: 		case SADB_EXT_SPIRANGE:
 2031: 		case SADB_X_EXT_POLICY:
 2032: 		case SADB_X_EXT_SA2:
 2033: #ifdef SADB_X_EXT_NAT_T_TYPE
 2034: 		case SADB_X_EXT_NAT_T_TYPE:
 2035: 		case SADB_X_EXT_NAT_T_SPORT:
 2036: 		case SADB_X_EXT_NAT_T_DPORT:
 2037: 		case SADB_X_EXT_NAT_T_OA:
 2038: #endif
 2039: #ifdef SADB_X_EXT_TAG
 2040: 		case SADB_X_EXT_TAG:
 2041: #endif
 2042: #ifdef SADB_X_EXT_PACKET
 2043: 		case SADB_X_EXT_PACKET:
 2044: #endif
 2045: #ifdef SADB_X_EXT_KMADDRESS
 2046: 		case SADB_X_EXT_KMADDRESS:
 2047: #endif
 2048: #ifdef SADB_X_EXT_SEC_CTX
 2049: 		case SADB_X_EXT_SEC_CTX:
 2050: #endif
 2051: 			mhp[ext->sadb_ext_type] = (void *)ext;
 2052: 			break;
 2053: 		default:
 2054: 			__ipsec_errcode = EIPSEC_INVAL_EXTTYPE;
 2055: 			return -1;
 2056: 		}
 2057: 
 2058: 		p += PFKEY_EXTLEN(ext);
 2059: 	}
 2060: 
 2061: 	if (p != ep) {
 2062: 		__ipsec_errcode = EIPSEC_INVAL_SADBMSG;
 2063: 		return -1;
 2064: 	}
 2065: 
 2066: 	__ipsec_errcode = EIPSEC_NO_ERROR;
 2067: 	return 0;
 2068: }
 2069: 
 2070: /*
 2071:  * check basic usage for sadb_msg,
 2072:  * NOTE: This routine is derived from netkey/key.c in KAME.
 2073:  * IN:	msg: pointer to message buffer.
 2074:  *	mhp: pointer to the buffer initialized like below:
 2075:  *
 2076:  *		caddr_t mhp[SADB_EXT_MAX + 1];
 2077:  *
 2078:  * OUT:	-1: invalid.
 2079:  *	 0: valid.
 2080:  */
 2081: int
 2082: pfkey_check(caddr_t *mhp)
 2083: {
 2084: 	struct sadb_msg *msg;
 2085: 
 2086: 	/* validity check */
 2087: 	if (mhp == NULL || mhp[0] == NULL) {
 2088: 		__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
 2089: 		return -1;
 2090: 	}
 2091: 
 2092: 	msg = (void *)mhp[0];
 2093: 
 2094: 	/* check version */
 2095: 	if (msg->sadb_msg_version != PF_KEY_V2) {
 2096: 		__ipsec_errcode = EIPSEC_INVAL_VERSION;
 2097: 		return -1;
 2098: 	}
 2099: 
 2100: 	/* check type */
 2101: 	if (msg->sadb_msg_type > SADB_MAX) {
 2102: 		__ipsec_errcode = EIPSEC_INVAL_MSGTYPE;
 2103: 		return -1;
 2104: 	}
 2105: 
 2106: 	/* check SA type */
 2107: 	switch (msg->sadb_msg_satype) {
 2108: 	case SADB_SATYPE_UNSPEC:
 2109: 		switch (msg->sadb_msg_type) {
 2110: 		case SADB_GETSPI:
 2111: 		case SADB_UPDATE:
 2112: 		case SADB_ADD:
 2113: 		case SADB_DELETE:
 2114: 		case SADB_GET:
 2115: 		case SADB_ACQUIRE:
 2116: 		case SADB_EXPIRE:
 2117: #ifdef SADB_X_NAT_T_NEW_MAPPING
 2118: 		case SADB_X_NAT_T_NEW_MAPPING:
 2119: #endif
 2120: 			__ipsec_errcode = EIPSEC_INVAL_SATYPE;
 2121: 			return -1;
 2122: 		}
 2123: 		break;
 2124: 	case SADB_SATYPE_ESP:
 2125: 	case SADB_SATYPE_AH:
 2126: 	case SADB_X_SATYPE_IPCOMP:
 2127: #ifdef SADB_X_SATYPE_TCPSIGNATURE
 2128: 	case SADB_X_SATYPE_TCPSIGNATURE:
 2129: #endif
 2130: 		switch (msg->sadb_msg_type) {
 2131: 		case SADB_X_SPDADD:
 2132: 		case SADB_X_SPDDELETE:
 2133: 		case SADB_X_SPDGET:
 2134: 		case SADB_X_SPDDUMP:
 2135: 		case SADB_X_SPDFLUSH:
 2136: 			__ipsec_errcode = EIPSEC_INVAL_SATYPE;
 2137: 			return -1;
 2138: 		}
 2139: #ifdef SADB_X_NAT_T_NEW_MAPPING
 2140: 		if (msg->sadb_msg_type == SADB_X_NAT_T_NEW_MAPPING &&
 2141: 		    msg->sadb_msg_satype != SADB_SATYPE_ESP) {
 2142: 			__ipsec_errcode = EIPSEC_INVAL_SATYPE;
 2143: 			return -1;
 2144: 		}
 2145: #endif
 2146: 		break;
 2147: 	case SADB_SATYPE_RSVP:
 2148: 	case SADB_SATYPE_OSPFV2:
 2149: 	case SADB_SATYPE_RIPV2:
 2150: 	case SADB_SATYPE_MIP:
 2151: 		__ipsec_errcode = EIPSEC_NOT_SUPPORTED;
 2152: 		return -1;
 2153: 	case 1:	/* XXX: What does it do ? */
 2154: 		if (msg->sadb_msg_type == SADB_X_PROMISC)
 2155: 			break;
 2156: 		/*FALLTHROUGH*/
 2157: 	default:
 2158: #ifdef __linux__
 2159: 		/* Linux kernel seems to be buggy and return
 2160: 		 * uninitialized satype for spd flush message */
 2161: 		if (msg->sadb_msg_type == SADB_X_SPDFLUSH)
 2162: 			break;
 2163: #endif
 2164: 		__ipsec_errcode = EIPSEC_INVAL_SATYPE;
 2165: 		return -1;
 2166: 	}
 2167: 
 2168: 	/* check field of upper layer protocol and address family */
 2169: 	if (mhp[SADB_EXT_ADDRESS_SRC] != NULL
 2170: 	 && mhp[SADB_EXT_ADDRESS_DST] != NULL) {
 2171: 		struct sadb_address *src0, *dst0;
 2172: 
 2173: 		src0 = (void *)(mhp[SADB_EXT_ADDRESS_SRC]);
 2174: 		dst0 = (void *)(mhp[SADB_EXT_ADDRESS_DST]);
 2175: 
 2176: 		if (src0->sadb_address_proto != dst0->sadb_address_proto) {
 2177: 			__ipsec_errcode = EIPSEC_PROTO_MISMATCH;
 2178: 			return -1;
 2179: 		}
 2180: 
 2181: 		if (PFKEY_ADDR_SADDR(src0)->sa_family
 2182: 		 != PFKEY_ADDR_SADDR(dst0)->sa_family) {
 2183: 			__ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
 2184: 			return -1;
 2185: 		}
 2186: 
 2187: 		switch (PFKEY_ADDR_SADDR(src0)->sa_family) {
 2188: 		case AF_INET:
 2189: 		case AF_INET6:
 2190: 			break;
 2191: 		default:
 2192: 			__ipsec_errcode = EIPSEC_INVAL_FAMILY;
 2193: 			return -1;
 2194: 		}
 2195: 
 2196: 		/*
 2197: 		 * prefixlen == 0 is valid because there must be the case
 2198: 		 * all addresses are matched.
 2199: 		 */
 2200: 	}
 2201: 
 2202: 	__ipsec_errcode = EIPSEC_NO_ERROR;
 2203: 	return 0;
 2204: }
 2205: 
 2206: /*
 2207:  * set data into sadb_msg.
 2208:  * `buf' must has been allocated sufficiently.
 2209:  */
 2210: static caddr_t
 2211: pfkey_setsadbmsg(caddr_t buf, caddr_t lim, u_int type, u_int tlen,
 2212:     u_int satype, u_int32_t seq, pid_t pid)
 2213: {
 2214: 	struct sadb_msg *p;
 2215: 	u_int len;
 2216: 
 2217: 	p = (void *)buf;
 2218: 	len = sizeof(struct sadb_msg);
 2219: 
 2220: 	if (buf + len > lim)
 2221: 		return NULL;
 2222: 
 2223: 	memset(p, 0, len);
 2224: 	p->sadb_msg_version = PF_KEY_V2;
 2225: 	p->sadb_msg_type = type;
 2226: 	p->sadb_msg_errno = 0;
 2227: 	p->sadb_msg_satype = satype;
 2228: 	p->sadb_msg_len = PFKEY_UNIT64(tlen);
 2229: 	p->sadb_msg_reserved = 0;
 2230: 	p->sadb_msg_seq = seq;
 2231: 	p->sadb_msg_pid = (u_int32_t)pid;
 2232: 
 2233: 	return(buf + len);
 2234: }
 2235: 
 2236: /*
 2237:  * copy secasvar data into sadb_address.
 2238:  * `buf' must has been allocated sufficiently.
 2239:  */
 2240: static caddr_t
 2241: pfkey_setsadbsa(caddr_t buf, caddr_t lim, u_int32_t spi, u_int wsize,
 2242:     u_int auth, u_int enc, u_int32_t flags)
 2243: {
 2244: 	struct sadb_sa *p;
 2245: 	u_int len;
 2246: 
 2247: 	p = (void *)buf;
 2248: 	len = sizeof(struct sadb_sa);
 2249: 
 2250: 	if (buf + len > lim)
 2251: 		return NULL;
 2252: 
 2253: 	memset(p, 0, len);
 2254: 	p->sadb_sa_len = PFKEY_UNIT64(len);
 2255: 	p->sadb_sa_exttype = SADB_EXT_SA;
 2256: 	p->sadb_sa_spi = spi;
 2257: 	p->sadb_sa_replay = wsize;
 2258: 	p->sadb_sa_state = SADB_SASTATE_LARVAL;
 2259: 	p->sadb_sa_auth = auth;
 2260: 	p->sadb_sa_encrypt = enc;
 2261: 	p->sadb_sa_flags = flags;
 2262: 
 2263: 	return(buf + len);
 2264: }
 2265: 
 2266: /*
 2267:  * set data into sadb_address.
 2268:  * `buf' must has been allocated sufficiently.
 2269:  * prefixlen is in bits.
 2270:  */
 2271: static caddr_t
 2272: pfkey_setsadbaddr(caddr_t buf, caddr_t lim, u_int exttype,
 2273:     struct sockaddr *saddr, u_int prefixlen, u_int ul_proto)
 2274: {
 2275: 	struct sadb_address *p;
 2276: 	u_int len;
 2277: 
 2278: 	p = (void *)buf;
 2279: 	len = sizeof(struct sadb_address) + PFKEY_ALIGN8(sysdep_sa_len(saddr));
 2280: 
 2281: 	if (buf + len > lim)
 2282: 		return NULL;
 2283: 
 2284: 	memset(p, 0, len);
 2285: 	p->sadb_address_len = PFKEY_UNIT64(len);
 2286: 	p->sadb_address_exttype = exttype & 0xffff;
 2287: 	p->sadb_address_proto = ul_proto & 0xff;
 2288: 	p->sadb_address_prefixlen = prefixlen;
 2289: 	p->sadb_address_reserved = 0;
 2290: 
 2291: 	memcpy(p + 1, saddr, (size_t)sysdep_sa_len(saddr));
 2292: 
 2293: 	return(buf + len);
 2294: }
 2295: 
 2296: #ifdef SADB_X_EXT_KMADDRESS
 2297: /*
 2298:  * set data into sadb_x_kmaddress.
 2299:  * `buf' must has been allocated sufficiently.
 2300:  */
 2301: static caddr_t
 2302: pfkey_setsadbkmaddr(caddr_t buf, caddr_t lim, struct sockaddr *local,
 2303:     struct sockaddr *remote)
 2304: {
 2305: 	struct sadb_x_kmaddress *p;
 2306: 	struct sockaddr *sa;
 2307: 	u_int salen = sysdep_sa_len(local);
 2308: 	u_int len;
 2309: 
 2310: 	/* sanity check */
 2311: 	if (local->sa_family != remote->sa_family)
 2312: 		return NULL;
 2313: 
 2314: 	p = (void *)buf;
 2315: 	len = sizeof(struct sadb_x_kmaddress) + PFKEY_ALIGN8(2*salen);
 2316: 
 2317: 	if (buf + len > lim)
 2318: 		return NULL;
 2319: 
 2320: 	memset(p, 0, len);
 2321: 	p->sadb_x_kmaddress_len = PFKEY_UNIT64(len);
 2322: 	p->sadb_x_kmaddress_exttype = SADB_X_EXT_KMADDRESS;
 2323: 	p->sadb_x_kmaddress_reserved = 0;
 2324: 	sa = (struct sockaddr *)(p + 1);
 2325: 	memcpy(sa, local, salen);
 2326: 	sa = (struct sockaddr *)((char *)sa + salen);
 2327: 	memcpy(sa, remote, salen);
 2328: 
 2329: 	return(buf + len);
 2330: }
 2331: #endif
 2332: 
 2333: /*
 2334:  * set sadb_key structure after clearing buffer with zero.
 2335:  * OUT: the pointer of buf + len.
 2336:  */
 2337: static caddr_t
 2338: pfkey_setsadbkey(caddr_t buf, caddr_t lim, u_int type, caddr_t key,
 2339:     u_int keylen)
 2340: {
 2341: 	struct sadb_key *p;
 2342: 	u_int len;
 2343: 
 2344: 	p = (void *)buf;
 2345: 	len = sizeof(struct sadb_key) + PFKEY_ALIGN8(keylen);
 2346: 
 2347: 	if (buf + len > lim)
 2348: 		return NULL;
 2349: 
 2350: 	memset(p, 0, len);
 2351: 	p->sadb_key_len = PFKEY_UNIT64(len);
 2352: 	p->sadb_key_exttype = type;
 2353: 	p->sadb_key_bits = keylen << 3;
 2354: 	p->sadb_key_reserved = 0;
 2355: 
 2356: 	memcpy(p + 1, key, keylen);
 2357: 
 2358: 	return buf + len;
 2359: }
 2360: 
 2361: /*
 2362:  * set sadb_lifetime structure after clearing buffer with zero.
 2363:  * OUT: the pointer of buf + len.
 2364:  */
 2365: static caddr_t
 2366: pfkey_setsadblifetime(caddr_t buf, caddr_t lim, u_int type, u_int32_t l_alloc,
 2367:     u_int32_t l_bytes, u_int32_t l_addtime, u_int32_t l_usetime)
 2368: {
 2369: 	struct sadb_lifetime *p;
 2370: 	u_int len;
 2371: 
 2372: 	p = (void *)buf;
 2373: 	len = sizeof(struct sadb_lifetime);
 2374: 
 2375: 	if (buf + len > lim)
 2376: 		return NULL;
 2377: 
 2378: 	memset(p, 0, len);
 2379: 	p->sadb_lifetime_len = PFKEY_UNIT64(len);
 2380: 	p->sadb_lifetime_exttype = type;
 2381: 
 2382: 	switch (type) {
 2383: 	case SADB_EXT_LIFETIME_SOFT:
 2384: 		p->sadb_lifetime_allocations
 2385: 			= (l_alloc * soft_lifetime_allocations_rate) /100;
 2386: 		p->sadb_lifetime_bytes
 2387: 			= (l_bytes * soft_lifetime_bytes_rate) /100;
 2388: 		p->sadb_lifetime_addtime
 2389: 			= (l_addtime * soft_lifetime_addtime_rate) /100;
 2390: 		p->sadb_lifetime_usetime
 2391: 			= (l_usetime * soft_lifetime_usetime_rate) /100;
 2392: 		break;
 2393: 	case SADB_EXT_LIFETIME_HARD:
 2394: 		p->sadb_lifetime_allocations = l_alloc;
 2395: 		p->sadb_lifetime_bytes = l_bytes;
 2396: 		p->sadb_lifetime_addtime = l_addtime;
 2397: 		p->sadb_lifetime_usetime = l_usetime;
 2398: 		break;
 2399: 	}
 2400: 
 2401: 	return buf + len;
 2402: }
 2403: 
 2404: /*
 2405:  * copy secasvar data into sadb_address.
 2406:  * `buf' must has been allocated sufficiently.
 2407:  */
 2408: static caddr_t
 2409: pfkey_setsadbxsa2(caddr_t buf, caddr_t lim, u_int32_t mode0, u_int32_t reqid)
 2410: {
 2411: 	struct sadb_x_sa2 *p;
 2412: 	u_int8_t mode = mode0 & 0xff;
 2413: 	u_int len;
 2414: 
 2415: 	p = (void *)buf;
 2416: 	len = sizeof(struct sadb_x_sa2);
 2417: 
 2418: 	if (buf + len > lim)
 2419: 		return NULL;
 2420: 
 2421: 	memset(p, 0, len);
 2422: 	p->sadb_x_sa2_len = PFKEY_UNIT64(len);
 2423: 	p->sadb_x_sa2_exttype = SADB_X_EXT_SA2;
 2424: 	p->sadb_x_sa2_mode = mode;
 2425: 	p->sadb_x_sa2_reqid = reqid;
 2426: 
 2427: 	return(buf + len);
 2428: }
 2429: 
 2430: #ifdef SADB_X_EXT_NAT_T_TYPE
 2431: static caddr_t
 2432: pfkey_set_natt_type(caddr_t buf, caddr_t lim, u_int type, u_int8_t l_natt_type)
 2433: {
 2434: 	struct sadb_x_nat_t_type *p;
 2435: 	u_int len;
 2436: 
 2437: 	p = (void *)buf;
 2438: 	len = sizeof(struct sadb_x_nat_t_type);
 2439: 
 2440: 	if (buf + len > lim)
 2441: 		return NULL;
 2442: 
 2443: 	memset(p, 0, len);
 2444: 	p->sadb_x_nat_t_type_len = PFKEY_UNIT64(len);
 2445: 	p->sadb_x_nat_t_type_exttype = type;
 2446: 	p->sadb_x_nat_t_type_type = l_natt_type;
 2447: 
 2448: 	return(buf + len);
 2449: }
 2450: 
 2451: static caddr_t
 2452: pfkey_set_natt_port(caddr_t buf, caddr_t lim, u_int type, u_int16_t l_natt_port)
 2453: {
 2454: 	struct sadb_x_nat_t_port *p;
 2455: 	u_int len;
 2456: 
 2457: 	p = (void *)buf;
 2458: 	len = sizeof(struct sadb_x_nat_t_port);
 2459: 
 2460: 	if (buf + len > lim)
 2461: 		return NULL;
 2462: 
 2463: 	memset(p, 0, len);
 2464: 	p->sadb_x_nat_t_port_len = PFKEY_UNIT64(len);
 2465: 	p->sadb_x_nat_t_port_exttype = type;
 2466: 	p->sadb_x_nat_t_port_port = htons(l_natt_port);
 2467: 
 2468: 	return(buf + len);
 2469: }
 2470: #endif
 2471: 
 2472: #ifdef SADB_X_EXT_NAT_T_FRAG
 2473: static caddr_t
 2474: pfkey_set_natt_frag(caddr_t buf, caddr_t lim, u_int type, 
 2475:     u_int16_t l_natt_frag)
 2476: {
 2477: 	struct sadb_x_nat_t_frag *p;
 2478: 	u_int len;
 2479: 
 2480: 	p = (void *)buf;
 2481: 	len = sizeof(struct sadb_x_nat_t_frag);
 2482: 
 2483: 	if (buf + len > lim)
 2484: 		return NULL;
 2485: 
 2486: 	memset(p, 0, len);
 2487: 	p->sadb_x_nat_t_frag_len = PFKEY_UNIT64(len);
 2488: 	p->sadb_x_nat_t_frag_exttype = type;
 2489: 	p->sadb_x_nat_t_frag_fraglen = l_natt_frag;
 2490: 
 2491: 	return(buf + len);
 2492: }
 2493: #endif
 2494: 
 2495: #ifdef SADB_X_EXT_SEC_CTX
 2496: static caddr_t
 2497: pfkey_setsecctx(caddr_t buf, caddr_t lim, u_int type, u_int8_t ctx_doi,
 2498:     u_int8_t ctx_alg, caddr_t sec_ctx, u_int16_t sec_ctxlen)
 2499: {
 2500: 	struct sadb_x_sec_ctx *p;
 2501: 	u_int len;
 2502: 
 2503: 	p = (struct sadb_x_sec_ctx *)buf;
 2504: 	len = sizeof(struct sadb_x_sec_ctx) + PFKEY_ALIGN8(sec_ctxlen);
 2505: 
 2506: 	if (buf + len > lim)
 2507: 		return NULL;
 2508: 
 2509: 	memset(p, 0, len);
 2510: 	p->sadb_x_sec_len = PFKEY_UNIT64(len);
 2511: 	p->sadb_x_sec_exttype = type;
 2512: 	p->sadb_x_ctx_len = sec_ctxlen;
 2513: 	p->sadb_x_ctx_doi = ctx_doi;
 2514: 	p->sadb_x_ctx_alg = ctx_alg;
 2515: 
 2516: 	memcpy(p + 1, sec_ctx, sec_ctxlen);
 2517: 
 2518: 	return buf + len;
 2519: }
 2520: #endif
 2521: 
 2522: /* 
 2523:  * Deprecated, available for backward compatibility with third party 
 2524:  * libipsec users. Please use pfkey_send_update2 and pfkey_send_add2 instead 
 2525:  */
 2526: int
 2527: pfkey_send_update(int so, u_int satype, u_int mode, struct sockaddr *src,
 2528:     struct sockaddr *dst, u_int32_t spi, u_int32_t reqid, u_int wsize,
 2529:     caddr_t keymat, u_int e_type, u_int e_keylen, u_int a_type,
 2530:     u_int a_keylen, u_int flags, u_int32_t l_alloc, u_int64_t l_bytes,
 2531:     u_int64_t l_addtime, u_int64_t l_usetime, u_int32_t seq)
 2532: {
 2533: 	struct pfkey_send_sa_args psaa;
 2534: 
 2535: 	memset(&psaa, 0, sizeof(psaa));
 2536: 	psaa.so = so;
 2537: 	psaa.type = SADB_UPDATE;
 2538: 	psaa.satype = satype;
 2539: 	psaa.mode = mode;
 2540: 	psaa.wsize = wsize;
 2541: 	psaa.src = src;
 2542: 	psaa.dst = dst;
 2543: 	psaa.spi = spi;
 2544: 	psaa.reqid = reqid;
 2545: 	psaa.keymat = keymat;
 2546: 	psaa.e_type = e_type;
 2547: 	psaa.e_keylen = e_keylen;
 2548: 	psaa.a_type = a_type;
 2549: 	psaa.a_keylen = a_keylen;
 2550: 	psaa.flags = flags;
 2551: 	psaa.l_alloc = l_alloc;
 2552: 	psaa.l_bytes = l_bytes;
 2553: 	psaa.l_addtime = l_addtime;
 2554: 	psaa.l_usetime = l_usetime;
 2555: 	psaa.seq = seq;
 2556: 
 2557: 	return pfkey_send_update2(&psaa);
 2558: }
 2559: 
 2560: int
 2561: pfkey_send_update_nat(int so, u_int satype, u_int mode, struct sockaddr *src,
 2562:     struct sockaddr *dst, u_int32_t spi, u_int32_t reqid, u_int wsize,
 2563:     caddr_t keymat, u_int e_type, u_int e_keylen, u_int a_type,
 2564:     u_int a_keylen, u_int flags, u_int32_t l_alloc, u_int64_t l_bytes,
 2565:     u_int64_t l_addtime, u_int64_t l_usetime, u_int32_t seq,
 2566:     u_int8_t l_natt_type, u_int16_t l_natt_sport, u_int16_t l_natt_dport,
 2567:     struct sockaddr *l_natt_oa, u_int16_t l_natt_frag)
 2568: {
 2569: 	struct pfkey_send_sa_args psaa;
 2570: 
 2571: 	memset(&psaa, 0, sizeof(psaa));
 2572: 	psaa.so = so;
 2573: 	psaa.type = SADB_UPDATE;
 2574: 	psaa.satype = satype;
 2575: 	psaa.mode = mode;
 2576: 	psaa.wsize = wsize;
 2577: 	psaa.src = src;
 2578: 	psaa.dst = dst;
 2579: 	psaa.spi = spi;
 2580: 	psaa.reqid = reqid;
 2581: 	psaa.keymat = keymat;
 2582: 	psaa.e_type = e_type;
 2583: 	psaa.e_keylen = e_keylen;
 2584: 	psaa.a_type = a_type;
 2585: 	psaa.a_keylen = a_keylen;
 2586: 	psaa.flags = flags;
 2587: 	psaa.l_alloc = l_alloc;
 2588: 	psaa.l_bytes = l_bytes;
 2589: 	psaa.l_addtime = l_addtime;
 2590: 	psaa.l_usetime = l_usetime;
 2591: 	psaa.seq = seq;
 2592: 	psaa.l_natt_type = l_natt_type;
 2593: 	psaa.l_natt_sport = l_natt_sport;
 2594: 	psaa.l_natt_dport = l_natt_dport;
 2595: 	psaa.l_natt_oa = l_natt_oa;
 2596: 	psaa.l_natt_frag = l_natt_frag;
 2597: 
 2598: 	return pfkey_send_update2(&psaa);
 2599: }
 2600: 
 2601: int
 2602: pfkey_send_add(int so, u_int satype, u_int mode, struct sockaddr *src,
 2603:     struct sockaddr *dst, u_int32_t spi, u_int32_t reqid, u_int wsize,
 2604:     caddr_t keymat, u_int e_type, u_int e_keylen, u_int a_type,
 2605:     u_int a_keylen, u_int flags, u_int32_t l_alloc, u_int64_t l_bytes,
 2606:     u_int64_t l_addtime, u_int64_t l_usetime, u_int32_t seq)
 2607: {
 2608: 	struct pfkey_send_sa_args psaa;
 2609: 
 2610: 	memset(&psaa, 0, sizeof(psaa));
 2611: 	psaa.so = so;
 2612: 	psaa.type = SADB_ADD;
 2613: 	psaa.satype = satype;
 2614: 	psaa.mode = mode;
 2615: 	psaa.wsize = wsize;
 2616: 	psaa.src = src;
 2617: 	psaa.dst = dst;
 2618: 	psaa.spi = spi;
 2619: 	psaa.reqid = reqid;
 2620: 	psaa.keymat = keymat;
 2621: 	psaa.e_type = e_type;
 2622: 	psaa.e_keylen = e_keylen;
 2623: 	psaa.a_type = a_type;
 2624: 	psaa.a_keylen = a_keylen;
 2625: 	psaa.flags = flags;
 2626: 	psaa.l_alloc = l_alloc;
 2627: 	psaa.l_bytes = l_bytes;
 2628: 	psaa.l_addtime = l_addtime;
 2629: 	psaa.l_usetime = l_usetime;
 2630: 	psaa.seq = seq;
 2631: 
 2632: 	return pfkey_send_add2(&psaa);
 2633: }
 2634: 
 2635: int
 2636: pfkey_send_add_nat(int so, u_int satype, u_int mode, struct sockaddr *src,
 2637:     struct sockaddr *dst, u_int32_t spi, u_int32_t reqid, u_int wsize,
 2638:     caddr_t keymat, u_int e_type, u_int e_keylen, u_int a_type,
 2639:     u_int a_keylen, u_int flags, u_int32_t l_alloc, u_int64_t l_bytes,
 2640:     u_int64_t l_addtime, u_int64_t l_usetime, u_int32_t seq,
 2641:     u_int8_t l_natt_type, u_int16_t l_natt_sport, u_int16_t l_natt_dport,
 2642:     struct sockaddr *l_natt_oa, u_int16_t l_natt_frag)
 2643: {
 2644: 	struct pfkey_send_sa_args psaa;
 2645: 
 2646: 	memset(&psaa, 0, sizeof(psaa));
 2647: 	psaa.so = so;
 2648: 	psaa.type = SADB_ADD;
 2649: 	psaa.satype = satype;
 2650: 	psaa.mode = mode;
 2651: 	psaa.wsize = wsize;
 2652: 	psaa.src = src;
 2653: 	psaa.dst = dst;
 2654: 	psaa.spi = spi;
 2655: 	psaa.reqid = reqid;
 2656: 	psaa.keymat = keymat;
 2657: 	psaa.e_type = e_type;
 2658: 	psaa.e_keylen = e_keylen;
 2659: 	psaa.a_type = a_type;
 2660: 	psaa.a_keylen = a_keylen;
 2661: 	psaa.flags = flags;
 2662: 	psaa.l_alloc = l_alloc;
 2663: 	psaa.l_bytes = l_bytes;
 2664: 	psaa.l_addtime = l_addtime;
 2665: 	psaa.l_usetime = l_usetime;
 2666: 	psaa.seq = seq;
 2667: 	psaa.l_natt_type = l_natt_type;
 2668: 	psaa.l_natt_sport = l_natt_sport;
 2669: 	psaa.l_natt_dport = l_natt_dport;
 2670: 	psaa.l_natt_oa = l_natt_oa;
 2671: 	psaa.l_natt_frag = l_natt_frag;
 2672: 
 2673: 	return pfkey_send_add2(&psaa);
 2674: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>