proposal.c revision c91307af2622f6625525f3c1f9c954376df950ad
1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)/*	$NetBSD: proposal.c,v 1.13.4.2 2008/07/22 13:25:42 vanhu Exp $	*/
2868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)/* $Id: proposal.c,v 1.13.4.2 2008/07/22 13:25:42 vanhu Exp $ */
4868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)/*
6868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * All rights reserved.
87dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch *
9f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Redistribution and use in source and binary forms, with or without
10f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * modification, are permitted provided that the following conditions
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * are met:
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * 1. Redistributions of source code must retain the above copyright
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *    notice, this list of conditions and the following disclaimer.
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * 2. Redistributions in binary form must reproduce the above copyright
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *    notice, this list of conditions and the following disclaimer in the
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *    documentation and/or other materials provided with the distribution.
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * 3. Neither the name of the project nor the names of its contributors
18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *    may be used to endorse or promote products derived from this software
19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *    without specific prior written permission.
20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *
21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * SUCH DAMAGE.
327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch */
337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "config.h"
357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
36a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include <sys/param.h>
37a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include <sys/types.h>
38a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include <sys/socket.h>
397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include <sys/queue.h>
40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include <netinet/in.h>
427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include PATH_IPSEC_H
43868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include <stdlib.h>
45010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include <stdio.h>
46010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include <string.h>
47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <errno.h>
48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "var.h"
50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "misc.h"
51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "vmbuf.h"
52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "plog.h"
53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "sockmisc.h"
54868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "debug.h"
55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
56868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "policy.h"
57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "pfkey.h"
58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "isakmp_var.h"
59868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "isakmp.h"
60a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "ipsec_doi.h"
61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "algorithm.h"
62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "proposal.h"
63868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "sainfo.h"
64868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "localconf.h"
65868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "remoteconf.h"
66868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "oakley.h"
67868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "handler.h"
68868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "strnames.h"
69868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "gcmalloc.h"
70868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#ifdef ENABLE_NATT
71010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "nattraversal.h"
72010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#endif
73010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
74868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static uint g_nextreqid = 1;
75868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
76868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)/* %%%
77868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * modules for ipsec sa spec
78868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) */
79868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)struct saprop *
80868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)newsaprop()
817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch{
82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	struct saprop *new;
83a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
84a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	new = racoon_calloc(1, sizeof(*new));
85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	if (new == NULL)
86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		return NULL;
877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch	return new;
89eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)struct saproto *
92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)newsaproto()
93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles){
94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	struct saproto *new;
95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
96868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	new = racoon_calloc(1, sizeof(*new));
97868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	if (new == NULL)
98868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		return NULL;
99868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
100868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	return new;
101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)/* set saprop to last part of the prop tree */
104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void
105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)inssaprop(head, new)
106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	struct saprop **head;
107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	struct saprop *new;
108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles){
109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	struct saprop *p;
110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	if (*head == NULL) {
112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		*head = new;
113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		return;
114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	}
115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	for (p = *head; p->next; p = p->next)
117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		;
118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	p->next = new;
119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	return;
121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)/* set saproto to the end of the proto tree in saprop */
124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void
125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)inssaproto(pp, new)
126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	struct saprop *pp;
127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	struct saproto *new;
1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci{
1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	struct saproto *p;
1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	for (p = pp->head; p && p->next; p = p->next)
1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci		;
1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	if (p == NULL)
1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci		pp->head = new;
1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	else
1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci		p->next = new;
1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	return;
1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci/* set saproto to the top of the proto tree in saprop */
1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid
14346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)inssaprotorev(pp, new)
144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      struct saprop *pp;
145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      struct saproto *new;
146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles){
147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new->next = pp->head;
148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      pp->head = new;
149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return;
151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)struct satrns *
154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)newsatrns()
155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles){
156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	struct satrns *new;
157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	new = racoon_calloc(1, sizeof(*new));
159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	if (new == NULL)
160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		return NULL;
161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	return new;
163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)/* set saproto to last part of the proto tree in saprop */
166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void
167868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)inssatrns(pr, new)
168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	struct saproto *pr;
1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	struct satrns *new;
1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci{
1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	struct satrns *tr;
1721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
173868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	for (tr = pr->head; tr && tr->next; tr = tr->next)
174868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		;
175868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	if (tr == NULL)
176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		pr->head = new;
1777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch	else
178868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		tr->next = new;
179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
180868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	return;
181868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)/*
184868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * take a single match between saprop.  allocate a new proposal and return it
185868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * for future use (like picking single proposal from a bundle).
186868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *	pp1: peer's proposal.
1877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch *	pp2: my proposal.
188868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * NOTE: In the case of initiator, must be ensured that there is no
189868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * modification of the proposal by calling cmp_aproppair_i() before
190a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * this function.
191a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * XXX cannot understand the comment!
192a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) */
193a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)struct saprop *
194a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)cmpsaprop_alloc(ph1, pp1, pp2, side)
195a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	struct ph1handle *ph1;
196a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	const struct saprop *pp1, *pp2;
197a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	int side;
198a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles){
199a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	struct saprop *newpp = NULL;
200868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	struct saproto *pr1, *pr2, *newpr = NULL;
201868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	struct satrns *tr1, *tr2, *newtr;
202868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	const int ordermatters = 0;
203ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch	int npr1, npr2;
2047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch	int spisizematch;
2057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
206868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	newpp = newsaprop();
207868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	if (newpp == NULL) {
208868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		plog(LLV_ERROR, LOCATION, NULL,
209868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)			"failed to allocate saprop.\n");
210868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		return NULL;
211868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	}
212868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	newpp->prop_no = pp1->prop_no;
213868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
214868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	/* see proposal.h about lifetime/key length and PFS selection. */
215ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
2167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch	/* check time/bytes lifetime and PFS */
217a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	switch (ph1->rmconf->pcheck_level) {
2187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch	case PROP_CHECK_OBEY:
219eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		newpp->lifetime = pp1->lifetime;
2207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		newpp->lifebyte = pp1->lifebyte;
221eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		newpp->pfs_group = pp1->pfs_group;
222a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)		break;
223a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
224868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	case PROP_CHECK_STRICT:
225868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		if (pp1->lifetime > pp2->lifetime) {
226868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)			plog(LLV_ERROR, LOCATION, NULL,
227a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)				"long lifetime proposed: "
228a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)				"my:%d peer:%d\n",
229a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)				(int)pp2->lifetime, (int)pp1->lifetime);
230868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)			goto err;
231868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		}
232868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		if (pp1->lifebyte > pp2->lifebyte) {
233868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)			plog(LLV_ERROR, LOCATION, NULL,
234868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)				"long lifebyte proposed: "
235868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)				"my:%d peer:%d\n",
236868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)				pp2->lifebyte, pp1->lifebyte);
237868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)			goto err;
238868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		}
239868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		newpp->lifetime = pp1->lifetime;
240a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		newpp->lifebyte = pp1->lifebyte;
241a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
242868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    prop_pfs_check:
243868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		if (pp2->pfs_group != 0 && pp1->pfs_group != pp2->pfs_group) {
244010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)			plog(LLV_ERROR, LOCATION, NULL,
24523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)				"pfs group mismatched: "
24623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)				"my:%d peer:%d\n",
24723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)				pp2->pfs_group, pp1->pfs_group);
248a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			goto err;
249a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		}
2507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		newpp->pfs_group = pp1->pfs_group;
2517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		break;
252868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
253868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	case PROP_CHECK_CLAIM:
254868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		/* lifetime */
255868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		if (pp1->lifetime <= pp2->lifetime) {
256868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)			newpp->lifetime = pp1->lifetime;
257868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		} else {
258868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)			newpp->lifetime = pp2->lifetime;
259868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)			newpp->claim |= IPSECDOI_ATTR_SA_LD_TYPE_SEC;
260868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)			plog(LLV_NOTIFY, LOCATION, NULL,
261868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)				"use own lifetime: "
262868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)				"my:%d peer:%d\n",
263868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)				(int)pp2->lifetime, (int)pp1->lifetime);
264868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		}
265868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
266868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		/* lifebyte */
267868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		if (pp1->lifebyte > pp2->lifebyte) {
268ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch			newpp->lifebyte = pp2->lifebyte;
2697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch			newpp->claim |= IPSECDOI_ATTR_SA_LD_TYPE_SEC;
2707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch			plog(LLV_NOTIFY, LOCATION, NULL,
2717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch				"use own lifebyte: "
2727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch				"my:%d peer:%d\n",
2737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch				pp2->lifebyte, pp1->lifebyte);
2747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		}
275868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		newpp->lifebyte = pp1->lifebyte;
276868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
277868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    		goto prop_pfs_check;
278868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		break;
279868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
280868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	case PROP_CHECK_EXACT:
281868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		if (pp1->lifetime != pp2->lifetime) {
282868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)			plog(LLV_ERROR, LOCATION, NULL,
283868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)				"lifetime mismatched: "
284868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)				"my:%d peer:%d\n",
285868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)				(int)pp2->lifetime, (int)pp1->lifetime);
286868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)			goto err;
287868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		}
288868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
289868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		if (pp1->lifebyte != pp2->lifebyte) {
290868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)			plog(LLV_ERROR, LOCATION, NULL,
291868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)				"lifebyte mismatched: "
292868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)				"my:%d peer:%d\n",
293868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)				pp2->lifebyte, pp1->lifebyte);
294ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch			goto err;
2957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		}
2967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		if (pp1->pfs_group != pp2->pfs_group) {
2977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch			plog(LLV_ERROR, LOCATION, NULL,
2987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch				"pfs group mismatched: "
2997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch				"my:%d peer:%d\n",
3007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch				pp2->pfs_group, pp1->pfs_group);
3017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch			goto err;
302868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		}
3037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		newpp->lifetime = pp1->lifetime;
304868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		newpp->lifebyte = pp1->lifebyte;
305868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		newpp->pfs_group = pp1->pfs_group;
306868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		break;
307868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
308868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	default:
309868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		plog(LLV_ERROR, LOCATION, NULL,
310868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)			"invalid pcheck_level why?.\n");
311868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		goto err;
312868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	}
313868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
314868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#ifdef HAVE_SECCTX
315868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	/* check the security_context properties.
316868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	 * It is possible for one side to have a security context
317ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch	 * and the other side doesn't. If so, this is an error.
3187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch	 */
3197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch	if (*pp1->sctx.ctx_str && !(*pp2->sctx.ctx_str)) {
321868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		plog(LLV_ERROR, LOCATION, NULL,
322868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		     "My proposal missing security context\n");
323868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		goto err;
324868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	}
325868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	if (!(*pp1->sctx.ctx_str) && *pp2->sctx.ctx_str) {
326868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		plog(LLV_ERROR, LOCATION, NULL,
327868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		     "Peer is missing security context\n");
328868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		goto err;
329868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	}
330868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
331ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch	if (*pp1->sctx.ctx_str && *pp2->sctx.ctx_str) {
3327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		if (pp1->sctx.ctx_doi == pp2->sctx.ctx_doi)
3337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch			newpp->sctx.ctx_doi = pp1->sctx.ctx_doi;
3347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		else {
3357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch			plog(LLV_ERROR, LOCATION, NULL,
3367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch			     "sec doi mismatched: my:%d peer:%d\n",
337868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)			     pp2->sctx.ctx_doi, pp1->sctx.ctx_doi);
338868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)			     goto err;
339868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		}
340868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
341868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		if (pp1->sctx.ctx_alg == pp2->sctx.ctx_alg)
342868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)			newpp->sctx.ctx_alg = pp1->sctx.ctx_alg;
343868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		else {
344868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)			plog(LLV_ERROR, LOCATION, NULL,
345868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)			     "sec alg mismatched: my:%d peer:%d\n",
346868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)			     pp2->sctx.ctx_alg, pp1->sctx.ctx_alg);
347868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)			goto err;
348868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		}
349868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
350868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		if ((pp1->sctx.ctx_strlen != pp2->sctx.ctx_strlen) ||
351ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch		     memcmp(pp1->sctx.ctx_str, pp2->sctx.ctx_str,
352a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)		     pp1->sctx.ctx_strlen) != 0) {
353a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)			plog(LLV_ERROR, LOCATION, NULL,
354a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)			     "sec ctx string mismatched: my:%s peer:%s\n",
355868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)			     pp2->sctx.ctx_str, pp1->sctx.ctx_str);
356a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)				goto err;
357868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		} else {
358868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)			newpp->sctx.ctx_strlen = pp1->sctx.ctx_strlen;
359eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			memcpy(newpp->sctx.ctx_str, pp1->sctx.ctx_str,
360a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)				pp1->sctx.ctx_strlen);
361868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		}
362868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	}
363868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#endif /* HAVE_SECCTX */
364868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
365868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	npr1 = npr2 = 0;
366868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	for (pr1 = pp1->head; pr1; pr1 = pr1->next)
367868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		npr1++;
368ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch	for (pr2 = pp2->head; pr2; pr2 = pr2->next)
3697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		npr2++;
3707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch	if (npr1 != npr2)
371a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)		goto err;
372868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
373a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	/* check protocol order */
374868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	pr1 = pp1->head;
375868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	pr2 = pp2->head;
376868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
377a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	while (1) {
378868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		if (!ordermatters) {
379868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)			/*
380868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)			 * XXX does not work if we have multiple proposals
381868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)			 * with the same proto_id
3821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci			 */
3831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci			switch (side) {
3841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci			case RESPONDER:
3851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci				if (!pr2)
3861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci					break;
387ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch				for (pr1 = pp1->head; pr1; pr1 = pr1->next) {
3887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch					if (pr1->proto_id == pr2->proto_id)
3897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch						break;
3907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch				}
3917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch				break;
3927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch			case INITIATOR:
3937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch				if (!pr1)
394868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)					break;
395868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)				for (pr2 = pp2->head; pr2; pr2 = pr2->next) {
3967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch					if (pr2->proto_id == pr1->proto_id)
397868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)						break;
398868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)				}
399868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)				break;
400868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)			}
401868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		}
402868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		if (!pr1 || !pr2)
403868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)			break;
404ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
4057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		if (pr1->proto_id != pr2->proto_id) {
4067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch			plog(LLV_ERROR, LOCATION, NULL,
4077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch				"proto_id mismatched: "
4087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch				"my:%s peer:%s\n",
4097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch				s_ipsecdoi_proto(pr2->proto_id),
4107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch				s_ipsecdoi_proto(pr1->proto_id));
411868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)			goto err;
412868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		}
4131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci		spisizematch = 0;
414868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		if (pr1->spisize == pr2->spisize)
415868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)			spisizematch = 1;
4167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		else if (pr1->proto_id == IPSECDOI_PROTO_IPCOMP) {
417868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)			/*
418868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)			 * draft-shacham-ippcp-rfc2393bis-05.txt:
419868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)			 * need to accept 16bit and 32bit SPI (CPI) for IPComp.
420a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			 */
421a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			if (pr1->spisize == sizeof(u_int16_t) &&
422a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			    pr2->spisize == sizeof(u_int32_t)) {
423a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				spisizematch = 1;
424a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			} else if (pr2->spisize == sizeof(u_int16_t) &&
425a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				 pr1->spisize == sizeof(u_int32_t)) {
426a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				spisizematch = 1;
427a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			}
428a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			if (spisizematch) {
429a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				plog(LLV_ERROR, LOCATION, NULL,
430a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				    "IPComp SPI size promoted "
431a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				    "from 16bit to 32bit\n");
432a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			}
433a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		}
434a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		if (!spisizematch) {
435a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			plog(LLV_ERROR, LOCATION, NULL,
436a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				"spisize mismatched: "
437a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				"my:%d peer:%d\n",
4381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci				(int)pr2->spisize, (int)pr1->spisize);
439a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			goto err;
440a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		}
441a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
442a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#ifdef ENABLE_NATT
443a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		if ((ph1->natt_flags & NAT_DETECTED) &&
444a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		    natt_udp_encap (pr2->encmode))
445a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		{
446a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			plog(LLV_INFO, LOCATION, NULL, "Adjusting my encmode %s->%s\n",
447a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			     s_ipsecdoi_encmode(pr2->encmode),
448a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			     s_ipsecdoi_encmode(pr2->encmode - ph1->natt_options->mode_udp_diff));
449a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			pr2->encmode -= ph1->natt_options->mode_udp_diff;
450868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)			pr2->udp_encap = 1;
451868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		}
452868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
453868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		if ((ph1->natt_flags & NAT_DETECTED) &&
454ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch		    natt_udp_encap (pr1->encmode))
4557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		{
456868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)			plog(LLV_INFO, LOCATION, NULL, "Adjusting peer's encmode %s(%d)->%s(%d)\n",
457868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)			     s_ipsecdoi_encmode(pr1->encmode),
458868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)			     pr1->encmode,
4597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch			     s_ipsecdoi_encmode(pr1->encmode - ph1->natt_options->mode_udp_diff),
4607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch			     pr1->encmode - ph1->natt_options->mode_udp_diff);
461eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			pr1->encmode -= ph1->natt_options->mode_udp_diff;
4627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch			pr1->udp_encap = 1;
4637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		}
4647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#endif
4657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
466f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)		if (pr1->encmode != pr2->encmode) {
467f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)			plog(LLV_ERROR, LOCATION, NULL,
468f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				"encmode mismatched: "
469f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				"my:%s peer:%s\n",
470f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				s_ipsecdoi_encmode(pr2->encmode),
4717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch				s_ipsecdoi_encmode(pr1->encmode));
472868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)			goto err;
4737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		}
4747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
4757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		for (tr1 = pr1->head; tr1; tr1 = tr1->next) {
4767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch			for (tr2 = pr2->head; tr2; tr2 = tr2->next) {
477868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)				if (cmpsatrns(pr1->proto_id, tr1, tr2, ph1->rmconf->pcheck_level) == 0)
478868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)					goto found;
479868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)			}
480868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		}
481868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
482868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		goto err;
483868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
484868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	    found:
485868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		newpr = newsaproto();
486868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		if (newpr == NULL) {
4877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch			plog(LLV_ERROR, LOCATION, NULL,
4887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch				"failed to allocate saproto.\n");
489868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)			goto err;
490868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		}
491868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		newpr->proto_id = pr1->proto_id;
492868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		newpr->spisize = pr1->spisize;
493868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		newpr->encmode = pr1->encmode;
494868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		newpr->spi = pr2->spi;		/* copy my SPI */
495868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		newpr->spi_p = pr1->spi;	/* copy peer's SPI */
496868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		newpr->reqid_in = pr2->reqid_in;
497		newpr->reqid_out = pr2->reqid_out;
498#ifdef ENABLE_NATT
499		newpr->udp_encap = pr1->udp_encap | pr2->udp_encap;
500#endif
501
502		newtr = newsatrns();
503		if (newtr == NULL) {
504			plog(LLV_ERROR, LOCATION, NULL,
505				"failed to allocate satrns.\n");
506			racoon_free(newpr);
507			goto err;
508		}
509		newtr->trns_no = tr1->trns_no;
510		newtr->trns_id = tr1->trns_id;
511		newtr->encklen = tr1->encklen;
512		newtr->authtype = tr1->authtype;
513
514		inssatrns(newpr, newtr);
515		inssaproto(newpp, newpr);
516
517		pr1 = pr1->next;
518		pr2 = pr2->next;
519	}
520
521	/* XXX should check if we have visited all items or not */
522	if (!ordermatters) {
523		switch (side) {
524		case RESPONDER:
525			if (!pr2)
526				pr1 = NULL;
527			break;
528		case INITIATOR:
529			if (!pr1)
530				pr2 = NULL;
531			break;
532		}
533	}
534
535	/* should be matched all protocols in a proposal */
536	if (pr1 != NULL || pr2 != NULL)
537		goto err;
538
539	return newpp;
540
541err:
542	flushsaprop(newpp);
543	return NULL;
544}
545
546/* take a single match between saprop.  returns 0 if pp1 equals to pp2. */
547int
548cmpsaprop(pp1, pp2)
549	const struct saprop *pp1, *pp2;
550{
551	if (pp1->pfs_group != pp2->pfs_group) {
552		plog(LLV_WARNING, LOCATION, NULL,
553			"pfs_group mismatch. mine:%d peer:%d\n",
554			pp1->pfs_group, pp2->pfs_group);
555		/* FALLTHRU */
556	}
557
558	if (pp1->lifetime > pp2->lifetime) {
559		plog(LLV_WARNING, LOCATION, NULL,
560			"less lifetime proposed. mine:%d peer:%d\n",
561			(int)pp1->lifetime, (int)pp2->lifetime);
562		/* FALLTHRU */
563	}
564	if (pp1->lifebyte > pp2->lifebyte) {
565		plog(LLV_WARNING, LOCATION, NULL,
566			"less lifebyte proposed. mine:%d peer:%d\n",
567			pp1->lifebyte, pp2->lifebyte);
568		/* FALLTHRU */
569	}
570
571	return 0;
572}
573
574/*
575 * take a single match between satrns.  returns 0 if tr1 equals to tr2.
576 * tr1: peer's satrns
577 * tr2: my satrns
578 */
579int
580cmpsatrns(proto_id, tr1, tr2, check_level)
581	int proto_id;
582	const struct satrns *tr1, *tr2;
583	int check_level;
584{
585	if (tr1->trns_id != tr2->trns_id) {
586		plog(LLV_WARNING, LOCATION, NULL,
587			"trns_id mismatched: "
588			"my:%s peer:%s\n",
589			s_ipsecdoi_trns(proto_id, tr2->trns_id),
590			s_ipsecdoi_trns(proto_id, tr1->trns_id));
591		return 1;
592	}
593
594	if (tr1->authtype != tr2->authtype) {
595		plog(LLV_WARNING, LOCATION, NULL,
596			"authtype mismatched: "
597			"my:%s peer:%s\n",
598			s_ipsecdoi_attr_v(IPSECDOI_ATTR_AUTH, tr2->authtype),
599			s_ipsecdoi_attr_v(IPSECDOI_ATTR_AUTH, tr1->authtype));
600		return 1;
601	}
602
603	/* Check key length regarding checkmode
604	 * XXX Shall we send some kind of notify message when key length rejected ?
605	 */
606	switch(check_level){
607	case PROP_CHECK_OBEY:
608		return 0;
609		break;
610
611	case PROP_CHECK_STRICT:
612		/* FALLTHROUGH */
613	case PROP_CHECK_CLAIM:
614		if (tr1->encklen < tr2->encklen) {
615		plog(LLV_WARNING, LOCATION, NULL,
616				 "low key length proposed, "
617				 "mine:%d peer:%d.\n",
618			tr2->encklen, tr1->encklen);
619			return 1;
620		}
621		break;
622	case PROP_CHECK_EXACT:
623		if (tr1->encklen != tr2->encklen) {
624			plog(LLV_WARNING, LOCATION, NULL,
625				 "key length mismatched, "
626				 "mine:%d peer:%d.\n",
627				 tr2->encklen, tr1->encklen);
628			return 1;
629		}
630		break;
631	}
632
633	return 0;
634}
635
636int
637set_satrnsbysainfo(pr, sainfo)
638	struct saproto *pr;
639	struct sainfo *sainfo;
640{
641	struct sainfoalg *a, *b;
642	struct satrns *newtr;
643	int t;
644
645	switch (pr->proto_id) {
646	case IPSECDOI_PROTO_IPSEC_AH:
647		if (sainfo->algs[algclass_ipsec_auth] == NULL) {
648			plog(LLV_ERROR, LOCATION, NULL,
649				"no auth algorithm found\n");
650			goto err;
651		}
652		t = 1;
653		for (a = sainfo->algs[algclass_ipsec_auth]; a; a = a->next) {
654
655			if (a->alg == IPSECDOI_ATTR_AUTH_NONE)
656				continue;
657
658			/* allocate satrns */
659			newtr = newsatrns();
660			if (newtr == NULL) {
661				plog(LLV_ERROR, LOCATION, NULL,
662					"failed to allocate satrns.\n");
663				goto err;
664			}
665
666			newtr->trns_no = t++;
667			newtr->trns_id = ipsecdoi_authalg2trnsid(a->alg);
668			newtr->authtype = a->alg;
669
670			inssatrns(pr, newtr);
671		}
672		break;
673	case IPSECDOI_PROTO_IPSEC_ESP:
674		if (sainfo->algs[algclass_ipsec_enc] == NULL) {
675			plog(LLV_ERROR, LOCATION, NULL,
676				"no encryption algorithm found\n");
677			goto err;
678		}
679		t = 1;
680		for (a = sainfo->algs[algclass_ipsec_enc]; a; a = a->next) {
681			for (b = sainfo->algs[algclass_ipsec_auth]; b; b = b->next) {
682				/* allocate satrns */
683				newtr = newsatrns();
684				if (newtr == NULL) {
685					plog(LLV_ERROR, LOCATION, NULL,
686						"failed to allocate satrns.\n");
687					goto err;
688				}
689
690				newtr->trns_no = t++;
691				newtr->trns_id = a->alg;
692				newtr->encklen = a->encklen;
693				newtr->authtype = b->alg;
694
695				inssatrns(pr, newtr);
696			}
697		}
698		break;
699	case IPSECDOI_PROTO_IPCOMP:
700		if (sainfo->algs[algclass_ipsec_comp] == NULL) {
701			plog(LLV_ERROR, LOCATION, NULL,
702				"no ipcomp algorithm found\n");
703			goto err;
704		}
705		t = 1;
706		for (a = sainfo->algs[algclass_ipsec_comp]; a; a = a->next) {
707
708			/* allocate satrns */
709			newtr = newsatrns();
710			if (newtr == NULL) {
711				plog(LLV_ERROR, LOCATION, NULL,
712					"failed to allocate satrns.\n");
713				goto err;
714			}
715
716			newtr->trns_no = t++;
717			newtr->trns_id = a->alg;
718			newtr->authtype = IPSECDOI_ATTR_AUTH_NONE; /*no auth*/
719
720			inssatrns(pr, newtr);
721		}
722		break;
723	default:
724		plog(LLV_ERROR, LOCATION, NULL,
725			"unknown proto_id (%d).\n", pr->proto_id);
726		goto err;
727	}
728
729	/* no proposal found */
730	if (pr->head == NULL) {
731		plog(LLV_ERROR, LOCATION, NULL, "no algorithms found.\n");
732		return -1;
733	}
734
735	return 0;
736
737err:
738	flushsatrns(pr->head);
739	return -1;
740}
741
742struct saprop *
743aproppair2saprop(p0)
744	struct prop_pair *p0;
745{
746	struct prop_pair *p, *t;
747	struct saprop *newpp;
748	struct saproto *newpr;
749	struct satrns *newtr;
750	u_int8_t *spi;
751
752	if (p0 == NULL)
753		return NULL;
754
755	/* allocate ipsec a sa proposal */
756	newpp = newsaprop();
757	if (newpp == NULL) {
758		plog(LLV_ERROR, LOCATION, NULL,
759			"failed to allocate saprop.\n");
760		return NULL;
761	}
762	newpp->prop_no = p0->prop->p_no;
763	/* lifetime & lifebyte must be updated later */
764
765	for (p = p0; p; p = p->next) {
766
767		/* allocate ipsec sa protocol */
768		newpr = newsaproto();
769		if (newpr == NULL) {
770			plog(LLV_ERROR, LOCATION, NULL,
771				"failed to allocate saproto.\n");
772			goto err;
773		}
774
775		/* check spi size */
776		/* XXX should be handled isakmp cookie */
777		if (sizeof(newpr->spi) < p->prop->spi_size) {
778			plog(LLV_ERROR, LOCATION, NULL,
779				"invalid spi size %d.\n", p->prop->spi_size);
780			racoon_free(newpr);
781			goto err;
782		}
783
784		/*
785		 * XXX SPI bits are left-filled, for use with IPComp.
786		 * we should be switching to variable-length spi field...
787		 */
788		newpr->proto_id = p->prop->proto_id;
789		newpr->spisize = p->prop->spi_size;
790		memset(&newpr->spi, 0, sizeof(newpr->spi));
791		spi = (u_int8_t *)&newpr->spi;
792		spi += sizeof(newpr->spi);
793		spi -= p->prop->spi_size;
794		memcpy(spi, p->prop + 1, p->prop->spi_size);
795		newpr->reqid_in = 0;
796		newpr->reqid_out = 0;
797
798		for (t = p; t; t = t->tnext) {
799
800			plog(LLV_DEBUG, LOCATION, NULL,
801				"prop#=%d prot-id=%s spi-size=%d "
802				"#trns=%d trns#=%d trns-id=%s\n",
803				t->prop->p_no,
804				s_ipsecdoi_proto(t->prop->proto_id),
805				t->prop->spi_size, t->prop->num_t,
806				t->trns->t_no,
807				s_ipsecdoi_trns(t->prop->proto_id,
808				t->trns->t_id));
809
810			/* allocate ipsec sa transform */
811			newtr = newsatrns();
812			if (newtr == NULL) {
813				plog(LLV_ERROR, LOCATION, NULL,
814					"failed to allocate satrns.\n");
815				racoon_free(newpr);
816				goto err;
817			}
818
819			if (ipsecdoi_t2satrns(t->trns,
820			    newpp, newpr, newtr) < 0) {
821				flushsaprop(newpp);
822				racoon_free(newtr);
823				racoon_free(newpr);
824				return NULL;
825			}
826
827			inssatrns(newpr, newtr);
828		}
829
830		/*
831		 * If the peer does not specify encryption mode, use
832		 * transport mode by default.  This is to conform to
833		 * draft-shacham-ippcp-rfc2393bis-08.txt (explicitly specifies
834		 * that unspecified == transport), as well as RFC2407
835		 * (unspecified == implementation dependent default).
836		 */
837		if (newpr->encmode == 0)
838			newpr->encmode = IPSECDOI_ATTR_ENC_MODE_TRNS;
839
840		inssaproto(newpp, newpr);
841	}
842
843	return newpp;
844
845err:
846	flushsaprop(newpp);
847	return NULL;
848}
849
850void
851flushsaprop(head)
852	struct saprop *head;
853{
854	struct saprop *p, *save;
855
856	for (p = head; p != NULL; p = save) {
857		save = p->next;
858		flushsaproto(p->head);
859		racoon_free(p);
860	}
861
862	return;
863}
864
865void
866flushsaproto(head)
867	struct saproto *head;
868{
869	struct saproto *p, *save;
870
871	for (p = head; p != NULL; p = save) {
872		save = p->next;
873		flushsatrns(p->head);
874		vfree(p->keymat);
875		vfree(p->keymat_p);
876		racoon_free(p);
877	}
878
879	return;
880}
881
882void
883flushsatrns(head)
884	struct satrns *head;
885{
886	struct satrns *p, *save;
887
888	for (p = head; p != NULL; p = save) {
889		save = p->next;
890		racoon_free(p);
891	}
892
893	return;
894}
895
896/*
897 * print multiple proposals
898 */
899void
900printsaprop(pri, pp)
901	const int pri;
902	const struct saprop *pp;
903{
904	const struct saprop *p;
905
906	if (pp == NULL) {
907		plog(pri, LOCATION, NULL, "(null)");
908		return;
909	}
910
911	for (p = pp; p; p = p->next) {
912		printsaprop0(pri, p);
913	}
914
915	return;
916}
917
918/*
919 * print one proposal.
920 */
921void
922printsaprop0(pri, pp)
923	int pri;
924	const struct saprop *pp;
925{
926	const struct saproto *p;
927
928	if (pp == NULL)
929		return;
930
931	for (p = pp->head; p; p = p->next) {
932		printsaproto(pri, p);
933	}
934
935	return;
936}
937
938void
939printsaproto(pri, pr)
940	const int pri;
941	const struct saproto *pr;
942{
943	struct satrns *tr;
944
945	if (pr == NULL)
946		return;
947
948	plog(pri, LOCATION, NULL,
949		" (proto_id=%s spisize=%d spi=%08lx spi_p=%08lx "
950		"encmode=%s reqid=%d:%d)\n",
951		s_ipsecdoi_proto(pr->proto_id),
952		(int)pr->spisize,
953		(unsigned long)ntohl(pr->spi),
954		(unsigned long)ntohl(pr->spi_p),
955		s_ipsecdoi_attr_v(IPSECDOI_ATTR_ENC_MODE, pr->encmode),
956		(int)pr->reqid_in, (int)pr->reqid_out);
957
958	for (tr = pr->head; tr; tr = tr->next) {
959		printsatrns(pri, pr->proto_id, tr);
960	}
961
962	return;
963}
964
965void
966printsatrns(pri, proto_id, tr)
967	const int pri;
968	const int proto_id;
969	const struct satrns *tr;
970{
971	if (tr == NULL)
972		return;
973
974	switch (proto_id) {
975	case IPSECDOI_PROTO_IPSEC_AH:
976		plog(pri, LOCATION, NULL,
977			"  (trns_id=%s authtype=%s)\n",
978			s_ipsecdoi_trns(proto_id, tr->trns_id),
979			s_ipsecdoi_attr_v(IPSECDOI_ATTR_AUTH, tr->authtype));
980		break;
981	case IPSECDOI_PROTO_IPSEC_ESP:
982		plog(pri, LOCATION, NULL,
983			"  (trns_id=%s encklen=%d authtype=%s)\n",
984			s_ipsecdoi_trns(proto_id, tr->trns_id),
985			tr->encklen,
986			s_ipsecdoi_attr_v(IPSECDOI_ATTR_AUTH, tr->authtype));
987		break;
988	case IPSECDOI_PROTO_IPCOMP:
989		plog(pri, LOCATION, NULL,
990			"  (trns_id=%s)\n",
991			s_ipsecdoi_trns(proto_id, tr->trns_id));
992		break;
993	default:
994		plog(pri, LOCATION, NULL,
995			"(unknown proto_id %d)\n", proto_id);
996	}
997
998	return;
999}
1000
1001void
1002print_proppair0(pri, p, level)
1003	int pri;
1004	struct prop_pair *p;
1005	int level;
1006{
1007	char spc[21];
1008
1009	memset(spc, ' ', sizeof(spc));
1010	spc[sizeof(spc) - 1] = '\0';
1011	if (level < 20) {
1012		spc[level] = '\0';
1013	}
1014
1015	plog(pri, LOCATION, NULL,
1016		"%s%p: next=%p tnext=%p\n", spc, p, p->next, p->tnext);
1017	if (p->next)
1018		print_proppair0(pri, p->next, level + 1);
1019	if (p->tnext)
1020		print_proppair0(pri, p->tnext, level + 1);
1021}
1022
1023void
1024print_proppair(pri, p)
1025	int pri;
1026	struct prop_pair *p;
1027{
1028	print_proppair0(pri, p, 1);
1029}
1030
1031int
1032set_proposal_from_policy(iph2, sp_main, sp_sub)
1033	struct ph2handle *iph2;
1034	struct secpolicy *sp_main, *sp_sub;
1035{
1036	struct saprop *newpp;
1037	struct ipsecrequest *req;
1038	int encmodesv = IPSECDOI_ATTR_ENC_MODE_TRNS; /* use only when complex_bundle */
1039
1040	newpp = newsaprop();
1041	if (newpp == NULL) {
1042		plog(LLV_ERROR, LOCATION, NULL,
1043			"failed to allocate saprop.\n");
1044		goto err;
1045	}
1046	newpp->prop_no = 1;
1047	newpp->lifetime = iph2->sainfo->lifetime;
1048	newpp->lifebyte = iph2->sainfo->lifebyte;
1049	newpp->pfs_group = iph2->sainfo->pfs_group;
1050
1051	if (lcconf->complex_bundle)
1052		goto skip1;
1053
1054	/*
1055	 * decide the encryption mode of this SA bundle.
1056	 * the mode becomes tunnel mode when there is even one policy
1057	 * of tunnel mode in the SPD.  otherwise the mode becomes
1058	 * transport mode.
1059	 */
1060	for (req = sp_main->req; req; req = req->next) {
1061		if (req->saidx.mode == IPSEC_MODE_TUNNEL) {
1062			encmodesv = pfkey2ipsecdoi_mode(req->saidx.mode);
1063#ifdef ENABLE_NATT
1064			if (iph2->ph1 && (iph2->ph1->natt_flags & NAT_DETECTED))
1065				encmodesv += iph2->ph1->natt_options->mode_udp_diff;
1066#endif
1067			break;
1068		}
1069	}
1070
1071    skip1:
1072	for (req = sp_main->req; req; req = req->next) {
1073		struct saproto *newpr;
1074		caddr_t paddr = NULL;
1075
1076		/*
1077		 * check if SA bundle ?
1078		 * nested SAs negotiation is NOT supported.
1079		 *       me +--- SA1 ---+ peer1
1080		 *       me +--- SA2 --------------+ peer2
1081		 */
1082#ifdef __linux__
1083		if (req->saidx.src.ss_family && req->saidx.dst.ss_family) {
1084#else
1085		if (req->saidx.src.ss_len && req->saidx.dst.ss_len) {
1086#endif
1087			/* check the end of ip addresses of SA */
1088			if (iph2->side == INITIATOR)
1089				paddr = (caddr_t)&req->saidx.dst;
1090			else
1091				paddr = (caddr_t)&req->saidx.src;
1092		}
1093
1094		/* allocate ipsec sa protocol */
1095		newpr = newsaproto();
1096		if (newpr == NULL) {
1097			plog(LLV_ERROR, LOCATION, NULL,
1098				"failed to allocate saproto.\n");
1099			goto err;
1100		}
1101
1102		newpr->proto_id = ipproto2doi(req->saidx.proto);
1103		if (newpr->proto_id == IPSECDOI_PROTO_IPCOMP)
1104			newpr->spisize = 2;
1105		else
1106			newpr->spisize = 4;
1107		if (lcconf->complex_bundle) {
1108			newpr->encmode = pfkey2ipsecdoi_mode(req->saidx.mode);
1109#ifdef ENABLE_NATT
1110			if (iph2->ph1 && (iph2->ph1->natt_flags & NAT_DETECTED))
1111				newpr->encmode +=
1112				    iph2->ph1->natt_options->mode_udp_diff;
1113#endif
1114		}
1115		else
1116			newpr->encmode = encmodesv;
1117
1118		if (iph2->side == INITIATOR)
1119			newpr->reqid_out = req->saidx.reqid;
1120		else
1121			newpr->reqid_in = req->saidx.reqid;
1122
1123		if (set_satrnsbysainfo(newpr, iph2->sainfo) < 0) {
1124			plog(LLV_ERROR, LOCATION, NULL,
1125				"failed to get algorithms.\n");
1126			racoon_free(newpr);
1127			goto err;
1128		}
1129
1130		/* set new saproto */
1131		inssaprotorev(newpp, newpr);
1132	}
1133
1134	/* get reqid_in from inbound policy */
1135	if (sp_sub) {
1136		struct saproto *pr;
1137
1138		req = sp_sub->req;
1139		pr = newpp->head;
1140		while (req && pr) {
1141			if (iph2->side == INITIATOR)
1142				pr->reqid_in = req->saidx.reqid;
1143			else
1144				pr->reqid_out = req->saidx.reqid;
1145			pr = pr->next;
1146			req = req->next;
1147		}
1148		if (pr || req) {
1149			plog(LLV_NOTIFY, LOCATION, NULL,
1150				"There is a difference "
1151				"between the in/out bound policies in SPD.\n");
1152		}
1153	}
1154
1155	iph2->proposal = newpp;
1156
1157	printsaprop0(LLV_DEBUG, newpp);
1158
1159	return 0;
1160err:
1161	flushsaprop(newpp);
1162	return -1;
1163}
1164
1165/*
1166 * generate a policy from peer's proposal.
1167 * this function unconditionally choices first proposal in SA payload
1168 * passed by peer.
1169 */
1170int
1171set_proposal_from_proposal(iph2)
1172	struct ph2handle *iph2;
1173{
1174        struct saprop *newpp = NULL, *pp0, *pp_peer = NULL;
1175	struct saproto *newpr = NULL, *pr;
1176	struct prop_pair **pair;
1177	int error = -1;
1178	int i;
1179
1180	/* get proposal pair */
1181	pair = get_proppair(iph2->sa, IPSECDOI_TYPE_PH2);
1182	if (pair == NULL)
1183		goto end;
1184
1185	/*
1186	 * make my proposal according as the client proposal.
1187	 * XXX assumed there is only one proposal even if it's the SA bundle.
1188	 */
1189        for (i = 0; i < MAXPROPPAIRLEN; i++) {
1190                if (pair[i] == NULL)
1191                        continue;
1192
1193		if (pp_peer != NULL)
1194			flushsaprop(pp_peer);
1195
1196		pp_peer = aproppair2saprop(pair[i]);
1197		if (pp_peer == NULL)
1198			goto end;
1199
1200		pp0 = newsaprop();
1201		if (pp0 == NULL) {
1202			plog(LLV_ERROR, LOCATION, NULL,
1203				"failed to allocate saprop.\n");
1204			goto end;
1205		}
1206		pp0->prop_no = 1;
1207		pp0->lifetime = iph2->sainfo->lifetime;
1208		pp0->lifebyte = iph2->sainfo->lifebyte;
1209		pp0->pfs_group = iph2->sainfo->pfs_group;
1210
1211#ifdef HAVE_SECCTX
1212		if (*pp_peer->sctx.ctx_str) {
1213			pp0->sctx.ctx_doi = pp_peer->sctx.ctx_doi;
1214			pp0->sctx.ctx_alg = pp_peer->sctx.ctx_alg;
1215			pp0->sctx.ctx_strlen = pp_peer->sctx.ctx_strlen;
1216			memcpy(pp0->sctx.ctx_str, pp_peer->sctx.ctx_str,
1217			       pp_peer->sctx.ctx_strlen);
1218		}
1219#endif /* HAVE_SECCTX */
1220
1221		if (pp_peer->next != NULL) {
1222			plog(LLV_ERROR, LOCATION, NULL,
1223				"pp_peer is inconsistency, ignore it.\n");
1224			/*FALLTHROUGH*/
1225		}
1226
1227		for (pr = pp_peer->head; pr; pr = pr->next)
1228		{
1229			struct remoteconf *conf;
1230
1231			newpr = newsaproto();
1232			if (newpr == NULL)
1233			{
1234				plog(LLV_ERROR, LOCATION, NULL,
1235					"failed to allocate saproto.\n");
1236				racoon_free(pp0);
1237				goto end;
1238			}
1239			newpr->proto_id = pr->proto_id;
1240			newpr->spisize = pr->spisize;
1241			newpr->encmode = pr->encmode;
1242			newpr->spi = 0;
1243			newpr->spi_p = pr->spi;     /* copy peer's SPI */
1244			newpr->reqid_in = 0;
1245			newpr->reqid_out = 0;
1246
1247			conf = getrmconf(iph2->dst);
1248			if (conf != NULL &&
1249				conf->gen_policy == GENERATE_POLICY_UNIQUE){
1250				newpr->reqid_in = g_nextreqid ;
1251				newpr->reqid_out = g_nextreqid ++;
1252				/*
1253				 * XXX there is a (very limited)
1254				 * risk of reusing the same reqid
1255				 * as another SP entry for the same peer
1256				 */
1257				if(g_nextreqid >= IPSEC_MANUAL_REQID_MAX)
1258					g_nextreqid = 1;
1259			}else{
1260				newpr->reqid_in = 0;
1261				newpr->reqid_out = 0;
1262			}
1263
1264			if (set_satrnsbysainfo(newpr, iph2->sainfo) < 0)
1265			{
1266				plog(LLV_ERROR, LOCATION, NULL,
1267					"failed to get algorithms.\n");
1268				racoon_free(newpr);
1269				racoon_free(pp0);
1270				goto end;
1271			}
1272			inssaproto(pp0, newpr);
1273		}
1274
1275		inssaprop(&newpp, pp0);
1276        }
1277
1278	plog(LLV_DEBUG, LOCATION, NULL, "make a proposal from peer's:\n");
1279	printsaprop0(LLV_DEBUG, newpp);
1280
1281	iph2->proposal = newpp;
1282
1283	error = 0;
1284
1285end:
1286	if (error && newpp)
1287		flushsaprop(newpp);
1288
1289	if (pp_peer)
1290		flushsaprop(pp_peer);
1291	if (pair)
1292		free_proppair(pair);
1293	return error;
1294}
1295