Home | History | Annotate | Download | only in racoon
      1 /*	$NetBSD: ipsec_doi.c,v 1.46 2010/12/14 17:57:31 tteras Exp $	*/
      2 
      3 /* Id: ipsec_doi.c,v 1.55 2006/08/17 09:20:41 vanhu Exp */
      4 
      5 /*
      6  * Copyright (C) 1995, 1996, 1997, and 1998 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 #include "config.h"
     35 
     36 #include <sys/types.h>
     37 #include <sys/param.h>
     38 #include <sys/socket.h>
     39 
     40 #include <netinet/in.h>
     41 
     42 #include PATH_IPSEC_H
     43 
     44 #include <stdlib.h>
     45 #include <stdio.h>
     46 #include <string.h>
     47 #include <errno.h>
     48 #include <netdb.h>
     49 #if TIME_WITH_SYS_TIME
     50 # include <sys/time.h>
     51 # include <time.h>
     52 #else
     53 # if HAVE_SYS_TIME_H
     54 #  include <sys/time.h>
     55 # else
     56 #  include <time.h>
     57 # endif
     58 #endif
     59 
     60 #include "var.h"
     61 #include "vmbuf.h"
     62 #include "misc.h"
     63 #include "plog.h"
     64 #include "debug.h"
     65 
     66 #include "cfparse_proto.h"
     67 #include "isakmp_var.h"
     68 #include "isakmp.h"
     69 #include "ipsec_doi.h"
     70 #include "oakley.h"
     71 #include "remoteconf.h"
     72 #include "localconf.h"
     73 #include "sockmisc.h"
     74 #include "handler.h"
     75 #include "policy.h"
     76 #include "algorithm.h"
     77 #include "sainfo.h"
     78 #include "proposal.h"
     79 #include "crypto_openssl.h"
     80 #include "strnames.h"
     81 #include "gcmalloc.h"
     82 
     83 #ifdef ENABLE_NATT
     84 #include "nattraversal.h"
     85 #endif
     86 
     87 #ifdef HAVE_GSSAPI
     88 #include <iconv.h>
     89 #include "gssapi.h"
     90 #ifdef HAVE_ICONV_2ND_CONST
     91 #define __iconv_const const
     92 #else
     93 #define __iconv_const
     94 #endif
     95 #endif
     96 
     97 static vchar_t *get_ph1approval __P((struct ph1handle *, u_int32_t, u_int32_t,
     98 				     struct prop_pair **));
     99 static int get_ph1approvalx __P((struct remoteconf *, void *));
    100 
    101 static int t2isakmpsa __P((struct isakmp_pl_t *, struct isakmpsa *, u_int32_t));
    102 static int cmp_aproppair_i __P((struct prop_pair *, struct prop_pair *));
    103 static struct prop_pair *get_ph2approval __P((struct ph2handle *,
    104 	struct prop_pair **));
    105 static struct prop_pair *get_ph2approvalx __P((struct ph2handle *,
    106 	struct prop_pair *));
    107 static void free_proppair0 __P((struct prop_pair *));
    108 static struct prop_pair ** get_proppair_and_doi_sit __P((vchar_t *, int,
    109 							 u_int32_t *, u_int32_t *));
    110 
    111 static int get_transform
    112 	__P((struct isakmp_pl_p *, struct prop_pair **, int *));
    113 static u_int32_t ipsecdoi_set_ld __P((vchar_t *));
    114 
    115 static int check_doi __P((u_int32_t));
    116 static int check_situation __P((u_int32_t));
    117 
    118 static int check_prot_main __P((int));
    119 static int check_prot_quick __P((int));
    120 static int (*check_protocol[]) __P((int)) = {
    121 	check_prot_main,	/* IPSECDOI_TYPE_PH1 */
    122 	check_prot_quick,	/* IPSECDOI_TYPE_PH2 */
    123 };
    124 
    125 static int check_spi_size __P((int, int));
    126 
    127 static int check_trns_isakmp __P((int));
    128 static int check_trns_ah __P((int));
    129 static int check_trns_esp __P((int));
    130 static int check_trns_ipcomp __P((int));
    131 static int (*check_transform[]) __P((int)) = {
    132 	0,
    133 	check_trns_isakmp,	/* IPSECDOI_PROTO_ISAKMP */
    134 	check_trns_ah,		/* IPSECDOI_PROTO_IPSEC_AH */
    135 	check_trns_esp,		/* IPSECDOI_PROTO_IPSEC_ESP */
    136 	check_trns_ipcomp,	/* IPSECDOI_PROTO_IPCOMP */
    137 };
    138 
    139 static int check_attr_isakmp __P((struct isakmp_pl_t *));
    140 static int check_attr_ah __P((struct isakmp_pl_t *));
    141 static int check_attr_esp __P((struct isakmp_pl_t *));
    142 static int check_attr_ipsec __P((int, struct isakmp_pl_t *));
    143 static int check_attr_ipcomp __P((struct isakmp_pl_t *));
    144 static int (*check_attributes[]) __P((struct isakmp_pl_t *)) = {
    145 	0,
    146 	check_attr_isakmp,	/* IPSECDOI_PROTO_ISAKMP */
    147 	check_attr_ah,		/* IPSECDOI_PROTO_IPSEC_AH */
    148 	check_attr_esp,		/* IPSECDOI_PROTO_IPSEC_ESP */
    149 	check_attr_ipcomp,	/* IPSECDOI_PROTO_IPCOMP */
    150 };
    151 
    152 static int setph1prop __P((struct isakmpsa *, caddr_t));
    153 static int setph1trns __P((struct isakmpsa *, caddr_t));
    154 static int setph1attr __P((struct isakmpsa *, caddr_t));
    155 static vchar_t *setph2proposal0 __P((const struct ph2handle *,
    156 	const struct saprop *, const struct saproto *));
    157 
    158 struct ph1approvalx_ctx {
    159 	struct prop_pair *p;
    160 	struct isakmpsa *sa;
    161 };
    162 
    163 /*%%%*/
    164 /*
    165  * check phase 1 SA payload.
    166  * make new SA payload to be replyed not including general header.
    167  * the pointer to one of isakmpsa in proposal is set into iph1->approval.
    168  * OUT:
    169  *	positive: the pointer to new buffer of SA payload.
    170  *		  network byte order.
    171  *	NULL	: error occurd.
    172  */
    173 int
    174 ipsecdoi_checkph1proposal(sa, iph1)
    175 	vchar_t *sa;
    176 	struct ph1handle *iph1;
    177 {
    178 	vchar_t *newsa;		/* new SA payload approved. */
    179 	struct prop_pair **pair;
    180 	u_int32_t doitype, sittype;
    181 
    182 	/* get proposal pair */
    183 	pair = get_proppair_and_doi_sit(sa, IPSECDOI_TYPE_PH1,
    184 					&doitype, &sittype);
    185 	if (pair == NULL)
    186 		return -1;
    187 
    188 	/* check and get one SA for use */
    189 	newsa = get_ph1approval(iph1, doitype, sittype, pair);
    190 	free_proppair(pair);
    191 
    192 	if (newsa == NULL)
    193 		return -1;
    194 
    195 	iph1->sa_ret = newsa;
    196 	return 0;
    197 }
    198 
    199 static void
    200 print_ph1proposal(pair, s)
    201 	struct prop_pair *pair;
    202 	struct isakmpsa *s;
    203 {
    204 	struct isakmp_pl_p *prop = pair->prop;
    205 	struct isakmp_pl_t *trns = pair->trns;
    206 
    207 	plog(LLV_DEBUG, LOCATION, NULL,
    208 	     "prop#=%d, prot-id=%s, spi-size=%d, #trns=%d\n",
    209 	     prop->p_no, s_ipsecdoi_proto(prop->proto_id),
    210 	     prop->spi_size, prop->num_t);
    211 	plog(LLV_DEBUG, LOCATION, NULL,
    212 	     "trns#=%d, trns-id=%s\n",
    213 	     trns->t_no, s_ipsecdoi_trns(prop->proto_id, trns->t_id));
    214 	plog(LLV_DEBUG, LOCATION, NULL,
    215 	     "  lifetime = %ld\n", (long) s->lifetime);
    216 	plog(LLV_DEBUG, LOCATION, NULL,
    217 	     "  lifebyte = %zu\n", s->lifebyte);
    218 	plog(LLV_DEBUG, LOCATION, NULL,
    219 	     "  enctype = %s\n",
    220 	     s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG, s->enctype));
    221 	plog(LLV_DEBUG, LOCATION, NULL,
    222 	     "  encklen = %d\n", s->encklen);
    223 	plog(LLV_DEBUG, LOCATION, NULL,
    224 	     "  hashtype = %s\n",
    225 	     s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG, s->hashtype));
    226 	plog(LLV_DEBUG, LOCATION, NULL,
    227 	     "  authmethod = %s\n",
    228 	     s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD, s->authmethod));
    229 	plog(LLV_DEBUG, LOCATION, NULL,
    230 	     "  dh_group = %s\n",
    231 	     s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC, s->dh_group));
    232 }
    233 
    234 
    235 /*
    236  * acceptable check for remote configuration.
    237  * return a new SA payload to be reply to peer.
    238  */
    239 
    240 static vchar_t *
    241 get_ph1approval(iph1, doitype, sittype, pair)
    242 	struct ph1handle *iph1;
    243 	u_int32_t doitype, sittype;
    244 	struct prop_pair **pair;
    245 {
    246 	vchar_t *newsa;
    247 	struct ph1approvalx_ctx ctx;
    248 	struct prop_pair *s, *p;
    249 	struct rmconfselector rmsel;
    250 	struct isakmpsa *sa;
    251 	int i;
    252 
    253 	memset(&rmsel, 0, sizeof(rmsel));
    254 	rmsel.remote = iph1->remote;
    255 
    256 	if (iph1->approval) {
    257 		delisakmpsa(iph1->approval);
    258 		iph1->approval = NULL;
    259 	}
    260 
    261 	for (i = 0; i < MAXPROPPAIRLEN; i++) {
    262 		if (pair[i] == NULL)
    263 			continue;
    264 		for (s = pair[i]; s; s = s->next) {
    265 			/* compare proposal and select one */
    266 			for (p = s; p; p = p->tnext) {
    267 				struct isakmp_pl_p *prop = p->prop;
    268 
    269 				sa = newisakmpsa();
    270 				ctx.p = p;
    271 				ctx.sa = sa;
    272 				if (t2isakmpsa(p->trns, sa,
    273 					       iph1->vendorid_mask) < 0)
    274 					continue;
    275 				print_ph1proposal(p, sa);
    276 				if (iph1->rmconf != NULL) {
    277 					if (get_ph1approvalx(iph1->rmconf, &ctx))
    278 						goto found;
    279 				} else {
    280 					if (enumrmconf(&rmsel, get_ph1approvalx, &ctx))
    281 						goto found;
    282 				}
    283 				delisakmpsa(sa);
    284 			}
    285 		}
    286 	}
    287 
    288 	plog(LLV_ERROR, LOCATION, NULL, "no suitable proposal found.\n");
    289 
    290 	return NULL;
    291 
    292 found:
    293 	sa = ctx.sa;
    294 	plog(LLV_DEBUG, LOCATION, NULL, "an acceptable proposal found.\n");
    295 
    296 	/* check DH group settings */
    297 	if (sa->dhgrp) {
    298 		if (sa->dhgrp->prime && sa->dhgrp->gen1) {
    299 			/* it's ok */
    300 			goto saok;
    301 		}
    302 		plog(LLV_WARNING, LOCATION, NULL,
    303 			"invalid DH parameter found, use default.\n");
    304 		oakley_dhgrp_free(sa->dhgrp);
    305 		sa->dhgrp=NULL;
    306 	}
    307 
    308 	if (oakley_setdhgroup(sa->dh_group, &sa->dhgrp) == -1) {
    309 		sa->dhgrp = NULL;
    310 		delisakmpsa(sa);
    311 		return NULL;
    312 	}
    313 
    314 saok:
    315 #ifdef HAVE_GSSAPI
    316 	if (sa->gssid != NULL)
    317 		plog(LLV_DEBUG, LOCATION, NULL, "gss id in new sa '%.*s'\n",
    318 		    (int)sa->gssid->l, sa->gssid->v);
    319 	if (iph1->side == INITIATOR) {
    320 		if (iph1->rmconf->proposal->gssid != NULL)
    321 			iph1->gi_i = vdup(iph1->rmconf->proposal->gssid);
    322 		if (sa->gssid != NULL)
    323 			iph1->gi_r = vdup(sa->gssid);
    324 	} else {
    325 		if (sa->gssid != NULL) {
    326 			iph1->gi_r = vdup(sa->gssid);
    327 			iph1->gi_i = gssapi_get_id(iph1);
    328 		}
    329 	}
    330 	if (iph1->gi_i != NULL)
    331 		plog(LLV_DEBUG, LOCATION, NULL, "GIi is %.*s\n",
    332 		    (int)iph1->gi_i->l, iph1->gi_i->v);
    333 	if (iph1->gi_r != NULL)
    334 		plog(LLV_DEBUG, LOCATION, NULL, "GIr is %.*s\n",
    335 		    (int)iph1->gi_r->l, iph1->gi_r->v);
    336 #endif
    337 	plog(LLV_DEBUG, LOCATION, NULL, "agreed on %s auth.\n",
    338 	     s_oakley_attr_method(sa->authmethod));
    339 
    340 	newsa = get_sabyproppair(doitype, sittype, p);
    341 	if (newsa == NULL)
    342 		delisakmpsa(sa);
    343 	else
    344 		iph1->approval = sa;
    345 
    346 	return newsa;
    347 }
    348 
    349 /*
    350  * compare peer's single proposal and all of my proposal.
    351  * and select one if suiatable.
    352  */
    353 static int
    354 get_ph1approvalx(rmconf, ctx)
    355 	struct remoteconf *rmconf;
    356 	void *ctx;
    357 {
    358 	struct ph1approvalx_ctx *pctx = (struct ph1approvalx_ctx *) ctx;
    359 	struct isakmpsa *sa;
    360 
    361 	/* do the hard work */
    362 	sa = checkisakmpsa(rmconf->pcheck_level, pctx->sa, rmconf->proposal);
    363 	if (sa == NULL)
    364 		return 0;
    365 
    366 	/* duplicate and modify the found SA to match proposal */
    367 	sa = dupisakmpsa(sa);
    368 
    369 	switch (rmconf->pcheck_level) {
    370 	case PROP_CHECK_OBEY:
    371 		sa->lifetime = pctx->sa->lifetime;
    372 		sa->lifebyte = pctx->sa->lifebyte;
    373 		sa->encklen = pctx->sa->encklen;
    374 		break;
    375 	case PROP_CHECK_CLAIM:
    376 	case PROP_CHECK_STRICT:
    377 		if (pctx->sa->lifetime < sa->lifetime)
    378 			sa->lifetime = pctx->sa->lifetime;
    379 		if (pctx->sa->lifebyte < sa->lifebyte)
    380 			sa->lifebyte = pctx->sa->lifebyte;
    381 		if (pctx->sa->encklen > sa->encklen)
    382 			sa->encklen = pctx->sa->encklen;
    383 		break;
    384 	default:
    385 		break;
    386 	}
    387 
    388 	/* replace the proposal with our approval sa */
    389 	delisakmpsa(pctx->sa);
    390 	pctx->sa = sa;
    391 
    392 	return 1;
    393 }
    394 
    395 /*
    396  * get ISAKMP data attributes
    397  */
    398 static int
    399 t2isakmpsa(trns, sa, vendorid_mask)
    400 	struct isakmp_pl_t *trns;
    401 	struct isakmpsa *sa;
    402 	u_int32_t vendorid_mask;
    403 {
    404 	struct isakmp_data *d, *prev;
    405 	int flag, type;
    406 	int error = -1;
    407 	int life_t;
    408 	int keylen = 0;
    409 	vchar_t *val = NULL;
    410 	int len, tlen;
    411 	u_char *p;
    412 
    413 	tlen = ntohs(trns->h.len) - sizeof(*trns);
    414 	prev = (struct isakmp_data *)NULL;
    415 	d = (struct isakmp_data *)(trns + 1);
    416 
    417 	/* default */
    418 	life_t = OAKLEY_ATTR_SA_LD_TYPE_DEFAULT;
    419 	sa->lifetime = OAKLEY_ATTR_SA_LD_SEC_DEFAULT;
    420 	sa->lifebyte = 0;
    421 	sa->dhgrp = racoon_calloc(1, sizeof(struct dhgroup));
    422 	if (!sa->dhgrp)
    423 		goto err;
    424 
    425 	while (tlen > 0) {
    426 
    427 		type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
    428 		flag = ntohs(d->type) & ISAKMP_GEN_MASK;
    429 
    430 		plog(LLV_DEBUG, LOCATION, NULL,
    431 			"type=%s, flag=0x%04x, lorv=%s\n",
    432 			s_oakley_attr(type), flag,
    433 			s_oakley_attr_v(type, ntohs(d->lorv)));
    434 
    435 		/* get variable-sized item */
    436 		switch (type) {
    437 		case OAKLEY_ATTR_GRP_PI:
    438 		case OAKLEY_ATTR_GRP_GEN_ONE:
    439 		case OAKLEY_ATTR_GRP_GEN_TWO:
    440 		case OAKLEY_ATTR_GRP_CURVE_A:
    441 		case OAKLEY_ATTR_GRP_CURVE_B:
    442 		case OAKLEY_ATTR_SA_LD:
    443 		case OAKLEY_ATTR_GRP_ORDER:
    444 			if (flag) {	/*TV*/
    445 				len = 2;
    446 				p = (u_char *)&d->lorv;
    447 			} else {	/*TLV*/
    448 				len = ntohs(d->lorv);
    449 				p = (u_char *)(d + 1);
    450 			}
    451 			val = vmalloc(len);
    452 			if (!val)
    453 				return -1;
    454 			memcpy(val->v, p, len);
    455 			break;
    456 
    457 		default:
    458 			break;
    459 		}
    460 
    461 		switch (type) {
    462 		case OAKLEY_ATTR_ENC_ALG:
    463 			sa->enctype = (u_int16_t)ntohs(d->lorv);
    464 			break;
    465 
    466 		case OAKLEY_ATTR_HASH_ALG:
    467 			sa->hashtype = (u_int16_t)ntohs(d->lorv);
    468 			break;
    469 
    470 		case OAKLEY_ATTR_AUTH_METHOD:
    471 			sa->authmethod = ntohs(d->lorv);
    472 #ifdef HAVE_GSSAPI
    473 			if (sa->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB_REAL &&
    474 			    (vendorid_mask & VENDORID_GSSAPI_MASK))
    475 				sa->authmethod = OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB;
    476 #endif
    477 			break;
    478 
    479 		case OAKLEY_ATTR_GRP_DESC:
    480 			sa->dh_group = (u_int16_t)ntohs(d->lorv);
    481 			break;
    482 
    483 		case OAKLEY_ATTR_GRP_TYPE:
    484 		{
    485 			int type = (int)ntohs(d->lorv);
    486 			if (type == OAKLEY_ATTR_GRP_TYPE_MODP)
    487 				sa->dhgrp->type = type;
    488 			else
    489 				return -1;
    490 			break;
    491 		}
    492 		case OAKLEY_ATTR_GRP_PI:
    493 			sa->dhgrp->prime = val;
    494 			break;
    495 
    496 		case OAKLEY_ATTR_GRP_GEN_ONE:
    497 			vfree(val);
    498 			if (!flag)
    499 				sa->dhgrp->gen1 = ntohs(d->lorv);
    500 			else {
    501 				int len = ntohs(d->lorv);
    502 				sa->dhgrp->gen1 = 0;
    503 				if (len > 4)
    504 					return -1;
    505 				memcpy(&sa->dhgrp->gen1, d + 1, len);
    506 				sa->dhgrp->gen1 = ntohl(sa->dhgrp->gen1);
    507 			}
    508 			break;
    509 
    510 		case OAKLEY_ATTR_GRP_GEN_TWO:
    511 			vfree(val);
    512 			if (!flag)
    513 				sa->dhgrp->gen2 = ntohs(d->lorv);
    514 			else {
    515 				int len = ntohs(d->lorv);
    516 				sa->dhgrp->gen2 = 0;
    517 				if (len > 4)
    518 					return -1;
    519 				memcpy(&sa->dhgrp->gen2, d + 1, len);
    520 				sa->dhgrp->gen2 = ntohl(sa->dhgrp->gen2);
    521 			}
    522 			break;
    523 
    524 		case OAKLEY_ATTR_GRP_CURVE_A:
    525 			sa->dhgrp->curve_a = val;
    526 			break;
    527 
    528 		case OAKLEY_ATTR_GRP_CURVE_B:
    529 			sa->dhgrp->curve_b = val;
    530 			break;
    531 
    532 		case OAKLEY_ATTR_SA_LD_TYPE:
    533 		{
    534 			int type = (int)ntohs(d->lorv);
    535 			switch (type) {
    536 			case OAKLEY_ATTR_SA_LD_TYPE_SEC:
    537 			case OAKLEY_ATTR_SA_LD_TYPE_KB:
    538 				life_t = type;
    539 				break;
    540 			default:
    541 				life_t = OAKLEY_ATTR_SA_LD_TYPE_DEFAULT;
    542 				break;
    543 			}
    544 			break;
    545 		}
    546 		case OAKLEY_ATTR_SA_LD:
    547 			if (!prev
    548 			 || (ntohs(prev->type) & ~ISAKMP_GEN_MASK) !=
    549 					OAKLEY_ATTR_SA_LD_TYPE) {
    550 				plog(LLV_ERROR, LOCATION, NULL,
    551 				    "life duration must follow ltype\n");
    552 				break;
    553 			}
    554 
    555 			switch (life_t) {
    556 			case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
    557 				sa->lifetime = ipsecdoi_set_ld(val);
    558 				vfree(val);
    559 				if (sa->lifetime == 0) {
    560 					plog(LLV_ERROR, LOCATION, NULL,
    561 						"invalid life duration.\n");
    562 					goto err;
    563 				}
    564 				break;
    565 			case IPSECDOI_ATTR_SA_LD_TYPE_KB:
    566 				sa->lifebyte = ipsecdoi_set_ld(val);
    567 				vfree(val);
    568 				if (sa->lifebyte == 0) {
    569 					plog(LLV_ERROR, LOCATION, NULL,
    570 						"invalid life duration.\n");
    571 					goto err;
    572 				}
    573 				break;
    574 			default:
    575 				vfree(val);
    576 				plog(LLV_ERROR, LOCATION, NULL,
    577 					"invalid life type: %d\n", life_t);
    578 				goto err;
    579 			}
    580 			break;
    581 
    582 		case OAKLEY_ATTR_KEY_LEN:
    583 		{
    584 			int len = ntohs(d->lorv);
    585 			if (len % 8 != 0) {
    586 				plog(LLV_ERROR, LOCATION, NULL,
    587 					"keylen %d: not multiple of 8\n",
    588 					len);
    589 				goto err;
    590 			}
    591 			sa->encklen = (u_int16_t)len;
    592 			keylen++;
    593 			break;
    594 		}
    595 		case OAKLEY_ATTR_PRF:
    596 		case OAKLEY_ATTR_FIELD_SIZE:
    597 			/* unsupported */
    598 			break;
    599 
    600 		case OAKLEY_ATTR_GRP_ORDER:
    601 			sa->dhgrp->order = val;
    602 			break;
    603 #ifdef HAVE_GSSAPI
    604 		case OAKLEY_ATTR_GSS_ID:
    605 		{
    606 			int error = -1;
    607 			iconv_t cd = (iconv_t) -1;
    608 			size_t srcleft, dstleft, rv;
    609 			__iconv_const char *src;
    610 			char *dst;
    611 			int len = ntohs(d->lorv);
    612 
    613 			/*
    614 			 * Older verions of racoon just placed the
    615 			 * ISO-Latin-1 string on the wire directly.
    616 			 * Check to see if we are configured to be
    617 			 * compatible with this behavior.
    618 			 */
    619 			if (lcconf->gss_id_enc == LC_GSSENC_LATIN1) {
    620 				if ((sa->gssid = vmalloc(len)) == NULL) {
    621 					plog(LLV_ERROR, LOCATION, NULL,
    622 					    "failed to allocate memory\n");
    623 					goto out;
    624 				}
    625 				memcpy(sa->gssid->v, d + 1, len);
    626 				plog(LLV_DEBUG, LOCATION, NULL,
    627 				    "received old-style gss "
    628 				    "id '%.*s' (len %zu)\n",
    629 				    (int)sa->gssid->l, sa->gssid->v,
    630 				    sa->gssid->l);
    631 				error = 0;
    632 				goto out;
    633 			}
    634 
    635 			/*
    636 			 * For Windows 2000 compatibility, we expect
    637 			 * the GSS ID attribute on the wire to be
    638 			 * encoded in UTF-16LE.  Internally, we work
    639 			 * in ISO-Latin-1.  Therefore, we should need
    640 			 * 1/2 the specified length, which should always
    641 			 * be a multiple of 2 octets.
    642 			 */
    643 			cd = iconv_open("latin1", "utf-16le");
    644 			if (cd == (iconv_t) -1) {
    645 				plog(LLV_ERROR, LOCATION, NULL,
    646 				    "unable to initialize utf-16le -> latin1 "
    647 				    "conversion descriptor: %s\n",
    648 				    strerror(errno));
    649 				goto out;
    650 			}
    651 
    652 			if ((sa->gssid = vmalloc(len / 2)) == NULL) {
    653 				plog(LLV_ERROR, LOCATION, NULL,
    654 				    "failed to allocate memory\n");
    655 				goto out;
    656 			}
    657 
    658 			src = (__iconv_const char *)(d + 1);
    659 			srcleft = len;
    660 
    661 			dst = sa->gssid->v;
    662 			dstleft = len / 2;
    663 
    664 			rv = iconv(cd, (__iconv_const char **)&src, &srcleft,
    665 				   &dst, &dstleft);
    666 			if (rv != 0) {
    667 				if (rv == -1) {
    668 					plog(LLV_ERROR, LOCATION, NULL,
    669 					    "unable to convert GSS ID from "
    670 					    "utf-16le -> latin1: %s\n",
    671 					    strerror(errno));
    672 				} else {
    673 					plog(LLV_ERROR, LOCATION, NULL,
    674 					    "%zd character%s in GSS ID cannot "
    675 					    "be represented in latin1\n",
    676 					    rv, rv == 1 ? "" : "s");
    677 				}
    678 				goto out;
    679 			}
    680 
    681 			/* XXX dstleft should always be 0; assert it? */
    682 			sa->gssid->l = (len / 2) - dstleft;
    683 
    684 			plog(LLV_DEBUG, LOCATION, NULL,
    685 			    "received gss id '%.*s' (len %zu)\n",
    686 			    (int)sa->gssid->l, sa->gssid->v, sa->gssid->l);
    687 
    688 			error = 0;
    689 out:
    690 			if (cd != (iconv_t)-1)
    691 				(void)iconv_close(cd);
    692 
    693 			if ((error != 0) && (sa->gssid != NULL)) {
    694 				vfree(sa->gssid);
    695 				sa->gssid = NULL;
    696 			}
    697 			break;
    698 		}
    699 #endif /* HAVE_GSSAPI */
    700 
    701 		default:
    702 			break;
    703 		}
    704 
    705 		prev = d;
    706 		if (flag) {
    707 			tlen -= sizeof(*d);
    708 			d = (struct isakmp_data *)((char *)d + sizeof(*d));
    709 		} else {
    710 			tlen -= (sizeof(*d) + ntohs(d->lorv));
    711 			d = (struct isakmp_data *)((char *)d + sizeof(*d) + ntohs(d->lorv));
    712 		}
    713 	}
    714 
    715 	/* key length must not be specified on some algorithms */
    716 	if (keylen) {
    717 		if (sa->enctype == OAKLEY_ATTR_ENC_ALG_DES
    718 #ifdef HAVE_OPENSSL_IDEA_H
    719 		 || sa->enctype == OAKLEY_ATTR_ENC_ALG_IDEA
    720 #endif
    721 		 || sa->enctype == OAKLEY_ATTR_ENC_ALG_3DES) {
    722 			plog(LLV_ERROR, LOCATION, NULL,
    723 				"keylen must not be specified "
    724 				"for encryption algorithm %d\n",
    725 				sa->enctype);
    726 			return -1;
    727 		}
    728 	}
    729 
    730 	return 0;
    731 err:
    732 	return error;
    733 }
    734 
    735 /*%%%*/
    736 /*
    737  * check phase 2 SA payload and select single proposal.
    738  * make new SA payload to be replyed not including general header.
    739  * This function is called by responder only.
    740  * OUT:
    741  *	0: succeed.
    742  *	-1: error occured.
    743  */
    744 int
    745 ipsecdoi_selectph2proposal(iph2)
    746 	struct ph2handle *iph2;
    747 {
    748 	struct prop_pair **pair;
    749 	struct prop_pair *ret;
    750 	u_int32_t doitype, sittype;
    751 
    752 	/* get proposal pair */
    753 	pair = get_proppair_and_doi_sit(iph2->sa, IPSECDOI_TYPE_PH2,
    754 					&doitype, &sittype);
    755 	if (pair == NULL)
    756 		return -1;
    757 
    758 	/* check and select a proposal. */
    759 	ret = get_ph2approval(iph2, pair);
    760 	free_proppair(pair);
    761 	if (ret == NULL)
    762 		return -1;
    763 
    764 	/* make a SA to be replayed. */
    765 	/* SPI must be updated later. */
    766 	iph2->sa_ret = get_sabyproppair(doitype, sittype, ret);
    767 	free_proppair0(ret);
    768 	if (iph2->sa_ret == NULL)
    769 		return -1;
    770 
    771 	return 0;
    772 }
    773 
    774 /*
    775  * check phase 2 SA payload returned from responder.
    776  * This function is called by initiator only.
    777  * OUT:
    778  *	0: valid.
    779  *	-1: invalid.
    780  */
    781 int
    782 ipsecdoi_checkph2proposal(iph2)
    783 	struct ph2handle *iph2;
    784 {
    785 	struct prop_pair **rpair = NULL, **spair = NULL;
    786 	struct prop_pair *p;
    787 	int i, n, num;
    788 	int error = -1;
    789 	vchar_t *sa_ret = NULL;
    790 	u_int32_t doitype, sittype;
    791 
    792 	/* get proposal pair of SA sent. */
    793 	spair = get_proppair_and_doi_sit(iph2->sa, IPSECDOI_TYPE_PH2,
    794 					 &doitype, &sittype);
    795 	if (spair == NULL) {
    796 		plog(LLV_ERROR, LOCATION, NULL,
    797 			"failed to get prop pair.\n");
    798 		goto end;
    799 	}
    800 
    801 	/* XXX should check the number of transform */
    802 
    803 	/* get proposal pair of SA replayed */
    804 	rpair = get_proppair(iph2->sa_ret, IPSECDOI_TYPE_PH2);
    805 	if (rpair == NULL) {
    806 		plog(LLV_ERROR, LOCATION, NULL,
    807 			"failed to get prop pair.\n");
    808 		goto end;
    809 	}
    810 
    811 	/* check proposal is only one ? */
    812 	n = 0;
    813 	num = 0;
    814 	for (i = 0; i < MAXPROPPAIRLEN; i++) {
    815 		if (rpair[i]) {
    816 			n = i;
    817 			num++;
    818 		}
    819 	}
    820 	if (num == 0) {
    821 		plog(LLV_ERROR, LOCATION, NULL,
    822 			"no proposal received.\n");
    823 		goto end;
    824 	}
    825 	if (num != 1) {
    826 		plog(LLV_ERROR, LOCATION, NULL,
    827 			"some proposals received.\n");
    828 		goto end;
    829 	}
    830 
    831 	if (spair[n] == NULL) {
    832 		plog(LLV_WARNING, LOCATION, NULL,
    833 			"invalid proposal number:%d received.\n", i);
    834 	}
    835 
    836 
    837 	if (rpair[n]->tnext != NULL) {
    838 		plog(LLV_ERROR, LOCATION, NULL,
    839 			"multi transforms replyed.\n");
    840 		goto end;
    841 	}
    842 
    843 	if (cmp_aproppair_i(rpair[n], spair[n])) {
    844 		plog(LLV_ERROR, LOCATION, NULL,
    845 			"proposal mismathed.\n");
    846 		goto end;
    847 	}
    848 
    849 	/*
    850 	 * check and select a proposal.
    851 	 * ensure that there is no modification of the proposal by
    852 	 * cmp_aproppair_i()
    853 	 */
    854 	p = get_ph2approval(iph2, rpair);
    855 	if (p == NULL)
    856 		goto end;
    857 
    858 	/* make a SA to be replayed. */
    859 	sa_ret = iph2->sa_ret;
    860 	iph2->sa_ret = get_sabyproppair(doitype, sittype, p);
    861 	free_proppair0(p);
    862 	if (iph2->sa_ret == NULL)
    863 		goto end;
    864 
    865 	error = 0;
    866 
    867 end:
    868 	if (rpair)
    869 		free_proppair(rpair);
    870 	if (spair)
    871 		free_proppair(spair);
    872 	if (sa_ret)
    873 		vfree(sa_ret);
    874 
    875 	return error;
    876 }
    877 
    878 /*
    879  * compare two prop_pair which is assumed to have same proposal number.
    880  * the case of bundle or single SA, NOT multi transforms.
    881  * a: a proposal that is multi protocols and single transform, usually replyed.
    882  * b: a proposal that is multi protocols and multi transform, usually sent.
    883  * NOTE: this function is for initiator.
    884  * OUT
    885  *	0: equal
    886  *	1: not equal
    887  * XXX cannot understand the comment!
    888  */
    889 static int
    890 cmp_aproppair_i(a, b)
    891 	struct prop_pair *a, *b;
    892 {
    893 	struct prop_pair *p, *q, *r;
    894 	int len;
    895 
    896 	for (p = a, q = b; p && q; p = p->next, q = q->next) {
    897 		for (r = q; r; r = r->tnext) {
    898 			/* compare trns */
    899 			if (p->trns->t_no == r->trns->t_no)
    900 				break;
    901 		}
    902 		if (!r) {
    903 			/* no suitable transform found */
    904 			plog(LLV_ERROR, LOCATION, NULL,
    905 				"no suitable transform found.\n");
    906 			return -1;
    907 		}
    908 
    909 		/* compare prop */
    910 		if (p->prop->p_no != r->prop->p_no) {
    911 			plog(LLV_WARNING, LOCATION, NULL,
    912 				"proposal #%d mismatched, "
    913 				"expected #%d.\n",
    914 				r->prop->p_no, p->prop->p_no);
    915 			/*FALLTHROUGH*/
    916 		}
    917 
    918 		if (p->prop->proto_id != r->prop->proto_id) {
    919 			plog(LLV_ERROR, LOCATION, NULL,
    920 				"proto_id mismathed: my:%d peer:%d\n",
    921 				r->prop->proto_id, p->prop->proto_id);
    922 			return -1;
    923 		}
    924 
    925 		if (p->prop->spi_size != r->prop->spi_size) {
    926 			plog(LLV_ERROR, LOCATION, NULL,
    927 				"invalid spi size: %d.\n",
    928 				p->prop->spi_size);
    929 			return -1;
    930 		}
    931 
    932 		/* check #of transforms */
    933 		if (p->prop->num_t != 1) {
    934 			plog(LLV_WARNING, LOCATION, NULL,
    935 				"#of transform is %d, "
    936 				"but expected 1.\n", p->prop->num_t);
    937 			/*FALLTHROUGH*/
    938 		}
    939 
    940 		if (p->trns->t_id != r->trns->t_id) {
    941 			plog(LLV_WARNING, LOCATION, NULL,
    942 				"transform number has been modified.\n");
    943 			/*FALLTHROUGH*/
    944 		}
    945 		if (p->trns->reserved != r->trns->reserved) {
    946 			plog(LLV_WARNING, LOCATION, NULL,
    947 				"reserved field should be zero.\n");
    948 			/*FALLTHROUGH*/
    949 		}
    950 
    951 		/* compare attribute */
    952 		len = ntohs(r->trns->h.len) - sizeof(*p->trns);
    953 		if (memcmp(p->trns + 1, r->trns + 1, len) != 0) {
    954 			plog(LLV_WARNING, LOCATION, NULL,
    955 				"attribute has been modified.\n");
    956 			/*FALLTHROUGH*/
    957 		}
    958 	}
    959 	if ((p && !q) || (!p && q)) {
    960 		/* # of protocols mismatched */
    961 		plog(LLV_ERROR, LOCATION, NULL,
    962 			"#of protocols mismatched.\n");
    963 		return -1;
    964 	}
    965 
    966 	return 0;
    967 }
    968 
    969 /*
    970  * acceptable check for policy configuration.
    971  * return a new SA payload to be reply to peer.
    972  */
    973 static struct prop_pair *
    974 get_ph2approval(iph2, pair)
    975 	struct ph2handle *iph2;
    976 	struct prop_pair **pair;
    977 {
    978 	struct prop_pair *ret;
    979 	int i;
    980 
    981 	iph2->approval = NULL;
    982 
    983 	plog(LLV_DEBUG, LOCATION, NULL,
    984 		"begin compare proposals.\n");
    985 
    986 	for (i = 0; i < MAXPROPPAIRLEN; i++) {
    987 		if (pair[i] == NULL)
    988 			continue;
    989 		plog(LLV_DEBUG, LOCATION, NULL,
    990 			"pair[%d]: %p\n", i, pair[i]);
    991 		print_proppair(LLV_DEBUG, pair[i]);;
    992 
    993 		/* compare proposal and select one */
    994 		ret = get_ph2approvalx(iph2, pair[i]);
    995 		if (ret != NULL) {
    996 			/* found */
    997 			return ret;
    998 		}
    999 	}
   1000 
   1001 	plog(LLV_ERROR, LOCATION, NULL, "no suitable policy found.\n");
   1002 
   1003 	return NULL;
   1004 }
   1005 
   1006 /*
   1007  * compare my proposal and peers just one proposal.
   1008  * set a approval.
   1009  */
   1010 static struct prop_pair *
   1011 get_ph2approvalx(iph2, pp)
   1012 	struct ph2handle *iph2;
   1013 	struct prop_pair *pp;
   1014 {
   1015 	struct prop_pair *ret = NULL;
   1016 	struct saprop *pr0, *pr = NULL;
   1017 	struct saprop *q1, *q2;
   1018 
   1019 	pr0 = aproppair2saprop(pp);
   1020 	if (pr0 == NULL)
   1021 		return NULL;
   1022 
   1023 	for (q1 = pr0; q1; q1 = q1->next) {
   1024 		for (q2 = iph2->proposal; q2; q2 = q2->next) {
   1025 			plog(LLV_DEBUG, LOCATION, NULL,
   1026 				"peer's single bundle:\n");
   1027 			printsaprop0(LLV_DEBUG, q1);
   1028 			plog(LLV_DEBUG, LOCATION, NULL,
   1029 				"my single bundle:\n");
   1030 			printsaprop0(LLV_DEBUG, q2);
   1031 
   1032 			pr = cmpsaprop_alloc(iph2->ph1, q1, q2, iph2->side);
   1033 			if (pr != NULL)
   1034 				goto found;
   1035 
   1036 			plog(LLV_ERROR, LOCATION, NULL,
   1037 				"not matched\n");
   1038 		}
   1039 	}
   1040 	/* no proposal matching */
   1041 err:
   1042 	flushsaprop(pr0);
   1043 	return NULL;
   1044 
   1045 found:
   1046 	flushsaprop(pr0);
   1047 	plog(LLV_DEBUG, LOCATION, NULL, "matched\n");
   1048 	iph2->approval = pr;
   1049 
   1050     {
   1051 	struct saproto *sp;
   1052 	struct prop_pair *p, *x;
   1053 	struct prop_pair *n = NULL;
   1054 
   1055 	ret = NULL;
   1056 
   1057 	for (p = pp; p; p = p->next) {
   1058 		/*
   1059 		 * find a proposal with matching proto_id.
   1060 		 * we have analyzed validity already, in cmpsaprop_alloc().
   1061 		 */
   1062 		for (sp = pr->head; sp; sp = sp->next) {
   1063 			if (sp->proto_id == p->prop->proto_id)
   1064 				break;
   1065 		}
   1066 		if (!sp)
   1067 			goto err;
   1068 		if (sp->head->next)
   1069 			goto err;	/* XXX */
   1070 
   1071 		for (x = p; x; x = x->tnext)
   1072 			if (sp->head->trns_no == x->trns->t_no)
   1073 				break;
   1074 		if (!x)
   1075 			goto err;	/* XXX */
   1076 
   1077 		n = racoon_calloc(1, sizeof(struct prop_pair));
   1078 		if (n == NULL) {
   1079 			plog(LLV_ERROR, LOCATION, NULL,
   1080 				"failed to get buffer.\n");
   1081 			goto err;
   1082 		}
   1083 
   1084 		n->prop = x->prop;
   1085 		n->trns = x->trns;
   1086 
   1087 		/* need to preserve the order */
   1088 		for (x = ret; x && x->next; x = x->next)
   1089 			;
   1090 		if (x && x->prop == n->prop) {
   1091 			for (/*nothing*/; x && x->tnext; x = x->tnext)
   1092 				;
   1093 			x->tnext = n;
   1094 		} else {
   1095 			if (x)
   1096 				x->next = n;
   1097 			else {
   1098 				ret = n;
   1099 			}
   1100 		}
   1101 
   1102 		/* #of transforms should be updated ? */
   1103 	}
   1104     }
   1105 
   1106 	return ret;
   1107 }
   1108 
   1109 void
   1110 free_proppair(pair)
   1111 	struct prop_pair **pair;
   1112 {
   1113 	int i;
   1114 
   1115 	for (i = 0; i < MAXPROPPAIRLEN; i++) {
   1116 		free_proppair0(pair[i]);
   1117 		pair[i] = NULL;
   1118 	}
   1119 	racoon_free(pair);
   1120 }
   1121 
   1122 static void
   1123 free_proppair0(pair)
   1124 	struct prop_pair *pair;
   1125 {
   1126 	struct prop_pair *p, *q, *r, *s;
   1127 
   1128 	p = pair;
   1129 	while (p) {
   1130 		q = p->next;
   1131 		r = p;
   1132 		while (r) {
   1133 			s = r->tnext;
   1134 			racoon_free(r);
   1135 			r = s;
   1136 		}
   1137 		p = q;
   1138 	}
   1139 }
   1140 
   1141 /*
   1142  * get proposal pairs from SA payload.
   1143  * tiny check for proposal payload.
   1144  */
   1145 static struct prop_pair **
   1146 get_proppair_and_doi_sit(sa, mode, doitype, sittype)
   1147 	vchar_t *sa;
   1148 	int mode;
   1149 	u_int32_t *doitype, *sittype;
   1150 {
   1151 	struct prop_pair **pair = NULL;
   1152 	int num_p = 0;			/* number of proposal for use */
   1153 	int tlen;
   1154 	caddr_t bp;
   1155 	int i;
   1156 	struct ipsecdoi_sa_b *sab = (struct ipsecdoi_sa_b *)sa->v;
   1157 
   1158 	plog(LLV_DEBUG, LOCATION, NULL, "total SA len=%zu\n", sa->l);
   1159 	plogdump(LLV_DEBUG, sa->v, sa->l);
   1160 
   1161 	/* check SA payload size */
   1162 	if (sa->l < sizeof(*sab)) {
   1163 		plog(LLV_ERROR, LOCATION, NULL,
   1164 			"Invalid SA length = %zu.\n", sa->l);
   1165 		goto bad;
   1166 	}
   1167 
   1168 	/* check DOI */
   1169 	if (check_doi(ntohl(sab->doi)) < 0)
   1170 		goto bad;
   1171 	if (doitype != NULL)
   1172 		*doitype = ntohl(sab->doi);
   1173 
   1174 	/* check SITUATION */
   1175 	if (check_situation(ntohl(sab->sit)) < 0)
   1176 		goto bad;
   1177 	if (sittype != NULL)
   1178 		*sittype = ntohl(sab->sit);
   1179 
   1180 	pair = racoon_calloc(1, MAXPROPPAIRLEN * sizeof(*pair));
   1181 	if (pair == NULL) {
   1182 		plog(LLV_ERROR, LOCATION, NULL,
   1183 			"failed to get buffer.\n");
   1184 		goto bad;
   1185 	}
   1186 	memset(pair, 0, sizeof(pair));
   1187 
   1188 	bp = (caddr_t)(sab + 1);
   1189 	tlen = sa->l - sizeof(*sab);
   1190 
   1191     {
   1192 	struct isakmp_pl_p *prop;
   1193 	int proplen;
   1194 	vchar_t *pbuf = NULL;
   1195 	struct isakmp_parse_t *pa;
   1196 
   1197 	pbuf = isakmp_parsewoh(ISAKMP_NPTYPE_P, (struct isakmp_gen *)bp, tlen);
   1198 	if (pbuf == NULL)
   1199 		goto bad;
   1200 
   1201 	for (pa = (struct isakmp_parse_t *)pbuf->v;
   1202 	     pa->type != ISAKMP_NPTYPE_NONE;
   1203 	     pa++) {
   1204 		/* check the value of next payload */
   1205 		if (pa->type != ISAKMP_NPTYPE_P) {
   1206 			plog(LLV_ERROR, LOCATION, NULL,
   1207 				"Invalid payload type=%u\n", pa->type);
   1208 			vfree(pbuf);
   1209 			goto bad;
   1210 		}
   1211 
   1212 		prop = (struct isakmp_pl_p *)pa->ptr;
   1213 		proplen = pa->len;
   1214 
   1215 		plog(LLV_DEBUG, LOCATION, NULL,
   1216 			"proposal #%u len=%d\n", prop->p_no, proplen);
   1217 
   1218 		if (proplen == 0) {
   1219 			plog(LLV_ERROR, LOCATION, NULL,
   1220 				"invalid proposal with length %d\n", proplen);
   1221 			vfree(pbuf);
   1222 			goto bad;
   1223 		}
   1224 
   1225 		/* check Protocol ID */
   1226 		if (!check_protocol[mode]) {
   1227 			plog(LLV_ERROR, LOCATION, NULL,
   1228 				"unsupported mode %d\n", mode);
   1229 			continue;
   1230 		}
   1231 
   1232 		if (check_protocol[mode](prop->proto_id) < 0)
   1233 			continue;
   1234 
   1235 		/* check SPI length when IKE. */
   1236 		if (check_spi_size(prop->proto_id, prop->spi_size) < 0)
   1237 			continue;
   1238 
   1239 		/* get transform */
   1240 		if (get_transform(prop, pair, &num_p) < 0) {
   1241 			vfree(pbuf);
   1242 			goto bad;
   1243 		}
   1244 	}
   1245 	vfree(pbuf);
   1246 	pbuf = NULL;
   1247     }
   1248 
   1249     {
   1250 	int notrans, nprop;
   1251 	struct prop_pair *p, *q;
   1252 
   1253 	/* check for proposals with no transforms */
   1254 	for (i = 0; i < MAXPROPPAIRLEN; i++) {
   1255 		if (!pair[i])
   1256 			continue;
   1257 
   1258 		plog(LLV_DEBUG, LOCATION, NULL, "pair %d:\n", i);
   1259 		print_proppair(LLV_DEBUG, pair[i]);
   1260 
   1261 		notrans = nprop = 0;
   1262 		for (p = pair[i]; p; p = p->next) {
   1263 			if (p->trns == NULL) {
   1264 				notrans++;
   1265 				break;
   1266 			}
   1267 			for (q = p; q; q = q->tnext)
   1268 				nprop++;
   1269 		}
   1270 
   1271 #if 0
   1272 		/*
   1273 		 * XXX at this moment, we cannot accept proposal group
   1274 		 * with multiple proposals.  this should be fixed.
   1275 		 */
   1276 		if (pair[i]->next) {
   1277 			plog(LLV_WARNING, LOCATION, NULL,
   1278 				"proposal #%u ignored "
   1279 				"(multiple proposal not supported)\n",
   1280 				pair[i]->prop->p_no);
   1281 			notrans++;
   1282 		}
   1283 #endif
   1284 
   1285 		if (notrans) {
   1286 			for (p = pair[i]; p; p = q) {
   1287 				q = p->next;
   1288 				racoon_free(p);
   1289 			}
   1290 			pair[i] = NULL;
   1291 			num_p--;
   1292 		} else {
   1293 			plog(LLV_DEBUG, LOCATION, NULL,
   1294 				"proposal #%u: %d transform\n",
   1295 				pair[i]->prop->p_no, nprop);
   1296 		}
   1297 	}
   1298     }
   1299 
   1300 	/* bark if no proposal is found. */
   1301 	if (num_p <= 0) {
   1302 		plog(LLV_ERROR, LOCATION, NULL,
   1303 			"no Proposal found.\n");
   1304 		goto bad;
   1305 	}
   1306 
   1307 	return pair;
   1308 bad:
   1309 	if (pair != NULL)
   1310 		racoon_free(pair);
   1311 	return NULL;
   1312 }
   1313 
   1314 struct prop_pair **
   1315 get_proppair(sa, mode)
   1316 	vchar_t *sa;
   1317 	int mode;
   1318 {
   1319 	return get_proppair_and_doi_sit(sa, mode, NULL, NULL);
   1320 }
   1321 
   1322 
   1323 /*
   1324  * check transform payload.
   1325  * OUT:
   1326  *	positive: return the pointer to the payload of valid transform.
   1327  *	0	: No valid transform found.
   1328  */
   1329 static int
   1330 get_transform(prop, pair, num_p)
   1331 	struct isakmp_pl_p *prop;
   1332 	struct prop_pair **pair;
   1333 	int *num_p;
   1334 {
   1335 	int tlen; /* total length of all transform in a proposal */
   1336 	caddr_t bp;
   1337 	struct isakmp_pl_t *trns;
   1338 	int trnslen;
   1339 	vchar_t *pbuf = NULL;
   1340 	struct isakmp_parse_t *pa;
   1341 	struct prop_pair *p = NULL, *q;
   1342 	int num_t;
   1343 
   1344 	bp = (caddr_t)prop + sizeof(struct isakmp_pl_p) + prop->spi_size;
   1345 	tlen = ntohs(prop->h.len)
   1346 		- (sizeof(struct isakmp_pl_p) + prop->spi_size);
   1347 	pbuf = isakmp_parsewoh(ISAKMP_NPTYPE_T, (struct isakmp_gen *)bp, tlen);
   1348 	if (pbuf == NULL)
   1349 		return -1;
   1350 
   1351 	/* check and get transform for use */
   1352 	num_t = 0;
   1353 	for (pa = (struct isakmp_parse_t *)pbuf->v;
   1354 	     pa->type != ISAKMP_NPTYPE_NONE;
   1355 	     pa++) {
   1356 
   1357 		num_t++;
   1358 
   1359 		/* check the value of next payload */
   1360 		if (pa->type != ISAKMP_NPTYPE_T) {
   1361 			plog(LLV_ERROR, LOCATION, NULL,
   1362 				"Invalid payload type=%u\n", pa->type);
   1363 			break;
   1364 		}
   1365 
   1366 		trns = (struct isakmp_pl_t *)pa->ptr;
   1367 		trnslen = pa->len;
   1368 
   1369 		plog(LLV_DEBUG, LOCATION, NULL,
   1370 			"transform #%u len=%u\n", trns->t_no, trnslen);
   1371 
   1372 		/* check transform ID */
   1373 		if (prop->proto_id >= ARRAYLEN(check_transform)) {
   1374 			plog(LLV_WARNING, LOCATION, NULL,
   1375 				"unsupported proto_id %u\n",
   1376 				prop->proto_id);
   1377 			continue;
   1378 		}
   1379 		if (prop->proto_id >= ARRAYLEN(check_attributes)) {
   1380 			plog(LLV_WARNING, LOCATION, NULL,
   1381 				"unsupported proto_id %u\n",
   1382 				prop->proto_id);
   1383 			continue;
   1384 		}
   1385 
   1386 		if (!check_transform[prop->proto_id]
   1387 		 || !check_attributes[prop->proto_id]) {
   1388 			plog(LLV_WARNING, LOCATION, NULL,
   1389 				"unsupported proto_id %u\n",
   1390 				prop->proto_id);
   1391 			continue;
   1392 		}
   1393 		if (check_transform[prop->proto_id](trns->t_id) < 0)
   1394 			continue;
   1395 
   1396 		/* check data attributes */
   1397 		if (check_attributes[prop->proto_id](trns) != 0)
   1398 			continue;
   1399 
   1400 		p = racoon_calloc(1, sizeof(*p));
   1401 		if (p == NULL) {
   1402 			plog(LLV_ERROR, LOCATION, NULL,
   1403 				"failed to get buffer.\n");
   1404 			vfree(pbuf);
   1405 			return -1;
   1406 		}
   1407 		p->prop = prop;
   1408 		p->trns = trns;
   1409 
   1410 		/* need to preserve the order */
   1411 		for (q = pair[prop->p_no]; q && q->next; q = q->next)
   1412 			;
   1413 		if (q && q->prop == p->prop) {
   1414 			for (/*nothing*/; q && q->tnext; q = q->tnext)
   1415 				;
   1416 			q->tnext = p;
   1417 		} else {
   1418 			if (q)
   1419 				q->next = p;
   1420 			else {
   1421 				pair[prop->p_no] = p;
   1422 				(*num_p)++;
   1423 			}
   1424 		}
   1425 	}
   1426 
   1427 	vfree(pbuf);
   1428 
   1429 	return 0;
   1430 }
   1431 
   1432 /*
   1433  * make a new SA payload from prop_pair.
   1434  * NOTE: this function make spi value clear.
   1435  */
   1436 vchar_t *
   1437 get_sabyproppair(doitype, sittype, pair)
   1438 	u_int32_t doitype, sittype;
   1439 	struct prop_pair *pair;
   1440 {
   1441 	vchar_t *newsa;
   1442 	int newtlen;
   1443 	u_int8_t *np_p = NULL;
   1444 	struct prop_pair *p;
   1445 	int prophlen, trnslen;
   1446 	caddr_t bp;
   1447 
   1448 	newtlen = sizeof(struct ipsecdoi_sa_b);
   1449 	for (p = pair; p; p = p->next) {
   1450 		newtlen += sizeof(struct isakmp_pl_p);
   1451 		newtlen += p->prop->spi_size;
   1452 		newtlen += ntohs(p->trns->h.len);
   1453 	}
   1454 
   1455 	newsa = vmalloc(newtlen);
   1456 	if (newsa == NULL) {
   1457 		plog(LLV_ERROR, LOCATION, NULL, "failed to get newsa.\n");
   1458 		return NULL;
   1459 	}
   1460 	bp = newsa->v;
   1461 
   1462 	((struct isakmp_gen *)bp)->len = htons(newtlen);
   1463 
   1464 	/* update some of values in SA header */
   1465 	((struct ipsecdoi_sa_b *)bp)->doi = htonl(doitype);
   1466 	((struct ipsecdoi_sa_b *)bp)->sit = htonl(sittype);
   1467 	bp += sizeof(struct ipsecdoi_sa_b);
   1468 
   1469 	/* create proposal payloads */
   1470 	for (p = pair; p; p = p->next) {
   1471 		prophlen = sizeof(struct isakmp_pl_p)
   1472 				+ p->prop->spi_size;
   1473 		trnslen = ntohs(p->trns->h.len);
   1474 
   1475 		if (np_p)
   1476 			*np_p = ISAKMP_NPTYPE_P;
   1477 
   1478 		/* create proposal */
   1479 
   1480 		memcpy(bp, p->prop, prophlen);
   1481 		((struct isakmp_pl_p *)bp)->h.np = ISAKMP_NPTYPE_NONE;
   1482 		((struct isakmp_pl_p *)bp)->h.len = htons(prophlen + trnslen);
   1483 		((struct isakmp_pl_p *)bp)->num_t = 1;
   1484 		np_p = &((struct isakmp_pl_p *)bp)->h.np;
   1485 		memset(bp + sizeof(struct isakmp_pl_p), 0, p->prop->spi_size);
   1486 		bp += prophlen;
   1487 
   1488 		/* create transform */
   1489 		memcpy(bp, p->trns, trnslen);
   1490 		((struct isakmp_pl_t *)bp)->h.np = ISAKMP_NPTYPE_NONE;
   1491 		((struct isakmp_pl_t *)bp)->h.len = htons(trnslen);
   1492 		bp += trnslen;
   1493 	}
   1494 
   1495 	return newsa;
   1496 }
   1497 
   1498 /*
   1499  * update responder's spi
   1500  */
   1501 int
   1502 ipsecdoi_updatespi(iph2)
   1503 	struct ph2handle *iph2;
   1504 {
   1505 	struct prop_pair **pair, *p;
   1506 	struct saprop *pp;
   1507 	struct saproto *pr;
   1508 	int i;
   1509 	int error = -1;
   1510 	u_int8_t *spi;
   1511 
   1512 	pair = get_proppair(iph2->sa_ret, IPSECDOI_TYPE_PH2);
   1513 	if (pair == NULL)
   1514 		return -1;
   1515 	for (i = 0; i < MAXPROPPAIRLEN; i++) {
   1516 		if (pair[i])
   1517 			break;
   1518 	}
   1519 	if (i == MAXPROPPAIRLEN || pair[i]->tnext) {
   1520 		/* multiple transform must be filtered by selectph2proposal.*/
   1521 		goto end;
   1522 	}
   1523 
   1524 	pp = iph2->approval;
   1525 
   1526 	/* create proposal payloads */
   1527 	for (p = pair[i]; p; p = p->next) {
   1528 		/*
   1529 		 * find a proposal/transform with matching proto_id/t_id.
   1530 		 * we have analyzed validity already, in cmpsaprop_alloc().
   1531 		 */
   1532 		for (pr = pp->head; pr; pr = pr->next) {
   1533 			if (p->prop->proto_id == pr->proto_id &&
   1534 			    p->trns->t_id == pr->head->trns_id) {
   1535 				break;
   1536 			}
   1537 		}
   1538 		if (!pr)
   1539 			goto end;
   1540 
   1541 		/*
   1542 		 * XXX SPI bits are left-filled, for use with IPComp.
   1543 		 * we should be switching to variable-length spi field...
   1544 		 */
   1545 		spi = (u_int8_t *)&pr->spi;
   1546 		spi += sizeof(pr->spi);
   1547 		spi -= pr->spisize;
   1548 		memcpy((caddr_t)p->prop + sizeof(*p->prop), spi, pr->spisize);
   1549 	}
   1550 
   1551 	error = 0;
   1552 end:
   1553 	free_proppair(pair);
   1554 	return error;
   1555 }
   1556 
   1557 /*
   1558  * make a new SA payload from prop_pair.
   1559  */
   1560 vchar_t *
   1561 get_sabysaprop(pp0, sa0)
   1562 	struct saprop *pp0;
   1563 	vchar_t *sa0;
   1564 {
   1565 	struct prop_pair **pair = NULL;
   1566 	vchar_t *newsa = NULL;
   1567 	int newtlen;
   1568 	u_int8_t *np_p = NULL;
   1569 	struct prop_pair *p = NULL;
   1570 	struct saprop *pp;
   1571 	struct saproto *pr;
   1572 	struct satrns *tr;
   1573 	int prophlen, trnslen;
   1574 	caddr_t bp;
   1575 	int error = -1;
   1576 
   1577 	/* get proposal pair */
   1578 	pair = get_proppair(sa0, IPSECDOI_TYPE_PH2);
   1579 	if (pair == NULL)
   1580 		goto out;
   1581 
   1582 	newtlen = sizeof(struct ipsecdoi_sa_b);
   1583 	for (pp = pp0; pp; pp = pp->next) {
   1584 
   1585 		if (pair[pp->prop_no] == NULL)
   1586 			goto out;
   1587 
   1588 		for (pr = pp->head; pr; pr = pr->next) {
   1589 			newtlen += (sizeof(struct isakmp_pl_p)
   1590 				+ pr->spisize);
   1591 
   1592 			for (tr = pr->head; tr; tr = tr->next) {
   1593 				for (p = pair[pp->prop_no]; p; p = p->tnext) {
   1594 					if (tr->trns_no == p->trns->t_no)
   1595 						break;
   1596 				}
   1597 				if (p == NULL)
   1598 					goto out;
   1599 
   1600 				newtlen += ntohs(p->trns->h.len);
   1601 			}
   1602 		}
   1603 	}
   1604 
   1605 	newsa = vmalloc(newtlen);
   1606 	if (newsa == NULL) {
   1607 		plog(LLV_ERROR, LOCATION, NULL, "failed to get newsa.\n");
   1608 		goto out;
   1609 	}
   1610 	bp = newsa->v;
   1611 
   1612 	/* some of values of SA must be updated in the out of this function */
   1613 	((struct isakmp_gen *)bp)->len = htons(newtlen);
   1614 	bp += sizeof(struct ipsecdoi_sa_b);
   1615 
   1616 	/* create proposal payloads */
   1617 	for (pp = pp0; pp; pp = pp->next) {
   1618 
   1619 		for (pr = pp->head; pr; pr = pr->next) {
   1620 			prophlen = sizeof(struct isakmp_pl_p)
   1621 					+ p->prop->spi_size;
   1622 
   1623 			for (tr = pr->head; tr; tr = tr->next) {
   1624 				for (p = pair[pp->prop_no]; p; p = p->tnext) {
   1625 					if (tr->trns_no == p->trns->t_no)
   1626 						break;
   1627 				}
   1628 				if (p == NULL)
   1629 					goto out;
   1630 
   1631 				trnslen = ntohs(p->trns->h.len);
   1632 
   1633 				if (np_p)
   1634 					*np_p = ISAKMP_NPTYPE_P;
   1635 
   1636 				/* create proposal */
   1637 
   1638 				memcpy(bp, p->prop, prophlen);
   1639 				((struct isakmp_pl_p *)bp)->h.np = ISAKMP_NPTYPE_NONE;
   1640 				((struct isakmp_pl_p *)bp)->h.len = htons(prophlen + trnslen);
   1641 				((struct isakmp_pl_p *)bp)->num_t = 1;
   1642 				np_p = &((struct isakmp_pl_p *)bp)->h.np;
   1643 				bp += prophlen;
   1644 
   1645 				/* create transform */
   1646 				memcpy(bp, p->trns, trnslen);
   1647 				((struct isakmp_pl_t *)bp)->h.np = ISAKMP_NPTYPE_NONE;
   1648 				((struct isakmp_pl_t *)bp)->h.len = htons(trnslen);
   1649 				bp += trnslen;
   1650 			}
   1651 		}
   1652 	}
   1653 
   1654 	error = 0;
   1655 out:
   1656 	if (pair != NULL)
   1657 		racoon_free(pair);
   1658 
   1659 	if (error != 0) {
   1660 		if (newsa != NULL) {
   1661 			vfree(newsa);
   1662 			newsa = NULL;
   1663 		}
   1664 	}
   1665 
   1666 	return newsa;
   1667 }
   1668 
   1669 /*
   1670  * If some error happens then return 0.  Although 0 means that lifetime is zero,
   1671  * such a value should not be accepted.
   1672  * Also 0 of lifebyte should not be included in a packet although 0 means not
   1673  * to care of it.
   1674  */
   1675 static u_int32_t
   1676 ipsecdoi_set_ld(buf)
   1677 	vchar_t *buf;
   1678 {
   1679 	u_int32_t ld;
   1680 
   1681 	if (buf == 0)
   1682 		return 0;
   1683 
   1684 	switch (buf->l) {
   1685 	case 2:
   1686 		ld = ntohs(*(u_int16_t *)buf->v);
   1687 		break;
   1688 	case 4:
   1689 		ld = ntohl(*(u_int32_t *)buf->v);
   1690 		break;
   1691 	default:
   1692 		plog(LLV_ERROR, LOCATION, NULL,
   1693 			"length %zu of life duration "
   1694 			"isn't supported.\n", buf->l);
   1695 		return 0;
   1696 	}
   1697 
   1698 	return ld;
   1699 }
   1700 
   1701 /*
   1702  * parse responder-lifetime attributes from payload
   1703  */
   1704 int
   1705 ipsecdoi_parse_responder_lifetime(notify, lifetime_sec, lifetime_kb)
   1706 	struct isakmp_pl_n *notify;
   1707 	u_int32_t *lifetime_sec;
   1708 	u_int32_t *lifetime_kb;
   1709 {
   1710 	struct isakmp_data *d;
   1711 	int flag, type, tlen, ld_type = -1;
   1712 	u_int16_t lorv;
   1713 	u_int32_t value;
   1714 
   1715 	tlen = ntohs(notify->h.len) - sizeof(*notify) - notify->spi_size;
   1716         d = (struct isakmp_data *)((char *)(notify + 1) +
   1717 		notify->spi_size);
   1718 
   1719 	while (tlen >= sizeof(struct isakmp_data)) {
   1720 		type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
   1721 		flag = ntohs(d->type) & ISAKMP_GEN_MASK;
   1722 		lorv = ntohs(d->lorv);
   1723 
   1724 		plog(LLV_DEBUG, LOCATION, NULL,
   1725 			"type=%s, flag=0x%04x, lorv=%s\n",
   1726 			s_ipsecdoi_attr(type), flag,
   1727 			s_ipsecdoi_attr_v(type, lorv));
   1728 
   1729 		switch (type) {
   1730 		case IPSECDOI_ATTR_SA_LD_TYPE:
   1731 			if (! flag) {
   1732 				plog(LLV_ERROR, LOCATION, NULL,
   1733 					"must be TV when LD_TYPE.\n");
   1734 				return -1;
   1735 			}
   1736 			ld_type = lorv;
   1737 			break;
   1738 		case IPSECDOI_ATTR_SA_LD:
   1739 			if (flag)
   1740 				value = lorv;
   1741 			else if (lorv == 2)
   1742 				value = ntohs(*(u_int16_t *)(d + 1));
   1743 			else if (lorv == 4)
   1744 				value = ntohl(*(u_int32_t *)(d + 1));
   1745 			else {
   1746 				plog(LLV_ERROR, LOCATION, NULL,
   1747 					"payload length %d for lifetime "
   1748 					"data length is unsupported.\n", lorv);
   1749 				return -1;
   1750 			}
   1751 
   1752 			switch (ld_type) {
   1753 			case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
   1754 				if (lifetime_sec != NULL)
   1755 					*lifetime_sec = value;
   1756 				plog(LLV_INFO, LOCATION, NULL,
   1757 					"received RESPONDER-LIFETIME: %d "
   1758 					"seconds\n", value);
   1759 				break;
   1760 			case IPSECDOI_ATTR_SA_LD_TYPE_KB:
   1761 				if (lifetime_kb != NULL)
   1762 					*lifetime_kb = value;
   1763 				plog(LLV_INFO, LOCATION, NULL,
   1764 					"received RESPONDER-LIFETIME: %d "
   1765 					"kbytes\n", value);
   1766 				break;
   1767 			default:
   1768 				plog(LLV_ERROR, LOCATION, NULL,
   1769 					"lifetime data received without "
   1770 					"lifetime data type.\n");
   1771 				return -1;
   1772 			}
   1773 			break;
   1774 		}
   1775 
   1776 		if (flag) {
   1777 			tlen -= sizeof(*d);
   1778 			d = (struct isakmp_data *)((char *)d
   1779 				+ sizeof(*d));
   1780 		} else {
   1781 			tlen -= (sizeof(*d) + lorv);
   1782 			d = (struct isakmp_data *)((char *)d
   1783 				+ sizeof(*d) + lorv);
   1784 		}
   1785 	}
   1786 
   1787 	return 0;
   1788 }
   1789 
   1790 
   1791 /*%%%*/
   1792 /*
   1793  * check DOI
   1794  */
   1795 static int
   1796 check_doi(doi)
   1797 	u_int32_t doi;
   1798 {
   1799 	switch (doi) {
   1800 	case IPSEC_DOI:
   1801 		return 0;
   1802 	default:
   1803 		plog(LLV_ERROR, LOCATION, NULL,
   1804 			"invalid value of DOI 0x%08x.\n", doi);
   1805 		return -1;
   1806 	}
   1807 	/* NOT REACHED */
   1808 }
   1809 
   1810 /*
   1811  * check situation
   1812  */
   1813 static int
   1814 check_situation(sit)
   1815 	u_int32_t sit;
   1816 {
   1817 	switch (sit) {
   1818 	case IPSECDOI_SIT_IDENTITY_ONLY:
   1819 		return 0;
   1820 
   1821 	case IPSECDOI_SIT_SECRECY:
   1822 	case IPSECDOI_SIT_INTEGRITY:
   1823 		plog(LLV_ERROR, LOCATION, NULL,
   1824 			"situation 0x%08x unsupported yet.\n", sit);
   1825 		return -1;
   1826 
   1827 	default:
   1828 		plog(LLV_ERROR, LOCATION, NULL,
   1829 			"invalid situation 0x%08x.\n", sit);
   1830 		return -1;
   1831 	}
   1832 	/* NOT REACHED */
   1833 }
   1834 
   1835 /*
   1836  * check protocol id in main mode
   1837  */
   1838 static int
   1839 check_prot_main(proto_id)
   1840 	int proto_id;
   1841 {
   1842 	switch (proto_id) {
   1843 	case IPSECDOI_PROTO_ISAKMP:
   1844 		return 0;
   1845 
   1846 	default:
   1847 		plog(LLV_ERROR, LOCATION, NULL,
   1848 			"Illegal protocol id=%u.\n", proto_id);
   1849 		return -1;
   1850 	}
   1851 	/* NOT REACHED */
   1852 }
   1853 
   1854 /*
   1855  * check protocol id in quick mode
   1856  */
   1857 static int
   1858 check_prot_quick(proto_id)
   1859 	int proto_id;
   1860 {
   1861 	switch (proto_id) {
   1862 	case IPSECDOI_PROTO_IPSEC_AH:
   1863 	case IPSECDOI_PROTO_IPSEC_ESP:
   1864 		return 0;
   1865 
   1866 	case IPSECDOI_PROTO_IPCOMP:
   1867 		return 0;
   1868 
   1869 	default:
   1870 		plog(LLV_ERROR, LOCATION, NULL,
   1871 			"invalid protocol id %d.\n", proto_id);
   1872 		return -1;
   1873 	}
   1874 	/* NOT REACHED */
   1875 }
   1876 
   1877 static int
   1878 check_spi_size(proto_id, size)
   1879 	int proto_id, size;
   1880 {
   1881 	switch (proto_id) {
   1882 	case IPSECDOI_PROTO_ISAKMP:
   1883 		if (size != 0) {
   1884 			/* WARNING */
   1885 			plog(LLV_WARNING, LOCATION, NULL,
   1886 				"SPI size isn't zero, but IKE proposal.\n");
   1887 		}
   1888 		return 0;
   1889 
   1890 	case IPSECDOI_PROTO_IPSEC_AH:
   1891 	case IPSECDOI_PROTO_IPSEC_ESP:
   1892 		if (size != 4) {
   1893 			plog(LLV_ERROR, LOCATION, NULL,
   1894 				"invalid SPI size=%d for IPSEC proposal.\n",
   1895 				size);
   1896 			return -1;
   1897 		}
   1898 		return 0;
   1899 
   1900 	case IPSECDOI_PROTO_IPCOMP:
   1901 		if (size != 2 && size != 4) {
   1902 			plog(LLV_ERROR, LOCATION, NULL,
   1903 				"invalid SPI size=%d for IPCOMP proposal.\n",
   1904 				size);
   1905 			return -1;
   1906 		}
   1907 		return 0;
   1908 
   1909 	default:
   1910 		/* ??? */
   1911 		return -1;
   1912 	}
   1913 	/* NOT REACHED */
   1914 }
   1915 
   1916 /*
   1917  * check transform ID in ISAKMP.
   1918  */
   1919 static int
   1920 check_trns_isakmp(t_id)
   1921 	int t_id;
   1922 {
   1923 	switch (t_id) {
   1924 	case IPSECDOI_KEY_IKE:
   1925 		return 0;
   1926 	default:
   1927 		plog(LLV_ERROR, LOCATION, NULL,
   1928 			"invalid transform-id=%u in proto_id=%u.\n",
   1929 			t_id, IPSECDOI_KEY_IKE);
   1930 		return -1;
   1931 	}
   1932 	/* NOT REACHED */
   1933 }
   1934 
   1935 /*
   1936  * check transform ID in AH.
   1937  */
   1938 static int
   1939 check_trns_ah(t_id)
   1940 	int t_id;
   1941 {
   1942 	switch (t_id) {
   1943 	case IPSECDOI_AH_MD5:
   1944 	case IPSECDOI_AH_SHA:
   1945 	case IPSECDOI_AH_SHA256:
   1946 	case IPSECDOI_AH_SHA384:
   1947 	case IPSECDOI_AH_SHA512:
   1948 		return 0;
   1949 	case IPSECDOI_AH_DES:
   1950 		plog(LLV_ERROR, LOCATION, NULL,
   1951 			"not support transform-id=%u in AH.\n", t_id);
   1952 		return -1;
   1953 	default:
   1954 		plog(LLV_ERROR, LOCATION, NULL,
   1955 			"invalid transform-id=%u in AH.\n", t_id);
   1956 		return -1;
   1957 	}
   1958 	/* NOT REACHED */
   1959 }
   1960 
   1961 /*
   1962  * check transform ID in ESP.
   1963  */
   1964 static int
   1965 check_trns_esp(t_id)
   1966 	int t_id;
   1967 {
   1968 	switch (t_id) {
   1969 	case IPSECDOI_ESP_DES:
   1970 	case IPSECDOI_ESP_3DES:
   1971 	case IPSECDOI_ESP_NULL:
   1972 	case IPSECDOI_ESP_RC5:
   1973 	case IPSECDOI_ESP_CAST:
   1974 	case IPSECDOI_ESP_BLOWFISH:
   1975 	case IPSECDOI_ESP_AES:
   1976 	case IPSECDOI_ESP_TWOFISH:
   1977 	case IPSECDOI_ESP_CAMELLIA:
   1978 		return 0;
   1979 	case IPSECDOI_ESP_DES_IV32:
   1980 	case IPSECDOI_ESP_DES_IV64:
   1981 	case IPSECDOI_ESP_IDEA:
   1982 	case IPSECDOI_ESP_3IDEA:
   1983 	case IPSECDOI_ESP_RC4:
   1984 		plog(LLV_ERROR, LOCATION, NULL,
   1985 			"not support transform-id=%u in ESP.\n", t_id);
   1986 		return -1;
   1987 	default:
   1988 		plog(LLV_ERROR, LOCATION, NULL,
   1989 			"invalid transform-id=%u in ESP.\n", t_id);
   1990 		return -1;
   1991 	}
   1992 	/* NOT REACHED */
   1993 }
   1994 
   1995 /*
   1996  * check transform ID in IPCOMP.
   1997  */
   1998 static int
   1999 check_trns_ipcomp(t_id)
   2000 	int t_id;
   2001 {
   2002 	switch (t_id) {
   2003 	case IPSECDOI_IPCOMP_OUI:
   2004 	case IPSECDOI_IPCOMP_DEFLATE:
   2005 	case IPSECDOI_IPCOMP_LZS:
   2006 		return 0;
   2007 	default:
   2008 		plog(LLV_ERROR, LOCATION, NULL,
   2009 			"invalid transform-id=%u in IPCOMP.\n", t_id);
   2010 		return -1;
   2011 	}
   2012 	/* NOT REACHED */
   2013 }
   2014 
   2015 /*
   2016  * check data attributes in IKE.
   2017  */
   2018 static int
   2019 check_attr_isakmp(trns)
   2020 	struct isakmp_pl_t *trns;
   2021 {
   2022 	struct isakmp_data *d;
   2023 	int tlen;
   2024 	int flag, type;
   2025 	u_int16_t lorv;
   2026 
   2027 	tlen = ntohs(trns->h.len) - sizeof(struct isakmp_pl_t);
   2028 	d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t));
   2029 
   2030 	while (tlen > 0) {
   2031 		type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
   2032 		flag = ntohs(d->type) & ISAKMP_GEN_MASK;
   2033 		lorv = ntohs(d->lorv);
   2034 
   2035 		plog(LLV_DEBUG, LOCATION, NULL,
   2036 			"type=%s, flag=0x%04x, lorv=%s\n",
   2037 			s_oakley_attr(type), flag,
   2038 			s_oakley_attr_v(type, lorv));
   2039 
   2040 		/*
   2041 		 * some of the attributes must be encoded in TV.
   2042 		 * see RFC2409 Appendix A "Attribute Classes".
   2043 		 */
   2044 		switch (type) {
   2045 		case OAKLEY_ATTR_ENC_ALG:
   2046 		case OAKLEY_ATTR_HASH_ALG:
   2047 		case OAKLEY_ATTR_AUTH_METHOD:
   2048 		case OAKLEY_ATTR_GRP_DESC:
   2049 		case OAKLEY_ATTR_GRP_TYPE:
   2050 		case OAKLEY_ATTR_SA_LD_TYPE:
   2051 		case OAKLEY_ATTR_PRF:
   2052 		case OAKLEY_ATTR_KEY_LEN:
   2053 		case OAKLEY_ATTR_FIELD_SIZE:
   2054 			if (!flag) {	/* TLV*/
   2055 				plog(LLV_ERROR, LOCATION, NULL,
   2056 					"oakley attribute %d must be TV.\n",
   2057 					type);
   2058 				return -1;
   2059 			}
   2060 			break;
   2061 		}
   2062 
   2063 		/* sanity check for TLV.  length must be specified. */
   2064 		if (!flag && lorv == 0) {	/*TLV*/
   2065 			plog(LLV_ERROR, LOCATION, NULL,
   2066 				"invalid length %d for TLV attribute %d.\n",
   2067 				lorv, type);
   2068 			return -1;
   2069 		}
   2070 
   2071 		switch (type) {
   2072 		case OAKLEY_ATTR_ENC_ALG:
   2073 			if (!alg_oakley_encdef_ok(lorv)) {
   2074 				plog(LLV_ERROR, LOCATION, NULL,
   2075 					"invalied encryption algorithm=%d.\n",
   2076 					lorv);
   2077 				return -1;
   2078 			}
   2079 			break;
   2080 
   2081 		case OAKLEY_ATTR_HASH_ALG:
   2082 			if (!alg_oakley_hashdef_ok(lorv)) {
   2083 				plog(LLV_ERROR, LOCATION, NULL,
   2084 					"invalied hash algorithm=%d.\n",
   2085 					lorv);
   2086 				return -1;
   2087 			}
   2088 			break;
   2089 
   2090 		case OAKLEY_ATTR_AUTH_METHOD:
   2091 			switch (lorv) {
   2092 			case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
   2093 			case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
   2094 #ifdef ENABLE_HYBRID
   2095 			case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
   2096 			case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
   2097 #endif
   2098 #if defined(ENABLE_HYBRID) || defined(HAVE_GSSAPI)
   2099 				/* These two authentication method IDs overlap. */
   2100 			case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I:
   2101 			/*case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:*/
   2102 #endif
   2103 				break;
   2104 			case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
   2105 #ifdef ENABLE_HYBRID
   2106 			case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
   2107 			case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
   2108 			case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
   2109 			case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
   2110 			case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
   2111 			case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
   2112 			case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
   2113 			case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I:
   2114 			case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
   2115 			case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I:
   2116 			case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
   2117 #endif
   2118 			case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
   2119 			case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
   2120 				plog(LLV_ERROR, LOCATION, NULL,
   2121 					"auth method %s isn't supported.\n",
   2122 					s_oakley_attr_method(lorv));
   2123 				return -1;
   2124 			default:
   2125 				plog(LLV_ERROR, LOCATION, NULL,
   2126 					"invalid auth method %d.\n",
   2127 					lorv);
   2128 				return -1;
   2129 			}
   2130 			break;
   2131 
   2132 		case OAKLEY_ATTR_GRP_DESC:
   2133 			if (!alg_oakley_dhdef_ok(lorv)) {
   2134 				plog(LLV_ERROR, LOCATION, NULL,
   2135 					"invalid DH group %d.\n",
   2136 					lorv);
   2137 				return -1;
   2138 			}
   2139 			break;
   2140 
   2141 		case OAKLEY_ATTR_GRP_TYPE:
   2142 			switch (lorv) {
   2143 			case OAKLEY_ATTR_GRP_TYPE_MODP:
   2144 				break;
   2145 			default:
   2146 				plog(LLV_ERROR, LOCATION, NULL,
   2147 					"unsupported DH group type %d.\n",
   2148 					lorv);
   2149 				return -1;
   2150 			}
   2151 			break;
   2152 
   2153 		case OAKLEY_ATTR_GRP_PI:
   2154 		case OAKLEY_ATTR_GRP_GEN_ONE:
   2155 			/* sanity checks? */
   2156 			break;
   2157 
   2158 		case OAKLEY_ATTR_GRP_GEN_TWO:
   2159 		case OAKLEY_ATTR_GRP_CURVE_A:
   2160 		case OAKLEY_ATTR_GRP_CURVE_B:
   2161 			plog(LLV_ERROR, LOCATION, NULL,
   2162 				"attr type=%u isn't supported.\n", type);
   2163 			return -1;
   2164 
   2165 		case OAKLEY_ATTR_SA_LD_TYPE:
   2166 			switch (lorv) {
   2167 			case OAKLEY_ATTR_SA_LD_TYPE_SEC:
   2168 			case OAKLEY_ATTR_SA_LD_TYPE_KB:
   2169 				break;
   2170 			default:
   2171 				plog(LLV_ERROR, LOCATION, NULL,
   2172 					"invalid life type %d.\n", lorv);
   2173 				return -1;
   2174 			}
   2175 			break;
   2176 
   2177 		case OAKLEY_ATTR_SA_LD:
   2178 			/* should check the value */
   2179 			break;
   2180 
   2181 		case OAKLEY_ATTR_PRF:
   2182 		case OAKLEY_ATTR_KEY_LEN:
   2183 			break;
   2184 
   2185 		case OAKLEY_ATTR_FIELD_SIZE:
   2186 			plog(LLV_ERROR, LOCATION, NULL,
   2187 				"attr type=%u isn't supported.\n", type);
   2188 			return -1;
   2189 
   2190 		case OAKLEY_ATTR_GRP_ORDER:
   2191 			break;
   2192 
   2193 		case OAKLEY_ATTR_GSS_ID:
   2194 			break;
   2195 
   2196 		default:
   2197 			plog(LLV_ERROR, LOCATION, NULL,
   2198 				"invalid attribute type %d.\n", type);
   2199 			return -1;
   2200 		}
   2201 
   2202 		if (flag) {
   2203 			tlen -= sizeof(*d);
   2204 			d = (struct isakmp_data *)((char *)d
   2205 				+ sizeof(*d));
   2206 		} else {
   2207 			tlen -= (sizeof(*d) + lorv);
   2208 			d = (struct isakmp_data *)((char *)d
   2209 				+ sizeof(*d) + lorv);
   2210 		}
   2211 	}
   2212 
   2213 	return 0;
   2214 }
   2215 
   2216 /*
   2217  * check data attributes in IPSEC AH/ESP.
   2218  */
   2219 static int
   2220 check_attr_ah(trns)
   2221 	struct isakmp_pl_t *trns;
   2222 {
   2223 	return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_AH, trns);
   2224 }
   2225 
   2226 static int
   2227 check_attr_esp(trns)
   2228 	struct isakmp_pl_t *trns;
   2229 {
   2230 	return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_ESP, trns);
   2231 }
   2232 
   2233 static int
   2234 check_attr_ipsec(proto_id, trns)
   2235 	int proto_id;
   2236 	struct isakmp_pl_t *trns;
   2237 {
   2238 	struct isakmp_data *d;
   2239 	int tlen;
   2240 	int flag, type = 0;
   2241 	u_int16_t lorv;
   2242 	int attrseen[16];	/* XXX magic number */
   2243 
   2244 	tlen = ntohs(trns->h.len) - sizeof(struct isakmp_pl_t);
   2245 	d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t));
   2246 	memset(attrseen, 0, sizeof(attrseen));
   2247 
   2248 	while (tlen > 0) {
   2249 		type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
   2250 		flag = ntohs(d->type) & ISAKMP_GEN_MASK;
   2251 		lorv = ntohs(d->lorv);
   2252 
   2253 		plog(LLV_DEBUG, LOCATION, NULL,
   2254 			"type=%s, flag=0x%04x, lorv=%s\n",
   2255 			s_ipsecdoi_attr(type), flag,
   2256 			s_ipsecdoi_attr_v(type, lorv));
   2257 
   2258 		if (type < sizeof(attrseen)/sizeof(attrseen[0]))
   2259 			attrseen[type]++;
   2260 
   2261 		switch (type) {
   2262 		case IPSECDOI_ATTR_ENC_MODE:
   2263 			if (! flag) {
   2264 				plog(LLV_ERROR, LOCATION, NULL,
   2265 					"must be TV when ENC_MODE.\n");
   2266 				return -1;
   2267 			}
   2268 
   2269 			switch (lorv) {
   2270 			case IPSECDOI_ATTR_ENC_MODE_TUNNEL:
   2271 			case IPSECDOI_ATTR_ENC_MODE_TRNS:
   2272 				break;
   2273 #ifdef ENABLE_NATT
   2274 			case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC:
   2275 			case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC:
   2276 			case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT:
   2277 			case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT:
   2278 				plog(LLV_DEBUG, LOCATION, NULL,
   2279 				     "UDP encapsulation requested\n");
   2280 				break;
   2281 #endif
   2282 			default:
   2283 				plog(LLV_ERROR, LOCATION, NULL,
   2284 					"invalid encryption mode=%u.\n",
   2285 					lorv);
   2286 				return -1;
   2287 			}
   2288 			break;
   2289 
   2290 		case IPSECDOI_ATTR_AUTH:
   2291 			if (! flag) {
   2292 				plog(LLV_ERROR, LOCATION, NULL,
   2293 					"must be TV when AUTH.\n");
   2294 				return -1;
   2295 			}
   2296 
   2297 			switch (lorv) {
   2298 			case IPSECDOI_ATTR_AUTH_HMAC_MD5:
   2299 				if (proto_id == IPSECDOI_PROTO_IPSEC_AH &&
   2300 				    trns->t_id != IPSECDOI_AH_MD5) {
   2301 ahmismatch:
   2302 					plog(LLV_ERROR, LOCATION, NULL,
   2303 						"auth algorithm %u conflicts "
   2304 						"with transform %u.\n",
   2305 						lorv, trns->t_id);
   2306 					return -1;
   2307 				}
   2308 				break;
   2309 			case IPSECDOI_ATTR_AUTH_HMAC_SHA1:
   2310 				if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
   2311 					if (trns->t_id != IPSECDOI_AH_SHA)
   2312 						goto ahmismatch;
   2313 				}
   2314 				break;
   2315  			case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256:
   2316  				if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
   2317  					if (trns->t_id != IPSECDOI_AH_SHA256)
   2318  						goto ahmismatch;
   2319  				}
   2320  				break;
   2321  			case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384:
   2322  				if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
   2323  					if (trns->t_id != IPSECDOI_AH_SHA384)
   2324  						goto ahmismatch;
   2325  				}
   2326  				break;
   2327  			case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512:
   2328  				if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
   2329  					if (trns->t_id != IPSECDOI_AH_SHA512)
   2330  					goto ahmismatch;
   2331  				}
   2332  				break;
   2333 			case IPSECDOI_ATTR_AUTH_DES_MAC:
   2334 			case IPSECDOI_ATTR_AUTH_KPDK:
   2335 				plog(LLV_ERROR, LOCATION, NULL,
   2336 					"auth algorithm %u isn't supported.\n",
   2337 					lorv);
   2338 				return -1;
   2339 			default:
   2340 				plog(LLV_ERROR, LOCATION, NULL,
   2341 					"invalid auth algorithm=%u.\n",
   2342 					lorv);
   2343 				return -1;
   2344 			}
   2345 			break;
   2346 
   2347 		case IPSECDOI_ATTR_SA_LD_TYPE:
   2348 			if (! flag) {
   2349 				plog(LLV_ERROR, LOCATION, NULL,
   2350 					"must be TV when LD_TYPE.\n");
   2351 				return -1;
   2352 			}
   2353 
   2354 			switch (lorv) {
   2355 			case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
   2356 			case IPSECDOI_ATTR_SA_LD_TYPE_KB:
   2357 				break;
   2358 			default:
   2359 				plog(LLV_ERROR, LOCATION, NULL,
   2360 					"invalid life type %d.\n", lorv);
   2361 				return -1;
   2362 			}
   2363 			break;
   2364 
   2365 		case IPSECDOI_ATTR_SA_LD:
   2366 			if (flag) {
   2367 				/* i.e. ISAKMP_GEN_TV */
   2368 				plog(LLV_DEBUG, LOCATION, NULL,
   2369 					"life duration was in TLV.\n");
   2370 			} else {
   2371 				/* i.e. ISAKMP_GEN_TLV */
   2372 				if (lorv == 0) {
   2373 					plog(LLV_ERROR, LOCATION, NULL,
   2374 						"invalid length of LD\n");
   2375 					return -1;
   2376 				}
   2377 			}
   2378 			break;
   2379 
   2380 		case IPSECDOI_ATTR_GRP_DESC:
   2381 			if (! flag) {
   2382 				plog(LLV_ERROR, LOCATION, NULL,
   2383 					"must be TV when GRP_DESC.\n");
   2384 				return -1;
   2385 			}
   2386 
   2387 			if (!alg_oakley_dhdef_ok(lorv)) {
   2388 				plog(LLV_ERROR, LOCATION, NULL,
   2389 					"invalid group description=%u.\n",
   2390 					lorv);
   2391 				return -1;
   2392 			}
   2393 			break;
   2394 
   2395 		case IPSECDOI_ATTR_KEY_LENGTH:
   2396 			if (! flag) {
   2397 				plog(LLV_ERROR, LOCATION, NULL,
   2398 					"must be TV when KEY_LENGTH.\n");
   2399 				return -1;
   2400 			}
   2401 			break;
   2402 
   2403 #ifdef HAVE_SECCTX
   2404 		case IPSECDOI_ATTR_SECCTX:
   2405 			if (flag) {
   2406 				plog(LLV_ERROR, LOCATION, NULL,
   2407 					"SECCTX must be in TLV.\n");
   2408 				return -1;
   2409 			}
   2410 		break;
   2411 #endif
   2412 
   2413 		case IPSECDOI_ATTR_KEY_ROUNDS:
   2414 		case IPSECDOI_ATTR_COMP_DICT_SIZE:
   2415 		case IPSECDOI_ATTR_COMP_PRIVALG:
   2416 			plog(LLV_ERROR, LOCATION, NULL,
   2417 				"attr type=%u isn't supported.\n", type);
   2418 			return -1;
   2419 
   2420 		default:
   2421 			plog(LLV_ERROR, LOCATION, NULL,
   2422 				"invalid attribute type %d.\n", type);
   2423 			return -1;
   2424 		}
   2425 
   2426 		if (flag) {
   2427 			tlen -= sizeof(*d);
   2428 			d = (struct isakmp_data *)((char *)d
   2429 				+ sizeof(*d));
   2430 		} else {
   2431 			tlen -= (sizeof(*d) + lorv);
   2432 			d = (struct isakmp_data *)((caddr_t)d
   2433 				+ sizeof(*d) + lorv);
   2434 		}
   2435 	}
   2436 
   2437 	if (proto_id == IPSECDOI_PROTO_IPSEC_AH &&
   2438 	    !attrseen[IPSECDOI_ATTR_AUTH]) {
   2439 		plog(LLV_ERROR, LOCATION, NULL,
   2440 			"attr AUTH must be present for AH.\n");
   2441 		return -1;
   2442 	}
   2443 
   2444 	if (proto_id == IPSECDOI_PROTO_IPSEC_ESP &&
   2445 	    trns->t_id == IPSECDOI_ESP_NULL &&
   2446 	    !attrseen[IPSECDOI_ATTR_AUTH]) {
   2447 		plog(LLV_ERROR, LOCATION, NULL,
   2448 		    "attr AUTH must be present for ESP NULL encryption.\n");
   2449 		return -1;
   2450 	}
   2451 
   2452 	return 0;
   2453 }
   2454 
   2455 static int
   2456 check_attr_ipcomp(trns)
   2457 	struct isakmp_pl_t *trns;
   2458 {
   2459 	struct isakmp_data *d;
   2460 	int tlen;
   2461 	int flag, type = 0;
   2462 	u_int16_t lorv;
   2463 	int attrseen[16];	/* XXX magic number */
   2464 
   2465 	tlen = ntohs(trns->h.len) - sizeof(struct isakmp_pl_t);
   2466 	d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t));
   2467 	memset(attrseen, 0, sizeof(attrseen));
   2468 
   2469 	while (tlen > 0) {
   2470 		type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
   2471 		flag = ntohs(d->type) & ISAKMP_GEN_MASK;
   2472 		lorv = ntohs(d->lorv);
   2473 
   2474 		plog(LLV_DEBUG, LOCATION, NULL,
   2475 			"type=%d, flag=0x%04x, lorv=0x%04x\n",
   2476 			type, flag, lorv);
   2477 
   2478 		if (type < sizeof(attrseen)/sizeof(attrseen[0]))
   2479 			attrseen[type]++;
   2480 
   2481 		switch (type) {
   2482 		case IPSECDOI_ATTR_ENC_MODE:
   2483 			if (! flag) {
   2484 				plog(LLV_ERROR, LOCATION, NULL,
   2485 					"must be TV when ENC_MODE.\n");
   2486 				return -1;
   2487 			}
   2488 
   2489 			switch (lorv) {
   2490 			case IPSECDOI_ATTR_ENC_MODE_TUNNEL:
   2491 			case IPSECDOI_ATTR_ENC_MODE_TRNS:
   2492 				break;
   2493 #ifdef ENABLE_NATT
   2494 			case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC:
   2495 			case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC:
   2496 			case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT:
   2497 			case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT:
   2498 				plog(LLV_DEBUG, LOCATION, NULL,
   2499 				     "UDP encapsulation requested\n");
   2500 				break;
   2501 #endif
   2502 			default:
   2503 				plog(LLV_ERROR, LOCATION, NULL,
   2504 					"invalid encryption mode=%u.\n",
   2505 					lorv);
   2506 				return -1;
   2507 			}
   2508 			break;
   2509 
   2510 		case IPSECDOI_ATTR_SA_LD_TYPE:
   2511 			if (! flag) {
   2512 				plog(LLV_ERROR, LOCATION, NULL,
   2513 					"must be TV when LD_TYPE.\n");
   2514 				return -1;
   2515 			}
   2516 
   2517 			switch (lorv) {
   2518 			case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
   2519 			case IPSECDOI_ATTR_SA_LD_TYPE_KB:
   2520 				break;
   2521 			default:
   2522 				plog(LLV_ERROR, LOCATION, NULL,
   2523 					"invalid life type %d.\n", lorv);
   2524 				return -1;
   2525 			}
   2526 			break;
   2527 
   2528 		case IPSECDOI_ATTR_SA_LD:
   2529 			if (flag) {
   2530 				/* i.e. ISAKMP_GEN_TV */
   2531 				plog(LLV_DEBUG, LOCATION, NULL,
   2532 					"life duration was in TLV.\n");
   2533 			} else {
   2534 				/* i.e. ISAKMP_GEN_TLV */
   2535 				if (lorv == 0) {
   2536 					plog(LLV_ERROR, LOCATION, NULL,
   2537 						"invalid length of LD\n");
   2538 					return -1;
   2539 				}
   2540 			}
   2541 			break;
   2542 
   2543 		case IPSECDOI_ATTR_GRP_DESC:
   2544 			if (! flag) {
   2545 				plog(LLV_ERROR, LOCATION, NULL,
   2546 					"must be TV when GRP_DESC.\n");
   2547 				return -1;
   2548 			}
   2549 
   2550 			if (!alg_oakley_dhdef_ok(lorv)) {
   2551 				plog(LLV_ERROR, LOCATION, NULL,
   2552 					"invalid group description=%u.\n",
   2553 					lorv);
   2554 				return -1;
   2555 			}
   2556 			break;
   2557 
   2558 		case IPSECDOI_ATTR_AUTH:
   2559 			plog(LLV_ERROR, LOCATION, NULL,
   2560 				"invalid attr type=%u.\n", type);
   2561 			return -1;
   2562 
   2563 		case IPSECDOI_ATTR_KEY_LENGTH:
   2564 		case IPSECDOI_ATTR_KEY_ROUNDS:
   2565 		case IPSECDOI_ATTR_COMP_DICT_SIZE:
   2566 		case IPSECDOI_ATTR_COMP_PRIVALG:
   2567 			plog(LLV_ERROR, LOCATION, NULL,
   2568 				"attr type=%u isn't supported.\n", type);
   2569 			return -1;
   2570 
   2571 		default:
   2572 			plog(LLV_ERROR, LOCATION, NULL,
   2573 				"invalid attribute type %d.\n", type);
   2574 			return -1;
   2575 		}
   2576 
   2577 		if (flag) {
   2578 			tlen -= sizeof(*d);
   2579 			d = (struct isakmp_data *)((char *)d
   2580 				+ sizeof(*d));
   2581 		} else {
   2582 			tlen -= (sizeof(*d) + lorv);
   2583 			d = (struct isakmp_data *)((caddr_t)d
   2584 				+ sizeof(*d) + lorv);
   2585 		}
   2586 	}
   2587 
   2588 #if 0
   2589 	if (proto_id == IPSECDOI_PROTO_IPCOMP &&
   2590 	    !attrseen[IPSECDOI_ATTR_AUTH]) {
   2591 		plog(LLV_ERROR, LOCATION, NULL,
   2592 			"attr AUTH must be present for AH.\n", type);
   2593 		return -1;
   2594 	}
   2595 #endif
   2596 
   2597 	return 0;
   2598 }
   2599 
   2600 /* %%% */
   2601 /*
   2602  * create phase1 proposal from remote configuration.
   2603  * NOT INCLUDING isakmp general header of SA payload
   2604  */
   2605 vchar_t *
   2606 ipsecdoi_setph1proposal(rmconf, props)
   2607 	struct remoteconf *rmconf;
   2608 	struct isakmpsa *props;
   2609 {
   2610 	vchar_t *mysa;
   2611 	int sablen;
   2612 
   2613 	/* count total size of SA minus isakmp general header */
   2614 	/* not including isakmp general header of SA payload */
   2615 	sablen = sizeof(struct ipsecdoi_sa_b);
   2616 	sablen += setph1prop(props, NULL);
   2617 
   2618 	mysa = vmalloc(sablen);
   2619 	if (mysa == NULL) {
   2620 		plog(LLV_ERROR, LOCATION, NULL,
   2621 			"failed to allocate my sa buffer\n");
   2622 		return NULL;
   2623 	}
   2624 
   2625 	/* create SA payload */
   2626 	/* not including isakmp general header */
   2627 	((struct ipsecdoi_sa_b *)mysa->v)->doi = htonl(rmconf->doitype);
   2628 	((struct ipsecdoi_sa_b *)mysa->v)->sit = htonl(rmconf->sittype);
   2629 
   2630 	(void)setph1prop(props, mysa->v + sizeof(struct ipsecdoi_sa_b));
   2631 
   2632 	return mysa;
   2633 }
   2634 
   2635 static int
   2636 setph1prop(props, buf)
   2637 	struct isakmpsa *props;
   2638 	caddr_t buf;
   2639 {
   2640 	struct isakmp_pl_p *prop = NULL;
   2641 	struct isakmpsa *s = NULL;
   2642 	int proplen, trnslen;
   2643 	u_int8_t *np_t; /* pointer next trns type in previous header */
   2644 	int trns_num;
   2645 	caddr_t p = buf;
   2646 
   2647 	proplen = sizeof(*prop);
   2648 	if (buf) {
   2649 		/* create proposal */
   2650 		prop = (struct isakmp_pl_p *)p;
   2651 		prop->h.np = ISAKMP_NPTYPE_NONE;
   2652 		prop->p_no = props->prop_no;
   2653 		prop->proto_id = IPSECDOI_PROTO_ISAKMP;
   2654 		prop->spi_size = 0;
   2655 		p += sizeof(*prop);
   2656 	}
   2657 
   2658 	np_t = NULL;
   2659 	trns_num = 0;
   2660 
   2661 	for (s = props; s != NULL; s = s->next) {
   2662 		if (np_t)
   2663 			*np_t = ISAKMP_NPTYPE_T;
   2664 
   2665 		trnslen = setph1trns(s, p);
   2666 		proplen += trnslen;
   2667 		if (buf) {
   2668 			/* save buffer to pre-next payload */
   2669 			np_t = &((struct isakmp_pl_t *)p)->h.np;
   2670 			p += trnslen;
   2671 
   2672 			/* count up transform length */
   2673 			trns_num++;
   2674 		}
   2675 	}
   2676 
   2677 	/* update proposal length */
   2678 	if (buf) {
   2679 		prop->h.len = htons(proplen);
   2680 		prop->num_t = trns_num;
   2681 	}
   2682 
   2683 	return proplen;
   2684 }
   2685 
   2686 static int
   2687 setph1trns(sa, buf)
   2688 	struct isakmpsa *sa;
   2689 	caddr_t buf;
   2690 {
   2691 	struct isakmp_pl_t *trns = NULL;
   2692 	int trnslen, attrlen;
   2693 	caddr_t p = buf;
   2694 
   2695 	trnslen = sizeof(*trns);
   2696 	if (buf) {
   2697 		/* create transform */
   2698 		trns = (struct isakmp_pl_t *)p;
   2699 		trns->h.np  = ISAKMP_NPTYPE_NONE;
   2700 		trns->t_no  = sa->trns_no;
   2701 		trns->t_id  = IPSECDOI_KEY_IKE;
   2702 		p += sizeof(*trns);
   2703 	}
   2704 
   2705 	attrlen = setph1attr(sa, p);
   2706 	trnslen += attrlen;
   2707 	if (buf)
   2708 		p += attrlen;
   2709 
   2710 	if (buf)
   2711 		trns->h.len = htons(trnslen);
   2712 
   2713 	return trnslen;
   2714 }
   2715 
   2716 static int
   2717 setph1attr(sa, buf)
   2718 	struct isakmpsa *sa;
   2719 	caddr_t buf;
   2720 {
   2721 	caddr_t p = buf;
   2722 	int attrlen = 0;
   2723 
   2724 	if (sa->lifetime) {
   2725 		u_int32_t lifetime = htonl((u_int32_t)sa->lifetime);
   2726 
   2727 		attrlen += sizeof(struct isakmp_data)
   2728 			+ sizeof(struct isakmp_data);
   2729 		if (sa->lifetime > 0xffff)
   2730 			attrlen += sizeof(lifetime);
   2731 		if (buf) {
   2732 			p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD_TYPE,
   2733 						OAKLEY_ATTR_SA_LD_TYPE_SEC);
   2734 			if (sa->lifetime > 0xffff) {
   2735 				p = isakmp_set_attr_v(p, OAKLEY_ATTR_SA_LD,
   2736 						(caddr_t)&lifetime,
   2737 						sizeof(lifetime));
   2738 			} else {
   2739 				p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD,
   2740 							sa->lifetime);
   2741 			}
   2742 		}
   2743 	}
   2744 
   2745 	if (sa->lifebyte) {
   2746 		u_int32_t lifebyte = htonl((u_int32_t)sa->lifebyte);
   2747 
   2748 		attrlen += sizeof(struct isakmp_data)
   2749 			+ sizeof(struct isakmp_data);
   2750 		if (sa->lifebyte > 0xffff)
   2751 			attrlen += sizeof(lifebyte);
   2752 		if (buf) {
   2753 			p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD_TYPE,
   2754 						OAKLEY_ATTR_SA_LD_TYPE_KB);
   2755 			if (sa->lifebyte > 0xffff) {
   2756 				p = isakmp_set_attr_v(p, OAKLEY_ATTR_SA_LD,
   2757 							(caddr_t)&lifebyte,
   2758 							sizeof(lifebyte));
   2759 			} else {
   2760 				p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD,
   2761 							sa->lifebyte);
   2762 			}
   2763 		}
   2764 	}
   2765 
   2766 	if (sa->enctype) {
   2767 		attrlen += sizeof(struct isakmp_data);
   2768 		if (buf)
   2769 			p = isakmp_set_attr_l(p, OAKLEY_ATTR_ENC_ALG, sa->enctype);
   2770 	}
   2771 	if (sa->encklen) {
   2772 		attrlen += sizeof(struct isakmp_data);
   2773 		if (buf)
   2774 			p = isakmp_set_attr_l(p, OAKLEY_ATTR_KEY_LEN, sa->encklen);
   2775 	}
   2776 	if (sa->authmethod) {
   2777 		int authmethod;
   2778 
   2779 		authmethod = isakmpsa_switch_authmethod(sa->authmethod);
   2780 		authmethod &= 0xffff;
   2781 		attrlen += sizeof(struct isakmp_data);
   2782 		if (buf)
   2783 			p = isakmp_set_attr_l(p, OAKLEY_ATTR_AUTH_METHOD, authmethod);
   2784 	}
   2785 	if (sa->hashtype) {
   2786 		attrlen += sizeof(struct isakmp_data);
   2787 		if (buf)
   2788 			p = isakmp_set_attr_l(p, OAKLEY_ATTR_HASH_ALG, sa->hashtype);
   2789 	}
   2790 	switch (sa->dh_group) {
   2791 	case OAKLEY_ATTR_GRP_DESC_MODP768:
   2792 	case OAKLEY_ATTR_GRP_DESC_MODP1024:
   2793 	case OAKLEY_ATTR_GRP_DESC_MODP1536:
   2794 	case OAKLEY_ATTR_GRP_DESC_MODP2048:
   2795 	case OAKLEY_ATTR_GRP_DESC_MODP3072:
   2796 	case OAKLEY_ATTR_GRP_DESC_MODP4096:
   2797 	case OAKLEY_ATTR_GRP_DESC_MODP6144:
   2798 	case OAKLEY_ATTR_GRP_DESC_MODP8192:
   2799 		/* don't attach group type for known groups */
   2800 		attrlen += sizeof(struct isakmp_data);
   2801 		if (buf) {
   2802 			p = isakmp_set_attr_l(p, OAKLEY_ATTR_GRP_DESC,
   2803 				sa->dh_group);
   2804 		}
   2805 		break;
   2806 	case OAKLEY_ATTR_GRP_DESC_EC2N155:
   2807 	case OAKLEY_ATTR_GRP_DESC_EC2N185:
   2808 		/* don't attach group type for known groups */
   2809 		attrlen += sizeof(struct isakmp_data);
   2810 		if (buf) {
   2811 			p = isakmp_set_attr_l(p, OAKLEY_ATTR_GRP_TYPE,
   2812 				OAKLEY_ATTR_GRP_TYPE_EC2N);
   2813 		}
   2814 		break;
   2815 	case 0:
   2816 	default:
   2817 		break;
   2818 	}
   2819 
   2820 #ifdef HAVE_GSSAPI
   2821 	if (sa->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB &&
   2822 	    sa->gssid != NULL) {
   2823 		attrlen += sizeof(struct isakmp_data);
   2824 		/*
   2825 		 * Older versions of racoon just placed the ISO-Latin-1
   2826 		 * string on the wire directly.  Check to see if we are
   2827 		 * configured to be compatible with this behavior.  Otherwise,
   2828 		 * we encode the GSS ID as UTF-16LE for Windows 2000
   2829 		 * compatibility, which requires twice the number of octets.
   2830 		 */
   2831 		if (lcconf->gss_id_enc == LC_GSSENC_LATIN1)
   2832 			attrlen += sa->gssid->l;
   2833 		else
   2834 			attrlen += sa->gssid->l * 2;
   2835 		if (buf) {
   2836 			plog(LLV_DEBUG, LOCATION, NULL, "gss id attr: len %zu, "
   2837 			    "val '%.*s'\n", sa->gssid->l, (int)sa->gssid->l,
   2838 			    sa->gssid->v);
   2839 			if (lcconf->gss_id_enc == LC_GSSENC_LATIN1) {
   2840 				p = isakmp_set_attr_v(p, OAKLEY_ATTR_GSS_ID,
   2841 					(caddr_t)sa->gssid->v,
   2842 					sa->gssid->l);
   2843 			} else {
   2844 				size_t dstleft = sa->gssid->l * 2;
   2845 				size_t srcleft = sa->gssid->l;
   2846 				const char *src = (const char *)sa->gssid->v;
   2847 				char *odst, *dst = racoon_malloc(dstleft);
   2848 				iconv_t cd;
   2849 				size_t rv;
   2850 
   2851 				cd = iconv_open("utf-16le", "latin1");
   2852 				if (cd == (iconv_t) -1) {
   2853 					plog(LLV_ERROR, LOCATION, NULL,
   2854 					    "unable to initialize "
   2855 					    "latin1 -> utf-16le "
   2856 					    "converstion descriptor: %s\n",
   2857 					    strerror(errno));
   2858 					attrlen -= sa->gssid->l * 2;
   2859 					goto gssid_done;
   2860 				}
   2861 				odst = dst;
   2862 				rv = iconv(cd, (__iconv_const char **)&src,
   2863 				    &srcleft, &dst, &dstleft);
   2864 				if (rv != 0) {
   2865 					if (rv == -1) {
   2866 						plog(LLV_ERROR, LOCATION, NULL,
   2867 						    "unable to convert GSS ID "
   2868 						    "from latin1 -> utf-16le: "
   2869 						    "%s\n", strerror(errno));
   2870 					} else {
   2871 						/* should never happen */
   2872 						plog(LLV_ERROR, LOCATION, NULL,
   2873 						    "%zd character%s in GSS ID "
   2874 						    "cannot be represented "
   2875 						    "in utf-16le\n",
   2876 						    rv, rv == 1 ? "" : "s");
   2877 					}
   2878 					(void) iconv_close(cd);
   2879 					attrlen -= sa->gssid->l * 2;
   2880 					goto gssid_done;
   2881 				}
   2882 				(void) iconv_close(cd);
   2883 
   2884 				/* XXX Check srcleft and dstleft? */
   2885 
   2886 				p = isakmp_set_attr_v(p, OAKLEY_ATTR_GSS_ID,
   2887 					odst, sa->gssid->l * 2);
   2888 
   2889 				racoon_free(odst);
   2890 			}
   2891 		}
   2892 	}
   2893  gssid_done:
   2894 #endif /* HAVE_GSSAPI */
   2895 
   2896 	return attrlen;
   2897 }
   2898 
   2899 static vchar_t *
   2900 setph2proposal0(iph2, pp, pr)
   2901 	const struct ph2handle *iph2;
   2902 	const struct saprop *pp;
   2903 	const struct saproto *pr;
   2904 {
   2905 	vchar_t *p;
   2906 	struct isakmp_pl_p *prop;
   2907 	struct isakmp_pl_t *trns;
   2908 	struct satrns *tr;
   2909 	int attrlen;
   2910 	size_t trnsoff;
   2911 	caddr_t x0, x;
   2912 	u_int8_t *np_t; /* pointer next trns type in previous header */
   2913 	const u_int8_t *spi;
   2914 #ifdef HAVE_SECCTX
   2915 	int truectxlen = 0;
   2916 #endif
   2917 
   2918 	p = vmalloc(sizeof(*prop) + sizeof(pr->spi));
   2919 	if (p == NULL)
   2920 		return NULL;
   2921 
   2922 	/* create proposal */
   2923 	prop = (struct isakmp_pl_p *)p->v;
   2924 	prop->h.np = ISAKMP_NPTYPE_NONE;
   2925 	prop->p_no = pp->prop_no;
   2926 	prop->proto_id = pr->proto_id;
   2927 	prop->num_t = 1;
   2928 
   2929 	spi = (const u_int8_t *)&pr->spi;
   2930 	switch (pr->proto_id) {
   2931 	case IPSECDOI_PROTO_IPCOMP:
   2932 		/*
   2933 		 * draft-shacham-ippcp-rfc2393bis-05.txt:
   2934 		 * construct 16bit SPI (CPI).
   2935 		 * XXX we may need to provide a configuration option to
   2936 		 * generate 32bit SPI.  otherwise we cannot interoeprate
   2937 		 * with nodes that uses 32bit SPI, in case we are initiator.
   2938 		 */
   2939 		prop->spi_size = sizeof(u_int16_t);
   2940 		spi += sizeof(pr->spi) - sizeof(u_int16_t);
   2941 		p->l -= sizeof(pr->spi);
   2942 		p->l += sizeof(u_int16_t);
   2943 		break;
   2944 	default:
   2945 		prop->spi_size = sizeof(pr->spi);
   2946 		break;
   2947 	}
   2948 	memcpy(prop + 1, spi, prop->spi_size);
   2949 
   2950 	/* create transform */
   2951 	trnsoff = sizeof(*prop) + prop->spi_size;
   2952 	np_t = NULL;
   2953 
   2954 	for (tr = pr->head; tr; tr = tr->next) {
   2955 
   2956 		switch (pr->proto_id) {
   2957 		case IPSECDOI_PROTO_IPSEC_ESP:
   2958 			/*
   2959 			 * don't build a null encryption
   2960 			 * with no authentication transform.
   2961 			 */
   2962 			if (tr->trns_id == IPSECDOI_ESP_NULL &&
   2963 			    tr->authtype == IPSECDOI_ATTR_AUTH_NONE)
   2964 				continue;
   2965 			break;
   2966 		}
   2967 
   2968 		if (np_t) {
   2969 			*np_t = ISAKMP_NPTYPE_T;
   2970 			prop->num_t++;
   2971 		}
   2972 
   2973 		/* get attribute length */
   2974 		attrlen = 0;
   2975 		if (pp->lifetime) {
   2976 			attrlen += sizeof(struct isakmp_data)
   2977 				+ sizeof(struct isakmp_data);
   2978 			if (pp->lifetime > 0xffff)
   2979 				attrlen += sizeof(u_int32_t);
   2980 		}
   2981 		if (pp->lifebyte && pp->lifebyte != IPSECDOI_ATTR_SA_LD_KB_MAX) {
   2982 			attrlen += sizeof(struct isakmp_data)
   2983 				+ sizeof(struct isakmp_data);
   2984 			if (pp->lifebyte > 0xffff)
   2985 				attrlen += sizeof(u_int32_t);
   2986 		}
   2987 		attrlen += sizeof(struct isakmp_data);	/* enc mode */
   2988 		if (tr->encklen)
   2989 			attrlen += sizeof(struct isakmp_data);
   2990 
   2991 		switch (pr->proto_id) {
   2992 		case IPSECDOI_PROTO_IPSEC_ESP:
   2993 			/* non authentication mode ? */
   2994 			if (tr->authtype != IPSECDOI_ATTR_AUTH_NONE)
   2995 				attrlen += sizeof(struct isakmp_data);
   2996 			break;
   2997 		case IPSECDOI_PROTO_IPSEC_AH:
   2998 			if (tr->authtype == IPSECDOI_ATTR_AUTH_NONE) {
   2999 				plog(LLV_ERROR, LOCATION, NULL,
   3000 					"no authentication algorithm found "
   3001 					"but protocol is AH.\n");
   3002 				vfree(p);
   3003 				return NULL;
   3004 			}
   3005 			attrlen += sizeof(struct isakmp_data);
   3006 			break;
   3007 		case IPSECDOI_PROTO_IPCOMP:
   3008 			break;
   3009 		default:
   3010 			plog(LLV_ERROR, LOCATION, NULL,
   3011 				"invalid protocol: %d\n", pr->proto_id);
   3012 			vfree(p);
   3013 			return NULL;
   3014 		}
   3015 
   3016 		if (alg_oakley_dhdef_ok(iph2->sainfo->pfs_group))
   3017 			attrlen += sizeof(struct isakmp_data);
   3018 
   3019 #ifdef HAVE_SECCTX
   3020 		/* ctx_str is defined as char ctx_str[MAX_CTXSTR_SIZ].
   3021 		 * The string may be smaller than MAX_CTXSTR_SIZ.
   3022 		 */
   3023 		if (*pp->sctx.ctx_str) {
   3024 			truectxlen = sizeof(struct security_ctx) -
   3025 				     (MAX_CTXSTR_SIZE - pp->sctx.ctx_strlen);
   3026 			attrlen += sizeof(struct isakmp_data) + truectxlen;
   3027 		}
   3028 #endif /* HAVE_SECCTX */
   3029 
   3030 		p = vrealloc(p, p->l + sizeof(*trns) + attrlen);
   3031 		if (p == NULL)
   3032 			return NULL;
   3033 		prop = (struct isakmp_pl_p *)p->v;
   3034 
   3035 		/* set transform's values */
   3036 		trns = (struct isakmp_pl_t *)(p->v + trnsoff);
   3037 		trns->h.np  = ISAKMP_NPTYPE_NONE;
   3038 		trns->t_no  = tr->trns_no;
   3039 		trns->t_id  = tr->trns_id;
   3040 
   3041 		/* set attributes */
   3042 		x = x0 = p->v + trnsoff + sizeof(*trns);
   3043 
   3044 		if (pp->lifetime) {
   3045 			x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD_TYPE,
   3046 						IPSECDOI_ATTR_SA_LD_TYPE_SEC);
   3047 			if (pp->lifetime > 0xffff) {
   3048 				u_int32_t v = htonl((u_int32_t)pp->lifetime);
   3049 				x = isakmp_set_attr_v(x, IPSECDOI_ATTR_SA_LD,
   3050 							(caddr_t)&v, sizeof(v));
   3051 			} else {
   3052 				x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD,
   3053 							pp->lifetime);
   3054 			}
   3055 		}
   3056 
   3057 		if (pp->lifebyte && pp->lifebyte != IPSECDOI_ATTR_SA_LD_KB_MAX) {
   3058 			x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD_TYPE,
   3059 						IPSECDOI_ATTR_SA_LD_TYPE_KB);
   3060 			if (pp->lifebyte > 0xffff) {
   3061 				u_int32_t v = htonl((u_int32_t)pp->lifebyte);
   3062 				x = isakmp_set_attr_v(x, IPSECDOI_ATTR_SA_LD,
   3063 							(caddr_t)&v, sizeof(v));
   3064 			} else {
   3065 				x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD,
   3066 							pp->lifebyte);
   3067 			}
   3068 		}
   3069 
   3070 		x = isakmp_set_attr_l(x, IPSECDOI_ATTR_ENC_MODE, pr->encmode);
   3071 
   3072 		if (tr->encklen)
   3073 			x = isakmp_set_attr_l(x, IPSECDOI_ATTR_KEY_LENGTH, tr->encklen);
   3074 
   3075 		/* mandatory check has done above. */
   3076 		if ((pr->proto_id == IPSECDOI_PROTO_IPSEC_ESP && tr->authtype != IPSECDOI_ATTR_AUTH_NONE)
   3077 		 || pr->proto_id == IPSECDOI_PROTO_IPSEC_AH)
   3078 			x = isakmp_set_attr_l(x, IPSECDOI_ATTR_AUTH, tr->authtype);
   3079 
   3080 		if (alg_oakley_dhdef_ok(iph2->sainfo->pfs_group))
   3081 			x = isakmp_set_attr_l(x, IPSECDOI_ATTR_GRP_DESC,
   3082 				iph2->sainfo->pfs_group);
   3083 
   3084 #ifdef HAVE_SECCTX
   3085 		if (*pp->sctx.ctx_str) {
   3086 			struct security_ctx secctx;
   3087 			secctx = pp->sctx;
   3088 			secctx.ctx_strlen = htons(pp->sctx.ctx_strlen);
   3089 			x = isakmp_set_attr_v(x, IPSECDOI_ATTR_SECCTX,
   3090 					     (caddr_t)&secctx, truectxlen);
   3091 		}
   3092 #endif
   3093 		/* update length of this transform. */
   3094 		trns = (struct isakmp_pl_t *)(p->v + trnsoff);
   3095 		trns->h.len = htons(sizeof(*trns) + attrlen);
   3096 
   3097 		/* save buffer to pre-next payload */
   3098 		np_t = &trns->h.np;
   3099 
   3100 		trnsoff += (sizeof(*trns) + attrlen);
   3101 	}
   3102 
   3103 	if (np_t == NULL) {
   3104 		plog(LLV_ERROR, LOCATION, NULL,
   3105 			"no suitable proposal was created.\n");
   3106 		return NULL;
   3107 	}
   3108 
   3109 	/* update length of this protocol. */
   3110 	prop->h.len = htons(p->l);
   3111 
   3112 	return p;
   3113 }
   3114 
   3115 /*
   3116  * create phase2 proposal from policy configuration.
   3117  * NOT INCLUDING isakmp general header of SA payload.
   3118  * This function is called by initiator only.
   3119  */
   3120 int
   3121 ipsecdoi_setph2proposal(iph2)
   3122 	struct ph2handle *iph2;
   3123 {
   3124 	struct saprop *proposal, *a;
   3125 	struct saproto *b = NULL;
   3126 	vchar_t *q;
   3127 	struct ipsecdoi_sa_b *sab;
   3128 	struct isakmp_pl_p *prop;
   3129 	size_t propoff;	/* for previous field of type of next payload. */
   3130 
   3131 	proposal = iph2->proposal;
   3132 
   3133 	iph2->sa = vmalloc(sizeof(*sab));
   3134 	if (iph2->sa == NULL) {
   3135 		plog(LLV_ERROR, LOCATION, NULL,
   3136 			"failed to allocate my sa buffer\n");
   3137 		return -1;
   3138 	}
   3139 
   3140 	/* create SA payload */
   3141 	sab = (struct ipsecdoi_sa_b *)iph2->sa->v;
   3142 	sab->doi = htonl(IPSEC_DOI);
   3143 	sab->sit = htonl(IPSECDOI_SIT_IDENTITY_ONLY);	/* XXX configurable ? */
   3144 
   3145 	prop = NULL;
   3146 	propoff = 0;
   3147 	for (a = proposal; a; a = a->next) {
   3148 		for (b = a->head; b; b = b->next) {
   3149 #ifdef ENABLE_NATT
   3150 			if (iph2->ph1->natt_flags & NAT_DETECTED) {
   3151 			  int udp_diff = iph2->ph1->natt_options->mode_udp_diff;
   3152 			  plog (LLV_INFO, LOCATION, NULL,
   3153 				"NAT detected -> UDP encapsulation "
   3154 				"(ENC_MODE %d->%d).\n",
   3155 				b->encmode,
   3156 				b->encmode+udp_diff);
   3157 			  /* Tunnel -> UDP-Tunnel, Transport -> UDP_Transport */
   3158 			  b->encmode += udp_diff;
   3159 			  b->udp_encap = 1;
   3160 			}
   3161 #endif
   3162 
   3163 			q = setph2proposal0(iph2, a, b);
   3164 			if (q == NULL) {
   3165 				VPTRINIT(iph2->sa);
   3166 				return -1;
   3167 			}
   3168 
   3169 			iph2->sa = vrealloc(iph2->sa, iph2->sa->l + q->l);
   3170 			if (iph2->sa == NULL) {
   3171 				plog(LLV_ERROR, LOCATION, NULL,
   3172 					"failed to allocate my sa buffer\n");
   3173 				if (q)
   3174 					vfree(q);
   3175 				return -1;
   3176 			}
   3177 			memcpy(iph2->sa->v + iph2->sa->l - q->l, q->v, q->l);
   3178 			if (propoff != 0) {
   3179 				prop = (struct isakmp_pl_p *)(iph2->sa->v +
   3180 					propoff);
   3181 				prop->h.np = ISAKMP_NPTYPE_P;
   3182 			}
   3183 			propoff = iph2->sa->l - q->l;
   3184 
   3185 			vfree(q);
   3186 		}
   3187 	}
   3188 
   3189 	return 0;
   3190 }
   3191 
   3192 /*
   3193  * return 1 if all of the given protocols are transport mode.
   3194  */
   3195 int
   3196 ipsecdoi_transportmode(pp)
   3197 	struct saprop *pp;
   3198 {
   3199 	struct saproto *pr = NULL;
   3200 
   3201 	for (; pp; pp = pp->next) {
   3202 		for (pr = pp->head; pr; pr = pr->next) {
   3203 			if (pr->encmode != IPSECDOI_ATTR_ENC_MODE_TRNS &&
   3204 			    pr->encmode != IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC &&
   3205 			    pr->encmode != IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT)
   3206 				return 0;
   3207 		}
   3208 	}
   3209 
   3210 	return 1;
   3211 }
   3212 
   3213 int
   3214 ipsecdoi_get_defaultlifetime()
   3215 {
   3216 	return IPSECDOI_ATTR_SA_LD_SEC_DEFAULT;
   3217 }
   3218 
   3219 int
   3220 ipsecdoi_checkalgtypes(proto_id, enc, auth, comp)
   3221 	int proto_id, enc, auth, comp;
   3222 {
   3223 #define TMPALGTYPE2STR(n) s_algtype(algclass_ipsec_##n, n)
   3224 	switch (proto_id) {
   3225 	case IPSECDOI_PROTO_IPSEC_ESP:
   3226 		if (enc == 0 || comp != 0) {
   3227 			plog(LLV_ERROR, LOCATION, NULL,
   3228 				"illegal algorithm defined "
   3229 				"ESP enc=%s auth=%s comp=%s.\n",
   3230 				TMPALGTYPE2STR(enc),
   3231 				TMPALGTYPE2STR(auth),
   3232 				TMPALGTYPE2STR(comp));
   3233 			return -1;
   3234 		}
   3235 		break;
   3236 	case IPSECDOI_PROTO_IPSEC_AH:
   3237 		if (enc != 0 || auth == 0 || comp != 0) {
   3238 			plog(LLV_ERROR, LOCATION, NULL,
   3239 				"illegal algorithm defined "
   3240 				"AH enc=%s auth=%s comp=%s.\n",
   3241 				TMPALGTYPE2STR(enc),
   3242 				TMPALGTYPE2STR(auth),
   3243 				TMPALGTYPE2STR(comp));
   3244 			return -1;
   3245 		}
   3246 		break;
   3247 	case IPSECDOI_PROTO_IPCOMP:
   3248 		if (enc != 0 || auth != 0 || comp == 0) {
   3249 			plog(LLV_ERROR, LOCATION, NULL,
   3250 				"illegal algorithm defined "
   3251 				"IPcomp enc=%s auth=%s comp=%s.\n",
   3252 				TMPALGTYPE2STR(enc),
   3253 				TMPALGTYPE2STR(auth),
   3254 				TMPALGTYPE2STR(comp));
   3255 			return -1;
   3256 		}
   3257 		break;
   3258 	default:
   3259 		plog(LLV_ERROR, LOCATION, NULL,
   3260 			"invalid ipsec protocol %d\n", proto_id);
   3261 		return -1;
   3262 	}
   3263 #undef TMPALGTYPE2STR
   3264 	return 0;
   3265 }
   3266 
   3267 int
   3268 ipproto2doi(proto)
   3269 	int proto;
   3270 {
   3271 	switch (proto) {
   3272 	case IPPROTO_AH:
   3273 		return IPSECDOI_PROTO_IPSEC_AH;
   3274 	case IPPROTO_ESP:
   3275 		return IPSECDOI_PROTO_IPSEC_ESP;
   3276 	case IPPROTO_IPCOMP:
   3277 		return IPSECDOI_PROTO_IPCOMP;
   3278 	}
   3279 	return -1;	/* XXX */
   3280 }
   3281 
   3282 int
   3283 doi2ipproto(proto)
   3284 	int proto;
   3285 {
   3286 	switch (proto) {
   3287 	case IPSECDOI_PROTO_IPSEC_AH:
   3288 		return IPPROTO_AH;
   3289 	case IPSECDOI_PROTO_IPSEC_ESP:
   3290 		return IPPROTO_ESP;
   3291 	case IPSECDOI_PROTO_IPCOMP:
   3292 		return IPPROTO_IPCOMP;
   3293 	}
   3294 	return -1;	/* XXX */
   3295 }
   3296 
   3297 /*
   3298  * Check if a subnet id is valid for comparison
   3299  * with an address id ( address length mask )
   3300  * and compare them
   3301  * Return value
   3302  * =  0 for match
   3303  * =  1 for mismatch
   3304  */
   3305 
   3306 int
   3307 ipsecdoi_subnetisaddr_v4( subnet, address )
   3308 	const vchar_t *subnet;
   3309 	const vchar_t *address;
   3310 {
   3311 	struct in_addr *mask;
   3312 
   3313 	if (address->l != sizeof(struct in_addr))
   3314 		return 1;
   3315 
   3316 	if (subnet->l != (sizeof(struct in_addr)*2))
   3317 		return 1;
   3318 
   3319 	mask = (struct in_addr*)(subnet->v + sizeof(struct in_addr));
   3320 
   3321 	if (mask->s_addr!=0xffffffff)
   3322 		return 1;
   3323 
   3324 	return memcmp(subnet->v,address->v,address->l);
   3325 }
   3326 
   3327 #ifdef INET6
   3328 
   3329 int
   3330 ipsecdoi_subnetisaddr_v6( subnet, address )
   3331 	const vchar_t *subnet;
   3332 	const vchar_t *address;
   3333 {
   3334 	struct in6_addr *mask;
   3335 	int i;
   3336 
   3337 	if (address->l != sizeof(struct in6_addr))
   3338 		return 1;
   3339 
   3340 	if (subnet->l != (sizeof(struct in6_addr)*2))
   3341 		return 1;
   3342 
   3343 	mask = (struct in6_addr*)(subnet->v + sizeof(struct in6_addr));
   3344 
   3345 	for (i=0; i<16; i++)
   3346 		if(mask->s6_addr[i]!=0xff)
   3347 			return 1;
   3348 
   3349 	return memcmp(subnet->v,address->v,address->l);
   3350 }
   3351 
   3352 #endif
   3353 
   3354 /*
   3355  * Check and Compare two IDs
   3356  * - specify 0 for exact if wildcards are allowed
   3357  * Return value
   3358  * =  0 for match
   3359  * =  1 for misatch
   3360  * = -1 for integrity error
   3361  */
   3362 
   3363 int
   3364 ipsecdoi_chkcmpids( idt, ids, exact )
   3365 	const vchar_t *idt; /* id cmp target */
   3366 	const vchar_t *ids; /* id cmp source */
   3367 	int exact;
   3368 {
   3369 	struct ipsecdoi_id_b *id_bt;
   3370 	struct ipsecdoi_id_b *id_bs;
   3371 	vchar_t ident_t;
   3372 	vchar_t ident_s;
   3373 	int result;
   3374 
   3375 	/* handle wildcard IDs */
   3376 
   3377 	if (idt == NULL || ids == NULL)
   3378 	{
   3379 		if( !exact )
   3380 		{
   3381 			plog(LLV_DEBUG, LOCATION, NULL,
   3382 				"check and compare ids : values matched (ANONYMOUS)\n" );
   3383 			return 0;
   3384 		}
   3385 		else
   3386 		{
   3387 			plog(LLV_DEBUG, LOCATION, NULL,
   3388 				"check and compare ids : value mismatch (ANONYMOUS)\n" );
   3389 			return -1;
   3390 		}
   3391 	}
   3392 
   3393 	/* make sure the ids are of the same type */
   3394 
   3395 	id_bt = (struct ipsecdoi_id_b *) idt->v;
   3396 	id_bs = (struct ipsecdoi_id_b *) ids->v;
   3397 
   3398 	ident_t.v = idt->v + sizeof(*id_bt);
   3399 	ident_t.l = idt->l - sizeof(*id_bt);
   3400 	ident_s.v = ids->v + sizeof(*id_bs);
   3401 	ident_s.l = ids->l - sizeof(*id_bs);
   3402 
   3403 	if (id_bs->type != id_bt->type)
   3404 	{
   3405 		/*
   3406 		 * special exception for comparing
   3407                  * address to subnet id types when
   3408                  * the netmask is address length
   3409                  */
   3410 
   3411 		if ((id_bs->type == IPSECDOI_ID_IPV4_ADDR)&&
   3412 		    (id_bt->type == IPSECDOI_ID_IPV4_ADDR_SUBNET)) {
   3413 			result = ipsecdoi_subnetisaddr_v4(&ident_t,&ident_s);
   3414 			goto cmpid_result;
   3415 		}
   3416 
   3417 		if ((id_bs->type == IPSECDOI_ID_IPV4_ADDR_SUBNET)&&
   3418 		    (id_bt->type == IPSECDOI_ID_IPV4_ADDR)) {
   3419 			result = ipsecdoi_subnetisaddr_v4(&ident_s,&ident_t);
   3420 			goto cmpid_result;
   3421 		}
   3422 
   3423 #ifdef INET6
   3424 		if ((id_bs->type == IPSECDOI_ID_IPV6_ADDR)&&
   3425 		    (id_bt->type == IPSECDOI_ID_IPV6_ADDR_SUBNET)) {
   3426 			result = ipsecdoi_subnetisaddr_v6(&ident_t,&ident_s);
   3427 			goto cmpid_result;
   3428 		}
   3429 
   3430 		if ((id_bs->type == IPSECDOI_ID_IPV6_ADDR_SUBNET)&&
   3431 		    (id_bt->type == IPSECDOI_ID_IPV6_ADDR)) {
   3432 			result = ipsecdoi_subnetisaddr_v6(&ident_s,&ident_t);
   3433 			goto cmpid_result;
   3434 		}
   3435 #endif
   3436 		plog(LLV_DEBUG, LOCATION, NULL,
   3437 			"check and compare ids : id type mismatch %s != %s\n",
   3438 			s_ipsecdoi_ident(id_bs->type),
   3439 			s_ipsecdoi_ident(id_bt->type));
   3440 
   3441 		return 1;
   3442 	}
   3443 
   3444 	if(id_bs->proto_id != id_bt->proto_id){
   3445 		plog(LLV_DEBUG, LOCATION, NULL,
   3446 			"check and compare ids : proto_id mismatch %d != %d\n",
   3447 			id_bs->proto_id, id_bt->proto_id);
   3448 
   3449 		return 1;
   3450 	}
   3451 
   3452 	/* compare the ID data. */
   3453 
   3454 	switch (id_bt->type) {
   3455 	        case IPSECDOI_ID_DER_ASN1_DN:
   3456         	case IPSECDOI_ID_DER_ASN1_GN:
   3457 			/* compare asn1 ids */
   3458 			result = eay_cmp_asn1dn(&ident_t, &ident_s);
   3459 			goto cmpid_result;
   3460 
   3461 		case IPSECDOI_ID_IPV4_ADDR:
   3462 			/* validate lengths */
   3463 			if ((ident_t.l != sizeof(struct in_addr))||
   3464 			    (ident_s.l != sizeof(struct in_addr)))
   3465 				goto cmpid_invalid;
   3466 			break;
   3467 
   3468 		case IPSECDOI_ID_IPV4_ADDR_SUBNET:
   3469 		case IPSECDOI_ID_IPV4_ADDR_RANGE:
   3470 			/* validate lengths */
   3471 			if ((ident_t.l != (sizeof(struct in_addr)*2))||
   3472 			    (ident_s.l != (sizeof(struct in_addr)*2)))
   3473 				goto cmpid_invalid;
   3474 			break;
   3475 
   3476 #ifdef INET6
   3477 		case IPSECDOI_ID_IPV6_ADDR:
   3478 			/* validate lengths */
   3479 			if ((ident_t.l != sizeof(struct in6_addr))||
   3480 			    (ident_s.l != sizeof(struct in6_addr)))
   3481 				goto cmpid_invalid;
   3482 			break;
   3483 
   3484 		case IPSECDOI_ID_IPV6_ADDR_SUBNET:
   3485 		case IPSECDOI_ID_IPV6_ADDR_RANGE:
   3486 			/* validate lengths */
   3487 			if ((ident_t.l != (sizeof(struct in6_addr)*2))||
   3488 			    (ident_s.l != (sizeof(struct in6_addr)*2)))
   3489 				goto cmpid_invalid;
   3490 			break;
   3491 #endif
   3492 		case IPSECDOI_ID_FQDN:
   3493 		case IPSECDOI_ID_USER_FQDN:
   3494 		case IPSECDOI_ID_KEY_ID:
   3495 			break;
   3496 
   3497 		default:
   3498 			plog(LLV_ERROR, LOCATION, NULL,
   3499 				"Unhandled id type %i specified for comparison\n",
   3500 				id_bt->type);
   3501 			return -1;
   3502 	}
   3503 
   3504 	/* validate matching data and length */
   3505 	if (ident_t.l == ident_s.l)
   3506 		result = memcmp(ident_t.v,ident_s.v,ident_t.l);
   3507 	else
   3508 		result = 1;
   3509 
   3510 cmpid_result:
   3511 
   3512 	/* debug level output */
   3513 	if(loglevel >= LLV_DEBUG) {
   3514 		char *idstrt = ipsecdoi_id2str(idt);
   3515 		char *idstrs = ipsecdoi_id2str(ids);
   3516 
   3517 		if (!result)
   3518 	 		plog(LLV_DEBUG, LOCATION, NULL,
   3519 				"check and compare ids : values matched (%s)\n",
   3520 				 s_ipsecdoi_ident(id_bs->type) );
   3521 		else
   3522  			plog(LLV_DEBUG, LOCATION, NULL,
   3523 				"check and compare ids : value mismatch (%s)\n",
   3524 				 s_ipsecdoi_ident(id_bs->type));
   3525 
   3526 		plog(LLV_DEBUG, LOCATION, NULL, "cmpid target: \'%s\'\n", idstrt );
   3527 		plog(LLV_DEBUG, LOCATION, NULL, "cmpid source: \'%s\'\n", idstrs );
   3528 
   3529 		racoon_free(idstrs);
   3530 		racoon_free(idstrt);
   3531 	}
   3532 
   3533 	/* return result */
   3534 	if( !result )
   3535 		return 0;
   3536 	else
   3537 		return 1;
   3538 
   3539 cmpid_invalid:
   3540 
   3541 	/* id integrity error */
   3542 	plog(LLV_DEBUG, LOCATION, NULL, "check and compare ids : %s integrity error\n",
   3543 		s_ipsecdoi_ident(id_bs->type));
   3544 	plog(LLV_DEBUG, LOCATION, NULL, "cmpid target: length = \'%zu\'\n", ident_t.l );
   3545 	plog(LLV_DEBUG, LOCATION, NULL, "cmpid source: length = \'%zu\'\n", ident_s.l );
   3546 
   3547 	return -1;
   3548 }
   3549 
   3550 /*
   3551  * check the following:
   3552  * - In main mode with pre-shared key, only address type can be used.
   3553  * - if proper type for phase 1 ?
   3554  * - if phase 1 ID payload conformed RFC2407 4.6.2.
   3555  *   (proto, port) must be (0, 0), (udp, 500) or (udp, [specified]).
   3556  * - if ID payload sent from peer is equal to the ID expected by me.
   3557  *
   3558  * both of "id" and "id_p" should be ID payload without general header,
   3559  */
   3560 int
   3561 ipsecdoi_checkid1(iph1)
   3562 	struct ph1handle *iph1;
   3563 {
   3564 	struct ipsecdoi_id_b *id_b;
   3565 
   3566 	if (iph1->id_p == NULL) {
   3567 		plog(LLV_ERROR, LOCATION, NULL,
   3568 			"invalid iph1 passed id_p == NULL\n");
   3569 		return ISAKMP_INTERNAL_ERROR;
   3570 	}
   3571 	if (iph1->id_p->l < sizeof(*id_b)) {
   3572 		plog(LLV_ERROR, LOCATION, NULL,
   3573 			"invalid value passed as \"ident\" (len=%lu)\n",
   3574 			(u_long)iph1->id_p->l);
   3575 		return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
   3576 	}
   3577 
   3578 	id_b = (struct ipsecdoi_id_b *)iph1->id_p->v;
   3579 
   3580 	/* In main mode with pre-shared key, only address type can be used. */
   3581 	if (iph1->etype == ISAKMP_ETYPE_IDENT &&
   3582 	    iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_PSKEY) {
   3583 		 if (id_b->type != IPSECDOI_ID_IPV4_ADDR
   3584 		  && id_b->type != IPSECDOI_ID_IPV6_ADDR) {
   3585 			plog(LLV_ERROR, LOCATION, NULL,
   3586 				"Expecting IP address type in main mode, "
   3587 				"but %s.\n", s_ipsecdoi_ident(id_b->type));
   3588 			return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
   3589 		}
   3590 	}
   3591 
   3592 	/* if proper type for phase 1 ? */
   3593 	switch (id_b->type) {
   3594 	case IPSECDOI_ID_IPV4_ADDR_SUBNET:
   3595 	case IPSECDOI_ID_IPV6_ADDR_SUBNET:
   3596 	case IPSECDOI_ID_IPV4_ADDR_RANGE:
   3597 	case IPSECDOI_ID_IPV6_ADDR_RANGE:
   3598 		plog(LLV_WARNING, LOCATION, NULL,
   3599 			"such ID type %s is not proper.\n",
   3600 			s_ipsecdoi_ident(id_b->type));
   3601 		/*FALLTHROUGH*/
   3602 	}
   3603 
   3604 	/* if phase 1 ID payload conformed RFC2407 4.6.2. */
   3605 	if (id_b->type == IPSECDOI_ID_IPV4_ADDR ||
   3606 	    id_b->type == IPSECDOI_ID_IPV6_ADDR) {
   3607 
   3608 		if (id_b->proto_id == 0 && ntohs(id_b->port) != 0) {
   3609 			plog(LLV_WARNING, LOCATION, NULL,
   3610 				"protocol ID and Port mismatched. "
   3611 				"proto_id:%d port:%d\n",
   3612 				id_b->proto_id, ntohs(id_b->port));
   3613 			/*FALLTHROUGH*/
   3614 
   3615 		} else if (id_b->proto_id == IPPROTO_UDP) {
   3616 			/*
   3617 			 * copmaring with expecting port.
   3618 			 * always permit if port is equal to PORT_ISAKMP
   3619 			 */
   3620 			if (ntohs(id_b->port) != PORT_ISAKMP) {
   3621 				u_int16_t port;
   3622 
   3623 				port = extract_port(iph1->remote);
   3624 				if (ntohs(id_b->port) != port) {
   3625 					plog(LLV_WARNING, LOCATION, NULL,
   3626 						"port %d expected, but %d\n",
   3627 						port, ntohs(id_b->port));
   3628 					/*FALLTHROUGH*/
   3629 				}
   3630 			}
   3631 		}
   3632 	}
   3633 
   3634 	/* resolve remote configuration if not done yet */
   3635 	if (resolveph1rmconf(iph1) < 0)
   3636 		return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
   3637 
   3638 	if (iph1->rmconf == NULL)
   3639 		return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
   3640 
   3641 	return 0;
   3642 }
   3643 
   3644 /*
   3645  * create ID payload for phase 1 and set into iph1->id.
   3646  * NOT INCLUDING isakmp general header.
   3647  * see, RFC2407 4.6.2.1
   3648  */
   3649 int
   3650 ipsecdoi_setid1(iph1)
   3651 	struct ph1handle *iph1;
   3652 {
   3653 	vchar_t *ret = NULL;
   3654 	struct ipsecdoi_id_b id_b;
   3655 	vchar_t *ident = NULL;
   3656 	struct sockaddr *ipid = NULL;
   3657 
   3658 	/* init */
   3659 	id_b.proto_id = 0;
   3660 	id_b.port = 0;
   3661 	ident = NULL;
   3662 
   3663 	switch (iph1->rmconf->idvtype) {
   3664 	case IDTYPE_FQDN:
   3665 		id_b.type = IPSECDOI_ID_FQDN;
   3666 		ident = vdup(iph1->rmconf->idv);
   3667 		break;
   3668 	case IDTYPE_USERFQDN:
   3669 		id_b.type = IPSECDOI_ID_USER_FQDN;
   3670 		ident = vdup(iph1->rmconf->idv);
   3671 		break;
   3672 	case IDTYPE_KEYID:
   3673 		id_b.type = IPSECDOI_ID_KEY_ID;
   3674 		ident = vdup(iph1->rmconf->idv);
   3675 		break;
   3676 	case IDTYPE_ASN1DN:
   3677 		id_b.type = IPSECDOI_ID_DER_ASN1_DN;
   3678 		if (iph1->rmconf->idv) {
   3679 			/* XXX it must be encoded to asn1dn. */
   3680 			ident = vdup(iph1->rmconf->idv);
   3681 		} else {
   3682 			if (oakley_getmycert(iph1) < 0) {
   3683 				plog(LLV_ERROR, LOCATION, NULL,
   3684 					"failed to get own CERT.\n");
   3685 				goto err;
   3686 			}
   3687 			ident = eay_get_x509asn1subjectname(iph1->cert);
   3688 		}
   3689 		break;
   3690 	case IDTYPE_ADDRESS:
   3691 		/*
   3692 		 * if the value of the id type was set by the configuration
   3693 		 * file, then use it.  otherwise the value is get from local
   3694 		 * ip address by using ike negotiation.
   3695 		 */
   3696 		if (iph1->rmconf->idv)
   3697 			ipid = (struct sockaddr *)iph1->rmconf->idv->v;
   3698 		/*FALLTHROUGH*/
   3699 	default:
   3700 	    {
   3701 		int l;
   3702 		caddr_t p;
   3703 
   3704 		if (ipid == NULL)
   3705 			ipid = iph1->local;
   3706 
   3707 		/* use IP address */
   3708 		switch (ipid->sa_family) {
   3709 		case AF_INET:
   3710 			id_b.type = IPSECDOI_ID_IPV4_ADDR;
   3711 			l = sizeof(struct in_addr);
   3712 			p = (caddr_t)&((struct sockaddr_in *)ipid)->sin_addr;
   3713 			break;
   3714 #ifdef INET6
   3715 		case AF_INET6:
   3716 			id_b.type = IPSECDOI_ID_IPV6_ADDR;
   3717 			l = sizeof(struct in6_addr);
   3718 			p = (caddr_t)&((struct sockaddr_in6 *)ipid)->sin6_addr;
   3719 			break;
   3720 #endif
   3721 		default:
   3722 			plog(LLV_ERROR, LOCATION, NULL,
   3723 				"invalid address family.\n");
   3724 			goto err;
   3725 		}
   3726 		id_b.proto_id = IPPROTO_UDP;
   3727 		id_b.port = htons(PORT_ISAKMP);
   3728 		ident = vmalloc(l);
   3729 		if (!ident) {
   3730 			plog(LLV_ERROR, LOCATION, NULL,
   3731 				"failed to get ID buffer.\n");
   3732 			return -1;
   3733 		}
   3734 		memcpy(ident->v, p, ident->l);
   3735 	    }
   3736 	}
   3737 	if (!ident) {
   3738 		plog(LLV_ERROR, LOCATION, NULL,
   3739 			"failed to get ID buffer.\n");
   3740 		return -1;
   3741 	}
   3742 
   3743 	ret = vmalloc(sizeof(id_b) + ident->l);
   3744 	if (ret == NULL) {
   3745 		plog(LLV_ERROR, LOCATION, NULL,
   3746 			"failed to get ID buffer.\n");
   3747 		goto err;
   3748 	}
   3749 
   3750 	memcpy(ret->v, &id_b, sizeof(id_b));
   3751 	memcpy(ret->v + sizeof(id_b), ident->v, ident->l);
   3752 
   3753 	iph1->id = ret;
   3754 
   3755 	plog(LLV_DEBUG, LOCATION, NULL,
   3756 		"use ID type of %s\n", s_ipsecdoi_ident(id_b.type));
   3757 	if (ident)
   3758 		vfree(ident);
   3759 	return 0;
   3760 
   3761 err:
   3762 	if (ident)
   3763 		vfree(ident);
   3764 	plog(LLV_ERROR, LOCATION, NULL, "failed get my ID\n");
   3765 	return -1;
   3766 }
   3767 
   3768 /* it's only called by cfparse.y. */
   3769 int
   3770 set_identifier(vpp, type, value)
   3771 	vchar_t **vpp, *value;
   3772 	int type;
   3773 {
   3774 	return set_identifier_qual(vpp, type, value, IDQUAL_UNSPEC);
   3775 }
   3776 
   3777 int
   3778 set_identifier_qual(vpp, type, value, qual)
   3779 	vchar_t **vpp, *value;
   3780 	int type;
   3781 	int qual;
   3782 {
   3783 	vchar_t *new = NULL;
   3784 
   3785 	/* simply return if value is null. */
   3786 	if (!value){
   3787 		if( type == IDTYPE_FQDN || type == IDTYPE_USERFQDN){
   3788 			plog(LLV_ERROR, LOCATION, NULL,
   3789 				 "No %s\n", type == IDTYPE_FQDN ? "fqdn":"user fqdn");
   3790 			return -1;
   3791 		}
   3792 		return 0;
   3793 	}
   3794 
   3795 	switch (type) {
   3796 	case IDTYPE_FQDN:
   3797 	case IDTYPE_USERFQDN:
   3798 		if(value->l <= 1){
   3799 			plog(LLV_ERROR, LOCATION, NULL,
   3800 				 "Empty %s\n", type == IDTYPE_FQDN ? "fqdn":"user fqdn");
   3801 			return -1;
   3802 		}
   3803 		/* length is adjusted since QUOTEDSTRING teminates NULL. */
   3804 		new = vmalloc(value->l - 1);
   3805 		if (new == NULL)
   3806 			return -1;
   3807 		memcpy(new->v, value->v, new->l);
   3808 		break;
   3809 	case IDTYPE_KEYID:
   3810 		/*
   3811 		 * If no qualifier is specified: IDQUAL_UNSPEC. It means
   3812 		 * to use a file for backward compatibility sake.
   3813 		 */
   3814 		switch(qual) {
   3815 		case IDQUAL_FILE:
   3816 		case IDQUAL_UNSPEC: {
   3817 			FILE *fp;
   3818 			char b[512];
   3819 			int tlen, len;
   3820 
   3821 			fp = fopen(value->v, "r");
   3822 			if (fp == NULL) {
   3823 				plog(LLV_ERROR, LOCATION, NULL,
   3824 					"can not open %s\n", value->v);
   3825 				return -1;
   3826 			}
   3827 			tlen = 0;
   3828 			while ((len = fread(b, 1, sizeof(b), fp)) != 0) {
   3829 				new = vrealloc(new, tlen + len);
   3830 				if (!new) {
   3831 					fclose(fp);
   3832 					return -1;
   3833 				}
   3834 				memcpy(new->v + tlen, b, len);
   3835 				tlen += len;
   3836 			}
   3837 			fclose(fp);
   3838 			break;
   3839 		}
   3840 
   3841 		case IDQUAL_TAG:
   3842 			new = vmalloc(value->l - 1);
   3843 			if (new == NULL) {
   3844 				plog(LLV_ERROR, LOCATION, NULL,
   3845 					"can not allocate memory");
   3846 				return -1;
   3847 			}
   3848 			memcpy(new->v, value->v, new->l);
   3849 			break;
   3850 
   3851 		default:
   3852 			plog(LLV_ERROR, LOCATION, NULL,
   3853 				"unknown qualifier");
   3854 			return -1;
   3855 		}
   3856 		break;
   3857 
   3858 	case IDTYPE_ADDRESS: {
   3859 		struct sockaddr *sa;
   3860 
   3861 		/* length is adjusted since QUOTEDSTRING teminates NULL. */
   3862 		if (value->l == 0)
   3863 			break;
   3864 
   3865 		sa = str2saddr(value->v, NULL);
   3866 		if (sa == NULL) {
   3867 			plog(LLV_ERROR, LOCATION, NULL,
   3868 				"invalid ip address %s\n", value->v);
   3869 			return -1;
   3870 		}
   3871 
   3872 		new = vmalloc(sysdep_sa_len(sa));
   3873 		if (new == NULL) {
   3874 			racoon_free(sa);
   3875 			return -1;
   3876 		}
   3877 		memcpy(new->v, sa, new->l);
   3878 		racoon_free(sa);
   3879 		break;
   3880 	}
   3881 	case IDTYPE_ASN1DN:
   3882 		if (value->v[0] == '~')
   3883 			/* Hex-encoded ASN1 strings */
   3884 			new = eay_hex2asn1dn(value->v + 1, - 1);
   3885 		else
   3886 			/* DN encoded strings */
   3887 			new = eay_str2asn1dn(value->v, value->l - 1);
   3888 
   3889 		if (new == NULL)
   3890 			return -1;
   3891 
   3892 		if (loglevel >= LLV_DEBUG) {
   3893 			X509_NAME *xn;
   3894 			BIO *bio;
   3895 			unsigned char *ptr = (unsigned char *) new->v, *buf;
   3896 			size_t len;
   3897 			char save;
   3898 
   3899 			xn = d2i_X509_NAME(NULL, (void *)&ptr, new->l);
   3900 			bio = BIO_new(BIO_s_mem());
   3901 
   3902 			X509_NAME_print_ex(bio, xn, 0, 0);
   3903 			len = BIO_get_mem_data(bio, &ptr);
   3904 			save = ptr[len];
   3905 			ptr[len] = 0;
   3906 			plog(LLV_DEBUG, LOCATION, NULL, "Parsed DN: %s\n", ptr);
   3907 			ptr[len] = save;
   3908 			X509_NAME_free(xn);
   3909 			BIO_free(bio);
   3910 		}
   3911 
   3912 		break;
   3913 	}
   3914 
   3915 	*vpp = new;
   3916 
   3917 	return 0;
   3918 }
   3919 
   3920 /*
   3921  * create ID payload for phase 2, and set into iph2->id and id_p.  There are
   3922  * NOT INCLUDING isakmp general header.
   3923  * this function is for initiator.  responder will get to copy from payload.
   3924  * responder ID type is always address type.
   3925  * see, RFC2407 4.6.2.1
   3926  */
   3927 int
   3928 ipsecdoi_setid2(iph2)
   3929 	struct ph2handle *iph2;
   3930 {
   3931 	struct secpolicy *sp;
   3932 
   3933 	/* check there is phase 2 handler ? */
   3934 	sp = getspbyspid(iph2->spid);
   3935 	if (sp == NULL) {
   3936 		plog(LLV_ERROR, LOCATION, NULL,
   3937 			"no policy found for spid:%u.\n", iph2->spid);
   3938 		return -1;
   3939 	}
   3940 
   3941 	if (!ipsecdoi_transportmode(iph2->proposal))
   3942 		iph2->id = ipsecdoi_sockaddr2id((struct sockaddr *)&sp->spidx.src,
   3943 				sp->spidx.prefs, sp->spidx.ul_proto);
   3944 	else if (iph2->sa_src != NULL) {
   3945 		/* He have a specific hint indicating that the transport
   3946 		 * mode SA will be negotiated using addresses that differ
   3947 		 * with the one from the SA. We need to indicate that to
   3948 		 * our peer by setting the SA address as ID.
   3949 		 * This is typically the case for the bootstrapping of the
   3950 		 * transport mode SA protecting BU/BA for MIPv6 traffic
   3951 		 *
   3952 		 * --arno*/
   3953 		iph2->id = ipsecdoi_sockaddr2id(iph2->sa_src,
   3954 						IPSECDOI_PREFIX_HOST,
   3955 						sp->spidx.ul_proto);
   3956 	} else
   3957 		iph2->id = ipsecdoi_sockaddr2id(iph2->src, IPSECDOI_PREFIX_HOST,
   3958 						sp->spidx.ul_proto);
   3959 
   3960 	if (iph2->id == NULL) {
   3961 		plog(LLV_ERROR, LOCATION, NULL,
   3962 			"failed to get ID for %s\n",
   3963 			spidx2str(&sp->spidx));
   3964 		return -1;
   3965 	}
   3966 	plog(LLV_DEBUG, LOCATION, NULL, "use local ID type %s\n",
   3967 		s_ipsecdoi_ident(((struct ipsecdoi_id_b *)iph2->id->v)->type));
   3968 
   3969 	/* remote side */
   3970 #ifdef ANDROID_PATCHED
   3971 	if (1)
   3972 #else
   3973 	if (!ipsecdoi_transportmode(iph2->proposal))
   3974 #endif
   3975 		iph2->id_p = ipsecdoi_sockaddr2id((struct sockaddr *)&sp->spidx.dst,
   3976 				sp->spidx.prefd, sp->spidx.ul_proto);
   3977 	else if (iph2->sa_dst != NULL) {
   3978 		/* See comment above for local side. */
   3979 		iph2->id_p = ipsecdoi_sockaddr2id(iph2->sa_dst,
   3980 						  IPSECDOI_PREFIX_HOST,
   3981 						  sp->spidx.ul_proto);
   3982 	} else
   3983 		iph2->id_p = ipsecdoi_sockaddr2id(iph2->dst, IPSECDOI_PREFIX_HOST,
   3984 			sp->spidx.ul_proto);
   3985 
   3986 	if (iph2->id_p == NULL) {
   3987 		plog(LLV_ERROR, LOCATION, NULL,
   3988 			"failed to get ID for %s\n",
   3989 			spidx2str(&sp->spidx));
   3990 		VPTRINIT(iph2->id);
   3991 		return -1;
   3992 	}
   3993 	plog(LLV_DEBUG, LOCATION, NULL,
   3994 		"use remote ID type %s\n",
   3995 		s_ipsecdoi_ident(((struct ipsecdoi_id_b *)iph2->id_p->v)->type));
   3996 
   3997 	return 0;
   3998 }
   3999 
   4000 /*
   4001  * set address type of ID.
   4002  * NOT INCLUDING general header.
   4003  */
   4004 vchar_t *
   4005 ipsecdoi_sockaddr2id(saddr, prefixlen, ul_proto)
   4006 	struct sockaddr *saddr;
   4007 	u_int prefixlen;
   4008 	u_int ul_proto;
   4009 {
   4010 	vchar_t *new;
   4011 	int type, len1, len2;
   4012 	caddr_t sa;
   4013 	u_short port;
   4014 
   4015 	/*
   4016 	 * Q. When type is SUBNET, is it allowed to be ::1/128.
   4017 	 * A. Yes. (consensus at bake-off)
   4018 	 */
   4019 	switch (saddr->sa_family) {
   4020 	case AF_INET:
   4021 		len1 = sizeof(struct in_addr);
   4022 		if (prefixlen >= (sizeof(struct in_addr) << 3)) {
   4023 			type = IPSECDOI_ID_IPV4_ADDR;
   4024 			len2 = 0;
   4025 		} else {
   4026 			type = IPSECDOI_ID_IPV4_ADDR_SUBNET;
   4027 			len2 = sizeof(struct in_addr);
   4028 		}
   4029 		sa = (caddr_t)&((struct sockaddr_in *)(saddr))->sin_addr;
   4030 		port = ((struct sockaddr_in *)(saddr))->sin_port;
   4031 		break;
   4032 #ifdef INET6
   4033 	case AF_INET6:
   4034 		len1 = sizeof(struct in6_addr);
   4035 		if (prefixlen >= (sizeof(struct in6_addr) << 3)) {
   4036 			type = IPSECDOI_ID_IPV6_ADDR;
   4037 			len2 = 0;
   4038 		} else {
   4039 			type = IPSECDOI_ID_IPV6_ADDR_SUBNET;
   4040 			len2 = sizeof(struct in6_addr);
   4041 		}
   4042 		sa = (caddr_t)&((struct sockaddr_in6 *)(saddr))->sin6_addr;
   4043 		port = ((struct sockaddr_in6 *)(saddr))->sin6_port;
   4044 		break;
   4045 #endif
   4046 	default:
   4047 		plog(LLV_ERROR, LOCATION, NULL,
   4048 			"invalid family: %d.\n", saddr->sa_family);
   4049 		return NULL;
   4050 	}
   4051 
   4052 	/* get ID buffer */
   4053 	new = vmalloc(sizeof(struct ipsecdoi_id_b) + len1 + len2);
   4054 	if (new == NULL) {
   4055 		plog(LLV_ERROR, LOCATION, NULL,
   4056 			"failed to get ID buffer.\n");
   4057 		return NULL;
   4058 	}
   4059 
   4060 	memset(new->v, 0, new->l);
   4061 
   4062 	/* set the part of header. */
   4063 	((struct ipsecdoi_id_b *)new->v)->type = type;
   4064 
   4065 	/* set ul_proto and port */
   4066 	/*
   4067 	 * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card
   4068 	 * because 0 means port number of 0.  Instead of 0, we use IPSEC_*_ANY.
   4069 	 */
   4070 	((struct ipsecdoi_id_b *)new->v)->proto_id =
   4071 		ul_proto == IPSEC_ULPROTO_ANY ? 0 : ul_proto;
   4072 	((struct ipsecdoi_id_b *)new->v)->port =
   4073 		port == IPSEC_PORT_ANY ? 0 : port;
   4074 	memcpy(new->v + sizeof(struct ipsecdoi_id_b), sa, len1);
   4075 
   4076 	/* set address */
   4077 
   4078 	/* set prefix */
   4079 	if (len2) {
   4080 		u_char *p = (unsigned char *) new->v +
   4081 			sizeof(struct ipsecdoi_id_b) + len1;
   4082 		u_int bits = prefixlen;
   4083 
   4084 		while (bits >= 8) {
   4085 			*p++ = 0xff;
   4086 			bits -= 8;
   4087 		}
   4088 
   4089 		if (bits > 0)
   4090 			*p = ~((1 << (8 - bits)) - 1);
   4091 	}
   4092 
   4093 	return new;
   4094 }
   4095 
   4096 vchar_t *
   4097 ipsecdoi_sockrange2id(laddr, haddr, ul_proto)
   4098 	struct sockaddr *laddr, *haddr;
   4099 	u_int ul_proto;
   4100 {
   4101 	vchar_t *new;
   4102 	int type, len1, len2;
   4103 	u_short port;
   4104 
   4105 	if (laddr->sa_family != haddr->sa_family) {
   4106 	    plog(LLV_ERROR, LOCATION, NULL, "Address family mismatch\n");
   4107 	    return NULL;
   4108 	}
   4109 
   4110 	switch (laddr->sa_family) {
   4111 	case AF_INET:
   4112 	    type = IPSECDOI_ID_IPV4_ADDR_RANGE;
   4113 	    len1 = sizeof(struct in_addr);
   4114 	    len2 = sizeof(struct in_addr);
   4115 	    break;
   4116 #ifdef INET6
   4117 	case AF_INET6:
   4118 		type = IPSECDOI_ID_IPV6_ADDR_RANGE;
   4119 		len1 = sizeof(struct in6_addr);
   4120 		len2 = sizeof(struct in6_addr);
   4121 		break;
   4122 #endif
   4123 	default:
   4124 		plog(LLV_ERROR, LOCATION, NULL,
   4125 			"invalid family: %d.\n", laddr->sa_family);
   4126 		return NULL;
   4127 	}
   4128 
   4129 	/* get ID buffer */
   4130 	new = vmalloc(sizeof(struct ipsecdoi_id_b) + len1 + len2);
   4131 	if (new == NULL) {
   4132 		plog(LLV_ERROR, LOCATION, NULL,
   4133 			"failed to get ID buffer.\n");
   4134 		return NULL;
   4135 	}
   4136 
   4137 	memset(new->v, 0, new->l);
   4138 	/* set the part of header. */
   4139 	((struct ipsecdoi_id_b *)new->v)->type = type;
   4140 
   4141 	/* set ul_proto and port */
   4142 	/*
   4143 	 * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card
   4144 	 * because 0 means port number of 0.  Instead of 0, we use IPSEC_*_ANY.
   4145 	 */
   4146 	((struct ipsecdoi_id_b *)new->v)->proto_id =
   4147 		ul_proto == IPSEC_ULPROTO_ANY ? 0 : ul_proto;
   4148 	port = ((struct sockaddr_in *)(laddr))->sin_port;
   4149 	((struct ipsecdoi_id_b *)new->v)->port =
   4150 		port == IPSEC_PORT_ANY ? 0 : port;
   4151 	memcpy(new->v + sizeof(struct ipsecdoi_id_b),
   4152 	       (caddr_t)&((struct sockaddr_in *)(laddr))->sin_addr,
   4153 	       len1);
   4154 	memcpy(new->v + sizeof(struct ipsecdoi_id_b) + len1,
   4155 	       (caddr_t)&((struct sockaddr_in *)haddr)->sin_addr,
   4156 	       len2);
   4157 	return new;
   4158 }
   4159 
   4160 
   4161 /*
   4162  * create sockaddr structure from ID payload (buf).
   4163  * buffers (saddr, prefixlen, ul_proto) must be allocated.
   4164  * see, RFC2407 4.6.2.1
   4165  */
   4166 int
   4167 ipsecdoi_id2sockaddr(buf, saddr, prefixlen, ul_proto)
   4168 	vchar_t *buf;
   4169 	struct sockaddr *saddr;
   4170 	u_int8_t *prefixlen;
   4171 	u_int16_t *ul_proto;
   4172 {
   4173 	struct ipsecdoi_id_b *id_b = NULL;
   4174 	u_int plen = 0;
   4175 
   4176 	if (buf == NULL)
   4177 		return ISAKMP_INTERNAL_ERROR;
   4178 
   4179 	id_b = (struct ipsecdoi_id_b *)buf->v;
   4180 
   4181 	/*
   4182 	 * When a ID payload of subnet type with a IP address of full bit
   4183 	 * masked, it has to be processed as host address.
   4184 	 * e.g. below 2 type are same.
   4185 	 *      type = ipv6 subnet, data = 2001::1/128
   4186 	 *      type = ipv6 address, data = 2001::1
   4187 	 */
   4188 	switch (id_b->type) {
   4189 	case IPSECDOI_ID_IPV4_ADDR:
   4190 	case IPSECDOI_ID_IPV4_ADDR_SUBNET:
   4191 #ifndef __linux__
   4192 		saddr->sa_len = sizeof(struct sockaddr_in);
   4193 #endif
   4194 		saddr->sa_family = AF_INET;
   4195 		((struct sockaddr_in *)saddr)->sin_port =
   4196 			(id_b->port == 0
   4197 				? IPSEC_PORT_ANY
   4198 				: id_b->port);		/* see sockaddr2id() */
   4199 		memcpy(&((struct sockaddr_in *)saddr)->sin_addr,
   4200 			buf->v + sizeof(*id_b), sizeof(struct in_addr));
   4201 		break;
   4202 #ifdef INET6
   4203 	case IPSECDOI_ID_IPV6_ADDR:
   4204 	case IPSECDOI_ID_IPV6_ADDR_SUBNET:
   4205 #ifndef __linux__
   4206 		saddr->sa_len = sizeof(struct sockaddr_in6);
   4207 #endif
   4208 		saddr->sa_family = AF_INET6;
   4209 		((struct sockaddr_in6 *)saddr)->sin6_port =
   4210 			(id_b->port == 0
   4211 				? IPSEC_PORT_ANY
   4212 				: id_b->port);		/* see sockaddr2id() */
   4213 		memcpy(&((struct sockaddr_in6 *)saddr)->sin6_addr,
   4214 			buf->v + sizeof(*id_b), sizeof(struct in6_addr));
   4215 		((struct sockaddr_in6 *)saddr)->sin6_scope_id =
   4216 			(IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)saddr)->sin6_addr)
   4217 				? ((struct sockaddr_in6 *)id_b)->sin6_scope_id
   4218 				: 0);
   4219 
   4220 		break;
   4221 #endif
   4222 	default:
   4223 		plog(LLV_ERROR, LOCATION, NULL,
   4224 			"unsupported ID type %d\n", id_b->type);
   4225 		return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
   4226 	}
   4227 
   4228 	/* get prefix length */
   4229 	switch (id_b->type) {
   4230 	case IPSECDOI_ID_IPV4_ADDR:
   4231 		plen = sizeof(struct in_addr) << 3;
   4232 		break;
   4233 #ifdef INET6
   4234 	case IPSECDOI_ID_IPV6_ADDR:
   4235 		plen = sizeof(struct in6_addr) << 3;
   4236 		break;
   4237 #endif
   4238 	case IPSECDOI_ID_IPV4_ADDR_SUBNET:
   4239 #ifdef INET6
   4240 	case IPSECDOI_ID_IPV6_ADDR_SUBNET:
   4241 #endif
   4242 	    {
   4243 		u_char *p;
   4244 		u_int max;
   4245 		int alen = sizeof(struct in_addr);
   4246 
   4247 		switch (id_b->type) {
   4248 		case IPSECDOI_ID_IPV4_ADDR_SUBNET:
   4249 			alen = sizeof(struct in_addr);
   4250 			break;
   4251 #ifdef INET6
   4252 		case IPSECDOI_ID_IPV6_ADDR_SUBNET:
   4253 			alen = sizeof(struct in6_addr);
   4254 			break;
   4255 #endif
   4256 		}
   4257 
   4258 		/* sanity check */
   4259 		if (buf->l < alen)
   4260 			return ISAKMP_INTERNAL_ERROR;
   4261 
   4262 		/* get subnet mask length */
   4263 		plen = 0;
   4264 		max = alen <<3;
   4265 
   4266 		p = (unsigned char *) buf->v
   4267 			+ sizeof(struct ipsecdoi_id_b)
   4268 			+ alen;
   4269 
   4270 		for (; *p == 0xff; p++) {
   4271 			plen += 8;
   4272 			if (plen >= max)
   4273 				break;
   4274 		}
   4275 
   4276 		if (plen < max) {
   4277 			u_int l = 0;
   4278 			u_char b = ~(*p);
   4279 
   4280 			while (b) {
   4281 				b >>= 1;
   4282 				l++;
   4283 			}
   4284 
   4285 			l = 8 - l;
   4286 			plen += l;
   4287 		}
   4288 	    }
   4289 		break;
   4290 	}
   4291 
   4292 	*prefixlen = plen;
   4293 	*ul_proto = id_b->proto_id == 0
   4294 				? IPSEC_ULPROTO_ANY
   4295 				: id_b->proto_id;	/* see sockaddr2id() */
   4296 
   4297 	return 0;
   4298 }
   4299 
   4300 /*
   4301  * make printable string from ID payload except of general header.
   4302  */
   4303 char *
   4304 ipsecdoi_id2str(id)
   4305 	const vchar_t *id;
   4306 {
   4307 #define BUFLEN 512
   4308 	char * ret = NULL;
   4309 	int len = 0;
   4310 	char *dat;
   4311 	static char buf[BUFLEN];
   4312 	struct ipsecdoi_id_b *id_b = (struct ipsecdoi_id_b *)id->v;
   4313 	union sockaddr_any saddr;
   4314 	u_int plen = 0;
   4315 
   4316 	switch (id_b->type) {
   4317 	case IPSECDOI_ID_IPV4_ADDR:
   4318 	case IPSECDOI_ID_IPV4_ADDR_SUBNET:
   4319 	case IPSECDOI_ID_IPV4_ADDR_RANGE:
   4320 
   4321 #ifndef __linux__
   4322 		saddr.sa.sa_len = sizeof(struct sockaddr_in);
   4323 #endif
   4324 		saddr.sa.sa_family = AF_INET;
   4325 		saddr.sin.sin_port = IPSEC_PORT_ANY;
   4326 		memcpy(&saddr.sin.sin_addr,
   4327 			id->v + sizeof(*id_b), sizeof(struct in_addr));
   4328 		break;
   4329 #ifdef INET6
   4330 	case IPSECDOI_ID_IPV6_ADDR:
   4331 	case IPSECDOI_ID_IPV6_ADDR_SUBNET:
   4332 	case IPSECDOI_ID_IPV6_ADDR_RANGE:
   4333 
   4334 #ifndef __linux__
   4335 		saddr.sa.sa_len = sizeof(struct sockaddr_in6);
   4336 #endif
   4337 		saddr.sa.sa_family = AF_INET6;
   4338 		saddr.sin6.sin6_port = IPSEC_PORT_ANY;
   4339 		memcpy(&saddr.sin6.sin6_addr,
   4340 			id->v + sizeof(*id_b), sizeof(struct in6_addr));
   4341 		saddr.sin6.sin6_scope_id =
   4342 			(IN6_IS_ADDR_LINKLOCAL(&saddr.sin6.sin6_addr)
   4343 				? ((struct sockaddr_in6 *)id_b)->sin6_scope_id
   4344 				: 0);
   4345 		break;
   4346 #endif
   4347 	}
   4348 
   4349 	switch (id_b->type) {
   4350 	case IPSECDOI_ID_IPV4_ADDR:
   4351 #ifdef INET6
   4352 	case IPSECDOI_ID_IPV6_ADDR:
   4353 #endif
   4354 		len = snprintf( buf, BUFLEN, "%s", saddrwop2str(&saddr.sa));
   4355 		break;
   4356 
   4357 	case IPSECDOI_ID_IPV4_ADDR_SUBNET:
   4358 #ifdef INET6
   4359 	case IPSECDOI_ID_IPV6_ADDR_SUBNET:
   4360 #endif
   4361 	    {
   4362 		u_char *p;
   4363 		u_int max;
   4364 		int alen = sizeof(struct in_addr);
   4365 
   4366 		switch (id_b->type) {
   4367 		case IPSECDOI_ID_IPV4_ADDR_SUBNET:
   4368 			alen = sizeof(struct in_addr);
   4369 			break;
   4370 #ifdef INET6
   4371 		case IPSECDOI_ID_IPV6_ADDR_SUBNET:
   4372 			alen = sizeof(struct in6_addr);
   4373 			break;
   4374 #endif
   4375 		}
   4376 
   4377 		/* sanity check */
   4378 		if (id->l < alen) {
   4379 			len = 0;
   4380 			break;
   4381 		}
   4382 
   4383 		/* get subnet mask length */
   4384 		plen = 0;
   4385 		max = alen <<3;
   4386 
   4387 		p = (unsigned char *) id->v
   4388 			+ sizeof(struct ipsecdoi_id_b)
   4389 			+ alen;
   4390 
   4391 		for (; *p == 0xff; p++) {
   4392 			plen += 8;
   4393 			if (plen >= max)
   4394 				break;
   4395 		}
   4396 
   4397 		if (plen < max) {
   4398 			u_int l = 0;
   4399 			u_char b = ~(*p);
   4400 
   4401 			while (b) {
   4402 				b >>= 1;
   4403 				l++;
   4404 			}
   4405 
   4406 			l = 8 - l;
   4407 			plen += l;
   4408 		}
   4409 
   4410 		len = snprintf( buf, BUFLEN, "%s/%i", saddrwop2str(&saddr.sa), plen);
   4411 	    }
   4412 		break;
   4413 
   4414 	case IPSECDOI_ID_IPV4_ADDR_RANGE:
   4415 
   4416 		len = snprintf( buf, BUFLEN, "%s-", saddrwop2str(&saddr.sa));
   4417 
   4418 #ifndef __linux__
   4419 		saddr.sa.sa_len = sizeof(struct sockaddr_in);
   4420 #endif
   4421 		saddr.sa.sa_family = AF_INET;
   4422 		saddr.sin.sin_port = IPSEC_PORT_ANY;
   4423 		memcpy(&saddr.sin.sin_addr,
   4424 			id->v + sizeof(*id_b) + sizeof(struct in_addr),
   4425 			sizeof(struct in_addr));
   4426 
   4427 		len += snprintf(buf + len, BUFLEN - len, "%s", saddrwop2str(&saddr.sa));
   4428 		break;
   4429 
   4430 #ifdef INET6
   4431 	case IPSECDOI_ID_IPV6_ADDR_RANGE:
   4432 		len = snprintf( buf, BUFLEN, "%s-", saddrwop2str(&saddr.sa));
   4433 
   4434 #ifndef __linux__
   4435 		saddr.sa.sa_len = sizeof(struct sockaddr_in6);
   4436 #endif
   4437 		saddr.sa.sa_family = AF_INET6;
   4438 		saddr.sin6.sin6_port = IPSEC_PORT_ANY;
   4439 		memcpy(&saddr.sin6.sin6_addr,
   4440 			id->v + sizeof(*id_b) + sizeof(struct in6_addr),
   4441 			sizeof(struct in6_addr));
   4442 		saddr.sin6.sin6_scope_id =
   4443 			(IN6_IS_ADDR_LINKLOCAL(&saddr.sin6.sin6_addr)
   4444 				? ((struct sockaddr_in6 *)id_b)->sin6_scope_id
   4445 				: 0);
   4446 
   4447 		len += snprintf(buf + len, BUFLEN - len, "%s", saddrwop2str(&saddr.sa));
   4448 		break;
   4449 #endif
   4450 
   4451 	case IPSECDOI_ID_FQDN:
   4452 	case IPSECDOI_ID_USER_FQDN:
   4453 		len = id->l - sizeof(*id_b);
   4454 		if (len > BUFLEN)
   4455 			len = BUFLEN;
   4456 		memcpy(buf, id->v + sizeof(*id_b), len);
   4457 		break;
   4458 
   4459 	case IPSECDOI_ID_DER_ASN1_DN:
   4460 	case IPSECDOI_ID_DER_ASN1_GN:
   4461 	{
   4462 		X509_NAME *xn = NULL;
   4463 
   4464 		dat = id->v + sizeof(*id_b);
   4465 		len = id->l - sizeof(*id_b);
   4466 
   4467 		if (d2i_X509_NAME(&xn, (void*) &dat, len) != NULL) {
   4468 			BIO *bio = BIO_new(BIO_s_mem());
   4469 			X509_NAME_print_ex(bio, xn, 0, 0);
   4470 			len = BIO_get_mem_data(bio, &dat);
   4471 			if (len > BUFLEN)
   4472 				len = BUFLEN;
   4473 			memcpy(buf,dat,len);
   4474 			BIO_free(bio);
   4475 			X509_NAME_free(xn);
   4476 		} else {
   4477 			plog(LLV_ERROR, LOCATION, NULL,
   4478 				"unable to extract asn1dn from id\n");
   4479 
   4480 			len = sprintf(buf, "<ASN1-DN>");
   4481 		}
   4482 
   4483 		break;
   4484 	}
   4485 
   4486 	/* currently unhandled id types */
   4487 	case IPSECDOI_ID_KEY_ID:
   4488 		len = sprintf( buf, "<KEY-ID>");
   4489 		break;
   4490 
   4491 	default:
   4492 		plog(LLV_ERROR, LOCATION, NULL,
   4493 			"unknown ID type %d\n", id_b->type);
   4494 	}
   4495 
   4496 	if (!len)
   4497 		len = sprintf( buf, "<?>");
   4498 
   4499 	ret = racoon_malloc(len+1);
   4500 	if (ret != NULL) {
   4501 		memcpy(ret,buf,len);
   4502 		ret[len]=0;
   4503 	}
   4504 
   4505 	return ret;
   4506 }
   4507 
   4508 /*
   4509  * set IPsec data attributes into a proposal.
   4510  * NOTE: MUST called per a transform.
   4511  */
   4512 int
   4513 ipsecdoi_t2satrns(t, pp, pr, tr)
   4514 	struct isakmp_pl_t *t;
   4515 	struct saprop *pp;
   4516 	struct saproto *pr;
   4517 	struct satrns *tr;
   4518 {
   4519 	struct isakmp_data *d, *prev;
   4520 	int flag, type;
   4521 	int error = -1;
   4522 	int life_t;
   4523 	int tlen;
   4524 
   4525 	tr->trns_no = t->t_no;
   4526 	tr->trns_id = t->t_id;
   4527 
   4528 	tlen = ntohs(t->h.len) - sizeof(*t);
   4529 	prev = (struct isakmp_data *)NULL;
   4530 	d = (struct isakmp_data *)(t + 1);
   4531 
   4532 	/* default */
   4533 	life_t = IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT;
   4534 	pp->lifetime = IPSECDOI_ATTR_SA_LD_SEC_DEFAULT;
   4535 	pp->lifebyte = 0;
   4536 	tr->authtype = IPSECDOI_ATTR_AUTH_NONE;
   4537 
   4538 	while (tlen > 0) {
   4539 
   4540 		type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
   4541 		flag = ntohs(d->type) & ISAKMP_GEN_MASK;
   4542 
   4543 		plog(LLV_DEBUG, LOCATION, NULL,
   4544 			"type=%s, flag=0x%04x, lorv=%s\n",
   4545 			s_ipsecdoi_attr(type), flag,
   4546 			s_ipsecdoi_attr_v(type, ntohs(d->lorv)));
   4547 
   4548 		switch (type) {
   4549 		case IPSECDOI_ATTR_SA_LD_TYPE:
   4550 		{
   4551 			int type = ntohs(d->lorv);
   4552 			switch (type) {
   4553 			case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
   4554 			case IPSECDOI_ATTR_SA_LD_TYPE_KB:
   4555 				life_t = type;
   4556 				break;
   4557 			default:
   4558 				plog(LLV_WARNING, LOCATION, NULL,
   4559 					"invalid life duration type. "
   4560 					"use default\n");
   4561 				life_t = IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT;
   4562 				break;
   4563 			}
   4564 			break;
   4565 		}
   4566 		case IPSECDOI_ATTR_SA_LD:
   4567 			if (prev == NULL
   4568 			 || (ntohs(prev->type) & ~ISAKMP_GEN_MASK) !=
   4569 					IPSECDOI_ATTR_SA_LD_TYPE) {
   4570 				plog(LLV_ERROR, LOCATION, NULL,
   4571 				    "life duration must follow ltype\n");
   4572 				break;
   4573 			}
   4574 
   4575 		    {
   4576 			u_int32_t t;
   4577 			vchar_t *ld_buf = NULL;
   4578 
   4579 			if (flag) {
   4580 				/* i.e. ISAKMP_GEN_TV */
   4581 				ld_buf = vmalloc(sizeof(d->lorv));
   4582 				if (ld_buf == NULL) {
   4583 					plog(LLV_ERROR, LOCATION, NULL,
   4584 					    "failed to get LD buffer.\n");
   4585 					goto end;
   4586 				}
   4587 				memcpy(ld_buf->v, &d->lorv, sizeof(d->lorv));
   4588 			} else {
   4589 				int len = ntohs(d->lorv);
   4590 				/* i.e. ISAKMP_GEN_TLV */
   4591 				ld_buf = vmalloc(len);
   4592 				if (ld_buf == NULL) {
   4593 					plog(LLV_ERROR, LOCATION, NULL,
   4594 					    "failed to get LD buffer.\n");
   4595 					goto end;
   4596 				}
   4597 				memcpy(ld_buf->v, d + 1, len);
   4598 			}
   4599 			switch (life_t) {
   4600 			case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
   4601 				t = ipsecdoi_set_ld(ld_buf);
   4602 				vfree(ld_buf);
   4603 				if (t == 0) {
   4604 					plog(LLV_ERROR, LOCATION, NULL,
   4605 						"invalid life duration.\n");
   4606 					goto end;
   4607 				}
   4608 				/* lifetime must be equal in a proposal. */
   4609 				if (pp->lifetime == IPSECDOI_ATTR_SA_LD_SEC_DEFAULT)
   4610 					pp->lifetime = t;
   4611 				else if (pp->lifetime != t) {
   4612 					plog(LLV_ERROR, LOCATION, NULL,
   4613 						"lifetime mismatched "
   4614 						"in a proposal, "
   4615 						"prev:%ld curr:%u.\n",
   4616 						(long)pp->lifetime, t);
   4617 					goto end;
   4618 				}
   4619 				break;
   4620 			case IPSECDOI_ATTR_SA_LD_TYPE_KB:
   4621 				t = ipsecdoi_set_ld(ld_buf);
   4622 				vfree(ld_buf);
   4623 				if (t == 0) {
   4624 					plog(LLV_ERROR, LOCATION, NULL,
   4625 						"invalid life duration.\n");
   4626 					goto end;
   4627 				}
   4628 				/* lifebyte must be equal in a proposal. */
   4629 				if (pp->lifebyte == 0)
   4630 					pp->lifebyte = t;
   4631 				else if (pp->lifebyte != t) {
   4632 					plog(LLV_ERROR, LOCATION, NULL,
   4633 						"lifebyte mismatched "
   4634 						"in a proposal, "
   4635 						"prev:%d curr:%u.\n",
   4636 						pp->lifebyte, t);
   4637 					goto end;
   4638 				}
   4639 				break;
   4640 			default:
   4641 				vfree(ld_buf);
   4642 				plog(LLV_ERROR, LOCATION, NULL,
   4643 					"invalid life type: %d\n", life_t);
   4644 				goto end;
   4645 			}
   4646 		    }
   4647 			break;
   4648 
   4649 		case IPSECDOI_ATTR_GRP_DESC:
   4650 			/*
   4651 			 * RFC2407: 4.5 IPSEC Security Association Attributes
   4652 			 *   Specifies the Oakley Group to be used in a PFS QM
   4653 			 *   negotiation.  For a list of supported values, see
   4654 			 *   Appendix A of [IKE].
   4655 			 */
   4656 			if (pp->pfs_group == 0)
   4657 				pp->pfs_group = (u_int16_t)ntohs(d->lorv);
   4658 			else if (pp->pfs_group != (u_int16_t)ntohs(d->lorv)) {
   4659 				plog(LLV_ERROR, LOCATION, NULL,
   4660 					"pfs_group mismatched "
   4661 					"in a proposal.\n");
   4662 				goto end;
   4663 			}
   4664 			break;
   4665 
   4666 		case IPSECDOI_ATTR_ENC_MODE:
   4667 			if (pr->encmode &&
   4668 			    pr->encmode != (u_int16_t)ntohs(d->lorv)) {
   4669 				plog(LLV_ERROR, LOCATION, NULL,
   4670 					"multiple encmode exist "
   4671 					"in a transform.\n");
   4672 				goto end;
   4673 			}
   4674 			pr->encmode = (u_int16_t)ntohs(d->lorv);
   4675 			break;
   4676 
   4677 		case IPSECDOI_ATTR_AUTH:
   4678 			if (tr->authtype != IPSECDOI_ATTR_AUTH_NONE) {
   4679 				plog(LLV_ERROR, LOCATION, NULL,
   4680 					"multiple authtype exist "
   4681 					"in a transform.\n");
   4682 				goto end;
   4683 			}
   4684 			tr->authtype = (u_int16_t)ntohs(d->lorv);
   4685 			break;
   4686 
   4687 		case IPSECDOI_ATTR_KEY_LENGTH:
   4688 			if (pr->proto_id != IPSECDOI_PROTO_IPSEC_ESP) {
   4689 				plog(LLV_ERROR, LOCATION, NULL,
   4690 					"key length defined but not ESP");
   4691 				goto end;
   4692 			}
   4693 			tr->encklen = ntohs(d->lorv);
   4694 			break;
   4695 #ifdef HAVE_SECCTX
   4696 		case IPSECDOI_ATTR_SECCTX:
   4697 		{
   4698 			int len = ntohs(d->lorv);
   4699 			memcpy(&pp->sctx, d + 1, len);
   4700 			pp->sctx.ctx_strlen = ntohs(pp->sctx.ctx_strlen);
   4701 			break;
   4702 		}
   4703 #endif /* HAVE_SECCTX */
   4704 		case IPSECDOI_ATTR_KEY_ROUNDS:
   4705 		case IPSECDOI_ATTR_COMP_DICT_SIZE:
   4706 		case IPSECDOI_ATTR_COMP_PRIVALG:
   4707 		default:
   4708 			break;
   4709 		}
   4710 
   4711 		prev = d;
   4712 		if (flag) {
   4713 			tlen -= sizeof(*d);
   4714 			d = (struct isakmp_data *)((char *)d + sizeof(*d));
   4715 		} else {
   4716 			tlen -= (sizeof(*d) + ntohs(d->lorv));
   4717 			d = (struct isakmp_data *)((caddr_t)d + sizeof(*d) + ntohs(d->lorv));
   4718 		}
   4719 	}
   4720 
   4721 	error = 0;
   4722 end:
   4723 	return error;
   4724 }
   4725 
   4726 int
   4727 ipsecdoi_authalg2trnsid(alg)
   4728 	int alg;
   4729 {
   4730 	switch (alg) {
   4731         case IPSECDOI_ATTR_AUTH_HMAC_MD5:
   4732 		return IPSECDOI_AH_MD5;
   4733         case IPSECDOI_ATTR_AUTH_HMAC_SHA1:
   4734 		return IPSECDOI_AH_SHA;
   4735 	case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256:
   4736 		return IPSECDOI_AH_SHA256;
   4737 	case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384:
   4738 		return IPSECDOI_AH_SHA384;
   4739 	case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512:
   4740 		return IPSECDOI_AH_SHA512;
   4741         case IPSECDOI_ATTR_AUTH_DES_MAC:
   4742 		return IPSECDOI_AH_DES;
   4743 	case IPSECDOI_ATTR_AUTH_KPDK:
   4744 		return IPSECDOI_AH_MD5;	/* XXX */
   4745 	default:
   4746 		plog(LLV_ERROR, LOCATION, NULL,
   4747 			"invalid authentication algorithm:%d\n", alg);
   4748 	}
   4749 	return -1;
   4750 }
   4751 
   4752 static int rm_idtype2doi[] = {
   4753 	255,				/* IDTYPE_UNDEFINED, 0 */
   4754 	IPSECDOI_ID_FQDN,		/* IDTYPE_FQDN, 1 */
   4755 	IPSECDOI_ID_USER_FQDN,		/* IDTYPE_USERFQDN, 2 */
   4756 	IPSECDOI_ID_KEY_ID,		/* IDTYPE_KEYID, 3 */
   4757 	255,    /*			   IDTYPE_ADDRESS, 4
   4758 		 * it expands into 4 types by another function. */
   4759 	IPSECDOI_ID_DER_ASN1_DN,	/* IDTYPE_ASN1DN, 5 */
   4760 };
   4761 
   4762 /*
   4763  * convert idtype to DOI value.
   4764  * OUT	255  : NG
   4765  *	other: converted.
   4766  */
   4767 int
   4768 idtype2doi(idtype)
   4769 	int idtype;
   4770 {
   4771 	if (ARRAYLEN(rm_idtype2doi) > idtype)
   4772 		return rm_idtype2doi[idtype];
   4773 	return 255;
   4774 }
   4775 
   4776 int
   4777 doi2idtype(doi)
   4778 	int doi;
   4779 {
   4780 	switch(doi) {
   4781 	case IPSECDOI_ID_FQDN:
   4782 		return(IDTYPE_FQDN);
   4783 	case IPSECDOI_ID_USER_FQDN:
   4784 		return(IDTYPE_USERFQDN);
   4785 	case IPSECDOI_ID_KEY_ID:
   4786 		return(IDTYPE_KEYID);
   4787 	case IPSECDOI_ID_DER_ASN1_DN:
   4788 		return(IDTYPE_ASN1DN);
   4789 	case IPSECDOI_ID_IPV4_ADDR:
   4790 	case IPSECDOI_ID_IPV4_ADDR_SUBNET:
   4791 	case IPSECDOI_ID_IPV6_ADDR:
   4792 	case IPSECDOI_ID_IPV6_ADDR_SUBNET:
   4793 		return(IDTYPE_ADDRESS);
   4794 	default:
   4795 		plog(LLV_WARNING, LOCATION, NULL,
   4796 			"Inproper idtype:%s in this function.\n",
   4797 			s_ipsecdoi_ident(doi));
   4798 		return(IDTYPE_ADDRESS);	/* XXX */
   4799 	}
   4800 	/*NOTREACHED*/
   4801 }
   4802