1c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh/*	$NetBSD: isakmp_quick.c,v 1.11.4.1 2007/08/01 11:52:21 vanhu Exp $	*/
20a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
30a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang/* Id: isakmp_quick.c,v 1.29 2006/08/22 18:17:17 manubsd Exp */
40a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
50a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang/*
60a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
70a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * All rights reserved.
80a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang *
90a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * Redistribution and use in source and binary forms, with or without
100a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * modification, are permitted provided that the following conditions
110a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * are met:
120a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * 1. Redistributions of source code must retain the above copyright
130a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang *    notice, this list of conditions and the following disclaimer.
140a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * 2. Redistributions in binary form must reproduce the above copyright
150a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang *    notice, this list of conditions and the following disclaimer in the
160a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang *    documentation and/or other materials provided with the distribution.
170a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * 3. Neither the name of the project nor the names of its contributors
180a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang *    may be used to endorse or promote products derived from this software
190a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang *    without specific prior written permission.
200a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang *
210a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
220a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
230a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
240a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
250a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
260a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
270a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
280a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
290a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
300a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
310a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * SUCH DAMAGE.
320a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang */
330a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
340a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "config.h"
350a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
360a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include <sys/types.h>
370a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include <sys/param.h>
380a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include <sys/socket.h>
390a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
400a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include <netinet/in.h>
410a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
420a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include <stdlib.h>
430a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include <stdio.h>
440a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include <string.h>
450a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include <errno.h>
460a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#if TIME_WITH_SYS_TIME
470a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang# include <sys/time.h>
480a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang# include <time.h>
490a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#else
500a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang# if HAVE_SYS_TIME_H
510a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#  include <sys/time.h>
520a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang# else
530a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#  include <time.h>
540a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang# endif
550a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#endif
56c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh#ifdef ENABLE_HYBRID
57c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh#include <resolv.h>
58c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh#endif
590a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
600a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include PATH_IPSEC_H
610a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
620a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "var.h"
630a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "vmbuf.h"
640a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "schedule.h"
650a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "misc.h"
660a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "plog.h"
670a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "debug.h"
680a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
690a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "localconf.h"
700a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "remoteconf.h"
710a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "handler.h"
720a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "policy.h"
730a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "proposal.h"
740a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "isakmp_var.h"
750a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "isakmp.h"
760a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "isakmp_inf.h"
770a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "isakmp_quick.h"
780a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "oakley.h"
790a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "ipsec_doi.h"
800a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "crypto_openssl.h"
810a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "pfkey.h"
820a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "policy.h"
830a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "algorithm.h"
840a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "sockmisc.h"
850a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "proposal.h"
860a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "sainfo.h"
870a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "admin.h"
880a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#include "strnames.h"
890a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
900a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang/* quick mode */
910a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangstatic vchar_t *quick_ir1mx __P((struct ph2handle *, vchar_t *, vchar_t *));
920a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangstatic int get_sainfo_r __P((struct ph2handle *));
930a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangstatic int get_proposal_r __P((struct ph2handle *));
940a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
950a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang/* %%%
960a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * Quick Mode
970a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang */
980a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang/*
990a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * begin Quick Mode as initiator.  send pfkey getspi message to kernel.
1000a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang */
1010a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangint
1020a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangquick_i1prep(iph2, msg)
1030a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct ph2handle *iph2;
1040a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *msg; /* must be null pointer */
1050a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{
1060a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	int error = ISAKMP_INTERNAL_ERROR;
1070a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
1080a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* validity check */
1090a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (iph2->status != PHASE2ST_STATUS2) {
1100a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL,
1110a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"status mismatched %d.\n", iph2->status);
1120a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
1130a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
1140a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
1150a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	iph2->msgid = isakmp_newmsgid2(iph2->ph1);
1160a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	iph2->ivm = oakley_newiv2(iph2->ph1, iph2->msgid);
1170a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (iph2->ivm == NULL)
1180a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		return 0;
1190a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
1200a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	iph2->status = PHASE2ST_GETSPISENT;
1210a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
1220a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* don't anything if local test mode. */
1230a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (f_local) {
1240a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		error = 0;
1250a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
1260a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
1270a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
1280a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* send getspi message */
1290a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (pk_sendgetspi(iph2) < 0)
1300a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
1310a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
1320a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	plog(LLV_DEBUG, LOCATION, NULL, "pfkey getspi sent.\n");
1330a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
134c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh	iph2->sce = sched_new(lcconf->wait_ph2complete,
135c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh		pfkey_timeover_stub, iph2);
1360a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
1370a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	error = 0;
1380a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
1390a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangend:
1400a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	return error;
1410a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang}
1420a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
1430a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang/*
1440a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * send to responder
145c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh * 	HDR*, HASH(1), SA, Ni [, KE ] [, IDi2, IDr2 ]
1460a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang */
1470a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangint
1480a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangquick_i1send(iph2, msg)
1490a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct ph2handle *iph2;
1500a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *msg; /* must be null pointer */
1510a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{
1520a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *body = NULL;
1530a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *hash = NULL;
1540a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct isakmp_gen *gen;
1550a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	char *p;
1560a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	int tlen;
1570a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	int error = ISAKMP_INTERNAL_ERROR;
1580a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	int pfsgroup, idci, idcr;
1590a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	int np;
1600a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct ipsecdoi_id_b *id, *id_p;
1610a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
1620a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* validity check */
1630a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (msg != NULL) {
1640a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL,
1650a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"msg has to be NULL in this function.\n");
1660a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
1670a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
1680a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (iph2->status != PHASE2ST_GETSPIDONE) {
1690a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL,
1700a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"status mismatched %d.\n", iph2->status);
1710a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
1720a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
1730a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
1740a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* create SA payload for my proposal */
1750a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (ipsecdoi_setph2proposal(iph2) < 0)
1760a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
1770a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
1780a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* generate NONCE value */
1790a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	iph2->nonce = eay_set_random(iph2->ph1->rmconf->nonce_size);
1800a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (iph2->nonce == NULL)
1810a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
1820a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
1830a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/*
1840a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 * DH value calculation is kicked out into cfparse.y.
1850a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 * because pfs group can not be negotiated, it's only to be checked
1860a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 * acceptable.
1870a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 */
1880a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* generate KE value if need */
1890a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	pfsgroup = iph2->proposal->pfs_group;
1900a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (pfsgroup) {
1910a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		/* DH group settting if PFS is required. */
1920a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		if (oakley_setdhgroup(pfsgroup, &iph2->pfsgrp) < 0) {
1930a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			plog(LLV_ERROR, LOCATION, NULL,
1940a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				"failed to set DH value.\n");
1950a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			goto end;
1960a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		}
1970a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		if (oakley_dh_generate(iph2->pfsgrp,
1980a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				&iph2->dhpub, &iph2->dhpriv) < 0) {
1990a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			goto end;
2000a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		}
2010a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
2020a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
2030a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* generate ID value */
2040a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (ipsecdoi_setid2(iph2) < 0) {
2050a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL,
2060a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"failed to get ID.\n");
2070a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
2080a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
2090a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	plog(LLV_DEBUG, LOCATION, NULL, "IDci:\n");
2100a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	plogdump(LLV_DEBUG, iph2->id->v, iph2->id->l);
2110a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	plog(LLV_DEBUG, LOCATION, NULL, "IDcr:\n");
2120a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	plogdump(LLV_DEBUG, iph2->id_p->v, iph2->id_p->l);
2130a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
2140a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/*
2150a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 * we do not attach IDci nor IDcr, under the following condition:
2160a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 * - all proposals are transport mode
2170a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 * - no MIP6 or proxy
2180a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 * - id payload suggests to encrypt all the traffic (no specific
2190a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 *   protocol type)
2200a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 */
2210a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	id = (struct ipsecdoi_id_b *)iph2->id->v;
2220a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	id_p = (struct ipsecdoi_id_b *)iph2->id_p->v;
223c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh	if (id->proto_id == 0
224c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh	 && id_p->proto_id == 0
225c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh	 && iph2->ph1->rmconf->support_proxy == 0
226c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh	 && ipsecdoi_transportmode(iph2->proposal)) {
2270a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		idci = idcr = 0;
2280a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	} else
2290a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		idci = idcr = 1;
2300a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
2310a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* create SA;NONCE payload, and KE if need, and IDii, IDir. */
2320a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	tlen = + sizeof(*gen) + iph2->sa->l
2330a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		+ sizeof(*gen) + iph2->nonce->l;
2340a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (pfsgroup)
2350a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		tlen += (sizeof(*gen) + iph2->dhpub->l);
2360a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (idci)
2370a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		tlen += sizeof(*gen) + iph2->id->l;
2380a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (idcr)
2390a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		tlen += sizeof(*gen) + iph2->id_p->l;
2400a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
2410a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	body = vmalloc(tlen);
2420a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (body == NULL) {
2430a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL,
2440a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"failed to get buffer to send.\n");
2450a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
2460a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
2470a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
2480a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	p = body->v;
2490a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
2500a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* add SA payload */
2510a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	p = set_isakmp_payload(p, iph2->sa, ISAKMP_NPTYPE_NONCE);
2520a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
2530a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* add NONCE payload */
2540a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (pfsgroup)
2550a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		np = ISAKMP_NPTYPE_KE;
2560a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	else if (idci || idcr)
2570a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		np = ISAKMP_NPTYPE_ID;
2580a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	else
259c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh		np = ISAKMP_NPTYPE_NONE;
2600a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	p = set_isakmp_payload(p, iph2->nonce, np);
2610a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
2620a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* add KE payload if need. */
263c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh	np = (idci || idcr) ? ISAKMP_NPTYPE_ID : ISAKMP_NPTYPE_NONE;
2640a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (pfsgroup)
2650a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		p = set_isakmp_payload(p, iph2->dhpub, np);
2660a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
2670a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* IDci */
268c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh	np = (idcr) ? ISAKMP_NPTYPE_ID : ISAKMP_NPTYPE_NONE;
2690a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (idci)
2700a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		p = set_isakmp_payload(p, iph2->id, np);
2710a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
2720a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* IDcr */
2730a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (idcr)
274c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh		p = set_isakmp_payload(p, iph2->id_p, ISAKMP_NPTYPE_NONE);
2750a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
2760a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* generate HASH(1) */
2770a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	hash = oakley_compute_hash1(iph2->ph1, iph2->msgid, body);
2780a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (hash == NULL)
2790a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
2800a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
2810a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* send isakmp payload */
2820a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	iph2->sendbuf = quick_ir1mx(iph2, body, hash);
2830a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (iph2->sendbuf == NULL)
2840a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
2850a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
2860a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* send the packet, add to the schedule to resend */
287c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh	iph2->retry_counter = iph2->ph1->rmconf->retry_counter;
288c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh	if (isakmp_ph2resend(iph2) == -1)
2890a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
2900a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
2910a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* change status of isakmp status entry */
2920a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	iph2->status = PHASE2ST_MSG1SENT;
2930a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
2940a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	error = 0;
2950a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
2960a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangend:
2970a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (body != NULL)
2980a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		vfree(body);
2990a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (hash != NULL)
3000a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		vfree(hash);
3010a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
3020a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	return error;
3030a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang}
3040a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
3050a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang/*
3060a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * receive from responder
307c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh * 	HDR*, HASH(2), SA, Nr [, KE ] [, IDi2, IDr2 ]
3080a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang */
3090a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangint
3100a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangquick_i2recv(iph2, msg0)
3110a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct ph2handle *iph2;
3120a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *msg0;
3130a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{
3140a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *msg = NULL;
3150a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *hbuf = NULL;	/* for hash computing. */
3160a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *pbuf = NULL;	/* for payload parsing */
3170a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct isakmp_parse_t *pa;
3180a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct isakmp *isakmp = (struct isakmp *)msg0->v;
3190a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct isakmp_pl_hash *hash = NULL;
320c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh	int f_id;
3210a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	char *p;
3220a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	int tlen;
3230a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	int error = ISAKMP_INTERNAL_ERROR;
3240a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
3250a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* validity check */
3260a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (iph2->status != PHASE2ST_MSG1SENT) {
3270a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL,
3280a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"status mismatched %d.\n", iph2->status);
3290a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
3300a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
3310a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
3320a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* decrypt packet */
3330a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (!ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E)) {
3340a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
3350a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"Packet wasn't encrypted.\n");
3360a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
3370a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
3380a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	msg = oakley_do_decrypt(iph2->ph1, msg0, iph2->ivm->iv, iph2->ivm->ive);
3390a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (msg == NULL)
3400a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
3410a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
3420a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* create buffer for validating HASH(2) */
3430a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/*
3440a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 * ordering rule:
3450a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 *	1. the first one must be HASH
3460a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 *	2. the second one must be SA (added in isakmp-oakley-05!)
3470a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 *	3. two IDs must be considered as IDci, then IDcr
3480a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 */
3490a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	pbuf = isakmp_parse(msg);
3500a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (pbuf == NULL)
3510a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
3520a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	pa = (struct isakmp_parse_t *)pbuf->v;
3530a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
3540a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* HASH payload is fixed postion */
3550a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (pa->type != ISAKMP_NPTYPE_HASH) {
3560a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
3570a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"received invalid next payload type %d, "
3580a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"expecting %d.\n",
3590a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			pa->type, ISAKMP_NPTYPE_HASH);
3600a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
3610a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
3620a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	hash = (struct isakmp_pl_hash *)pa->ptr;
3630a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	pa++;
3640a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
3650a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/*
3660a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 * this restriction was introduced in isakmp-oakley-05.
3670a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 * we do not check this for backward compatibility.
3680a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 * TODO: command line/config file option to enable/disable this code
3690a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 */
3700a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* HASH payload is fixed postion */
3710a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (pa->type != ISAKMP_NPTYPE_SA) {
3720a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_WARNING, LOCATION, iph2->ph1->remote,
3730a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"received invalid next payload type %d, "
3740a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"expecting %d.\n",
3750a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			pa->type, ISAKMP_NPTYPE_HASH);
3760a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
3770a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
3780a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* allocate buffer for computing HASH(2) */
3790a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	tlen = iph2->nonce->l
3800a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		+ ntohl(isakmp->len) - sizeof(*isakmp);
3810a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	hbuf = vmalloc(tlen);
3820a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (hbuf == NULL) {
3830a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL,
3840a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"failed to get hash buffer.\n");
3850a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
3860a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
3870a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	p = hbuf->v + iph2->nonce->l;	/* retain the space for Ni_b */
3880a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
3890a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/*
3900a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 * parse the payloads.
3910a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 * copy non-HASH payloads into hbuf, so that we can validate HASH.
3920a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 */
3930a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	iph2->sa_ret = NULL;
394c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh	f_id = 0;	/* flag to use checking ID */
3950a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	tlen = 0;	/* count payload length except of HASH payload. */
3960a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	for (; pa->type; pa++) {
3970a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
3980a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		/* copy to buffer for HASH */
3990a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		/* Don't modify the payload */
4000a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		memcpy(p, pa->ptr, pa->len);
4010a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
4020a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		switch (pa->type) {
4030a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		case ISAKMP_NPTYPE_SA:
4040a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			if (iph2->sa_ret != NULL) {
4050a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				plog(LLV_ERROR, LOCATION, NULL,
4060a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang					"Ignored, multiple SA "
4070a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang					"isn't supported.\n");
4080a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				break;
4090a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			}
410c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh			if (isakmp_p2ph(&iph2->sa_ret, pa->ptr) < 0)
4110a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				goto end;
4120a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			break;
4130a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
4140a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		case ISAKMP_NPTYPE_NONCE:
415c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh			if (isakmp_p2ph(&iph2->nonce_p, pa->ptr) < 0)
4160a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				goto end;
4170a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			break;
4180a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
4190a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		case ISAKMP_NPTYPE_KE:
420c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh			if (isakmp_p2ph(&iph2->dhpub_p, pa->ptr) < 0)
4210a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				goto end;
4220a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			break;
4230a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
4240a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		case ISAKMP_NPTYPE_ID:
425c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh		    {
426c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh			vchar_t *vp;
427c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh
428c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh			/* check ID value */
429c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh			if (f_id == 0) {
430c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh				/* for IDci */
431c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh				f_id = 1;
432c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh				vp = iph2->id;
4330a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			} else {
434c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh				/* for IDcr */
435c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh				vp = iph2->id_p;
436c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh			}
437c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh
438c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh#ifndef ANDROID_PATCHED
439c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh			if (memcmp(vp->v, (caddr_t)pa->ptr + sizeof(struct isakmp_gen), vp->l)) {
440c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh
441c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh				plog(LLV_ERROR, LOCATION, NULL,
442c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh					"mismatched ID was returned.\n");
443c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh				error = ISAKMP_NTYPE_ATTRIBUTES_NOT_SUPPORTED;
4440a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				goto end;
4450a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			}
446c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh#endif
447c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh		    }
4480a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			break;
4490a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
4500a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		case ISAKMP_NPTYPE_N:
451c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh			isakmp_check_notify(pa->ptr, iph2->ph1);
4520a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			break;
4530a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
4540a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#ifdef ENABLE_NATT
4550a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		case ISAKMP_NPTYPE_NATOA_DRAFT:
4560a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		case ISAKMP_NPTYPE_NATOA_RFC:
457c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh			/* Ignore original source/destination messages */
4580a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			break;
4590a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#endif
4600a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
4610a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		default:
4620a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			/* don't send information, see ident_r1recv() */
4630a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
4640a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				"ignore the packet, "
4650a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				"received unexpecting payload type %d.\n",
4660a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				pa->type);
4670a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			goto end;
4680a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		}
4690a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
4700a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		p += pa->len;
4710a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
4720a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		/* compute true length of payload. */
4730a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		tlen += pa->len;
4740a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
4750a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
4760a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* payload existency check */
4770a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (hash == NULL || iph2->sa_ret == NULL || iph2->nonce_p == NULL) {
4780a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
4790a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"few isakmp message received.\n");
4800a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
4810a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
4820a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
4830a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* Fixed buffer for calculating HASH */
4840a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	memcpy(hbuf->v, iph2->nonce->v, iph2->nonce->l);
4850a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	plog(LLV_DEBUG, LOCATION, NULL,
4860a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		"HASH allocated:hbuf->l=%zu actual:tlen=%zu\n",
4870a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		hbuf->l, tlen + iph2->nonce->l);
4880a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* adjust buffer length for HASH */
4890a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	hbuf->l = iph2->nonce->l + tlen;
4900a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
4910a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* validate HASH(2) */
4920a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang    {
4930a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	char *r_hash;
4940a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *my_hash = NULL;
4950a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	int result;
4960a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
4970a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	r_hash = (char *)hash + sizeof(*hash);
4980a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
4990a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	plog(LLV_DEBUG, LOCATION, NULL, "HASH(2) received:");
5000a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	plogdump(LLV_DEBUG, r_hash, ntohs(hash->h.len) - sizeof(*hash));
5010a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
5020a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	my_hash = oakley_compute_hash1(iph2->ph1, iph2->msgid, hbuf);
5030a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (my_hash == NULL)
5040a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
5050a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
5060a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	result = memcmp(my_hash->v, r_hash, my_hash->l);
5070a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vfree(my_hash);
5080a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
5090a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (result) {
5100a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_DEBUG, LOCATION, iph2->ph1->remote,
5110a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"HASH(2) mismatch.\n");
5120a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		error = ISAKMP_NTYPE_INVALID_HASH_INFORMATION;
5130a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
5140a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
5150a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang    }
5160a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
5170a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* validity check SA payload sent from responder */
5180a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (ipsecdoi_checkph2proposal(iph2) < 0) {
5190a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		error = ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN;
5200a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
5210a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
5220a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
5230a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* change status of isakmp status entry */
5240a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	iph2->status = PHASE2ST_STATUS6;
5250a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
5260a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	error = 0;
5270a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
5280a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangend:
5290a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (hbuf)
5300a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		vfree(hbuf);
5310a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (pbuf)
5320a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		vfree(pbuf);
5330a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (msg)
5340a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		vfree(msg);
5350a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
5360a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (error) {
5370a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		VPTRINIT(iph2->sa_ret);
5380a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		VPTRINIT(iph2->nonce_p);
5390a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		VPTRINIT(iph2->dhpub_p);
5400a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		VPTRINIT(iph2->id);
5410a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		VPTRINIT(iph2->id_p);
5420a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
5430a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
5440a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	return error;
5450a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang}
5460a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
5470a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang/*
5480a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * send to responder
5490a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * 	HDR*, HASH(3)
5500a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang */
5510a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangint
5520a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangquick_i2send(iph2, msg0)
5530a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct ph2handle *iph2;
5540a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *msg0;
5550a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{
5560a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *msg = NULL;
5570a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *buf = NULL;
5580a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *hash = NULL;
5590a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	char *p = NULL;
5600a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	int tlen;
5610a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	int error = ISAKMP_INTERNAL_ERROR;
5620a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
5630a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* validity check */
5640a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (iph2->status != PHASE2ST_STATUS6) {
5650a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL,
5660a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"status mismatched %d.\n", iph2->status);
5670a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
5680a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
5690a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
5700a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* generate HASH(3) */
5710a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang    {
5720a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *tmp = NULL;
5730a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
5740a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	plog(LLV_DEBUG, LOCATION, NULL, "HASH(3) generate\n");
5750a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
5760a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	tmp = vmalloc(iph2->nonce->l + iph2->nonce_p->l);
5770a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (tmp == NULL) {
5780a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL,
5790a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"failed to get hash buffer.\n");
5800a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
5810a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
5820a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	memcpy(tmp->v, iph2->nonce->v, iph2->nonce->l);
5830a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	memcpy(tmp->v + iph2->nonce->l, iph2->nonce_p->v, iph2->nonce_p->l);
5840a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
5850a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	hash = oakley_compute_hash3(iph2->ph1, iph2->msgid, tmp);
5860a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vfree(tmp);
5870a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
5880a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (hash == NULL)
5890a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
5900a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang    }
5910a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
5920a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* create buffer for isakmp payload */
5930a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	tlen = sizeof(struct isakmp)
5940a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		+ sizeof(struct isakmp_gen) + hash->l;
5950a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	buf = vmalloc(tlen);
5960a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (buf == NULL) {
5970a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL,
5980a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"failed to get buffer to send.\n");
5990a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
6000a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
6010a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
6020a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* create isakmp header */
6030a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	p = set_isakmp_header2(buf, iph2, ISAKMP_NPTYPE_HASH);
6040a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (p == NULL)
6050a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
6060a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
6070a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* add HASH(3) payload */
6080a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	p = set_isakmp_payload(p, hash, ISAKMP_NPTYPE_NONE);
6090a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
6100a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#ifdef HAVE_PRINT_ISAKMP_C
6110a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	isakmp_printpacket(buf, iph2->ph1->local, iph2->ph1->remote, 1);
6120a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#endif
6130a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
6140a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* encoding */
6150a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	iph2->sendbuf = oakley_do_encrypt(iph2->ph1, buf, iph2->ivm->ive, iph2->ivm->iv);
6160a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (iph2->sendbuf == NULL)
6170a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
6180a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
6190a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* if there is commit bit, need resending */
6200a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (ISSET(iph2->flags, ISAKMP_FLAG_C)) {
6210a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		/* send the packet, add to the schedule to resend */
622c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh		iph2->retry_counter = iph2->ph1->rmconf->retry_counter;
623c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh		if (isakmp_ph2resend(iph2) == -1)
6240a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			goto end;
6250a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	} else {
6260a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		/* send the packet */
6270a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		if (isakmp_send(iph2->ph1, iph2->sendbuf) < 0)
6280a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			goto end;
6290a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
6300a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
6310a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* the sending message is added to the received-list. */
6320a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (add_recvdpkt(iph2->ph1->remote, iph2->ph1->local,
6330a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			iph2->sendbuf, msg0) == -1) {
6340a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR , LOCATION, NULL,
6350a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"failed to add a response packet to the tree.\n");
6360a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
6370a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
6380a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
6390a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* compute both of KEYMATs */
6400a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (oakley_compute_keymat(iph2, INITIATOR) < 0)
6410a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
6420a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
6430a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	iph2->status = PHASE2ST_ADDSA;
6440a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
6450a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* don't anything if local test mode. */
6460a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (f_local) {
6470a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		error = 0;
6480a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
6490a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
6500a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
6510a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* if there is commit bit don't set up SA now. */
6520a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (ISSET(iph2->flags, ISAKMP_FLAG_C)) {
6530a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		iph2->status = PHASE2ST_COMMIT;
6540a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		error = 0;
6550a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
6560a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
6570a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
6580a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* Do UPDATE for initiator */
6590a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	plog(LLV_DEBUG, LOCATION, NULL, "call pk_sendupdate\n");
6600a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (pk_sendupdate(iph2) < 0) {
6610a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL, "pfkey update failed.\n");
6620a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
6630a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
6640a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	plog(LLV_DEBUG, LOCATION, NULL, "pfkey update sent.\n");
6650a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
6660a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* Do ADD for responder */
6670a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (pk_sendadd(iph2) < 0) {
6680a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL, "pfkey add failed.\n");
6690a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
6700a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
6710a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	plog(LLV_DEBUG, LOCATION, NULL, "pfkey add sent.\n");
6720a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
6730a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	error = 0;
6740a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
6750a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangend:
6760a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (buf != NULL)
6770a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		vfree(buf);
6780a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (msg != NULL)
6790a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		vfree(msg);
6800a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (hash != NULL)
6810a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		vfree(hash);
6820a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
6830a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	return error;
6840a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang}
6850a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
6860a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang/*
6870a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * receive from responder
6880a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * 	HDR#*, HASH(4), notify
6890a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang */
6900a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangint
6910a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangquick_i3recv(iph2, msg0)
6920a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct ph2handle *iph2;
6930a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *msg0;
6940a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{
6950a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *msg = NULL;
6960a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *pbuf = NULL;	/* for payload parsing */
6970a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct isakmp_parse_t *pa;
6980a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct isakmp_pl_hash *hash = NULL;
6990a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *notify = NULL;
7000a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	int error = ISAKMP_INTERNAL_ERROR;
7010a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
7020a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* validity check */
7030a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (iph2->status != PHASE2ST_COMMIT) {
7040a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL,
7050a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"status mismatched %d.\n", iph2->status);
7060a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
7070a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
7080a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
7090a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* decrypt packet */
7100a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (!ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E)) {
7110a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
7120a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"Packet wasn't encrypted.\n");
7130a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
7140a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
7150a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	msg = oakley_do_decrypt(iph2->ph1, msg0, iph2->ivm->iv, iph2->ivm->ive);
7160a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (msg == NULL)
7170a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
7180a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
7190a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* validate the type of next payload */
7200a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	pbuf = isakmp_parse(msg);
7210a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (pbuf == NULL)
7220a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
7230a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
7240a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	for (pa = (struct isakmp_parse_t *)pbuf->v;
7250a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	     pa->type != ISAKMP_NPTYPE_NONE;
7260a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	     pa++) {
7270a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
7280a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		switch (pa->type) {
7290a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		case ISAKMP_NPTYPE_HASH:
7300a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			hash = (struct isakmp_pl_hash *)pa->ptr;
7310a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			break;
7320a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		case ISAKMP_NPTYPE_N:
7330a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			if (notify != NULL) {
7340a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				plog(LLV_WARNING, LOCATION, NULL,
7350a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				    "Ignoring multiples notifications\n");
7360a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				break;
7370a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			}
738c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh			isakmp_check_notify(pa->ptr, iph2->ph1);
7390a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			notify = vmalloc(pa->len);
7400a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			if (notify == NULL) {
7410a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				plog(LLV_ERROR, LOCATION, NULL,
7420a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang					"failed to get notify buffer.\n");
7430a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				goto end;
7440a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			}
7450a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			memcpy(notify->v, pa->ptr, notify->l);
7460a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			break;
7470a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		default:
7480a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			/* don't send information, see ident_r1recv() */
7490a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
7500a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				"ignore the packet, "
7510a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				"received unexpecting payload type %d.\n",
7520a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				pa->type);
7530a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			goto end;
7540a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		}
7550a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
7560a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
7570a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* payload existency check */
7580a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (hash == NULL) {
7590a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
7600a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"few isakmp message received.\n");
7610a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
7620a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
7630a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
7640a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* validate HASH(4) */
7650a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang    {
7660a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	char *r_hash;
7670a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *my_hash = NULL;
7680a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *tmp = NULL;
7690a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	int result;
7700a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
7710a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	r_hash = (char *)hash + sizeof(*hash);
7720a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
7730a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	plog(LLV_DEBUG, LOCATION, NULL, "HASH(4) validate:");
7740a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	plogdump(LLV_DEBUG, r_hash, ntohs(hash->h.len) - sizeof(*hash));
7750a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
7760a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	my_hash = oakley_compute_hash1(iph2->ph1, iph2->msgid, notify);
7770a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vfree(tmp);
7780a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (my_hash == NULL)
7790a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
7800a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
7810a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	result = memcmp(my_hash->v, r_hash, my_hash->l);
7820a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vfree(my_hash);
7830a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
7840a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (result) {
7850a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_DEBUG, LOCATION, iph2->ph1->remote,
7860a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"HASH(4) mismatch.\n");
7870a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		error = ISAKMP_NTYPE_INVALID_HASH_INFORMATION;
7880a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
7890a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
7900a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang    }
7910a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
7920a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	iph2->status = PHASE2ST_ADDSA;
7930a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	iph2->flags ^= ISAKMP_FLAG_C;	/* reset bit */
7940a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
7950a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* don't anything if local test mode. */
7960a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (f_local) {
7970a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		error = 0;
7980a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
7990a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
8000a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
8010a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* Do UPDATE for initiator */
8020a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	plog(LLV_DEBUG, LOCATION, NULL, "call pk_sendupdate\n");
8030a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (pk_sendupdate(iph2) < 0) {
8040a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL, "pfkey update failed.\n");
8050a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
8060a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
8070a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	plog(LLV_DEBUG, LOCATION, NULL, "pfkey update sent.\n");
8080a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
8090a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* Do ADD for responder */
8100a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (pk_sendadd(iph2) < 0) {
8110a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL, "pfkey add failed.\n");
8120a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
8130a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
8140a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	plog(LLV_DEBUG, LOCATION, NULL, "pfkey add sent.\n");
8150a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
8160a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	error = 0;
8170a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
8180a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangend:
8190a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (msg != NULL)
8200a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		vfree(msg);
8210a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (pbuf != NULL)
8220a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		vfree(pbuf);
8230a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (notify != NULL)
8240a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		vfree(notify);
8250a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
8260a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	return error;
8270a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang}
8280a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
8290a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang/*
8300a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * receive from initiator
831c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh * 	HDR*, HASH(1), SA, Ni [, KE ] [, IDi2, IDr2 ]
8320a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang */
8330a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangint
8340a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangquick_r1recv(iph2, msg0)
8350a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct ph2handle *iph2;
8360a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *msg0;
8370a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{
8380a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *msg = NULL;
8390a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *hbuf = NULL;	/* for hash computing. */
8400a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *pbuf = NULL;	/* for payload parsing */
8410a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct isakmp_parse_t *pa;
8420a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct isakmp *isakmp = (struct isakmp *)msg0->v;
8430a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct isakmp_pl_hash *hash = NULL;
8440a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	char *p;
8450a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	int tlen;
8460a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	int f_id_order;	/* for ID payload detection */
8470a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	int error = ISAKMP_INTERNAL_ERROR;
8480a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
8490a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* validity check */
8500a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (iph2->status != PHASE2ST_START) {
8510a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL,
8520a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"status mismatched %d.\n", iph2->status);
8530a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
8540a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
8550a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
8560a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* decrypting */
8570a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (!ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E)) {
8580a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
8590a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"Packet wasn't encrypted.\n");
8600a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		error = ISAKMP_NTYPE_PAYLOAD_MALFORMED;
8610a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
8620a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
8630a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* decrypt packet */
8640a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	msg = oakley_do_decrypt(iph2->ph1, msg0, iph2->ivm->iv, iph2->ivm->ive);
865c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh	if (msg == NULL)
8660a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
8670a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
8680a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* create buffer for using to validate HASH(1) */
8690a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/*
8700a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 * ordering rule:
8710a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 *	1. the first one must be HASH
8720a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 *	2. the second one must be SA (added in isakmp-oakley-05!)
8730a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 *	3. two IDs must be considered as IDci, then IDcr
8740a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 */
8750a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	pbuf = isakmp_parse(msg);
8760a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (pbuf == NULL)
8770a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
8780a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	pa = (struct isakmp_parse_t *)pbuf->v;
8790a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
8800a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* HASH payload is fixed postion */
8810a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (pa->type != ISAKMP_NPTYPE_HASH) {
8820a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
8830a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"received invalid next payload type %d, "
8840a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"expecting %d.\n",
8850a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			pa->type, ISAKMP_NPTYPE_HASH);
8860a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		error = ISAKMP_NTYPE_BAD_PROPOSAL_SYNTAX;
8870a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
8880a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
8890a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	hash = (struct isakmp_pl_hash *)pa->ptr;
8900a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	pa++;
8910a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
8920a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/*
8930a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 * this restriction was introduced in isakmp-oakley-05.
8940a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 * we do not check this for backward compatibility.
8950a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 * TODO: command line/config file option to enable/disable this code
8960a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 */
8970a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* HASH payload is fixed postion */
8980a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (pa->type != ISAKMP_NPTYPE_SA) {
8990a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_WARNING, LOCATION, iph2->ph1->remote,
9000a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"received invalid next payload type %d, "
9010a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"expecting %d.\n",
9020a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			pa->type, ISAKMP_NPTYPE_SA);
9030a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		error = ISAKMP_NTYPE_BAD_PROPOSAL_SYNTAX;
9040a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
9050a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
9060a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* allocate buffer for computing HASH(1) */
9070a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	tlen = ntohl(isakmp->len) - sizeof(*isakmp);
9080a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	hbuf = vmalloc(tlen);
9090a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (hbuf == NULL) {
9100a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL,
9110a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"failed to get hash buffer.\n");
9120a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
9130a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
9140a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	p = hbuf->v;
9150a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
9160a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/*
9170a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 * parse the payloads.
9180a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 * copy non-HASH payloads into hbuf, so that we can validate HASH.
9190a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 */
9200a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	iph2->sa = NULL;	/* we don't support multi SAs. */
9210a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	iph2->nonce_p = NULL;
9220a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	iph2->dhpub_p = NULL;
9230a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	iph2->id_p = NULL;
9240a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	iph2->id = NULL;
9250a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	tlen = 0;	/* count payload length except of HASH payload. */
9260a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
9270a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/*
9280a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 * IDi2 MUST be immediatelly followed by IDr2.  We allowed the
9290a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 * illegal case, but logged.  First ID payload is to be IDi2.
9300a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 * And next ID payload is to be IDr2.
9310a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 */
9320a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	f_id_order = 0;
9330a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
9340a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	for (; pa->type; pa++) {
9350a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
9360a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		/* copy to buffer for HASH */
9370a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		/* Don't modify the payload */
9380a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		memcpy(p, pa->ptr, pa->len);
9390a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
9400a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		if (pa->type != ISAKMP_NPTYPE_ID)
9410a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			f_id_order = 0;
9420a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
9430a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		switch (pa->type) {
9440a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		case ISAKMP_NPTYPE_SA:
9450a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			if (iph2->sa != NULL) {
9460a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				plog(LLV_ERROR, LOCATION, NULL,
9470a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang					"Multi SAs isn't supported.\n");
9480a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				goto end;
9490a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			}
950c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh			if (isakmp_p2ph(&iph2->sa, pa->ptr) < 0)
9510a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				goto end;
9520a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			break;
9530a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
9540a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		case ISAKMP_NPTYPE_NONCE:
955c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh			if (isakmp_p2ph(&iph2->nonce_p, pa->ptr) < 0)
9560a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				goto end;
9570a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			break;
9580a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
9590a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		case ISAKMP_NPTYPE_KE:
960c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh			if (isakmp_p2ph(&iph2->dhpub_p, pa->ptr) < 0)
9610a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				goto end;
9620a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			break;
9630a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
9640a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		case ISAKMP_NPTYPE_ID:
9650a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			if (iph2->id_p == NULL) {
9660a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				/* for IDci */
9670a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				f_id_order++;
9680a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
9690a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				if (isakmp_p2ph(&iph2->id_p, pa->ptr) < 0)
9700a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang					goto end;
9710a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
9720a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			} else if (iph2->id == NULL) {
9730a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				/* for IDcr */
9740a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				if (f_id_order == 0) {
9750a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang					plog(LLV_ERROR, LOCATION, NULL,
9760a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang						"IDr2 payload is not "
9770a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang						"immediatelly followed "
9780a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang						"by IDi2. We allowed.\n");
9790a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang					/* XXX we allowed in this case. */
9800a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				}
9810a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
9820a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				if (isakmp_p2ph(&iph2->id, pa->ptr) < 0)
9830a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang					goto end;
9840a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			} else {
9850a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				plog(LLV_ERROR, LOCATION, NULL,
9860a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang					"received too many ID payloads.\n");
9870a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				plogdump(LLV_ERROR, iph2->id->v, iph2->id->l);
9880a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				error = ISAKMP_NTYPE_INVALID_ID_INFORMATION;
9890a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				goto end;
9900a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			}
9910a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			break;
9920a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
9930a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		case ISAKMP_NPTYPE_N:
994c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh			isakmp_check_notify(pa->ptr, iph2->ph1);
9950a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			break;
9960a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
9970a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#ifdef ENABLE_NATT
9980a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		case ISAKMP_NPTYPE_NATOA_DRAFT:
9990a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		case ISAKMP_NPTYPE_NATOA_RFC:
1000c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh			/* Ignore original source/destination messages */
10010a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			break;
10020a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#endif
10030a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
10040a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		default:
10050a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
10060a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				"ignore the packet, "
10070a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				"received unexpecting payload type %d.\n",
10080a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				pa->type);
10090a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			error = ISAKMP_NTYPE_PAYLOAD_MALFORMED;
10100a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			goto end;
10110a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		}
10120a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
10130a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		p += pa->len;
10140a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
10150a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		/* compute true length of payload. */
10160a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		tlen += pa->len;
10170a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
10180a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
10190a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* payload existency check */
10200a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (hash == NULL || iph2->sa == NULL || iph2->nonce_p == NULL) {
10210a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
10220a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"few isakmp message received.\n");
10230a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		error = ISAKMP_NTYPE_PAYLOAD_MALFORMED;
10240a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
10250a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
10260a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
10270a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (iph2->id_p) {
10280a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_DEBUG, LOCATION, NULL, "received IDci2:");
10290a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plogdump(LLV_DEBUG, iph2->id_p->v, iph2->id_p->l);
10300a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
10310a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (iph2->id) {
10320a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_DEBUG, LOCATION, NULL, "received IDcr2:");
10330a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plogdump(LLV_DEBUG, iph2->id->v, iph2->id->l);
10340a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
10350a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
10360a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* adjust buffer length for HASH */
10370a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	hbuf->l = tlen;
10380a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
10390a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* validate HASH(1) */
10400a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang    {
10410a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	char *r_hash;
10420a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *my_hash = NULL;
10430a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	int result;
10440a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
10450a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	r_hash = (caddr_t)hash + sizeof(*hash);
10460a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
10470a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	plog(LLV_DEBUG, LOCATION, NULL, "HASH(1) validate:");
10480a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	plogdump(LLV_DEBUG, r_hash, ntohs(hash->h.len) - sizeof(*hash));
10490a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
10500a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	my_hash = oakley_compute_hash1(iph2->ph1, iph2->msgid, hbuf);
10510a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (my_hash == NULL)
10520a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
10530a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
10540a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	result = memcmp(my_hash->v, r_hash, my_hash->l);
10550a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vfree(my_hash);
10560a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
10570a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (result) {
10580a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_DEBUG, LOCATION, iph2->ph1->remote,
10590a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"HASH(1) mismatch.\n");
10600a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		error = ISAKMP_NTYPE_INVALID_HASH_INFORMATION;
10610a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
10620a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
10630a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang    }
10640a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
10650a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* get sainfo */
10660a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	error = get_sainfo_r(iph2);
10670a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (error) {
10680a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL,
10690a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"failed to get sainfo.\n");
10700a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
10710a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
10720a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
10730a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
10740a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* check the existence of ID payload and create responder's proposal */
10750a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	error = get_proposal_r(iph2);
10760a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	switch (error) {
10770a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	case -2:
10780a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		/* generate a policy template from peer's proposal */
10790a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		if (set_proposal_from_proposal(iph2)) {
10800a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			plog(LLV_ERROR, LOCATION, NULL,
10810a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				"failed to generate a proposal template "
10820a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				"from client's proposal.\n");
1083c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh			return ISAKMP_INTERNAL_ERROR;
10840a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		}
10850a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		/*FALLTHROUGH*/
10860a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	case 0:
10870a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		/* select single proposal or reject it. */
10880a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		if (ipsecdoi_selectph2proposal(iph2) < 0) {
10890a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			error = ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN;
10900a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			goto end;
10910a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		}
10920a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		break;
10930a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	default:
10940a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL,
10950a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"failed to get proposal for responder.\n");
10960a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
10970a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
10980a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
10990a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* check KE and attribute of PFS */
11000a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (iph2->dhpub_p != NULL && iph2->approval->pfs_group == 0) {
11010a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL,
11020a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"no PFS is specified, but peer sends KE.\n");
11030a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		error = ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN;
11040a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
11050a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
11060a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (iph2->dhpub_p == NULL && iph2->approval->pfs_group != 0) {
11070a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL,
11080a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"PFS is specified, but peer doesn't sends KE.\n");
11090a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		error = ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN;
11100a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
11110a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
11120a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
11130a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/*
11140a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 * save the packet from the initiator in order to resend the
11150a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 * responder's first packet against this packet.
11160a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 */
11170a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	iph2->msg1 = vdup(msg0);
11180a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
11190a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* change status of isakmp status entry */
11200a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	iph2->status = PHASE2ST_STATUS2;
11210a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
11220a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	error = 0;
11230a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
11240a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangend:
11250a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (hbuf)
11260a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		vfree(hbuf);
11270a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (msg)
11280a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		vfree(msg);
11290a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (pbuf)
11300a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		vfree(pbuf);
11310a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
11320a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (error) {
11330a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		VPTRINIT(iph2->sa);
11340a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		VPTRINIT(iph2->nonce_p);
11350a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		VPTRINIT(iph2->dhpub_p);
11360a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		VPTRINIT(iph2->id);
11370a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		VPTRINIT(iph2->id_p);
11380a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
11390a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
11400a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	return error;
11410a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang}
11420a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
11430a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang/*
11440a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * call pfkey_getspi.
11450a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang */
11460a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangint
11470a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangquick_r1prep(iph2, msg)
11480a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct ph2handle *iph2;
11490a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *msg;
11500a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{
11510a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	int error = ISAKMP_INTERNAL_ERROR;
11520a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
11530a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* validity check */
11540a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (iph2->status != PHASE2ST_STATUS2) {
11550a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL,
11560a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"status mismatched %d.\n", iph2->status);
11570a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
11580a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
11590a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
11600a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	iph2->status = PHASE2ST_GETSPISENT;
11610a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
11620a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* send getspi message */
11630a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (pk_sendgetspi(iph2) < 0)
11640a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
11650a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
11660a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	plog(LLV_DEBUG, LOCATION, NULL, "pfkey getspi sent.\n");
11670a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
1168c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh	iph2->sce = sched_new(lcconf->wait_ph2complete,
1169c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh		pfkey_timeover_stub, iph2);
11700a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
11710a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	error = 0;
11720a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
11730a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangend:
11740a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	return error;
11750a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang}
11760a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
11770a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang/*
11780a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * send to initiator
1179c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh * 	HDR*, HASH(2), SA, Nr [, KE ] [, IDi2, IDr2 ]
11800a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang */
11810a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangint
11820a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangquick_r2send(iph2, msg)
11830a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct ph2handle *iph2;
11840a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *msg;
11850a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{
11860a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *body = NULL;
11870a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *hash = NULL;
11880a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct isakmp_gen *gen;
11890a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	char *p;
11900a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	int tlen;
11910a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	int error = ISAKMP_INTERNAL_ERROR;
11920a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	int pfsgroup;
11930a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	u_int8_t *np_p = NULL;
11940a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
11950a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* validity check */
11960a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (msg != NULL) {
11970a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL,
11980a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"msg has to be NULL in this function.\n");
11990a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
12000a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
12010a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (iph2->status != PHASE2ST_GETSPIDONE) {
12020a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL,
12030a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"status mismatched %d.\n", iph2->status);
12040a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
12050a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
12060a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
12070a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* update responders SPI */
12080a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (ipsecdoi_updatespi(iph2) < 0) {
12090a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL, "failed to update spi.\n");
12100a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
12110a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
12120a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
12130a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* generate NONCE value */
12140a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	iph2->nonce = eay_set_random(iph2->ph1->rmconf->nonce_size);
12150a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (iph2->nonce == NULL)
12160a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
12170a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
12180a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* generate KE value if need */
12190a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	pfsgroup = iph2->approval->pfs_group;
12200a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (iph2->dhpub_p != NULL && pfsgroup != 0) {
12210a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		/* DH group settting if PFS is required. */
12220a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		if (oakley_setdhgroup(pfsgroup, &iph2->pfsgrp) < 0) {
12230a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			plog(LLV_ERROR, LOCATION, NULL,
12240a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				"failed to set DH value.\n");
12250a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			goto end;
12260a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		}
12270a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		/* generate DH public value */
12280a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		if (oakley_dh_generate(iph2->pfsgrp,
12290a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				&iph2->dhpub, &iph2->dhpriv) < 0) {
12300a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			goto end;
12310a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		}
12320a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
12330a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
12340a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* create SA;NONCE payload, and KE and ID if need */
12350a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	tlen = sizeof(*gen) + iph2->sa_ret->l
12360a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		+ sizeof(*gen) + iph2->nonce->l;
12370a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (iph2->dhpub_p != NULL && pfsgroup != 0)
12380a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		tlen += (sizeof(*gen) + iph2->dhpub->l);
12390a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (iph2->id_p != NULL)
12400a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		tlen += (sizeof(*gen) + iph2->id_p->l
12410a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			+ sizeof(*gen) + iph2->id->l);
12420a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
12430a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	body = vmalloc(tlen);
12440a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (body == NULL) {
12450a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL,
12460a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"failed to get buffer to send.\n");
12470a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
12480a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
12490a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	p = body->v;
12500a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
12510a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* make SA payload */
12520a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	p = set_isakmp_payload(body->v, iph2->sa_ret, ISAKMP_NPTYPE_NONCE);
12530a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
12540a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* add NONCE payload */
12550a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	np_p = &((struct isakmp_gen *)p)->np;	/* XXX */
12560a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	p = set_isakmp_payload(p, iph2->nonce,
12570a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		(iph2->dhpub_p != NULL && pfsgroup != 0)
12580a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				? ISAKMP_NPTYPE_KE
12590a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				: (iph2->id_p != NULL
12600a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang					? ISAKMP_NPTYPE_ID
1261c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh					: ISAKMP_NPTYPE_NONE));
12620a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
12630a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* add KE payload if need. */
12640a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (iph2->dhpub_p != NULL && pfsgroup != 0) {
12650a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		np_p = &((struct isakmp_gen *)p)->np;	/* XXX */
12660a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		p = set_isakmp_payload(p, iph2->dhpub,
12670a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			(iph2->id_p == NULL)
1268c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh				? ISAKMP_NPTYPE_NONE
12690a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				: ISAKMP_NPTYPE_ID);
12700a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
12710a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
12720a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* add ID payloads received. */
12730a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (iph2->id_p != NULL) {
12740a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		/* IDci */
12750a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		p = set_isakmp_payload(p, iph2->id_p, ISAKMP_NPTYPE_ID);
12760a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		/* IDcr */
12770a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		np_p = &((struct isakmp_gen *)p)->np;	/* XXX */
1278c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh		p = set_isakmp_payload(p, iph2->id, ISAKMP_NPTYPE_NONE);
12790a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
12800a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
12810a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* add a RESPONDER-LIFETIME notify payload if needed */
12820a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang    {
12830a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *data = NULL;
12840a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct saprop *pp = iph2->approval;
12850a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct saproto *pr;
12860a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
12870a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (pp->claim & IPSECDOI_ATTR_SA_LD_TYPE_SEC) {
12880a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		u_int32_t v = htonl((u_int32_t)pp->lifetime);
12890a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		data = isakmp_add_attr_l(data, IPSECDOI_ATTR_SA_LD_TYPE,
12900a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang					IPSECDOI_ATTR_SA_LD_TYPE_SEC);
12910a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		if (!data)
12920a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			goto end;
12930a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		data = isakmp_add_attr_v(data, IPSECDOI_ATTR_SA_LD,
12940a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang					(caddr_t)&v, sizeof(v));
12950a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		if (!data)
12960a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			goto end;
12970a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
12980a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (pp->claim & IPSECDOI_ATTR_SA_LD_TYPE_KB) {
12990a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		u_int32_t v = htonl((u_int32_t)pp->lifebyte);
13000a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		data = isakmp_add_attr_l(data, IPSECDOI_ATTR_SA_LD_TYPE,
13010a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang					IPSECDOI_ATTR_SA_LD_TYPE_KB);
13020a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		if (!data)
13030a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			goto end;
13040a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		data = isakmp_add_attr_v(data, IPSECDOI_ATTR_SA_LD,
13050a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang					(caddr_t)&v, sizeof(v));
13060a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		if (!data)
13070a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			goto end;
13080a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
13090a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
13100a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/*
13110a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 * XXX Is there only single RESPONDER-LIFETIME payload in a IKE message
13120a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 * in the case of SA bundle ?
13130a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 */
13140a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (data) {
13150a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		for (pr = pp->head; pr; pr = pr->next) {
13160a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			body = isakmp_add_pl_n(body, &np_p,
13170a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang					ISAKMP_NTYPE_RESPONDER_LIFETIME, pr, data);
13180a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			if (!body) {
13190a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				vfree(data);
13200a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				return error;	/* XXX */
13210a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			}
13220a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		}
13230a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		vfree(data);
13240a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
13250a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang    }
13260a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
13270a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* generate HASH(2) */
13280a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang    {
13290a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *tmp;
13300a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
13310a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	tmp = vmalloc(iph2->nonce_p->l + body->l);
13320a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (tmp == NULL) {
13330a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL,
13340a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"failed to get hash buffer.\n");
13350a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
13360a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
13370a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	memcpy(tmp->v, iph2->nonce_p->v, iph2->nonce_p->l);
13380a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	memcpy(tmp->v + iph2->nonce_p->l, body->v, body->l);
13390a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
13400a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	hash = oakley_compute_hash1(iph2->ph1, iph2->msgid, tmp);
13410a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vfree(tmp);
13420a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
13430a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (hash == NULL)
13440a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
13450a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang    }
13460a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
13470a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* send isakmp payload */
13480a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	iph2->sendbuf = quick_ir1mx(iph2, body, hash);
13490a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (iph2->sendbuf == NULL)
13500a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
13510a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
13520a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* send the packet, add to the schedule to resend */
1353c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh	iph2->retry_counter = iph2->ph1->rmconf->retry_counter;
1354c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh	if (isakmp_ph2resend(iph2) == -1)
13550a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
13560a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
13570a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* the sending message is added to the received-list. */
13580a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (add_recvdpkt(iph2->ph1->remote, iph2->ph1->local, iph2->sendbuf, iph2->msg1) == -1) {
13590a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR , LOCATION, NULL,
13600a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"failed to add a response packet to the tree.\n");
13610a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
13620a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
13630a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
13640a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* change status of isakmp status entry */
13650a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	iph2->status = PHASE2ST_MSG1SENT;
13660a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
13670a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	error = 0;
13680a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
13690a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangend:
13700a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (body != NULL)
13710a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		vfree(body);
13720a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (hash != NULL)
13730a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		vfree(hash);
13740a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
13750a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	return error;
13760a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang}
13770a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
13780a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang/*
13790a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * receive from initiator
13800a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * 	HDR*, HASH(3)
13810a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang */
13820a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangint
13830a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangquick_r3recv(iph2, msg0)
13840a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct ph2handle *iph2;
13850a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *msg0;
13860a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{
13870a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *msg = NULL;
13880a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *pbuf = NULL;	/* for payload parsing */
13890a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct isakmp_parse_t *pa;
13900a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct isakmp_pl_hash *hash = NULL;
13910a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	int error = ISAKMP_INTERNAL_ERROR;
13920a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
13930a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* validity check */
13940a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (iph2->status != PHASE2ST_MSG1SENT) {
13950a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL,
13960a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"status mismatched %d.\n", iph2->status);
13970a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
13980a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
13990a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
14000a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* decrypt packet */
14010a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (!ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E)) {
14020a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
14030a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"Packet wasn't encrypted.\n");
14040a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
14050a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
14060a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	msg = oakley_do_decrypt(iph2->ph1, msg0, iph2->ivm->iv, iph2->ivm->ive);
14070a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (msg == NULL)
14080a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
14090a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
14100a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* validate the type of next payload */
14110a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	pbuf = isakmp_parse(msg);
14120a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (pbuf == NULL)
14130a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
14140a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
14150a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	for (pa = (struct isakmp_parse_t *)pbuf->v;
14160a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	     pa->type != ISAKMP_NPTYPE_NONE;
14170a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	     pa++) {
14180a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
14190a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		switch (pa->type) {
14200a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		case ISAKMP_NPTYPE_HASH:
14210a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			hash = (struct isakmp_pl_hash *)pa->ptr;
14220a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			break;
14230a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		case ISAKMP_NPTYPE_N:
1424c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh			isakmp_check_notify(pa->ptr, iph2->ph1);
14250a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			break;
14260a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		default:
14270a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			/* don't send information, see ident_r1recv() */
14280a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
14290a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				"ignore the packet, "
14300a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				"received unexpecting payload type %d.\n",
14310a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				pa->type);
14320a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			goto end;
14330a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		}
14340a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
14350a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
14360a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* payload existency check */
14370a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (hash == NULL) {
14380a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
14390a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"few isakmp message received.\n");
14400a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
14410a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
14420a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
14430a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* validate HASH(3) */
14440a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* HASH(3) = prf(SKEYID_a, 0 | M-ID | Ni_b | Nr_b) */
14450a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang    {
14460a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	char *r_hash;
14470a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *my_hash = NULL;
14480a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *tmp = NULL;
14490a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	int result;
14500a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
14510a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	r_hash = (char *)hash + sizeof(*hash);
14520a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
14530a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	plog(LLV_DEBUG, LOCATION, NULL, "HASH(3) validate:");
14540a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	plogdump(LLV_DEBUG, r_hash, ntohs(hash->h.len) - sizeof(*hash));
14550a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
14560a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	tmp = vmalloc(iph2->nonce_p->l + iph2->nonce->l);
14570a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (tmp == NULL) {
14580a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL,
14590a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"failed to get hash buffer.\n");
14600a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
14610a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
14620a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	memcpy(tmp->v, iph2->nonce_p->v, iph2->nonce_p->l);
14630a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	memcpy(tmp->v + iph2->nonce_p->l, iph2->nonce->v, iph2->nonce->l);
14640a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
14650a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	my_hash = oakley_compute_hash3(iph2->ph1, iph2->msgid, tmp);
14660a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vfree(tmp);
14670a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (my_hash == NULL)
14680a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
14690a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
14700a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	result = memcmp(my_hash->v, r_hash, my_hash->l);
14710a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vfree(my_hash);
14720a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
14730a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (result) {
14740a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
14750a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"HASH(3) mismatch.\n");
14760a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		error = ISAKMP_NTYPE_INVALID_HASH_INFORMATION;
14770a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
14780a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
14790a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang    }
14800a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
14810a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* if there is commit bit, don't set up SA now. */
14820a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (ISSET(iph2->flags, ISAKMP_FLAG_C)) {
14830a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		iph2->status = PHASE2ST_COMMIT;
14840a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	} else
14850a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		iph2->status = PHASE2ST_STATUS6;
14860a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
14870a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	error = 0;
14880a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
14890a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangend:
14900a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (pbuf != NULL)
14910a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		vfree(pbuf);
14920a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (msg != NULL)
14930a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		vfree(msg);
14940a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
14950a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	return error;
14960a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang}
14970a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
14980a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang/*
14990a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * send to initiator
15000a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * 	HDR#*, HASH(4), notify
15010a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang */
15020a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangint
15030a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangquick_r3send(iph2, msg0)
15040a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct ph2handle *iph2;
15050a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *msg0;
15060a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{
15070a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *buf = NULL;
15080a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *myhash = NULL;
15090a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct isakmp_pl_n *n;
15100a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *notify = NULL;
15110a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	char *p;
15120a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	int tlen;
15130a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	int error = ISAKMP_INTERNAL_ERROR;
15140a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
15150a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* validity check */
15160a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (iph2->status != PHASE2ST_COMMIT) {
15170a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL,
15180a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"status mismatched %d.\n", iph2->status);
15190a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
15200a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
15210a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
15220a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* generate HASH(4) */
15230a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* XXX What can I do in the case of multiple different SA */
15240a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	plog(LLV_DEBUG, LOCATION, NULL, "HASH(4) generate\n");
15250a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
15260a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* XXX What should I do if there are multiple SAs ? */
15270a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	tlen = sizeof(struct isakmp_pl_n) + iph2->approval->head->spisize;
15280a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	notify = vmalloc(tlen);
15290a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (notify == NULL) {
15300a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL,
15310a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"failed to get notify buffer.\n");
15320a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
15330a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
15340a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	n = (struct isakmp_pl_n *)notify->v;
15350a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	n->h.np = ISAKMP_NPTYPE_NONE;
15360a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	n->h.len = htons(tlen);
15370a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	n->doi = htonl(IPSEC_DOI);
15380a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	n->proto_id = iph2->approval->head->proto_id;
15390a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	n->spi_size = sizeof(iph2->approval->head->spisize);
15400a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	n->type = htons(ISAKMP_NTYPE_CONNECTED);
15410a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	memcpy(n + 1, &iph2->approval->head->spi, iph2->approval->head->spisize);
15420a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
15430a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	myhash = oakley_compute_hash1(iph2->ph1, iph2->msgid, notify);
15440a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (myhash == NULL)
15450a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
15460a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
15470a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* create buffer for isakmp payload */
15480a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	tlen = sizeof(struct isakmp)
15490a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		+ sizeof(struct isakmp_gen) + myhash->l
15500a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		+ notify->l;
15510a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	buf = vmalloc(tlen);
15520a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (buf == NULL) {
15530a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL,
15540a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"failed to get buffer to send.\n");
15550a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
15560a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
15570a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
15580a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* create isakmp header */
15590a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	p = set_isakmp_header2(buf, iph2, ISAKMP_NPTYPE_HASH);
15600a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (p == NULL)
15610a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
15620a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
15630a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* add HASH(4) payload */
15640a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	p = set_isakmp_payload(p, myhash, ISAKMP_NPTYPE_N);
15650a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
15660a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* add notify payload */
15670a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	memcpy(p, notify->v, notify->l);
15680a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
15690a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#ifdef HAVE_PRINT_ISAKMP_C
15700a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	isakmp_printpacket(buf, iph2->ph1->local, iph2->ph1->remote, 1);
15710a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#endif
15720a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
15730a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* encoding */
15740a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	iph2->sendbuf = oakley_do_encrypt(iph2->ph1, buf, iph2->ivm->ive, iph2->ivm->iv);
15750a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (iph2->sendbuf == NULL)
15760a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
15770a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
15780a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* send the packet */
15790a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (isakmp_send(iph2->ph1, iph2->sendbuf) < 0)
15800a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
15810a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
15820a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* the sending message is added to the received-list. */
15830a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (add_recvdpkt(iph2->ph1->remote, iph2->ph1->local, iph2->sendbuf, msg0) == -1) {
15840a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR , LOCATION, NULL,
15850a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"failed to add a response packet to the tree.\n");
15860a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
15870a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
15880a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
15890a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	iph2->status = PHASE2ST_COMMIT;
15900a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
15910a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	error = 0;
15920a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
15930a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangend:
15940a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (buf != NULL)
15950a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		vfree(buf);
15960a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (myhash != NULL)
15970a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		vfree(myhash);
15980a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (notify != NULL)
15990a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		vfree(notify);
16000a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
16010a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	return error;
16020a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang}
16030a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
16040a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangint
16050a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangtunnel_mode_prop(p)
16060a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct saprop *p;
16070a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{
16080a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct saproto *pr;
16090a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
16100a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	for (pr = p->head; pr; pr = pr->next)
16110a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		if (pr->encmode == IPSECDOI_ATTR_ENC_MODE_TUNNEL)
16120a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			return 1;
16130a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	return 0;
16140a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang}
16150a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
16160a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang/*
16170a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * set SA to kernel.
16180a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang */
16190a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangint
16200a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangquick_r3prep(iph2, msg0)
16210a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct ph2handle *iph2;
16220a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *msg0;
16230a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{
16240a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	int error = ISAKMP_INTERNAL_ERROR;
16250a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
16260a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* validity check */
16270a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (iph2->status != PHASE2ST_STATUS6) {
16280a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL,
16290a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"status mismatched %d.\n", iph2->status);
16300a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
16310a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
16320a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
16330a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* compute both of KEYMATs */
16340a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (oakley_compute_keymat(iph2, RESPONDER) < 0)
16350a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
16360a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
16370a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	iph2->status = PHASE2ST_ADDSA;
16380a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	iph2->flags ^= ISAKMP_FLAG_C;	/* reset bit */
16390a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
16400a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* don't anything if local test mode. */
16410a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (f_local) {
16420a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		error = 0;
16430a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
16440a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
16450a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
16460a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* Do UPDATE as responder */
16470a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	plog(LLV_DEBUG, LOCATION, NULL, "call pk_sendupdate\n");
16480a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (pk_sendupdate(iph2) < 0) {
16490a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL, "pfkey update failed.\n");
16500a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
16510a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
16520a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	plog(LLV_DEBUG, LOCATION, NULL, "pfkey update sent.\n");
16530a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
16540a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* Do ADD for responder */
16550a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (pk_sendadd(iph2) < 0) {
16560a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL, "pfkey add failed.\n");
16570a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
16580a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
16590a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	plog(LLV_DEBUG, LOCATION, NULL, "pfkey add sent.\n");
16600a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
16610a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/*
16620a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 * set policies into SPD if the policy is generated
16630a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 * from peer's policy.
16640a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 */
16650a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (iph2->spidx_gen) {
16660a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
16670a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		struct policyindex *spidx;
16680a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		struct sockaddr_storage addr;
16690a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		u_int8_t pref;
16700a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		struct sockaddr *src = iph2->src;
16710a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		struct sockaddr *dst = iph2->dst;
16720a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
16730a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		/* make inbound policy */
16740a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		iph2->src = dst;
16750a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		iph2->dst = src;
16760a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		if (pk_sendspdupdate2(iph2) < 0) {
16770a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			plog(LLV_ERROR, LOCATION, NULL,
16780a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				"pfkey spdupdate2(inbound) failed.\n");
16790a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			goto end;
16800a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		}
16810a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_DEBUG, LOCATION, NULL,
16820a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"pfkey spdupdate2(inbound) sent.\n");
16830a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
16840a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		spidx = (struct policyindex *)iph2->spidx_gen;
16850a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#ifdef HAVE_POLICY_FWD
16860a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		/* make forward policy if required */
16870a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		if (tunnel_mode_prop(iph2->approval)) {
16880a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			spidx->dir = IPSEC_DIR_FWD;
16890a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			if (pk_sendspdupdate2(iph2) < 0) {
16900a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				plog(LLV_ERROR, LOCATION, NULL,
16910a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang					"pfkey spdupdate2(forward) failed.\n");
16920a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				goto end;
16930a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			}
16940a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			plog(LLV_DEBUG, LOCATION, NULL,
16950a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				"pfkey spdupdate2(forward) sent.\n");
16960a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		}
16970a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#endif
16980a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
16990a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		/* make outbound policy */
17000a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		iph2->src = src;
17010a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		iph2->dst = dst;
17020a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		spidx->dir = IPSEC_DIR_OUTBOUND;
17030a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		addr = spidx->src;
17040a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		spidx->src = spidx->dst;
17050a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		spidx->dst = addr;
17060a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		pref = spidx->prefs;
17070a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		spidx->prefs = spidx->prefd;
17080a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		spidx->prefd = pref;
17090a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
17100a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		if (pk_sendspdupdate2(iph2) < 0) {
17110a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			plog(LLV_ERROR, LOCATION, NULL,
17120a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				"pfkey spdupdate2(outbound) failed.\n");
17130a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			goto end;
17140a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		}
17150a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_DEBUG, LOCATION, NULL,
17160a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"pfkey spdupdate2(outbound) sent.\n");
17170a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
17180a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		/* spidx_gen is unnecessary any more */
17190a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		delsp_bothdir((struct policyindex *)iph2->spidx_gen);
17200a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		racoon_free(iph2->spidx_gen);
17210a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		iph2->spidx_gen = NULL;
17220a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		iph2->generated_spidx=1;
17230a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
17240a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
17250a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	error = 0;
17260a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
17270a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangend:
17280a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	return error;
17290a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang}
17300a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
17310a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang/*
17320a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * create HASH, body (SA, NONCE) payload with isakmp header.
17330a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang */
17340a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangstatic vchar_t *
17350a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangquick_ir1mx(iph2, body, hash)
17360a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct ph2handle *iph2;
17370a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *body, *hash;
17380a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{
17390a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct isakmp *isakmp;
17400a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vchar_t *buf = NULL, *new = NULL;
17410a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	char *p;
17420a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	int tlen;
17430a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct isakmp_gen *gen;
17440a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	int error = ISAKMP_INTERNAL_ERROR;
17450a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
17460a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* create buffer for isakmp payload */
17470a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	tlen = sizeof(*isakmp)
17480a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		+ sizeof(*gen) + hash->l
17490a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		+ body->l;
17500a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	buf = vmalloc(tlen);
17510a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (buf == NULL) {
17520a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL,
17530a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"failed to get buffer to send.\n");
17540a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
17550a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
17560a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
17570a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* re-set encryption flag, for serurity. */
17580a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	iph2->flags |= ISAKMP_FLAG_E;
17590a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
17600a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* set isakmp header */
17610a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	p = set_isakmp_header2(buf, iph2, ISAKMP_NPTYPE_HASH);
17620a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (p == NULL)
17630a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
17640a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
17650a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* add HASH payload */
17660a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* XXX is next type always SA ? */
17670a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	p = set_isakmp_payload(p, hash, ISAKMP_NPTYPE_SA);
17680a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
17690a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* add body payload */
17700a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	memcpy(p, body->v, body->l);
17710a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
17720a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#ifdef HAVE_PRINT_ISAKMP_C
17730a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	isakmp_printpacket(buf, iph2->ph1->local, iph2->ph1->remote, 1);
17740a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#endif
17750a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
17760a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* encoding */
17770a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	new = oakley_do_encrypt(iph2->ph1, buf, iph2->ivm->ive, iph2->ivm->iv);
17780a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
17790a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (new == NULL)
17800a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
17810a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
17820a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	vfree(buf);
17830a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
17840a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	buf = new;
17850a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
17860a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	error = 0;
17870a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
17880a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangend:
17890a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (error && buf != NULL) {
17900a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		vfree(buf);
17910a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		buf = NULL;
17920a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
17930a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
17940a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	return buf;
17950a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang}
17960a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
17970a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang/*
17980a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * get remote's sainfo.
17990a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * NOTE: this function is for responder.
18000a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang */
18010a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangstatic int
18020a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangget_sainfo_r(iph2)
18030a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct ph2handle *iph2;
18040a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{
1805c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh	vchar_t *idsrc = NULL, *iddst = NULL;
1806c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh	int prefixlen;
18070a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	int error = ISAKMP_INTERNAL_ERROR;
1808c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh	int remoteid = 0;
18090a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
18100a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (iph2->id == NULL) {
1811c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh		switch (iph2->src->sa_family) {
1812c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh		case AF_INET:
1813c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh			prefixlen = sizeof(struct in_addr) << 3;
1814c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh			break;
1815c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh		case AF_INET6:
1816c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh			prefixlen = sizeof(struct in6_addr) << 3;
1817c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh			break;
1818c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh		default:
1819c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh			plog(LLV_ERROR, LOCATION, NULL,
1820c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh				"invalid family: %d\n", iph2->src->sa_family);
1821c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh			goto end;
1822c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh		}
1823c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh		idsrc = ipsecdoi_sockaddr2id(iph2->src, prefixlen,
18240a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang					IPSEC_ULPROTO_ANY);
18250a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	} else {
18260a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		idsrc = vdup(iph2->id);
18270a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
18280a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (idsrc == NULL) {
18290a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL,
18300a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"failed to set ID for source.\n");
18310a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
18320a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
18330a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
18340a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (iph2->id_p == NULL) {
1835c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh		switch (iph2->dst->sa_family) {
1836c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh		case AF_INET:
1837c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh			prefixlen = sizeof(struct in_addr) << 3;
1838c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh			break;
1839c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh		case AF_INET6:
1840c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh			prefixlen = sizeof(struct in6_addr) << 3;
1841c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh			break;
1842c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh		default:
1843c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh			plog(LLV_ERROR, LOCATION, NULL,
1844c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh				"invalid family: %d\n", iph2->dst->sa_family);
1845c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh			goto end;
1846c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh		}
1847c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh		iddst = ipsecdoi_sockaddr2id(iph2->dst, prefixlen,
18480a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang					IPSEC_ULPROTO_ANY);
18490a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	} else {
18500a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		iddst = vdup(iph2->id_p);
18510a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
18520a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (iddst == NULL) {
18530a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL,
18540a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"failed to set ID for destination.\n");
18550a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
18560a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
18570a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
1858f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	{
1859c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh		struct remoteconf *conf;
1860c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh		conf = getrmconf(iph2->dst);
1861c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh		if (conf != NULL)
1862c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh			remoteid=conf->ph1id;
1863c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh		else{
1864c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh			plog(LLV_DEBUG, LOCATION, NULL, "Warning: no valid rmconf !\n");
1865c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh			remoteid=0;
1866c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh		}
1867c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh
1868f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh	}
1869f8a6a7636d53a5730c58ae041e4e09ae12e1657cChia-chi Yeh
1870c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh	iph2->sainfo = getsainfo(idsrc, iddst, iph2->ph1->id_p, remoteid);
18710a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (iph2->sainfo == NULL) {
18720a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL,
18730a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"failed to get sainfo.\n");
18740a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		goto end;
18750a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
18760a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
18770a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#ifdef ENABLE_HYBRID
18780a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* xauth group inclusion check */
18790a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (iph2->sainfo->group != NULL)
18800a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		if(group_check(iph2->ph1,&iph2->sainfo->group->v,1))
18810a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			goto end;
18820a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#endif
18830a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
18840a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	plog(LLV_DEBUG, LOCATION, NULL,
18850a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		"selected sainfo: %s\n", sainfo2str(iph2->sainfo));
18860a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
18870a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	error = 0;
18880a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangend:
18890a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (idsrc)
18900a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		vfree(idsrc);
18910a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (iddst)
18920a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		vfree(iddst);
18930a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
18940a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	return error;
18950a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang}
18960a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
18970a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang/*
18980a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * Copy both IP addresses in ID payloads into [src,dst]_id if both ID types
18990a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * are IP address and same address family.
19000a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * Then get remote's policy from SPD copied from kernel.
19010a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * If the type of ID payload is address or subnet type, then the index is
19020a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * made from the payload.  If there is no ID payload, or the type of ID
19030a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * payload is NOT address type, then the index is made from the address
19040a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * pair of phase 1.
19050a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang * NOTE: This function is only for responder.
19060a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang */
19070a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangstatic int
19080a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wangget_proposal_r(iph2)
19090a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct ph2handle *iph2;
19100a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang{
19110a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct policyindex spidx;
19120a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct secpolicy *sp_in, *sp_out;
19130a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	int idi2type = 0;	/* switch whether copy IDs into id[src,dst]. */
19140a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	int error = ISAKMP_INTERNAL_ERROR;
19150a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
19160a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* check the existence of ID payload */
19170a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if ((iph2->id_p != NULL && iph2->id == NULL)
19180a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 || (iph2->id_p == NULL && iph2->id != NULL)) {
19190a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL,
19200a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"Both IDs wasn't found in payload.\n");
19210a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
19220a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
19230a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
1924c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh	/* make sure if id[src,dst] is null. */
1925c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh	if (iph2->src_id || iph2->dst_id) {
19260a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL,
19270a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"Why do ID[src,dst] exist already.\n");
19280a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		return ISAKMP_INTERNAL_ERROR;
19290a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
19300a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
19310a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	memset(&spidx, 0, sizeof(spidx));
19320a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
19330a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#define _XIDT(d) ((struct ipsecdoi_id_b *)(d)->v)->type
19340a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
19350a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* make a spidx; a key to search SPD */
19360a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	spidx.dir = IPSEC_DIR_INBOUND;
19370a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	spidx.ul_proto = 0;
19380a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
19390a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/*
19400a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 * make destination address in spidx from either ID payload
19410a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 * or phase 1 address into a address in spidx.
19420a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 */
19430a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (iph2->id != NULL
19440a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 && (_XIDT(iph2->id) == IPSECDOI_ID_IPV4_ADDR
19450a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	  || _XIDT(iph2->id) == IPSECDOI_ID_IPV6_ADDR
19460a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	  || _XIDT(iph2->id) == IPSECDOI_ID_IPV4_ADDR_SUBNET
19470a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	  || _XIDT(iph2->id) == IPSECDOI_ID_IPV6_ADDR_SUBNET)) {
19480a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		/* get a destination address of a policy */
19490a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		error = ipsecdoi_id2sockaddr(iph2->id,
19500a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				(struct sockaddr *)&spidx.dst,
19510a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				&spidx.prefd, &spidx.ul_proto);
19520a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		if (error)
19530a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			return error;
19540a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
19550a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#ifdef INET6
19560a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		/*
19570a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		 * get scopeid from the SA address.
19580a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		 * note that the phase 1 source address is used as
19590a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		 * a destination address to search for a inbound policy entry
19600a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		 * because rcoon is responder.
19610a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		 */
19620a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		if (_XIDT(iph2->id) == IPSECDOI_ID_IPV6_ADDR) {
19630a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			error = setscopeid((struct sockaddr *)&spidx.dst,
19640a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			                    iph2->src);
19650a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			if (error)
19660a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				return error;
19670a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		}
19680a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#endif
19690a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
19700a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		if (_XIDT(iph2->id) == IPSECDOI_ID_IPV4_ADDR
19710a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		 || _XIDT(iph2->id) == IPSECDOI_ID_IPV6_ADDR)
19720a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			idi2type = _XIDT(iph2->id);
19730a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
19740a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	} else {
19750a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
19760a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_DEBUG, LOCATION, NULL,
19770a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"get a destination address of SP index "
19780a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"from phase1 address "
19790a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"due to no ID payloads found "
19800a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"OR because ID type is not address.\n");
19810a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
19820a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		/*
19830a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		 * copy the SOURCE address of IKE into the DESTINATION address
19840a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		 * of the key to search the SPD because the direction of policy
19850a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		 * is inbound.
19860a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		 */
19870a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		memcpy(&spidx.dst, iph2->src, sysdep_sa_len(iph2->src));
19880a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		switch (spidx.dst.ss_family) {
19890a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		case AF_INET:
19900a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			spidx.prefd = sizeof(struct in_addr) << 3;
19910a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			break;
19920a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#ifdef INET6
19930a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		case AF_INET6:
19940a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			spidx.prefd = sizeof(struct in6_addr) << 3;
19950a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			break;
19960a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#endif
19970a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		default:
19980a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			spidx.prefd = 0;
19990a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			break;
20000a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		}
20010a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
20020a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
20030a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* make source address in spidx */
20040a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (iph2->id_p != NULL
20050a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 && (_XIDT(iph2->id_p) == IPSECDOI_ID_IPV4_ADDR
20060a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	  || _XIDT(iph2->id_p) == IPSECDOI_ID_IPV6_ADDR
20070a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	  || _XIDT(iph2->id_p) == IPSECDOI_ID_IPV4_ADDR_SUBNET
20080a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	  || _XIDT(iph2->id_p) == IPSECDOI_ID_IPV6_ADDR_SUBNET)) {
20090a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		/* get a source address of inbound SA */
20100a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		error = ipsecdoi_id2sockaddr(iph2->id_p,
20110a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				(struct sockaddr *)&spidx.src,
20120a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				&spidx.prefs, &spidx.ul_proto);
20130a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		if (error)
20140a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			return error;
20150a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
20160a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#ifdef INET6
20170a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		/*
20180a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		 * get scopeid from the SA address.
20190a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		 * for more detail, see above of this function.
20200a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		 */
20210a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		if (_XIDT(iph2->id_p) == IPSECDOI_ID_IPV6_ADDR) {
20220a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			error = setscopeid((struct sockaddr *)&spidx.src,
20230a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			                    iph2->dst);
20240a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			if (error)
20250a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				return error;
20260a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		}
20270a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#endif
20280a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
2029c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh		/* make id[src,dst] if both ID types are IP address and same */
2030c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh		if (_XIDT(iph2->id_p) == idi2type
2031c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh		 && spidx.dst.ss_family == spidx.src.ss_family) {
2032c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh			iph2->src_id = dupsaddr((struct sockaddr *)&spidx.dst);
2033c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh			if (iph2->src_id  == NULL) {
20340a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				plog(LLV_ERROR, LOCATION, NULL,
20350a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				    "buffer allocation failed.\n");
20360a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				return ISAKMP_INTERNAL_ERROR;
20370a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			}
2038c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh			iph2->dst_id = dupsaddr((struct sockaddr *)&spidx.src);
2039c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh			if (iph2->dst_id  == NULL) {
20400a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				plog(LLV_ERROR, LOCATION, NULL,
20410a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				    "buffer allocation failed.\n");
20420a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				return ISAKMP_INTERNAL_ERROR;
20430a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			}
20440a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		}
2045c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh
20460a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	} else {
20470a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_DEBUG, LOCATION, NULL,
2048c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh			"get a source address of SP index "
2049c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh			"from phase1 address "
2050c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh			"due to no ID payloads found "
2051c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh			"OR because ID type is not address.\n");
20520a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
20530a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		/* see above comment. */
20540a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		memcpy(&spidx.src, iph2->dst, sysdep_sa_len(iph2->dst));
20550a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		switch (spidx.src.ss_family) {
20560a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		case AF_INET:
20570a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			spidx.prefs = sizeof(struct in_addr) << 3;
20580a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			break;
20590a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#ifdef INET6
20600a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		case AF_INET6:
20610a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			spidx.prefs = sizeof(struct in6_addr) << 3;
20620a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			break;
20630a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#endif
20640a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		default:
20650a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			spidx.prefs = 0;
20660a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			break;
20670a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		}
20680a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
20690a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
20700a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#undef _XIDT
20710a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
20720a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	plog(LLV_DEBUG, LOCATION, NULL,
2073c91307af2622f6625525f3c1f9c954376df950adChia-chi Yeh		"get a src address from ID payload "
20740a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		"%s prefixlen=%u ul_proto=%u\n",
20750a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		saddr2str((struct sockaddr *)&spidx.src),
20760a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		spidx.prefs, spidx.ul_proto);
20770a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	plog(LLV_DEBUG, LOCATION, NULL,
20780a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		"get dst address from ID payload "
20790a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		"%s prefixlen=%u ul_proto=%u\n",
20800a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		saddr2str((struct sockaddr *)&spidx.dst),
20810a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		spidx.prefd, spidx.ul_proto);
20820a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
20830a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/*
20840a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 * convert the ul_proto if it is 0
20850a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 * because 0 in ID payload means a wild card.
20860a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 */
20870a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (spidx.ul_proto == 0)
20880a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		spidx.ul_proto = IPSEC_ULPROTO_ANY;
20890a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
20900a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#ifdef HAVE_SECCTX
20910a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/*
20920a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 * Need to use security context in spidx to ensure the correct
20930a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 * policy is selected. The only way to get the security context
20940a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 * is to look into the proposal sent by peer ahead of time.
20950a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 */
20960a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (get_security_context(iph2->sa, &spidx)) {
20970a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL,
20980a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		     "error occurred trying to get security context.\n");
20990a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		return ISAKMP_INTERNAL_ERROR;
21000a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
21010a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#endif /* HAVE_SECCTX */
21020a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
21030a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* get inbound policy */
21040a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	sp_in = getsp_r(&spidx);
21050a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (sp_in == NULL) {
21060a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		if (iph2->ph1->rmconf->gen_policy) {
21070a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			plog(LLV_INFO, LOCATION, NULL,
21080a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				"no policy found, "
21090a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				"try to generate the policy : %s\n",
21100a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				spidx2str(&spidx));
21110a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			iph2->spidx_gen = racoon_malloc(sizeof(spidx));
21120a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			if (!iph2->spidx_gen) {
21130a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				plog(LLV_ERROR, LOCATION, NULL,
21140a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang					"buffer allocation failed.\n");
21150a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				return ISAKMP_INTERNAL_ERROR;
21160a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			}
21170a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			memcpy(iph2->spidx_gen, &spidx, sizeof(spidx));
21180a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			return -2;	/* special value */
21190a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		}
21200a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL,
21210a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"no policy found: %s\n", spidx2str(&spidx));
21220a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		return ISAKMP_INTERNAL_ERROR;
21230a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
21240a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* Refresh existing generated policies
21250a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 */
21260a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (iph2->ph1->rmconf->gen_policy) {
21270a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_INFO, LOCATION, NULL,
21280a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			 "Update the generated policy : %s\n",
21290a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			 spidx2str(&spidx));
21300a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		iph2->spidx_gen = racoon_malloc(sizeof(spidx));
21310a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		if (!iph2->spidx_gen) {
21320a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			plog(LLV_ERROR, LOCATION, NULL,
21330a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang				 "buffer allocation failed.\n");
21340a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			return ISAKMP_INTERNAL_ERROR;
21350a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		}
21360a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		memcpy(iph2->spidx_gen, &spidx, sizeof(spidx));
21370a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
21380a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
21390a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* get outbound policy */
21400a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang    {
21410a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	struct sockaddr_storage addr;
21420a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	u_int8_t pref;
21430a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
21440a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	spidx.dir = IPSEC_DIR_OUTBOUND;
21450a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	addr = spidx.src;
21460a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	spidx.src = spidx.dst;
21470a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	spidx.dst = addr;
21480a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	pref = spidx.prefs;
21490a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	spidx.prefs = spidx.prefd;
21500a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	spidx.prefd = pref;
21510a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
21520a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	sp_out = getsp_r(&spidx);
21530a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (!sp_out) {
21540a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_WARNING, LOCATION, NULL,
21550a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"no outbound policy found: %s\n",
21560a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			spidx2str(&spidx));
21570a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
21580a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang    }
21590a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
21600a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	plog(LLV_DEBUG, LOCATION, NULL,
21610a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		"suitable SP found:%s\n", spidx2str(&spidx));
21620a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
21630a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/*
21640a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 * In the responder side, the inbound policy should be using IPsec.
21650a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 * outbound policy is not checked currently.
21660a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	 */
21670a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (sp_in->policy != IPSEC_POLICY_IPSEC) {
21680a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL,
21690a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"policy found, but no IPsec required: %s\n",
21700a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			spidx2str(&spidx));
21710a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		return ISAKMP_INTERNAL_ERROR;
21720a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
21730a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
21740a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	/* set new proposal derived from a policy into the iph2->proposal. */
21750a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (set_proposal_from_policy(iph2, sp_in, sp_out) < 0) {
21760a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		plog(LLV_ERROR, LOCATION, NULL,
21770a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang			"failed to create saprop.\n");
21780a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		return ISAKMP_INTERNAL_ERROR;
21790a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
21800a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
21810a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#ifdef HAVE_SECCTX
21820a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	if (spidx.sec_ctx.ctx_str) {
21830a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang		set_secctx_in_proposal(iph2, spidx);
21840a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	}
21850a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang#endif /* HAVE_SECCTX */
21860a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
21870a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang	return 0;
21880a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang}
21890a1907d434839af6a9cb6329bbde60b237bf53dcChung-yih Wang
2190