1/* $Id: pfkey.c,v 1.31.2.10 2005/10/03 14:52:19 manubsd Exp $ */
2
3/*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 *    may be used to endorse or promote products derived from this software
17 *    without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include "config.h"
33#include "racoon_types.h"
34
35#include <stdlib.h>
36#include <string.h>
37#include <stdio.h>
38#include <netdb.h>
39#include <errno.h>
40#ifdef HAVE_UNISTD_H
41#include <unistd.h>
42#endif
43#include <netdb.h>
44#include <netinet/in.h>
45#include <arpa/inet.h>
46
47#ifdef ENABLE_NATT
48#include <netinet/udp.h>
49#endif
50
51#include <sys/types.h>
52#include <sys/param.h>
53#include <sys/socket.h>
54#include <sys/queue.h>
55#include <sys/sysctl.h>
56
57#include <net/route.h>
58#include <net/pfkeyv2.h>
59
60#include <netinet/in.h>
61#ifndef HAVE_NETINET6_IPSEC
62#include <netinet/ipsec.h>
63#else
64#include <netinet6/ipsec.h>
65#endif
66
67#include "libpfkey.h"
68
69#include "var.h"
70#include "misc.h"
71#include "vmbuf.h"
72#include "plog.h"
73#include "sockmisc.h"
74#include "debug.h"
75#include "fsm.h"
76#include "ike_session.h"
77
78#include "schedule.h"
79#include "localconf.h"
80#include "remoteconf.h"
81#include "isakmp_var.h"
82#include "isakmp.h"
83#include "isakmp_inf.h"
84#include "ipsec_doi.h"
85#include "oakley.h"
86#include "pfkey.h"
87#include "handler.h"
88#include "policy.h"
89#include "algorithm.h"
90#include "sainfo.h"
91#include "proposal.h"
92#include "strnames.h"
93#include "gcmalloc.h"
94#include "nattraversal.h"
95#include "crypto_openssl.h"
96#include "grabmyaddr.h"
97#include "vpn_control.h"
98#include "vpn_control_var.h"
99#include "ike_session.h"
100#include "ipsecSessionTracer.h"
101#include "ipsecMessageTracer.h"
102#include "power_mgmt.h"
103#include "session.h"
104
105#if defined(SADB_X_EALG_RIJNDAELCBC) && !defined(SADB_X_EALG_AESCBC)
106#define SADB_X_EALG_AESCBC  SADB_X_EALG_RIJNDAELCBC
107#endif
108
109/* prototype */
110static u_int ipsecdoi2pfkey_aalg (u_int);
111static u_int ipsecdoi2pfkey_ealg (u_int);
112static u_int ipsecdoi2pfkey_calg (u_int);
113static u_int ipsecdoi2pfkey_alg (u_int, u_int);
114static u_int keylen_aalg (u_int);
115static u_int keylen_ealg (u_int, int);
116
117static int pk_recvgetspi (caddr_t *);
118static int pk_recvupdate (caddr_t *);
119static int pk_recvadd (caddr_t *);
120static int pk_recvdelete (caddr_t *);
121static int pk_recvacquire (caddr_t *);
122static int pk_recvexpire (caddr_t *);
123static int pk_recvflush (caddr_t *);
124static int getsadbpolicy (caddr_t *, int *, int, phase2_handle_t *);
125static int pk_recvspdupdate (caddr_t *);
126static int pk_recvspdadd (caddr_t *);
127static int pk_recvspddelete (caddr_t *);
128static int pk_recvspdexpire (caddr_t *);
129static int pk_recvspdget (caddr_t *);
130static int pk_recvspddump (caddr_t *);
131static int pk_recvspdflush (caddr_t *);
132static int pk_recvgetsastat (caddr_t *);
133static struct sadb_msg *pk_recv (int, ssize_t *);
134
135static int (*pkrecvf[]) (caddr_t *) = {
136NULL,
137pk_recvgetspi,
138pk_recvupdate,
139pk_recvadd,
140pk_recvdelete,
141NULL,	/* SADB_GET */
142pk_recvacquire,
143NULL,	/* SABD_REGISTER */
144pk_recvexpire,
145pk_recvflush,
146NULL,	/* SADB_DUMP */
147NULL,	/* SADB_X_PROMISC */
148NULL,	/* SADB_X_PCHANGE */
149pk_recvspdupdate,
150pk_recvspdadd,
151pk_recvspddelete,
152pk_recvspdget,
153NULL,	/* SADB_X_SPDACQUIRE */
154pk_recvspddump,
155pk_recvspdflush,
156NULL,	/* SADB_X_SPDSETIDX */
157pk_recvspdexpire,
158NULL,	/* SADB_X_SPDDELETE2 */
159pk_recvgetsastat, /* SADB_GETSASTAT */
160NULL,	/* SADB_X_NAT_T_NEW_MAPPING */
161NULL, /* SADB_X_MIGRATE */
162#if (SADB_MAX > 25)
163#error "SADB extra message?"
164#endif
165};
166
167static int addnewsp (caddr_t *);
168
169/* cope with old kame headers - ugly */
170#ifndef SADB_X_AALG_MD5
171#define SADB_X_AALG_MD5		SADB_AALG_MD5
172#endif
173#ifndef SADB_X_AALG_SHA
174#define SADB_X_AALG_SHA		SADB_AALG_SHA
175#endif
176#ifndef SADB_X_AALG_NULL
177#define SADB_X_AALG_NULL	SADB_AALG_NULL
178#endif
179
180#ifndef SADB_X_EALG_BLOWFISHCBC
181#define SADB_X_EALG_BLOWFISHCBC	SADB_EALG_BLOWFISHCBC
182#endif
183#ifndef SADB_X_EALG_CAST128CBC
184#define SADB_X_EALG_CAST128CBC	SADB_EALG_CAST128CBC
185#endif
186#ifndef SADB_X_EALG_RC5CBC
187#ifdef SADB_EALG_RC5CBC
188#define SADB_X_EALG_RC5CBC	SADB_EALG_RC5CBC
189#endif
190#endif
191
192int
193pfkey_process(msg)
194	struct sadb_msg *msg;
195{
196	caddr_t mhp[SADB_EXT_MAX + 1];
197	int error = -1;
198
199    // Special debug use only - creates large logs
200	// plogdump(ASL_LEVEL_DEBUG, msg, msg->sadb_msg_len << 3, "get pfkey %s message\n",
201	//		 s_pfkey_type(msg->sadb_msg_type));
202
203	/* validity check */
204    /* check pfkey message. */
205	if (pfkey_align(msg, mhp)) {
206		plog(ASL_LEVEL_ERR,
207             "libipsec failed pfkey align (%s)\n",
208             ipsec_strerror());
209		goto end;
210	}
211	if (pfkey_check(mhp)) {
212		plog(ASL_LEVEL_ERR,
213             "libipsec failed pfkey check (%s)\n",
214             ipsec_strerror());
215		goto end;
216	}
217	msg = ALIGNED_CAST(struct sadb_msg *)mhp[0];             // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
218
219	if (msg->sadb_msg_errno) {
220		int pri;
221
222		/* when SPD is empty, treat the state as no error. */
223		if (msg->sadb_msg_type == SADB_X_SPDDUMP &&
224		    msg->sadb_msg_errno == ENOENT)
225			pri = ASL_LEVEL_DEBUG;
226		else
227			pri = ASL_LEVEL_ERR;
228
229		plog(pri,
230			"pfkey %s failed: %s\n",
231			s_pfkey_type(msg->sadb_msg_type),
232			strerror(msg->sadb_msg_errno));
233		goto end;
234	}
235
236	/* safety check */
237	if (msg->sadb_msg_type >= ARRAYLEN(pkrecvf)) {
238		plog(ASL_LEVEL_ERR,
239			"unknown PF_KEY message type=%u\n",
240			msg->sadb_msg_type);
241		goto end;
242	}
243
244	if (pkrecvf[msg->sadb_msg_type] == NULL) {
245		plog(ASL_LEVEL_INFO,
246			"unsupported PF_KEY message %s\n",
247			s_pfkey_type(msg->sadb_msg_type));
248		goto end;
249	}
250
251	if ((pkrecvf[msg->sadb_msg_type])(mhp) < 0)
252		goto end;
253
254	error = 0;
255end:
256	if (msg)
257		racoon_free(msg);
258	return(error);
259}
260
261/*
262 * PF_KEY packet handler
263 *	0: success
264 *	-1: fail
265 */
266
267//%%%%%%%%%%%%%%%%%% need to handle errors encountered here - this no longer returns a result
268void
269pfkey_handler(void *unused)
270{
271	struct sadb_msg *msg;
272	ssize_t len;
273
274	if (slept_at || woke_at) {
275		plog(ASL_LEVEL_DEBUG,
276			 "ignoring pfkey port until power-mgmt event is handled.\n");
277		return;
278	}
279
280	/* receive pfkey message. */
281	len = 0;
282	msg = (struct sadb_msg *)pk_recv(lcconf->sock_pfkey, &len);
283
284	if (msg == NULL) {
285		if (len < 0) {
286			plog(ASL_LEVEL_ERR,
287				 "failed to recv from pfkey (%s)\n",
288				 strerror(errno));
289			return;
290		} else {
291			/* short message - msg not ready */
292			plog(ASL_LEVEL_DEBUG, "recv short message from pfkey\n");
293			return;
294		}
295	}
296	pfkey_process(msg);
297}
298
299void
300pfkey_post_handler()
301{
302	struct saved_msg_elem *elem;
303	struct saved_msg_elem *elem_tmp = NULL;
304
305	if (slept_at || woke_at) {
306		plog(ASL_LEVEL_DEBUG,
307			 "ignoring (saved) pfkey messages until power-mgmt event is handled.\n");
308		return;
309	}
310
311	TAILQ_FOREACH_SAFE(elem, &lcconf->saved_msg_queue, chain, elem_tmp) {
312		pfkey_process((struct sadb_msg *)elem->msg);
313		TAILQ_REMOVE(&lcconf->saved_msg_queue, elem, chain);
314		racoon_free(elem);
315
316	}
317}
318
319int
320pfkey_save_msg(msg)
321	struct sadb_msg *msg;
322{
323	struct saved_msg_elem *elem;
324
325	elem = (struct saved_msg_elem *)racoon_calloc(sizeof(struct saved_msg_elem), 1);
326	if (elem == NULL)
327		return -1;
328	elem->msg = msg;
329	TAILQ_INSERT_TAIL(&lcconf->saved_msg_queue, elem, chain);
330	return 0;
331}
332
333/*
334 * dump SADB
335 */
336vchar_t *
337pfkey_dump_sadb(satype)
338	int satype;
339{
340	int s = -1;
341	vchar_t *buf = NULL;
342	pid_t pid = getpid();
343	struct sadb_msg *msg = NULL;
344	size_t bl, ml;
345	ssize_t len;
346
347	if ((s = pfkey_open()) < 0) {
348		plog(ASL_LEVEL_ERR,
349			"libipsec failed pfkey open: %s\n",
350			ipsec_strerror());
351		return NULL;
352	}
353
354	plog(ASL_LEVEL_DEBUG, "call pfkey_send_dump\n");
355	if (pfkey_send_dump(s, satype) < 0) {
356		plog(ASL_LEVEL_ERR,
357			"libipsec failed dump: %s\n", ipsec_strerror());
358		goto fail;
359	}
360
361	while (1) {
362		if (msg)
363			racoon_free(msg);
364		msg = pk_recv(s, &len);
365		if (msg == NULL) {
366			if (len < 0)
367				goto done;
368			else
369				continue;
370		}
371
372		/*
373		 * for multi-processor system this had to be added because the messages can
374		 * be interleaved - they won't all be dump messages
375		 */
376		if (msg->sadb_msg_type != SADB_DUMP) {	/* save for later processing */
377			pfkey_save_msg(msg);
378			msg = NULL;
379			continue;
380		}
381
382		// ignore dump messages that aren't racoon's
383		if (msg->sadb_msg_pid != pid)
384			continue;
385
386		ml = msg->sadb_msg_len << 3;
387		bl = buf ? buf->l : 0;
388		buf = vrealloc(buf, bl + ml);
389		if (buf == NULL) {
390			plog(ASL_LEVEL_ERR,
391				"failed to reallocate buffer to dump.\n");
392			goto fail;
393		}
394		memcpy(buf->v + bl, msg, ml);
395
396		if (msg->sadb_msg_seq == 0)
397			break;
398	}
399	goto done;
400
401fail:
402	if (buf)
403		vfree(buf);
404	buf = NULL;
405done:
406	if (msg)
407		racoon_free(msg);
408	if (s >= 0)
409		pfkey_close_sock(s);
410	return buf;
411}
412
413
414/*
415 * These are the SATYPEs that we manage.  We register to get
416 * PF_KEY messages related to these SATYPEs, and we also use
417 * this list to determine which SATYPEs to delete SAs for when
418 * we receive an INITIAL-CONTACT.
419 */
420const struct pfkey_satype pfkey_satypes[] = {
421	{ SADB_SATYPE_AH,	"AH" },
422	{ SADB_SATYPE_ESP,	"ESP" },
423	{ SADB_X_SATYPE_IPCOMP,	"IPCOMP" },
424};
425const int pfkey_nsatypes =
426    sizeof(pfkey_satypes) / sizeof(pfkey_satypes[0]);
427
428/*
429 * PF_KEY initialization
430 */
431int
432pfkey_init(void)
433{
434	int i, reg_fail, sock;
435
436	if ((lcconf->sock_pfkey = pfkey_open()) < 0) {
437		plog(ASL_LEVEL_ERR,
438			"libipsec failed pfkey open (%s)\n", ipsec_strerror());
439		return -1;
440	}
441
442	for (i = 0, reg_fail = 0; i < pfkey_nsatypes; i++) {
443		plog(ASL_LEVEL_DEBUG,
444		    "call pfkey_send_register for %s\n",
445		    pfkey_satypes[i].ps_name);
446		if (pfkey_send_register(lcconf->sock_pfkey,
447					pfkey_satypes[i].ps_satype) < 0 ||
448		    pfkey_recv_register(lcconf->sock_pfkey) < 0) {
449			plog(ASL_LEVEL_WARNING,
450			    "failed to register %s (%s)\n",
451			    pfkey_satypes[i].ps_name,
452			    ipsec_strerror());
453			reg_fail++;
454		}
455	}
456
457	if (reg_fail == pfkey_nsatypes) {
458		plog(ASL_LEVEL_ERR,
459			"failed to regist any protocol.\n");
460        close(lcconf->sock_pfkey);
461		return -1;
462	}
463    initsp();
464
465    lcconf->pfkey_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, lcconf->sock_pfkey, 0, dispatch_get_main_queue());
466    if (lcconf->pfkey_source == NULL) {
467        plog(ASL_LEVEL_ERR, "could not create pfkey socket source.");
468        return -1;
469    }
470    dispatch_source_set_event_handler_f(lcconf->pfkey_source, pfkey_handler);
471    sock = lcconf->sock_pfkey;
472    dispatch_source_set_cancel_handler(lcconf->pfkey_source,
473                                       ^{
474                                           pfkey_close_sock(sock);
475                                       });
476    dispatch_resume(lcconf->pfkey_source);
477
478	if (pfkey_send_spddump(lcconf->sock_pfkey) < 0) {
479		plog(ASL_LEVEL_ERR,
480			"libipsec sending spddump failed: %s\n",
481			ipsec_strerror());
482		pfkey_close();
483		return -1;
484	}
485#if 0
486	if (pfkey_promisc_toggle(1) < 0) {
487		pfkey_close();
488		return -1;
489	}
490#endif
491
492	return 0;
493}
494
495void
496pfkey_close(void)
497{
498    dispatch_source_cancel(lcconf->pfkey_source);
499    lcconf->pfkey_source = NULL;
500}
501
502/* %%% for conversion */
503/* IPSECDOI_ATTR_AUTH -> SADB_AALG */
504static u_int
505ipsecdoi2pfkey_aalg(hashtype)
506	u_int hashtype;
507{
508	switch (hashtype) {
509        case IPSECDOI_ATTR_AUTH_HMAC_MD5:
510        case IPSECDOI_ATTR_AUTH_HMAC_MD5_96:
511            return SADB_AALG_MD5HMAC;
512        case IPSECDOI_ATTR_AUTH_HMAC_SHA1:
513        case IPSECDOI_ATTR_AUTH_HMAC_SHA1_96:
514            return SADB_AALG_SHA1HMAC;
515        case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256:
516#if (defined SADB_X_AALG_SHA2_256) && !defined(SADB_X_AALG_SHA2_256HMAC)
517            return SADB_X_AALG_SHA2_256;
518#else
519            return SADB_X_AALG_SHA2_256HMAC;
520#endif
521        case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384:
522#if (defined SADB_X_AALG_SHA2_384) && !defined(SADB_X_AALG_SHA2_384HMAC)
523            return SADB_X_AALG_SHA2_384;
524#else
525            return SADB_X_AALG_SHA2_384HMAC;
526#endif
527        case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512:
528#if (defined SADB_X_AALG_SHA2_512) && !defined(SADB_X_AALG_SHA2_512HMAC)
529            return SADB_X_AALG_SHA2_512;
530#else
531            return SADB_X_AALG_SHA2_512HMAC;
532#endif
533        case IPSECDOI_ATTR_AUTH_KPDK:		/* need special care */
534            return SADB_AALG_NONE;
535
536            /* not supported */
537        case IPSECDOI_ATTR_AUTH_DES_MAC:
538            plog(ASL_LEVEL_ERR,
539                 "Not supported hash type: %u\n", hashtype);
540            return ~0;
541
542        case 0: /* reserved */
543        default:
544            return SADB_AALG_NONE;
545
546            plog(ASL_LEVEL_ERR,
547                 "Invalid hash type: %u\n", hashtype);
548            return ~0;
549	}
550	/*NOTREACHED*/
551}
552
553/* IPSECDOI_ESP -> SADB_EALG */
554static u_int
555ipsecdoi2pfkey_ealg(t_id)
556	u_int t_id;
557{
558	switch (t_id) {
559	case IPSECDOI_ESP_DES_IV64:		/* sa_flags |= SADB_X_EXT_OLD */
560		return SADB_EALG_DESCBC;
561	case IPSECDOI_ESP_DES:
562		return SADB_EALG_DESCBC;
563	case IPSECDOI_ESP_3DES:
564		return SADB_EALG_3DESCBC;
565#ifdef SADB_X_EALG_RC5CBC
566	case IPSECDOI_ESP_RC5:
567		return SADB_X_EALG_RC5CBC;
568#endif
569	case IPSECDOI_ESP_CAST:
570		return SADB_X_EALG_CAST128CBC;
571	case IPSECDOI_ESP_BLOWFISH:
572		return SADB_X_EALG_BLOWFISHCBC;
573	case IPSECDOI_ESP_DES_IV32:	/* flags |= (SADB_X_EXT_OLD|
574							SADB_X_EXT_IV4B)*/
575		return SADB_EALG_DESCBC;
576	case IPSECDOI_ESP_NULL:
577		return SADB_EALG_NULL;
578#ifdef SADB_X_EALG_AESCBC
579	case IPSECDOI_ESP_AES:
580		return SADB_X_EALG_AESCBC;
581#endif
582#ifdef SADB_X_EALG_TWOFISHCBC
583	case IPSECDOI_ESP_TWOFISH:
584		return SADB_X_EALG_TWOFISHCBC;
585#endif
586
587	/* not supported */
588	case IPSECDOI_ESP_3IDEA:
589	case IPSECDOI_ESP_IDEA:
590	case IPSECDOI_ESP_RC4:
591		plog(ASL_LEVEL_ERR,
592			"Not supported transform: %u\n", t_id);
593		return ~0;
594
595	case 0: /* reserved */
596	default:
597		plog(ASL_LEVEL_ERR,
598			"Invalid transform id: %u\n", t_id);
599		return ~0;
600	}
601	/*NOTREACHED*/
602}
603
604/* IPCOMP -> SADB_CALG */
605static u_int
606ipsecdoi2pfkey_calg(t_id)
607	u_int t_id;
608{
609	switch (t_id) {
610	case IPSECDOI_IPCOMP_OUI:
611		return SADB_X_CALG_OUI;
612	case IPSECDOI_IPCOMP_DEFLATE:
613		return SADB_X_CALG_DEFLATE;
614	case IPSECDOI_IPCOMP_LZS:
615		return SADB_X_CALG_LZS;
616
617	case 0: /* reserved */
618	default:
619		plog(ASL_LEVEL_ERR,
620			"Invalid transform id: %u\n", t_id);
621		return ~0;
622	}
623	/*NOTREACHED*/
624}
625
626/* IPSECDOI_PROTO -> SADB_SATYPE */
627u_int
628ipsecdoi2pfkey_proto(proto)
629	u_int proto;
630{
631	switch (proto) {
632	case IPSECDOI_PROTO_IPSEC_AH:
633		return SADB_SATYPE_AH;
634	case IPSECDOI_PROTO_IPSEC_ESP:
635		return SADB_SATYPE_ESP;
636	case IPSECDOI_PROTO_IPCOMP:
637		return SADB_X_SATYPE_IPCOMP;
638
639	default:
640		plog(ASL_LEVEL_ERR,
641			"Invalid ipsec_doi proto: %u\n", proto);
642		return ~0;
643	}
644	/*NOTREACHED*/
645}
646
647static u_int
648ipsecdoi2pfkey_alg(algclass, type)
649	u_int algclass, type;
650{
651	switch (algclass) {
652	case IPSECDOI_ATTR_AUTH:
653		return ipsecdoi2pfkey_aalg(type);
654	case IPSECDOI_PROTO_IPSEC_ESP:
655		return ipsecdoi2pfkey_ealg(type);
656	case IPSECDOI_PROTO_IPCOMP:
657		return ipsecdoi2pfkey_calg(type);
658	default:
659		plog(ASL_LEVEL_ERR,
660			"Invalid ipsec_doi algclass: %u\n", algclass);
661		return ~0;
662	}
663	/*NOTREACHED*/
664}
665
666/* SADB_SATYPE -> IPSECDOI_PROTO */
667u_int
668pfkey2ipsecdoi_proto(satype)
669	u_int satype;
670{
671	switch (satype) {
672	case SADB_SATYPE_AH:
673		return IPSECDOI_PROTO_IPSEC_AH;
674	case SADB_SATYPE_ESP:
675		return IPSECDOI_PROTO_IPSEC_ESP;
676	case SADB_X_SATYPE_IPCOMP:
677		return IPSECDOI_PROTO_IPCOMP;
678
679	default:
680		plog(ASL_LEVEL_ERR,
681			"Invalid pfkey proto: %u\n", satype);
682		return ~0;
683	}
684	/*NOTREACHED*/
685}
686
687/* IPSECDOI_ATTR_ENC_MODE -> IPSEC_MODE */
688u_int
689ipsecdoi2pfkey_mode(mode)
690	u_int mode;
691{
692	switch (mode) {
693	case IPSECDOI_ATTR_ENC_MODE_TUNNEL:
694#ifdef ENABLE_NATT
695	case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC:
696	case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT:
697#endif
698		return IPSEC_MODE_TUNNEL;
699	case IPSECDOI_ATTR_ENC_MODE_TRNS:
700#ifdef ENABLE_NATT
701	case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC:
702	case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT:
703#endif
704		return IPSEC_MODE_TRANSPORT;
705	default:
706		plog(ASL_LEVEL_ERR, "Invalid mode type: %u\n", mode);
707		return ~0;
708	}
709	/*NOTREACHED*/
710}
711
712/* IPSECDOI_ATTR_ENC_MODE -> IPSEC_MODE */
713u_int
714pfkey2ipsecdoi_mode(mode)
715	u_int mode;
716{
717	switch (mode) {
718	case IPSEC_MODE_TUNNEL:
719		return IPSECDOI_ATTR_ENC_MODE_TUNNEL;
720	case IPSEC_MODE_TRANSPORT:
721		return IPSECDOI_ATTR_ENC_MODE_TRNS;
722	case IPSEC_MODE_ANY:
723		return IPSECDOI_ATTR_ENC_MODE_ANY;
724	default:
725		plog(ASL_LEVEL_ERR, "Invalid mode type: %u\n", mode);
726		return ~0;
727	}
728	/*NOTREACHED*/
729}
730
731/* default key length for encryption algorithm */
732static u_int
733keylen_aalg(hashtype)
734	u_int hashtype;
735{
736	int res;
737
738	if (hashtype == 0)
739		return SADB_AALG_NONE;
740
741	res = alg_ipsec_hmacdef_hashlen(hashtype);
742	if (res == -1) {
743		plog(ASL_LEVEL_ERR,
744			"invalid hmac algorithm %u.\n", hashtype);
745		return ~0;
746	}
747	return res;
748}
749
750/* default key length for encryption algorithm */
751static u_int
752keylen_ealg(enctype, encklen)
753	u_int enctype;
754	int encklen;
755{
756	int res;
757
758	res = alg_ipsec_encdef_keylen(enctype, encklen);
759	if (res == -1) {
760		plog(ASL_LEVEL_ERR,
761			"invalid encryption algorithm %u.\n", enctype);
762		return ~0;
763	}
764	return res;
765}
766
767int
768pfkey_convertfromipsecdoi(iph2, proto_id, t_id, hashtype,
769		e_type, e_keylen, a_type, a_keylen, flags)
770    phase2_handle_t *iph2;
771	u_int proto_id;
772	u_int t_id;
773	u_int hashtype;
774	u_int *e_type;
775	u_int *e_keylen;
776	u_int *a_type;
777	u_int *a_keylen;
778	u_int *flags;
779{
780	*flags = 0;
781	switch (proto_id) {
782	case IPSECDOI_PROTO_IPSEC_ESP:
783		if ((*e_type = ipsecdoi2pfkey_ealg(t_id)) == ~0)
784			goto bad;
785		if ((*e_keylen = keylen_ealg(t_id, *e_keylen)) == ~0)
786			goto bad;
787		*e_keylen >>= 3;
788
789		if ((*a_type = ipsecdoi2pfkey_aalg(hashtype)) == ~0)
790			goto bad;
791		if ((*a_keylen = keylen_aalg(hashtype)) == ~0)
792			goto bad;
793		*a_keylen >>= 3;
794
795		if (*e_type == SADB_EALG_NONE) {
796			plog(ASL_LEVEL_ERR, "no ESP algorithm.\n");
797			goto bad;
798		}
799		break;
800
801	case IPSECDOI_PROTO_IPSEC_AH:
802		if ((*a_type = ipsecdoi2pfkey_aalg(hashtype)) == ~0)
803			goto bad;
804		if ((*a_keylen = keylen_aalg(hashtype)) == ~0)
805			goto bad;
806		*a_keylen >>= 3;
807
808		if (t_id == IPSECDOI_ATTR_AUTH_HMAC_MD5
809		 && hashtype == IPSECDOI_ATTR_AUTH_KPDK) {
810			/* AH_MD5 + Auth(KPDK) = RFC1826 keyed-MD5 */
811			*a_type = SADB_X_AALG_MD5;
812			*flags |= SADB_X_EXT_OLD;
813		}
814		*e_type = SADB_EALG_NONE;
815		*e_keylen = 0;
816		if (*a_type == SADB_AALG_NONE) {
817			plog(ASL_LEVEL_ERR, "no AH algorithm.\n");
818			goto bad;
819		}
820		break;
821
822	case IPSECDOI_PROTO_IPCOMP:
823		if ((*e_type = ipsecdoi2pfkey_calg(t_id)) == ~0)
824			goto bad;
825		*e_keylen = 0;
826
827		*flags = SADB_X_EXT_RAWCPI;
828
829		*a_type = SADB_AALG_NONE;
830		*a_keylen = 0;
831		if (*e_type == SADB_X_CALG_NONE) {
832			plog(ASL_LEVEL_ERR, "no IPCOMP algorithm.\n");
833			goto bad;
834		}
835		break;
836
837	default:
838		plog(ASL_LEVEL_ERR, "unknown IPsec protocol.\n");
839		goto bad;
840	}
841
842	return 0;
843
844    bad:
845	errno = EINVAL;
846	return -1;
847}
848
849/* called from scheduler */
850void
851pfkey_timeover_stub(p)
852	void *p;
853{
854
855	pfkey_timeover((phase2_handle_t *)p);
856}
857
858void
859pfkey_timeover(iph2)
860	phase2_handle_t *iph2;
861{
862	plog(ASL_LEVEL_ERR,
863		"%s give up to get IPsec-SA due to time up to wait.\n",
864		saddrwop2str((struct sockaddr *)iph2->dst));
865	SCHED_KILL(iph2->sce);
866
867	/* If initiator side, send error to kernel by SADB_ACQUIRE. */
868	if (iph2->side == INITIATOR)
869		pk_sendeacquire(iph2);
870
871	ike_session_unlink_phase2(iph2);
872
873	return;
874}
875
876/*%%%*/
877/* send getspi message per ipsec protocol per remote address */
878/*
879 * the local address and remote address in ph1handle are dealed
880 * with destination address and source address respectively.
881 * Because SPI is decided by responder.
882 */
883int
884pk_sendgetspi(iph2)
885	phase2_handle_t *iph2;
886{
887	struct sockaddr_storage *src = NULL, *dst = NULL;
888	u_int satype, mode;
889	struct saprop *pp;
890	struct saproto *pr;
891	u_int32_t minspi, maxspi;
892	int proxy = 0;
893
894	if (iph2->side == INITIATOR) {
895		pp = iph2->proposal;
896		proxy = iph2->ph1->rmconf->support_proxy;
897	} else {
898		pp = iph2->approval;
899		if (iph2->sainfo && iph2->sainfo->id_i)
900			proxy = 1;
901	}
902
903	/* for mobile IPv6 */
904	if (proxy && iph2->src_id && iph2->dst_id &&
905	    ipsecdoi_transportmode(pp)) {
906		src = iph2->src_id;
907		dst = iph2->dst_id;
908	} else {
909		src = iph2->src;
910		dst = iph2->dst;
911	}
912
913	for (pr = pp->head; pr != NULL; pr = pr->next) {
914
915		/* validity check */
916		satype = ipsecdoi2pfkey_proto(pr->proto_id);
917		if (satype == ~0) {
918			plog(ASL_LEVEL_ERR,
919				"invalid proto_id %d\n", pr->proto_id);
920			return -1;
921		}
922		/* this works around a bug in Linux kernel where it allocates 4 byte
923		   spi's for IPCOMP */
924		else if (satype == SADB_X_SATYPE_IPCOMP) {
925			minspi = 0x100;
926			maxspi = 0xffff;
927		}
928		else {
929			minspi = 0;
930			maxspi = 0;
931		}
932		mode = ipsecdoi2pfkey_mode(pr->encmode);
933		if (mode == ~0) {
934			plog(ASL_LEVEL_ERR,
935				"invalid encmode %d\n", pr->encmode);
936			return -1;
937		}
938
939		plog(ASL_LEVEL_DEBUG, "call pfkey_send_getspi\n");
940		if (pfkey_send_getspi(
941				lcconf->sock_pfkey,
942				satype,
943				mode,
944				dst,			/* src of SA */
945				src,			/* dst of SA */
946				minspi, maxspi,
947				pr->reqid_in, 0, 0, iph2->seq, 0) < 0) {
948			plog(ASL_LEVEL_ERR,
949				"ipseclib failed send getspi (%s)\n",
950				ipsec_strerror());
951			return -1;
952		}
953
954		plog(ASL_LEVEL_DEBUG,
955			"pfkey GETSPI sent: %s\n",
956			sadbsecas2str(dst, src, satype, 0, mode));
957	}
958
959	return 0;
960}
961
962/*
963 * receive GETSPI from kernel.
964 */
965static int
966pk_recvgetspi(mhp)
967	caddr_t *mhp;
968{
969	struct sadb_msg *msg;
970	struct sadb_sa *sa;
971	phase2_handle_t *iph2;
972	struct sockaddr_storage *dst;
973	int proto_id;
974	int allspiok, notfound;
975	struct saprop *pp;
976	struct saproto *pr;
977
978	/* validity check */
979	if (mhp[SADB_EXT_SA] == NULL
980	 || mhp[SADB_EXT_ADDRESS_DST] == NULL) {
981		plog(ASL_LEVEL_ERR,
982			"Inappropriate sadb getspi message passed.\n");
983		return -1;
984	}
985	msg = ALIGNED_CAST(struct sadb_msg *)mhp[0];                     // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
986	sa = ALIGNED_CAST(struct sadb_sa *)mhp[SADB_EXT_SA];
987	dst = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]); /* note SA dir */
988
989	/* the message has to be processed or not ? */
990	if (msg->sadb_msg_pid != getpid()) {
991		plog(ASL_LEVEL_DEBUG,
992			"%s message is not interesting "
993			"because pid %d is not mine.\n",
994			s_pfkey_type(msg->sadb_msg_type),
995			msg->sadb_msg_pid);
996		return -1;
997	}
998
999	iph2 = ike_session_getph2byseq(msg->sadb_msg_seq);
1000	if (iph2 == NULL) {
1001		plog(ASL_LEVEL_DEBUG,
1002			"Seq %d of %s message not interesting.\n",
1003			msg->sadb_msg_seq,
1004			s_pfkey_type(msg->sadb_msg_type));
1005		return -1;
1006	}
1007
1008	if (iph2->is_dying) {
1009		plog(ASL_LEVEL_ERR,
1010			 "Status mismatch Phase 2 dying (db:%d)\n",
1011			 iph2->status);
1012		return -1;
1013	}
1014
1015	switch (iph2->version) {
1016        case ISAKMP_VERSION_NUMBER_IKEV1:
1017            if (iph2->status != IKEV1_STATE_QUICK_I_GETSPISENT &&
1018                iph2->status != IKEV1_STATE_QUICK_R_GETSPISENT) {
1019                plog(ASL_LEVEL_ERR, "Status mismatch (db:%d)\n", iph2->status);
1020                return -1;
1021            }
1022            // check the underlying iph2->ph1
1023            if (!iph2->ph1) {
1024                if (!ike_session_update_ph2_ph1bind(iph2)) {
1025                    plog(ASL_LEVEL_ERR,
1026                         "Can't proceed with getspi for  %s. no suitable ISAKMP-SA found \n",
1027                         saddrwop2str((struct sockaddr *)iph2->dst));
1028                    ike_session_unlink_phase2(iph2);
1029                    return -1;
1030                }
1031            }
1032            break;
1033        default:
1034            plog(ASL_LEVEL_ERR, "Internal error: invalid IKE major version %d\n", iph2->version);
1035            return -1;
1036    }
1037
1038	/* set SPI, and check to get all spi whether or not */
1039	allspiok = 1;
1040	notfound = 1;
1041	proto_id = pfkey2ipsecdoi_proto(msg->sadb_msg_satype);
1042	pp = iph2->side == INITIATOR ? iph2->proposal : iph2->approval;
1043
1044	for (pr = pp->head; pr != NULL; pr = pr->next) {
1045		if (pr->proto_id == proto_id && pr->spi == 0) {
1046			pr->spi = sa->sadb_sa_spi;
1047			notfound = 0;
1048			plog(ASL_LEVEL_DEBUG,
1049				"pfkey GETSPI succeeded: %s\n",
1050				sadbsecas2str(iph2->dst, iph2->src,
1051				    msg->sadb_msg_satype,
1052				    sa->sadb_sa_spi,
1053				    ipsecdoi2pfkey_mode(pr->encmode)));
1054		}
1055		if (pr->spi == 0)
1056			allspiok = 0;	/* not get all spi */
1057	}
1058
1059	if (notfound) {
1060		plog(ASL_LEVEL_ERR,
1061			"Get spi for unknown address %s\n",
1062			saddrwop2str((struct sockaddr *)iph2->dst));
1063        ike_session_unlink_phase2(iph2);
1064		return -1;
1065	}
1066
1067	if (allspiok) {
1068        switch (iph2->version) {
1069            case ISAKMP_VERSION_NUMBER_IKEV1:
1070                if (isakmp_post_getspi(iph2) < 0) {
1071                    plog(ASL_LEVEL_ERR, "IKEv1 post getspi failed.\n");
1072                    ike_session_unlink_phase2(iph2);
1073                    iph2 = NULL;
1074                    return -1;
1075                }
1076                break;
1077        }
1078	}
1079	return 0;
1080}
1081
1082/*
1083 * set inbound SA
1084 */
1085int
1086pk_sendupdate(iph2)
1087	phase2_handle_t *iph2;
1088{
1089	struct saproto *pr;
1090	struct sockaddr_storage *src = NULL, *dst = NULL;
1091	u_int e_type, e_keylen, a_type, a_keylen, flags;
1092	u_int satype, mode;
1093	u_int64_t lifebyte = 0;
1094	u_int wsize = 4;  /* XXX static size of window */
1095	int proxy = 0;
1096	struct ph2natt natt;
1097    int authtype;
1098
1099	/* sanity check */
1100	if (iph2->approval == NULL) {
1101		plog(ASL_LEVEL_ERR,
1102			"No approved SAs found.\n");
1103	}
1104
1105	if (iph2->side == INITIATOR)
1106		proxy = iph2->ph1->rmconf->support_proxy;
1107	else if (iph2->sainfo && iph2->sainfo->id_i)
1108		proxy = 1;
1109
1110	/* for mobile IPv6 */
1111	if (proxy && iph2->src_id && iph2->dst_id &&
1112	    ipsecdoi_transportmode(iph2->approval)) {
1113		src = iph2->src_id;
1114		dst = iph2->dst_id;
1115	} else {
1116		src = iph2->src;
1117		dst = iph2->dst;
1118	}
1119
1120	for (pr = iph2->approval->head; pr != NULL; pr = pr->next) {
1121		/* validity check */
1122		satype = ipsecdoi2pfkey_proto(pr->proto_id);
1123		if (satype == ~0) {
1124			plog(ASL_LEVEL_ERR,
1125				"Invalid proto_id %d\n", pr->proto_id);
1126			return -1;
1127		}
1128		else if (satype == SADB_X_SATYPE_IPCOMP) {
1129			/* IPCOMP has no replay window */
1130			wsize = 0;
1131		}
1132#ifdef ENABLE_SAMODE_UNSPECIFIED
1133		mode = IPSEC_MODE_ANY;
1134#else
1135		mode = ipsecdoi2pfkey_mode(pr->encmode);
1136		if (mode == ~0) {
1137			plog(ASL_LEVEL_ERR,
1138				"Invalid encmode %d\n", pr->encmode);
1139			return -1;
1140		}
1141#endif
1142
1143		/* set algorithm type and key length */
1144		e_keylen = pr->head->encklen;
1145        authtype = pr->head->authtype;
1146        a_keylen = 0;
1147		if (pfkey_convertfromipsecdoi(
1148                iph2,
1149				pr->proto_id,
1150				pr->head->trns_id,
1151                authtype,
1152				&e_type, &e_keylen,
1153				&a_type, &a_keylen, &flags) < 0)
1154			return -1;
1155
1156#if 0
1157		lifebyte = iph2->approval->lifebyte * 1024,
1158#else
1159		lifebyte = 0;
1160#endif
1161
1162#ifdef ENABLE_NATT
1163		//plog(ASL_LEVEL_DEBUG, "call pfkey_send_update\n");
1164        plog(ASL_LEVEL_DEBUG, "call pfkey_send_update: e_type %d, e_klen %d, a_type %d, a_klen %d\n",
1165             e_type, e_keylen, a_type, a_keylen);
1166		if (pr->udp_encap) {
1167			memset (&natt, 0, sizeof (natt));
1168			natt.sport = extract_port (iph2->ph1->remote);
1169			flags |= SADB_X_EXT_NATT;
1170			if (iph2->ph1->rmconf->natt_multiple_user == TRUE &&
1171				mode == IPSEC_MODE_TRANSPORT &&
1172				src->ss_family == AF_INET) {
1173				flags |= SADB_X_EXT_NATT_MULTIPLEUSERS;
1174				if (iph2->ph1->natt_flags & NAT_DETECTED_PEER) {
1175					// is mutually exclusive with SADB_X_EXT_NATT_KEEPALIVE
1176					flags |= SADB_X_EXT_NATT_DETECTED_PEER;
1177				}
1178			} else if (iph2->ph1->natt_flags & NAT_DETECTED_ME) {
1179				if (iph2->ph1->rmconf->natt_keepalive == TRUE)
1180					flags |= SADB_X_EXT_NATT_KEEPALIVE;
1181			} else {
1182				if (iph2->ph1->natt_flags & NAT_DETECTED_PEER) {
1183					// is mutually exclusive with SADB_X_EXT_NATT_KEEPALIVE
1184					flags |= SADB_X_EXT_NATT_DETECTED_PEER;
1185				}
1186			}
1187		} else {
1188			memset (&natt, 0, sizeof (natt));
1189		}
1190
1191		if (pfkey_send_update(
1192				lcconf->sock_pfkey,
1193				satype,
1194				mode,
1195				dst,
1196				src,
1197				pr->spi,
1198				pr->reqid_in,
1199				wsize,
1200				pr->keymat->v,
1201				e_type, e_keylen, a_type, a_keylen, flags,
1202				0, lifebyte, iph2->approval->lifetime, 0,
1203				iph2->seq, natt.sport, 0) < 0) {
1204			plog(ASL_LEVEL_ERR,
1205				"libipsec failed send update (%s)\n",
1206				ipsec_strerror());
1207			return -1;
1208		}
1209#else
1210		plog(ASL_LEVEL_DEBUG, "call pfkey_send_update\n");
1211		if (pfkey_send_update(
1212				lcconf->sock_pfkey,
1213				satype,
1214				mode,
1215				dst,
1216				src,
1217				pr->spi,
1218				pr->reqid_in,
1219				wsize,
1220				pr->keymat->v,
1221				e_type, e_keylen, a_type, a_keylen, flags,
1222				0, lifebyte, iph2->approval->lifetime, 0,
1223				iph2->seq, 0, 0) < 0) {
1224			plog(ASL_LEVEL_ERR,
1225				"libipsec failed send update (%s)\n",
1226				ipsec_strerror());
1227			return -1;
1228		}
1229#endif /* ENABLE_NATT */
1230
1231
1232	}
1233
1234	return 0;
1235}
1236
1237static int
1238pk_recvupdate(mhp)
1239	caddr_t *mhp;
1240{
1241	struct sadb_msg *msg;
1242	struct sadb_sa *sa;
1243	struct sockaddr_storage *src, *dst;
1244	phase2_handle_t *iph2;
1245	u_int proto_id, encmode, sa_mode;
1246	int incomplete = 0;
1247	struct saproto *pr;
1248
1249	/* ignore this message because of local test mode. */
1250	if (f_local)
1251		return 0;
1252
1253	/* sanity check */
1254	if (mhp[0] == NULL
1255	 || mhp[SADB_EXT_SA] == NULL
1256	 || mhp[SADB_EXT_ADDRESS_SRC] == NULL
1257	 || mhp[SADB_EXT_ADDRESS_DST] == NULL) {
1258		plog(ASL_LEVEL_ERR,
1259			"inappropriate sadb update message passed.\n");
1260		return -1;
1261	}
1262	msg = ALIGNED_CAST(struct sadb_msg *)mhp[0];                 // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
1263	src = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
1264	dst = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
1265	sa = ALIGNED_CAST(struct sadb_sa *)mhp[SADB_EXT_SA];
1266
1267	sa_mode = mhp[SADB_X_EXT_SA2] == NULL
1268		? IPSEC_MODE_ANY
1269		: (ALIGNED_CAST(struct sadb_x_sa2 *)mhp[SADB_X_EXT_SA2])->sadb_x_sa2_mode;
1270
1271	/* the message has to be processed or not ? */
1272	if (msg->sadb_msg_pid != getpid()) {
1273		plog(ASL_LEVEL_DEBUG,
1274			"%s message is not interesting "
1275			"because pid %d is not mine.\n",
1276			s_pfkey_type(msg->sadb_msg_type),
1277			msg->sadb_msg_pid);
1278		return -1;
1279	}
1280
1281	iph2 = ike_session_getph2byseq(msg->sadb_msg_seq);
1282	if (iph2 == NULL) {
1283		plog(ASL_LEVEL_DEBUG,
1284			"Seq %d of %s message not interesting.\n",
1285			msg->sadb_msg_seq,
1286			s_pfkey_type(msg->sadb_msg_type));
1287		return -1;
1288	}
1289
1290	if (iph2->is_dying) {
1291		plog(ASL_LEVEL_ERR,
1292			 "Status mismatch Phase 2 dying (db:%d)\n",
1293			 iph2->status);
1294		return -1;
1295	}
1296	if (iph2->status != IKEV1_STATE_QUICK_I_ADDSA &&
1297        iph2->status != IKEV1_STATE_QUICK_R_ADDSA) {
1298		plog(ASL_LEVEL_ERR,
1299			"Status mismatch (db:%d)\n",
1300			iph2->status);
1301		return -1;
1302	}
1303
1304	/* check to complete all keys ? */
1305	for (pr = iph2->approval->head; pr != NULL; pr = pr->next) {
1306		proto_id = pfkey2ipsecdoi_proto(msg->sadb_msg_satype);
1307		if (proto_id == ~0) {
1308			plog(ASL_LEVEL_ERR,
1309				"invalid proto_id %d\n", msg->sadb_msg_satype);
1310			return -1;
1311		}
1312		encmode = pfkey2ipsecdoi_mode(sa_mode);
1313		if (encmode == ~0) {
1314			plog(ASL_LEVEL_ERR,
1315				"invalid encmode %d\n", sa_mode);
1316			return -1;
1317		}
1318
1319		if (pr->proto_id == proto_id
1320		 && pr->spi == sa->sadb_sa_spi) {
1321			pr->ok = 1;
1322			plog(ASL_LEVEL_DEBUG,
1323				"pfkey UPDATE succeeded: %s\n",
1324				sadbsecas2str(iph2->dst, iph2->src,
1325				    msg->sadb_msg_satype,
1326				    sa->sadb_sa_spi,
1327				    sa_mode));
1328
1329			plog(ASL_LEVEL_INFO,
1330				"IPsec-SA established: %s\n",
1331				sadbsecas2str(iph2->dst, iph2->src,
1332					msg->sadb_msg_satype, sa->sadb_sa_spi,
1333					sa_mode));
1334		}
1335
1336		if (pr->ok == 0)
1337			incomplete = 1;
1338	}
1339
1340	if (incomplete)
1341		return 0;
1342
1343	/* turn off the timer for calling pfkey_timeover() */
1344	SCHED_KILL(iph2->sce);
1345
1346	/* update status */
1347	fsm_set_state(&iph2->status, IKEV1_STATE_PHASE2_ESTABLISHED);
1348
1349	if (iph2->side == INITIATOR) {
1350		IPSECSESSIONTRACEREVENT(iph2->parent_session,
1351								IPSECSESSIONEVENTCODE_IKEV1_PH2_INIT_SUCC,
1352								CONSTSTR("Initiator, Quick-Mode"),
1353								CONSTSTR(NULL));
1354	} else {
1355		IPSECSESSIONTRACEREVENT(iph2->parent_session,
1356								IPSECSESSIONEVENTCODE_IKEV1_PH2_RESP_SUCC,
1357								CONSTSTR("Responder, Quick-Mode"),
1358								CONSTSTR(NULL));
1359	}
1360
1361	ike_session_ph2_established(iph2);
1362
1363	IPSECLOGASLMSG("IPSec Phase 2 established (Initiated by %s).\n",
1364				   (iph2->side == INITIATOR)? "me" : "peer");
1365
1366#ifdef ENABLE_STATS
1367	gettimeofday(&iph2->end, NULL);
1368	plog(ASL_LEVEL_NOTICE, "%s(%s): %8.6f",
1369		"Phase 2", "quick", timedelta(&iph2->start, &iph2->end));
1370#endif
1371
1372	/* count up */
1373	if (iph2->ph1)
1374		iph2->ph1->ph2cnt++;
1375
1376	/* turn off schedule */
1377	if (iph2->scr)
1378		SCHED_KILL(iph2->scr);
1379
1380	/*
1381	 * since we are going to reuse the phase2 handler, we need to
1382	 * remain it and refresh all the references between ph1 and ph2 to use.
1383	 */
1384	ike_session_unbindph12(iph2);   //%%%%% fix this
1385
1386	iph2->sce = sched_new(iph2->approval->lifetime,
1387	    isakmp_ph2expire_stub, iph2);
1388
1389	plog(ASL_LEVEL_DEBUG, "===\n");
1390	return 0;
1391}
1392
1393/*
1394 * set outbound SA
1395 */
1396int
1397pk_sendadd(iph2)
1398	phase2_handle_t *iph2;
1399{
1400	struct saproto *pr;
1401	struct sockaddr_storage *src = NULL, *dst = NULL;
1402	u_int e_type, e_keylen, a_type, a_keylen, flags;
1403	u_int satype, mode;
1404	u_int64_t lifebyte = 0;
1405	u_int wsize = 4; /* XXX static size of window */
1406	int proxy = 0;
1407	struct ph2natt natt;
1408    int authtype;
1409
1410	/* sanity check */
1411	if (iph2->approval == NULL) {
1412		plog(ASL_LEVEL_ERR,
1413			"no approvaled SAs found.\n");
1414	}
1415
1416	if (iph2->side == INITIATOR)
1417		proxy = iph2->ph1->rmconf->support_proxy;
1418	else if (iph2->sainfo && iph2->sainfo->id_i)
1419		proxy = 1;
1420
1421	/* for mobile IPv6 */
1422	if (proxy && iph2->src_id && iph2->dst_id &&
1423	    ipsecdoi_transportmode(iph2->approval)) {
1424		src = iph2->src_id;
1425		dst = iph2->dst_id;
1426	} else {
1427		src = iph2->src;
1428		dst = iph2->dst;
1429	}
1430
1431	for (pr = iph2->approval->head; pr != NULL; pr = pr->next) {
1432		/* validity check */
1433		satype = ipsecdoi2pfkey_proto(pr->proto_id);
1434		if (satype == ~0) {
1435			plog(ASL_LEVEL_ERR,
1436				"invalid proto_id %d\n", pr->proto_id);
1437			return -1;
1438		}
1439		else if (satype == SADB_X_SATYPE_IPCOMP) {
1440			/* no replay window for IPCOMP */
1441			wsize = 0;
1442		}
1443#ifdef ENABLE_SAMODE_UNSPECIFIED
1444		mode = IPSEC_MODE_ANY;
1445#else
1446		mode = ipsecdoi2pfkey_mode(pr->encmode);
1447		if (mode == ~0) {
1448			plog(ASL_LEVEL_ERR,
1449				"invalid encmode %d\n", pr->encmode);
1450			return -1;
1451		}
1452#endif
1453
1454		/* set algorithm type and key length */
1455		e_keylen = pr->head->encklen;
1456        authtype = pr->head->authtype;
1457        a_keylen = 0;
1458		if (pfkey_convertfromipsecdoi(
1459                iph2,
1460				pr->proto_id,
1461				pr->head->trns_id,
1462                authtype,
1463				&e_type, &e_keylen,
1464				&a_type, &a_keylen, &flags) < 0)
1465			return -1;
1466
1467#if 0
1468		lifebyte = iph2->approval->lifebyte * 1024,
1469#else
1470		lifebyte = 0;
1471#endif
1472
1473#ifdef ENABLE_NATT
1474		//plog(ASL_LEVEL_DEBUG, "call pfkey_send_add\n");
1475        plog(ASL_LEVEL_DEBUG, "call pfkey_send_add: e_type %d, e_klen %d, a_type %d, a_klen %d\n",
1476             e_type, e_keylen, a_type, a_keylen);
1477
1478		if (pr->udp_encap) {
1479			memset (&natt, 0, sizeof (natt));
1480			natt.dport = extract_port (iph2->ph1->remote);
1481			flags |= SADB_X_EXT_NATT;
1482			if (iph2->ph1->rmconf->natt_multiple_user == TRUE &&
1483				mode == IPSEC_MODE_TRANSPORT &&
1484				src->ss_family == AF_INET) {
1485				flags |= SADB_X_EXT_NATT_MULTIPLEUSERS;
1486				if (iph2->ph1->natt_flags & NAT_DETECTED_PEER) {
1487					// is mutually exclusive with SADB_X_EXT_NATT_KEEPALIVE
1488					flags |= SADB_X_EXT_NATT_DETECTED_PEER;
1489				}
1490			} else if (iph2->ph1->natt_flags & NAT_DETECTED_ME) {
1491				if (iph2->ph1->rmconf->natt_keepalive == TRUE)
1492					flags |= SADB_X_EXT_NATT_KEEPALIVE;
1493			} else {
1494				if (iph2->ph1->natt_flags & NAT_DETECTED_PEER) {
1495					// is mutually exclusive with SADB_X_EXT_NATT_KEEPALIVE
1496					flags |= SADB_X_EXT_NATT_DETECTED_PEER;
1497				}
1498			}
1499		} else {
1500			memset (&natt, 0, sizeof (natt));
1501
1502			/* Remove port information, that SA doesn't use it */
1503			//set_port(src, 0);
1504			//set_port(dst, 0);
1505		}
1506
1507		if (pfkey_send_add(
1508				lcconf->sock_pfkey,
1509				satype,
1510				mode,
1511				src,
1512				dst,
1513				pr->spi_p,
1514				pr->reqid_out,
1515				wsize,
1516				pr->keymat_p->v,
1517				e_type, e_keylen, a_type, a_keylen, flags,
1518				0, lifebyte, iph2->approval->lifetime, 0,
1519				iph2->seq,natt.dport, 0) < 0) {
1520			plog(ASL_LEVEL_ERR,
1521				"libipsec failed send add (%s)\n",
1522				ipsec_strerror());
1523			return -1;
1524		}
1525#else
1526		plog(ASL_LEVEL_DEBUG, "call pfkey_send_add\n");
1527
1528		/* Remove port information, it is not used without NAT-T */
1529		//set_port(src, 0);
1530		//set_port(dst, 0);
1531
1532		if (pfkey_send_add(
1533				lcconf->sock_pfkey,
1534				satype,
1535				mode,
1536				src,
1537				dst,
1538				pr->spi_p,
1539				pr->reqid_out,
1540				wsize,
1541				pr->keymat_p->v,
1542				e_type, e_keylen, a_type, a_keylen, flags,
1543				0, lifebyte, iph2->approval->lifetime, 0,
1544				iph2->seq, 0, 0) < 0) {
1545			plog(ASL_LEVEL_ERR,
1546				"libipsec failed send add (%s)\n",
1547				ipsec_strerror());
1548			return -1;
1549		}
1550#endif /* ENABLE_NATT */
1551	}
1552
1553	return 0;
1554}
1555
1556static int
1557pk_recvadd(mhp)
1558	caddr_t *mhp;
1559{
1560	struct sadb_msg *msg;
1561	struct sadb_sa *sa;
1562	struct sockaddr_storage *src, *dst;
1563	phase2_handle_t *iph2;
1564	u_int sa_mode;
1565
1566	/* ignore this message because of local test mode. */
1567	if (f_local)
1568		return 0;
1569
1570	/* sanity check */
1571	if (mhp[0] == NULL
1572	 || mhp[SADB_EXT_SA] == NULL
1573	 || mhp[SADB_EXT_ADDRESS_SRC] == NULL
1574	 || mhp[SADB_EXT_ADDRESS_DST] == NULL) {
1575		plog(ASL_LEVEL_ERR,
1576			"inappropriate sadb add message passed.\n");
1577		return -1;
1578	}
1579	msg = ALIGNED_CAST(struct sadb_msg *)mhp[0];                     // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
1580	src = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
1581	dst = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
1582	sa = ALIGNED_CAST(struct sadb_sa *)mhp[SADB_EXT_SA];
1583
1584	sa_mode = mhp[SADB_X_EXT_SA2] == NULL
1585		? IPSEC_MODE_ANY
1586		: (ALIGNED_CAST(struct sadb_x_sa2 *)mhp[SADB_X_EXT_SA2])->sadb_x_sa2_mode;
1587
1588	/* the message has to be processed or not ? */
1589	if (msg->sadb_msg_pid != getpid()) {
1590		plog(ASL_LEVEL_DEBUG,
1591			"%s message is not interesting "
1592			"because pid %d is not mine.\n",
1593			s_pfkey_type(msg->sadb_msg_type),
1594			msg->sadb_msg_pid);
1595		return -1;
1596	}
1597
1598	iph2 = ike_session_getph2byseq(msg->sadb_msg_seq);
1599	if (iph2 == NULL) {
1600		plog(ASL_LEVEL_DEBUG,
1601			"seq %d of %s message not interesting.\n",
1602			msg->sadb_msg_seq,
1603			s_pfkey_type(msg->sadb_msg_type));
1604		return -1;
1605	}
1606	/*
1607	 * NOTE don't update any status of phase2 handle
1608	 * because they must be updated by SADB_UPDATE message
1609	 */
1610
1611	plog(ASL_LEVEL_INFO,
1612		"IPsec-SA established: %s\n",
1613		sadbsecas2str(iph2->src, iph2->dst,
1614			msg->sadb_msg_satype, sa->sadb_sa_spi, sa_mode));
1615
1616	ike_session_cleanup_other_established_ph2s(iph2->parent_session, iph2);
1617
1618#ifdef ENABLE_VPNCONTROL_PORT
1619		{
1620			u_int32_t address;
1621
1622			if (iph2->dst->ss_family == AF_INET)
1623				address = ((struct sockaddr_in *)iph2->dst)->sin_addr.s_addr;
1624			else
1625				address = 0;
1626			vpncontrol_notify_phase_change(0, FROM_LOCAL, NULL, iph2);
1627		}
1628#endif
1629
1630	plog(ASL_LEVEL_DEBUG, "===\n");
1631	return 0;
1632}
1633
1634static int
1635pk_recvexpire(mhp)
1636	caddr_t *mhp;
1637{
1638	struct sadb_msg *msg;
1639	struct sadb_sa *sa;
1640	struct sockaddr_storage *src, *dst;
1641	phase2_handle_t *iph2;
1642	u_int proto_id, sa_mode;
1643
1644	/* sanity check */
1645	if (mhp[0] == NULL
1646	 || mhp[SADB_EXT_SA] == NULL
1647	 || mhp[SADB_EXT_ADDRESS_SRC] == NULL
1648	 || mhp[SADB_EXT_ADDRESS_DST] == NULL
1649	 || (mhp[SADB_EXT_LIFETIME_HARD] != NULL
1650	  && mhp[SADB_EXT_LIFETIME_SOFT] != NULL)) {
1651		plog(ASL_LEVEL_ERR,
1652			"inappropriate sadb expire message passed.\n");
1653		return -1;
1654	}
1655	msg = ALIGNED_CAST(struct sadb_msg *)mhp[0];                 // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
1656	sa = ALIGNED_CAST(struct sadb_sa *)mhp[SADB_EXT_SA];
1657	src = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
1658	dst = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
1659
1660	sa_mode = mhp[SADB_X_EXT_SA2] == NULL
1661		? IPSEC_MODE_ANY
1662		: (ALIGNED_CAST(struct sadb_x_sa2 *)mhp[SADB_X_EXT_SA2])->sadb_x_sa2_mode;
1663
1664	proto_id = pfkey2ipsecdoi_proto(msg->sadb_msg_satype);
1665	if (proto_id == ~0) {
1666		plog(ASL_LEVEL_ERR,
1667			"invalid proto_id %d\n", msg->sadb_msg_satype);
1668		return -1;
1669	}
1670
1671	plog(ASL_LEVEL_INFO,
1672		"IPsec-SA expired: %s\n",
1673		sadbsecas2str(src, dst,
1674			msg->sadb_msg_satype, sa->sadb_sa_spi, sa_mode));
1675
1676	iph2 = ike_session_getph2bysaidx(src, dst, proto_id, sa->sadb_sa_spi);
1677	if (iph2 == NULL) {
1678		/*
1679		 * Ignore it because two expire messages are come up.
1680		 * phase2 handler has been deleted already when 2nd message
1681		 * is received.
1682		 */
1683		plog(ASL_LEVEL_DEBUG,
1684			"no such a SA found: %s\n",
1685			sadbsecas2str(src, dst,
1686			    msg->sadb_msg_satype, sa->sadb_sa_spi,
1687			    sa_mode));
1688		return 0;
1689	}
1690	if (iph2->is_dying || !FSM_STATE_IS_ESTABLISHED(iph2->status)) {
1691		/*
1692		 * If the status is not equal to PHASE2ST_ESTABLISHED,
1693		 * racoon ignores this expire message.  There are two reason.
1694		 * One is that the phase 2 probably starts because there is
1695		 * a potential that racoon receives the acquire message
1696		 * without receiving a expire message.  Another is that racoon
1697		 * may receive the multiple expire messages from the kernel.
1698		 */
1699		plog(ASL_LEVEL_WARNING,
1700             "The expire message is received but the handler %s (status = 0x%x).\n",
1701             iph2->is_dying ? "is dying" : "has not been established", iph2->status);
1702		return 0;
1703	}
1704
1705	/* turn off the timer for calling isakmp_ph2expire() */
1706	SCHED_KILL(iph2->sce);
1707
1708	fsm_set_state(&iph2->status, IKEV1_STATE_PHASE2_EXPIRED);
1709
1710	/* INITIATOR, begin phase 2 exchange only if there's no other established ph2. */
1711	/* allocate buffer for status management of pfkey message */
1712	if (iph2->side == INITIATOR &&
1713		!ike_session_has_other_established_ph2(iph2->parent_session, iph2) &&
1714		!ike_session_drop_rekey(iph2->parent_session, IKE_SESSION_REKEY_TYPE_PH2)) {
1715
1716		ike_session_initph2(iph2);
1717
1718		/* start isakmp initiation by using ident exchange */
1719		if (isakmp_post_acquire(iph2) < 0) {
1720			plog(ASL_LEVEL_ERR,
1721				"failed to begin ipsec sa "
1722				"re-negotiation.\n");
1723			ike_session_unlink_phase2(iph2);
1724			return -1;
1725		}
1726
1727		return 0;
1728		/*NOTREACHED*/
1729	}
1730
1731
1732	/* If not received SADB_EXPIRE, INITIATOR delete ph2handle. */
1733	/* RESPONDER always delete ph2handle, keep silent.  RESPONDER doesn't
1734	 * manage IPsec SA, so delete the list */
1735	ike_session_unlink_phase2(iph2);
1736
1737	return 0;
1738}
1739
1740static int
1741pk_recvacquire(mhp)
1742	caddr_t *mhp;
1743{
1744	struct sadb_msg *msg;
1745	struct sadb_x_policy *xpl;
1746	struct secpolicy *sp_out = NULL, *sp_in = NULL;
1747	phase2_handle_t *iph2;
1748	struct sockaddr_storage *src, *dst;
1749    ike_session_t *session = NULL;
1750    struct remoteconf *rmconf;
1751
1752	/* ignore this message because of local test mode. */
1753	if (f_local)
1754		return 0;
1755
1756	/* sanity check */
1757	if (mhp[0] == NULL
1758	 || mhp[SADB_EXT_ADDRESS_SRC] == NULL
1759	 || mhp[SADB_EXT_ADDRESS_DST] == NULL
1760	 || mhp[SADB_X_EXT_POLICY] == NULL) {
1761		plog(ASL_LEVEL_ERR,
1762			"inappropriate sadb acquire message passed.\n");
1763		return -1;
1764	}
1765	msg = ALIGNED_CAST(struct sadb_msg *)mhp[0];                         // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
1766	xpl = ALIGNED_CAST(struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
1767	src = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
1768	dst = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
1769
1770	/* ignore if type is not IPSEC_POLICY_IPSEC */
1771	if (xpl->sadb_x_policy_type != IPSEC_POLICY_IPSEC) {
1772		plog(ASL_LEVEL_DEBUG,
1773			"ignore ACQUIRE message. type is not IPsec.\n");
1774		return 0;
1775	}
1776
1777	/* ignore it if src is multicast address */
1778    {
1779	struct sockaddr_storage *sa = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
1780
1781	if ((sa->ss_family == AF_INET
1782	  && IN_MULTICAST(ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr)))
1783#ifdef INET6
1784	 || (sa->ss_family == AF_INET6
1785	  && IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *)sa)->sin6_addr))
1786#endif
1787	) {
1788		plog(ASL_LEVEL_DEBUG,
1789			"ignore due to multicast address: %s.\n",
1790			saddrwop2str((struct sockaddr *)sa));
1791		return 0;
1792	}
1793    }
1794
1795    	/* ignore, if we do not listen on source address */
1796	{
1797		/* reasons behind:
1798		 * - if we'll contact peer from address we do not listen -
1799		 *   we will be unable to complete negotiation;
1800		 * - if we'll negotiate using address we're listening -
1801		 *   remote peer will send packets to address different
1802		 *   than one in the policy, so kernel will drop them;
1803		 * => therefore this acquire is not for us! --Aidas
1804		 */
1805                                                                    // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
1806		struct sockaddr_storage *sa = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
1807		struct myaddrs *p;
1808		int do_listen = 0;
1809        char * str;
1810		for (p = lcconf->myaddrs; p; p = p->next) {
1811            str = saddr2str((struct sockaddr *)p->addr);
1812            plog(ASL_LEVEL_DEBUG,
1813                 "checking listen addrs: %s", str);
1814
1815			if (!cmpsaddrwop(p->addr, sa)) {
1816				do_listen = 1;
1817				break;
1818			}
1819		}
1820
1821		if (!do_listen) {
1822			plog(ASL_LEVEL_DEBUG,
1823				"ignore because do not listen on source address : %s.\n",
1824				saddrwop2str((struct sockaddr *)sa));
1825			return 0;
1826		}
1827	}
1828
1829	/*
1830	 * If there is a phase 2 handler against the policy identifier in
1831	 * the acquire message, and if
1832	 *    1. its state is less than PHASE2ST_ESTABLISHED, then racoon
1833	 *       should ignore such a acquire message because the phase 2
1834	 *       is just negotiating.
1835	 *    2. its state is equal to PHASE2ST_ESTABLISHED, then racoon
1836	 *       has to process such a acquire message because racoon may
1837	 *       have lost the expire message.
1838	 */
1839	iph2 = ike_session_getph2byid(src, dst, xpl->sadb_x_policy_id);
1840	if (iph2 != NULL) {
1841        session = iph2->parent_session;
1842		if (!FSM_STATE_IS_ESTABLISHED(iph2->status)) {
1843			plog(ASL_LEVEL_DEBUG,
1844				"ignore the acquire because ph2 found\n");
1845			return -1;
1846		}
1847		if (FSM_STATE_IS_EXPIRED(iph2->status))
1848			iph2 = NULL;
1849		/*FALLTHROUGH*/
1850	}
1851
1852	/* search for proper policyindex */
1853	sp_out = getspbyspid(xpl->sadb_x_policy_id);
1854	if (sp_out == NULL) {
1855		plog(ASL_LEVEL_ERR, "no policy found: id:%d.\n",
1856			xpl->sadb_x_policy_id);
1857		return -1;
1858	}
1859	plog(ASL_LEVEL_DEBUG,
1860		"suitable outbound SP found: %s.\n", spidx2str(&sp_out->spidx));
1861
1862	/* get inbound policy */
1863    {
1864        struct policyindex spidx;
1865
1866        spidx.dir = IPSEC_DIR_INBOUND;
1867        memcpy(&spidx.src, &sp_out->spidx.dst, sizeof(spidx.src));
1868        memcpy(&spidx.dst, &sp_out->spidx.src, sizeof(spidx.dst));
1869        spidx.prefs = sp_out->spidx.prefd;
1870        spidx.prefd = sp_out->spidx.prefs;
1871        spidx.ul_proto = sp_out->spidx.ul_proto;
1872
1873        sp_in = getsp(&spidx);
1874        if (sp_in) {
1875            plog(ASL_LEVEL_DEBUG,
1876                "Suitable inbound SP found: %s.\n",
1877                spidx2str(&sp_in->spidx));
1878        } else {
1879            plog(ASL_LEVEL_NOTICE,
1880                "No in-bound policy found: %s\n",
1881                spidx2str(&spidx));
1882        }
1883    }
1884
1885	/* allocate a phase 2 */
1886    rmconf = getrmconf(dst);
1887	if (rmconf == NULL) {
1888		plog(ASL_LEVEL_ERR, "No configuration found for %s.\n",
1889             saddrwop2str((struct sockaddr *)dst));
1890		return -1;
1891	}
1892
1893	iph2 = ike_session_newph2(rmconf->ike_version, PHASE2_TYPE_SA);
1894	if (iph2 == NULL) {
1895		plog(ASL_LEVEL_ERR,
1896			"Failed to allocate Phase 2 entry.\n");
1897		return -1;
1898	}
1899	plog(ASL_LEVEL_DEBUG, "Got new Phase 2 version %d\n", iph2->version);
1900    iph2->version = rmconf->ike_version;
1901	iph2->side = INITIATOR;
1902	iph2->spid = xpl->sadb_x_policy_id;
1903
1904	iph2->satype = msg->sadb_msg_satype;
1905	iph2->seq = msg->sadb_msg_seq;
1906	/* set end addresses of SA */
1907                                                // Wcast_align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
1908	iph2->src = dupsaddr(ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]));
1909	if (iph2->src == NULL) {
1910		ike_session_delph2(iph2);
1911		return -1;
1912	}
1913    iph2->dst = dupsaddr(ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]));
1914	if (iph2->dst == NULL) {
1915        ike_session_delph2(iph2);
1916		return -1;
1917    }
1918
1919	if (iph2->version == ISAKMP_VERSION_NUMBER_IKEV1) {
1920		fsm_set_state(&iph2->status, IKEV1_STATE_QUICK_I_START);
1921	}
1922
1923	plog(ASL_LEVEL_DEBUG,
1924		"new acquire %s\n", spidx2str(&sp_out->spidx));
1925
1926	/* get sainfo */
1927    {
1928        vchar_t *idsrc, *iddst;
1929
1930        idsrc = ipsecdoi_sockaddr2id(&sp_out->spidx.src,
1931                    sp_out->spidx.prefs, sp_out->spidx.ul_proto);
1932        if (idsrc == NULL) {
1933            plog(ASL_LEVEL_ERR,
1934                "failed to get ID for %s\n",
1935                spidx2str(&sp_out->spidx));
1936            ike_session_delph2(iph2);
1937            return -1;
1938        }
1939        iddst = ipsecdoi_sockaddr2id(&sp_out->spidx.dst,
1940                    sp_out->spidx.prefd, sp_out->spidx.ul_proto);
1941        if (iddst == NULL) {
1942            plog(ASL_LEVEL_ERR,
1943                "failed to get ID for %s\n",
1944                spidx2str(&sp_out->spidx));
1945            vfree(idsrc);
1946            ike_session_delph2(iph2);
1947            return -1;
1948        }
1949        iph2->sainfo = getsainfo(idsrc, iddst, NULL, 0);
1950        vfree(idsrc);
1951        vfree(iddst);
1952        if (iph2->sainfo == NULL) {
1953            plog(ASL_LEVEL_ERR,
1954                "failed to get sainfo.\n");
1955            ike_session_delph2(iph2);
1956            return -1;
1957            /* XXX should use the algorithm list from register message */
1958        }
1959    }
1960    retain_sainfo(iph2->sainfo);
1961
1962	if (set_proposal_from_policy(iph2, sp_out, sp_in) < 0) {
1963		plog(ASL_LEVEL_ERR,
1964			 "failed to create saprop.\n");
1965			ike_session_delph2(iph2);
1966		return -1;
1967	}
1968
1969    if (session == NULL)
1970        session = ike_session_get_session(iph2->src, iph2->dst, 1, NULL);
1971    if (session == NULL)
1972        fatal_error(-1);
1973
1974    if (ike_session_link_phase2(session, iph2))
1975        fatal_error(-1);    //????? fix ???
1976
1977	/* start isakmp initiation by using ident exchange */
1978	/* XXX should be looped if there are multiple phase 2 handler. */
1979	if (isakmp_post_acquire(iph2) < 0) {
1980		plog(ASL_LEVEL_ERR,
1981			"failed to begin ipsec sa negotiation.\n");
1982		goto err;
1983	}
1984
1985#if !TARGET_OS_EMBEDDED
1986	if ( lcconf->vt == NULL){
1987		if (!(lcconf->vt = vproc_transaction_begin(NULL)))
1988			plog(ASL_LEVEL_ERR,
1989			 	"vproc_transaction_begin returns NULL.\n");
1990	}
1991#endif
1992
1993
1994	return 0;
1995
1996err:
1997    ike_session_unlink_phase2(iph2);
1998	return -1;
1999}
2000
2001static int
2002pk_recvdelete(mhp)
2003	caddr_t *mhp;
2004{
2005	struct sadb_msg *msg;
2006	struct sadb_sa *sa;
2007	struct sockaddr_storage *src, *dst;
2008	phase2_handle_t *iph2 = NULL;
2009	u_int proto_id;
2010
2011	/* ignore this message because of local test mode. */
2012	if (f_local)
2013		return 0;
2014
2015	/* sanity check */
2016	if (mhp[0] == NULL
2017	 || mhp[SADB_EXT_ADDRESS_SRC] == NULL
2018	 || mhp[SADB_EXT_ADDRESS_DST] == NULL) {
2019		plog(ASL_LEVEL_ERR,
2020			"inappropriate sadb delete message passed.\n");
2021		return -1;
2022	}
2023	msg = ALIGNED_CAST(struct sadb_msg *)mhp[0];                 // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
2024	sa = ALIGNED_CAST(struct sadb_sa *)mhp[SADB_EXT_SA];
2025	src = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
2026	dst = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
2027
2028	/* the message has to be processed or not ? */
2029	if (msg->sadb_msg_pid == getpid()) {
2030		plog(ASL_LEVEL_DEBUG,
2031			"%s message is not interesting "
2032			"because the message was originated by me.\n",
2033			s_pfkey_type(msg->sadb_msg_type));
2034		return -1;
2035	}
2036
2037	proto_id = pfkey2ipsecdoi_proto(msg->sadb_msg_satype);
2038	if (proto_id == ~0) {
2039		plog(ASL_LEVEL_ERR,
2040			"invalid proto_id %d\n", msg->sadb_msg_satype);
2041		return -1;
2042	}
2043
2044    plog(ASL_LEVEL_DEBUG, "SADB delete message: proto-id %d\n", proto_id);
2045    plog(ASL_LEVEL_DEBUG, "src: %s\n", saddr2str((struct sockaddr *)src));
2046    plog(ASL_LEVEL_DEBUG, "dst: %s\n", saddr2str((struct sockaddr *)dst));
2047
2048    if (!sa) {
2049        ike_session_deleteallph2(src, dst, proto_id);
2050        ike_session_deleteallph1(src, dst);
2051        return 0;
2052    }
2053
2054	iph2 = ike_session_getph2bysaidx(src, dst, proto_id, sa->sadb_sa_spi);
2055	if (iph2 == NULL) {
2056		/* ignore */
2057		plog(ASL_LEVEL_ERR,
2058			"no iph2 found: %s\n",
2059			sadbsecas2str(src, dst, msg->sadb_msg_satype,
2060				sa->sadb_sa_spi, IPSEC_MODE_ANY));
2061		return 0;
2062	}
2063
2064	plog(ASL_LEVEL_ERR,
2065		"pfkey DELETE received: %s\n",
2066		sadbsecas2str(iph2->src, iph2->dst,
2067			msg->sadb_msg_satype, sa->sadb_sa_spi, IPSEC_MODE_ANY));
2068
2069	/* send delete information */
2070
2071    /* TODO: Look into handling this properly. Currently, if we get here, we can end up sending delete messages to the server for their own SAs, which is rejected. */
2072	/*if (FSM_STATE_IS_ESTABLISHED(iph2->status))
2073		isakmp_info_send_d2(iph2);
2074
2075	ike_session_cleanup_ph1s_by_ph2(iph2);
2076	ike_session_unlink_phase2(iph2);*/
2077
2078	return 0;
2079}
2080
2081static int
2082pk_recvflush(mhp)
2083	caddr_t *mhp;
2084{
2085	/* sanity check */
2086	if (mhp[0] == NULL) {
2087		plog(ASL_LEVEL_ERR,
2088			"inappropriate sadb flush message passed.\n");
2089		return -1;
2090	}
2091
2092	ike_session_flush_all_phase2(false);
2093	ike_session_flush_all_phase1(false);
2094
2095	return 0;
2096}
2097
2098static int
2099getsadbpolicy(policy0, policylen0, type, iph2)
2100	caddr_t *policy0;
2101	int *policylen0, type;
2102	phase2_handle_t *iph2;
2103{
2104	struct policyindex *spidx = iph2->spidx_gen;
2105	struct sadb_x_policy *xpl;
2106	struct sadb_x_ipsecrequest *xisr;
2107	struct saproto *pr;
2108	caddr_t policy, p;
2109	int policylen;
2110	int xisrlen;
2111	u_int satype, mode;
2112
2113	/* get policy buffer size */
2114	policylen = sizeof(struct sadb_x_policy);
2115	if (type != SADB_X_SPDDELETE) {
2116		for (pr = iph2->approval->head; pr; pr = pr->next) {
2117			xisrlen = sizeof(*xisr);
2118			if (pr->encmode == IPSECDOI_ATTR_ENC_MODE_TUNNEL) {
2119				xisrlen += (sysdep_sa_len((struct sockaddr *)iph2->src)
2120				          + sysdep_sa_len((struct sockaddr *)iph2->dst));
2121			}
2122
2123			policylen += PFKEY_ALIGN8(xisrlen);
2124		}
2125	}
2126
2127	/* make policy structure */
2128	policy = racoon_malloc(policylen);
2129	if (!policy) {
2130		plog(ASL_LEVEL_ERR,
2131			"buffer allocation failed.\n");
2132		return -1;
2133	}
2134
2135	xpl = ALIGNED_CAST(struct sadb_x_policy *)policy;
2136	xpl->sadb_x_policy_len = PFKEY_UNIT64(policylen);
2137	xpl->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
2138	xpl->sadb_x_policy_type = IPSEC_POLICY_IPSEC;
2139	xpl->sadb_x_policy_dir = spidx->dir;
2140	xpl->sadb_x_policy_id = 0;
2141#ifdef HAVE_PFKEY_POLICY_PRIORITY
2142	xpl->sadb_x_policy_priority = PRIORITY_DEFAULT;
2143#endif
2144
2145	/* no need to append policy information any more if type is SPDDELETE */
2146	if (type == SADB_X_SPDDELETE)
2147		goto end;
2148
2149	xisr = (struct sadb_x_ipsecrequest *)(xpl + 1);
2150
2151	for (pr = iph2->approval->head; pr; pr = pr->next) {
2152
2153		satype = doi2ipproto(pr->proto_id);
2154		if (satype == ~0) {
2155			plog(ASL_LEVEL_ERR,
2156				"invalid proto_id %d\n", pr->proto_id);
2157			goto err;
2158		}
2159		mode = ipsecdoi2pfkey_mode(pr->encmode);
2160		if (mode == ~0) {
2161			plog(ASL_LEVEL_ERR,
2162				"invalid encmode %d\n", pr->encmode);
2163			goto err;
2164		}
2165
2166		/*
2167		 * the policy level cannot be unique because the policy
2168		 * is defined later than SA, so req_id cannot be bound to SA.
2169		 */
2170		xisr->sadb_x_ipsecrequest_proto = satype;
2171		xisr->sadb_x_ipsecrequest_mode = mode;
2172		xisr->sadb_x_ipsecrequest_level = IPSEC_LEVEL_REQUIRE;
2173		xisr->sadb_x_ipsecrequest_reqid = 0;
2174		p = (caddr_t)(xisr + 1);
2175
2176		xisrlen = sizeof(*xisr);
2177
2178		if (pr->encmode == IPSECDOI_ATTR_ENC_MODE_TUNNEL) {
2179			int src_len, dst_len;
2180
2181			src_len = sysdep_sa_len((struct sockaddr *)iph2->src);
2182			dst_len = sysdep_sa_len((struct sockaddr *)iph2->dst);
2183			xisrlen += src_len + dst_len;
2184
2185			memcpy(p, iph2->src, src_len);
2186			p += src_len;
2187
2188			memcpy(p, iph2->dst, dst_len);
2189			p += dst_len;
2190		}
2191
2192		xisr->sadb_x_ipsecrequest_len = PFKEY_ALIGN8(xisrlen);
2193	}
2194
2195end:
2196	*policy0 = policy;
2197	*policylen0 = policylen;
2198
2199	return 0;
2200
2201err:
2202	if (policy)
2203		racoon_free(policy);
2204
2205	return -1;
2206}
2207
2208int
2209pk_sendspdupdate2(iph2)
2210	phase2_handle_t *iph2;
2211{
2212	struct policyindex *spidx = iph2->spidx_gen;
2213	caddr_t policy = NULL;
2214	int policylen = 0;
2215	u_int64_t ltime, vtime;
2216
2217	ltime = iph2->approval->lifetime;
2218	vtime = 0;
2219
2220	if (getsadbpolicy(&policy, &policylen, SADB_X_SPDUPDATE, iph2)) {
2221		plog(ASL_LEVEL_ERR,
2222			"getting sadb policy failed.\n");
2223		return -1;
2224	}
2225
2226	if (pfkey_send_spdupdate2(
2227			lcconf->sock_pfkey,
2228			&spidx->src,
2229			spidx->prefs,
2230			&spidx->dst,
2231			spidx->prefd,
2232			spidx->ul_proto,
2233			ltime, vtime,
2234			policy, policylen, 0) < 0) {
2235		plog(ASL_LEVEL_ERR,
2236			"libipsec failed send spdupdate2 (%s)\n",
2237			ipsec_strerror());
2238		goto end;
2239	}
2240	plog(ASL_LEVEL_DEBUG, "call pfkey_send_spdupdate2\n");
2241
2242end:
2243	if (policy)
2244		racoon_free(policy);
2245
2246	return 0;
2247}
2248
2249static int
2250pk_recvspdupdate(mhp)
2251	caddr_t *mhp;
2252{
2253	struct sadb_address *saddr, *daddr;
2254	struct sadb_x_policy *xpl;
2255	struct policyindex spidx;
2256	struct secpolicy *sp;
2257
2258	/* sanity check */
2259	if (mhp[0] == NULL
2260	 || mhp[SADB_EXT_ADDRESS_SRC] == NULL
2261	 || mhp[SADB_EXT_ADDRESS_DST] == NULL
2262	 || mhp[SADB_X_EXT_POLICY] == NULL) {
2263		plog(ASL_LEVEL_ERR,
2264			"inappropriate sadb spdupdate message passed.\n");
2265		return -1;
2266	}
2267	saddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];        // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
2268	daddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
2269	xpl = ALIGNED_CAST(struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
2270
2271#ifdef HAVE_PFKEY_POLICY_PRIORITY
2272	KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
2273			saddr + 1,
2274			daddr + 1,
2275			saddr->sadb_address_prefixlen,
2276			daddr->sadb_address_prefixlen,
2277			saddr->sadb_address_proto,
2278			xpl->sadb_x_policy_priority,
2279			&spidx);
2280#else
2281	KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
2282			saddr + 1,
2283			daddr + 1,
2284			saddr->sadb_address_prefixlen,
2285			daddr->sadb_address_prefixlen,
2286			saddr->sadb_address_proto,
2287			&spidx);
2288#endif
2289
2290	sp = getsp(&spidx);
2291	if (sp == NULL) {
2292		plog(ASL_LEVEL_ERR,
2293			"such policy does not already exist: \"%s\"\n",
2294			spidx2str(&spidx));
2295	} else {
2296		remsp(sp);
2297		delsp(sp);
2298	}
2299
2300	if (addnewsp(mhp) < 0)
2301		return -1;
2302
2303	return 0;
2304}
2305
2306/*
2307 * this function has to be used by responder side.
2308 */
2309int
2310pk_sendspdadd2(iph2)
2311	phase2_handle_t *iph2;
2312{
2313	struct policyindex *spidx = iph2->spidx_gen;
2314	caddr_t policy = NULL;
2315	int policylen = 0;
2316	u_int64_t ltime, vtime;
2317
2318	ltime = iph2->approval->lifetime;
2319	vtime = 0;
2320
2321	if (getsadbpolicy(&policy, &policylen, SADB_X_SPDADD, iph2)) {
2322		plog(ASL_LEVEL_ERR,
2323			"getting sadb policy failed.\n");
2324		return -1;
2325	}
2326
2327	if (pfkey_send_spdadd2(
2328			lcconf->sock_pfkey,
2329			&spidx->src,
2330			spidx->prefs,
2331			&spidx->dst,
2332			spidx->prefd,
2333			spidx->ul_proto,
2334			ltime, vtime,
2335			policy, policylen, 0) < 0) {
2336		plog(ASL_LEVEL_ERR,
2337			"libipsec failed send spdadd2 (%s)\n",
2338			ipsec_strerror());
2339		goto end;
2340	}
2341	plog(ASL_LEVEL_DEBUG, "call pfkey_send_spdadd2\n");
2342
2343end:
2344	if (policy)
2345		racoon_free(policy);
2346
2347	return 0;
2348}
2349
2350static int
2351pk_recvspdadd(mhp)
2352	caddr_t *mhp;
2353{
2354	struct sadb_address *saddr, *daddr;
2355	struct sadb_x_policy *xpl;
2356	struct policyindex spidx;
2357	struct secpolicy *sp;
2358
2359	/* sanity check */
2360	if (mhp[0] == NULL
2361	 || mhp[SADB_EXT_ADDRESS_SRC] == NULL
2362	 || mhp[SADB_EXT_ADDRESS_DST] == NULL
2363	 || mhp[SADB_X_EXT_POLICY] == NULL) {
2364		plog(ASL_LEVEL_ERR,
2365			"inappropriate sadb spdadd message passed.\n");
2366		return -1;
2367	}
2368	saddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];    // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
2369	daddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
2370	xpl = ALIGNED_CAST(struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
2371
2372#ifdef HAVE_PFKEY_POLICY_PRIORITY
2373	KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
2374			saddr + 1,
2375			daddr + 1,
2376			saddr->sadb_address_prefixlen,
2377			daddr->sadb_address_prefixlen,
2378			saddr->sadb_address_proto,
2379			xpl->sadb_x_policy_priority,
2380			&spidx);
2381#else
2382	KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
2383			saddr + 1,
2384			daddr + 1,
2385			saddr->sadb_address_prefixlen,
2386			daddr->sadb_address_prefixlen,
2387			saddr->sadb_address_proto,
2388			&spidx);
2389#endif
2390
2391	sp = getsp(&spidx);
2392	if (sp != NULL) {
2393		plog(ASL_LEVEL_ERR,
2394			"such policy already exists. "
2395			"anyway replace it: %s\n",
2396			spidx2str(&spidx));
2397		remsp(sp);
2398		delsp(sp);
2399	}
2400
2401	if (addnewsp(mhp) < 0)
2402		return -1;
2403
2404	return 0;
2405}
2406
2407/*
2408 * this function has to be used by responder side.
2409 */
2410int
2411pk_sendspddelete(iph2)
2412	phase2_handle_t *iph2;
2413{
2414	struct policyindex *spidx = iph2->spidx_gen;
2415	caddr_t policy = NULL;
2416	int policylen;
2417
2418	if (getsadbpolicy(&policy, &policylen, SADB_X_SPDDELETE, iph2)) {
2419		plog(ASL_LEVEL_ERR,
2420			"getting sadb policy failed.\n");
2421		return -1;
2422	}
2423
2424	if (pfkey_send_spddelete(
2425			lcconf->sock_pfkey,
2426			&spidx->src,
2427			spidx->prefs,
2428			&spidx->dst,
2429			spidx->prefd,
2430			spidx->ul_proto,
2431			policy, policylen, 0) < 0) {
2432		plog(ASL_LEVEL_ERR,
2433			"libipsec failed send spddelete (%s)\n",
2434			ipsec_strerror());
2435		goto end;
2436	}
2437	plog(ASL_LEVEL_DEBUG, "call pfkey_send_spddelete\n");
2438
2439end:
2440	if (policy)
2441		racoon_free(policy);
2442
2443	return 0;
2444}
2445
2446static int
2447pk_recvspddelete(mhp)
2448	caddr_t *mhp;
2449{
2450	struct sadb_address *saddr, *daddr;
2451	struct sadb_x_policy *xpl;
2452	struct policyindex spidx;
2453	struct secpolicy *sp;
2454
2455	/* sanity check */
2456	if (mhp[0] == NULL
2457	 || mhp[SADB_EXT_ADDRESS_SRC] == NULL
2458	 || mhp[SADB_EXT_ADDRESS_DST] == NULL
2459	 || mhp[SADB_X_EXT_POLICY] == NULL) {
2460		plog(ASL_LEVEL_ERR,
2461			"inappropriate sadb spddelete message passed.\n");
2462		return -1;
2463	}
2464	saddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];    // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
2465	daddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
2466	xpl = ALIGNED_CAST(struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
2467
2468#ifdef HAVE_PFKEY_POLICY_PRIORITY
2469	KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
2470			saddr + 1,
2471			daddr + 1,
2472			saddr->sadb_address_prefixlen,
2473			daddr->sadb_address_prefixlen,
2474			saddr->sadb_address_proto,
2475			xpl->sadb_x_policy_priority,
2476			&spidx);
2477#else
2478	KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
2479			saddr + 1,
2480			daddr + 1,
2481			saddr->sadb_address_prefixlen,
2482			daddr->sadb_address_prefixlen,
2483			saddr->sadb_address_proto,
2484			&spidx);
2485#endif
2486
2487	sp = getsp(&spidx);
2488	if (sp == NULL) {
2489		plog(ASL_LEVEL_ERR,
2490			"no policy found: %s\n",
2491			spidx2str(&spidx));
2492		return -1;
2493	}
2494
2495    ike_session_purgephXbyspid(xpl->sadb_x_policy_id, true);
2496
2497	remsp(sp);
2498	delsp(sp);
2499
2500	return 0;
2501}
2502
2503static int
2504pk_recvspdexpire(mhp)
2505	caddr_t *mhp;
2506{
2507	struct sadb_address *saddr, *daddr;
2508	struct sadb_x_policy *xpl;
2509	struct policyindex spidx;
2510	struct secpolicy *sp;
2511
2512	/* sanity check */
2513	if (mhp[0] == NULL
2514	 || mhp[SADB_EXT_ADDRESS_SRC] == NULL
2515	 || mhp[SADB_EXT_ADDRESS_DST] == NULL
2516	 || mhp[SADB_X_EXT_POLICY] == NULL) {
2517		plog(ASL_LEVEL_ERR,
2518			"inappropriate sadb spdexpire message passed.\n");
2519		return -1;
2520	}
2521	saddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];    // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
2522	daddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
2523	xpl = ALIGNED_CAST(struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
2524
2525#ifdef HAVE_PFKEY_POLICY_PRIORITY
2526	KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
2527			saddr + 1,
2528			daddr + 1,
2529			saddr->sadb_address_prefixlen,
2530			daddr->sadb_address_prefixlen,
2531			saddr->sadb_address_proto,
2532			xpl->sadb_x_policy_priority,
2533			&spidx);
2534#else
2535	KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
2536			saddr + 1,
2537			daddr + 1,
2538			saddr->sadb_address_prefixlen,
2539			daddr->sadb_address_prefixlen,
2540			saddr->sadb_address_proto,
2541			&spidx);
2542#endif
2543
2544	sp = getsp(&spidx);
2545	if (sp == NULL) {
2546		plog(ASL_LEVEL_ERR,
2547			"no policy found: %s\n",
2548			spidx2str(&spidx));
2549		return -1;
2550	}
2551
2552    ike_session_purgephXbyspid(xpl->sadb_x_policy_id, false);
2553
2554	remsp(sp);
2555	delsp(sp);
2556
2557	return 0;
2558}
2559
2560static int
2561pk_recvspdget(mhp)
2562	caddr_t *mhp;
2563{
2564	/* sanity check */
2565	if (mhp[0] == NULL) {
2566		plog(ASL_LEVEL_ERR,
2567			"inappropriate sadb spdget message passed.\n");
2568		return -1;
2569	}
2570
2571	return 0;
2572}
2573
2574static int
2575pk_recvspddump(mhp)
2576	caddr_t *mhp;
2577{
2578	struct sadb_msg *msg;
2579	struct sadb_address *saddr, *daddr;
2580	struct sadb_x_policy *xpl;
2581	struct policyindex spidx;
2582	struct secpolicy *sp;
2583
2584	/* sanity check */
2585	if (mhp[0] == NULL) {
2586		plog(ASL_LEVEL_ERR,
2587			"inappropriate sadb spddump message passed.\n");
2588		return -1;
2589	}
2590	msg = ALIGNED_CAST(struct sadb_msg *)mhp[0];         // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
2591
2592	saddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
2593	daddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
2594	xpl = ALIGNED_CAST(struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
2595
2596	if (saddr == NULL || daddr == NULL || xpl == NULL) {
2597		plog(ASL_LEVEL_ERR,
2598			"inappropriate sadb spddump message passed.\n");
2599		return -1;
2600	}
2601
2602#ifdef HAVE_PFKEY_POLICY_PRIORITY
2603	KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
2604			saddr + 1,
2605			daddr + 1,
2606			saddr->sadb_address_prefixlen,
2607			daddr->sadb_address_prefixlen,
2608			saddr->sadb_address_proto,
2609			xpl->sadb_x_policy_priority,
2610			&spidx);
2611#else
2612	KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
2613			saddr + 1,
2614			daddr + 1,
2615			saddr->sadb_address_prefixlen,
2616			daddr->sadb_address_prefixlen,
2617			saddr->sadb_address_proto,
2618			&spidx);
2619#endif
2620
2621	sp = getsp(&spidx);
2622	if (sp != NULL) {
2623		plog(ASL_LEVEL_ERR,
2624			"such policy already exists. "
2625			"anyway replace it: %s\n",
2626			spidx2str(&spidx));
2627		remsp(sp);
2628		delsp(sp);
2629	}
2630
2631	if (addnewsp(mhp) < 0)
2632		return -1;
2633
2634	return 0;
2635}
2636
2637static int
2638pk_recvspdflush(mhp)
2639	caddr_t *mhp;
2640{
2641	/* sanity check */
2642	if (mhp[0] == NULL) {
2643		plog(ASL_LEVEL_ERR,
2644			"inappropriate sadb spdflush message passed.\n");
2645		return -1;
2646	}
2647
2648    ike_session_flush_all_phase2(false);
2649    ike_session_flush_all_phase1(false);
2650	flushsp();
2651
2652	return 0;
2653}
2654
2655/*
2656 * send error against acquire message to kenrel.
2657 */
2658int
2659pk_sendeacquire(iph2)
2660	phase2_handle_t *iph2;
2661{
2662	struct sadb_msg *newmsg;
2663	int len;
2664
2665	len = sizeof(struct sadb_msg);
2666	newmsg = racoon_calloc(1, len);
2667	if (newmsg == NULL) {
2668		plog(ASL_LEVEL_ERR,
2669			"failed to get buffer to send acquire.\n");
2670		return -1;
2671	}
2672
2673	memset(newmsg, 0, len);
2674	newmsg->sadb_msg_version = PF_KEY_V2;
2675	newmsg->sadb_msg_type = SADB_ACQUIRE;
2676	newmsg->sadb_msg_errno = ENOENT;	/* XXX */
2677	newmsg->sadb_msg_satype = iph2->satype;
2678	newmsg->sadb_msg_len = PFKEY_UNIT64(len);
2679	newmsg->sadb_msg_reserved = 0;
2680	newmsg->sadb_msg_seq = iph2->seq;
2681	newmsg->sadb_msg_pid = (u_int32_t)getpid();
2682
2683	/* send message */
2684	len = pfkey_send(lcconf->sock_pfkey, newmsg, len);
2685
2686	racoon_free(newmsg);
2687
2688	return 0;
2689}
2690
2691int
2692pk_sendget_inbound_sastats(ike_session_t *session)
2693{
2694    u_int32_t max_stats;
2695    u_int32_t seq;
2696
2697    if (!session) {
2698        plog(ASL_LEVEL_DEBUG, "invalid args in %s \n", __FUNCTION__);
2699        return -1;
2700    }
2701
2702    session->traffic_monitor.num_in_curr_req = 0;
2703    bzero(session->traffic_monitor.in_curr_req, sizeof(session->traffic_monitor.in_curr_req));
2704    max_stats = (sizeof(session->traffic_monitor.in_curr_req) / sizeof(session->traffic_monitor.in_curr_req[0]));
2705
2706    // get list of SAs
2707    if ((session->traffic_monitor.num_in_curr_req = ike_session_get_sas_for_stats(session,
2708                                                                                  IPSEC_DIR_INBOUND,
2709                                                                                  &seq,
2710                                                                                  session->traffic_monitor.in_curr_req,
2711                                                                                  max_stats))) {
2712        u_int64_t session_ids[] = {(u_int64_t)session, 0};
2713
2714        //plog(ASL_LEVEL_DEBUG, "about to call %s\n", __FUNCTION__);
2715
2716        if (pfkey_send_getsastats(lcconf->sock_pfkey,
2717                                  seq,
2718                                  session_ids,
2719                                  1,
2720                                  IPSEC_DIR_INBOUND,
2721                                  session->traffic_monitor.in_curr_req,
2722                                  session->traffic_monitor.num_in_curr_req) < 0) {
2723            return -1;
2724        }
2725        //plog(ASL_LEVEL_DEBUG, "%s successful\n", __FUNCTION__);
2726
2727        return session->traffic_monitor.num_in_curr_req;
2728    }
2729    return 0;
2730}
2731
2732int
2733pk_sendget_outbound_sastats(ike_session_t *session)
2734{
2735    u_int32_t max_stats;
2736    u_int32_t seq;
2737
2738    if (!session) {
2739        plog(ASL_LEVEL_DEBUG, "invalid args in %s \n", __FUNCTION__);
2740        return -1;
2741    }
2742
2743    session->traffic_monitor.num_out_curr_req = 0;
2744    bzero(session->traffic_monitor.out_curr_req, sizeof(session->traffic_monitor.out_curr_req));
2745    max_stats = (sizeof(session->traffic_monitor.out_curr_req) / sizeof(session->traffic_monitor.out_curr_req[0]));
2746
2747    // get list of SAs
2748    if ((session->traffic_monitor.num_out_curr_req = ike_session_get_sas_for_stats(session,
2749                                                                                   IPSEC_DIR_OUTBOUND,
2750                                                                                   &seq,
2751                                                                                   session->traffic_monitor.out_curr_req,
2752                                                                                   max_stats))) {
2753        u_int64_t session_ids[] = {(u_int64_t)session, 0};
2754
2755        //plog(ASL_LEVEL_DEBUG, "about to call %s\n", __FUNCTION__);
2756
2757        if (pfkey_send_getsastats(lcconf->sock_pfkey,
2758                                  seq,
2759                                  session_ids,
2760                                  1,
2761                                  IPSEC_DIR_OUTBOUND,
2762                                  session->traffic_monitor.out_curr_req,
2763                                  session->traffic_monitor.num_out_curr_req) < 0) {
2764            return -1;
2765        }
2766        //plog(ASL_LEVEL_DEBUG, "%s successful\n", __FUNCTION__);
2767
2768        return session->traffic_monitor.num_out_curr_req;
2769    }
2770    return 0;
2771}
2772
2773/*
2774 * receive GETSPDSTAT from kernel.
2775 */
2776static int
2777pk_recvgetsastat(mhp)
2778caddr_t *mhp;
2779{
2780	struct sadb_msg        *msg;
2781    struct sadb_session_id *session_id;
2782    struct sadb_sastat     *stat_resp;
2783	ike_session_t          *session;
2784
2785	/* validity check */
2786	if (mhp[0] == NULL ||
2787        mhp[SADB_EXT_SESSION_ID] == NULL ||
2788        mhp[SADB_EXT_SASTAT] == NULL) {
2789		plog(ASL_LEVEL_ERR,
2790             "inappropriate sadb getsastat response.\n");
2791		return -1;
2792	}
2793	msg = ALIGNED_CAST(struct sadb_msg *)mhp[0];                         // Wcast-align fix (void*) - mhp contains pointers to structs in an aligned buffer
2794    session_id = ALIGNED_CAST(struct sadb_session_id *)mhp[SADB_EXT_SESSION_ID];
2795	stat_resp = ALIGNED_CAST(struct sadb_sastat *)mhp[SADB_EXT_SASTAT];
2796
2797	/* the message has to be processed or not ? */
2798	if (msg->sadb_msg_pid != getpid()) {
2799		plog(ASL_LEVEL_DEBUG,
2800             "%s message is not interesting "
2801             "because pid %d is not mine.\n",
2802             s_pfkey_type(msg->sadb_msg_type),
2803             msg->sadb_msg_pid);
2804		return -1;
2805	}
2806    if (!session_id->sadb_session_id_v[0]) {
2807		plog(ASL_LEVEL_DEBUG,
2808             "%s message is bad "
2809             "because session-id[0] is invalid.\n",
2810             s_pfkey_type(msg->sadb_msg_type));
2811        return -1;
2812    }
2813    session = ALIGNED_CAST(__typeof__(session))session_id->sadb_session_id_v[0];
2814
2815    if (!stat_resp->sadb_sastat_list_len) {
2816		plog(ASL_LEVEL_DEBUG,
2817             "%s message is bad "
2818             "because it has no sastats.\n",
2819             s_pfkey_type(msg->sadb_msg_type));
2820        return -1;
2821    }
2822
2823    ike_session_update_traffic_idle_status(session,
2824                                           stat_resp->sadb_sastat_dir,
2825                                           (struct sastat *)(stat_resp + 1),
2826                                           stat_resp->sadb_sastat_list_len);
2827	return 0;
2828}
2829
2830/*
2831 * check if the algorithm is supported or not.
2832 * OUT	 0: ok
2833 *	-1: ng
2834 */
2835int
2836pk_checkalg(class, calg, keylen)
2837	int class, calg, keylen;
2838{
2839	int sup, error;
2840	u_int alg;
2841	struct sadb_alg alg0;
2842
2843	switch (algclass2doi(class)) {
2844	case IPSECDOI_PROTO_IPSEC_ESP:
2845		sup = SADB_EXT_SUPPORTED_ENCRYPT;
2846		break;
2847	case IPSECDOI_ATTR_AUTH:
2848		sup = SADB_EXT_SUPPORTED_AUTH;
2849		break;
2850	case IPSECDOI_PROTO_IPCOMP:
2851		return 0;
2852	default:
2853		plog(ASL_LEVEL_ERR,
2854			"invalid algorithm class.\n");
2855		return -1;
2856	}
2857	alg = ipsecdoi2pfkey_alg(algclass2doi(class), algtype2doi(class, calg));
2858	if (alg == ~0)
2859		return -1;
2860
2861	if (keylen == 0) {
2862		if (ipsec_get_keylen(sup, alg, &alg0)) {
2863			plog(ASL_LEVEL_ERR,
2864				"%s.\n", ipsec_strerror());
2865			return -1;
2866		}
2867		keylen = alg0.sadb_alg_minbits;
2868	}
2869
2870	error = ipsec_check_keylen(sup, alg, keylen);
2871	if (error)
2872		plog(ASL_LEVEL_ERR,
2873			"%s.\n", ipsec_strerror());
2874
2875	return error;
2876}
2877
2878/*
2879 * differences with pfkey_recv() in libipsec/pfkey.c:
2880 * - never performs busy wait loop.
2881 * - returns NULL and set *lenp to negative on fatal failures
2882 * - returns NULL and set *lenp to non-negative on non-fatal failures
2883 * - returns non-NULL on success
2884 */
2885static struct sadb_msg *
2886pk_recv(so, lenp)
2887	int so;
2888	ssize_t *lenp;
2889{
2890	struct sadb_msg *newmsg;
2891	int reallen = 0;
2892	socklen_t optlen = sizeof(reallen);
2893
2894	if (getsockopt(so, SOL_SOCKET, SO_NREAD, &reallen, &optlen) < 0)
2895		return NULL;	/*fatal*/
2896
2897	if (reallen == 0)
2898		return NULL;
2899
2900	if ((newmsg = racoon_calloc(1, reallen)) == NULL)
2901		return NULL;
2902
2903	while ((*lenp = recv(so, (caddr_t)newmsg, reallen, 0)) < 0) {
2904		if (errno == EINTR)
2905			continue;
2906		plog(ASL_LEVEL_ERR, "failed to recv pfkey message: %s\n", strerror(errno));
2907		break;
2908	}
2909	if (*lenp < 0) {
2910		racoon_free(newmsg);
2911		return NULL;	/*fatal*/
2912	} else if (*lenp != reallen || *lenp < sizeof(struct sadb_msg)) {
2913		racoon_free(newmsg);
2914		return NULL;
2915	}
2916
2917	return newmsg;
2918}
2919
2920/* see handler.h */
2921u_int32_t
2922pk_getseq()
2923{
2924	return eay_random();
2925}
2926
2927static int
2928addnewsp(mhp)
2929	caddr_t *mhp;
2930{
2931	struct secpolicy *new;
2932	struct sadb_address *saddr, *daddr;
2933	struct sadb_x_policy *xpl;
2934
2935	/* sanity check */
2936	if (mhp[SADB_EXT_ADDRESS_SRC] == NULL
2937	 || mhp[SADB_EXT_ADDRESS_DST] == NULL
2938	 || mhp[SADB_X_EXT_POLICY] == NULL) {
2939		plog(ASL_LEVEL_ERR,
2940			"inappropriate sadb spd management message passed.\n");
2941		return -1;
2942	}
2943
2944	saddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];    // Wcast-align fix (void*) - mhp contains pointers to aligned structs in malloc'd msg buffer
2945	daddr = ALIGNED_CAST(struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
2946	xpl = ALIGNED_CAST(struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
2947
2948	new = newsp();
2949	if (new == NULL) {
2950		plog(ASL_LEVEL_ERR,
2951			"failed to allocate buffer\n");
2952		return -1;
2953	}
2954
2955	new->spidx.dir = xpl->sadb_x_policy_dir;
2956	new->id = xpl->sadb_x_policy_id;
2957	new->policy = xpl->sadb_x_policy_type;
2958	new->req = NULL;
2959
2960	/* check policy */
2961	switch (xpl->sadb_x_policy_type) {
2962	case IPSEC_POLICY_DISCARD:
2963	case IPSEC_POLICY_GENERATE:
2964	case IPSEC_POLICY_NONE:
2965	case IPSEC_POLICY_ENTRUST:
2966	case IPSEC_POLICY_BYPASS:
2967		break;
2968
2969	case IPSEC_POLICY_IPSEC:
2970	    {
2971		int tlen;
2972		struct sadb_x_ipsecrequest *xisr;
2973		struct ipsecrequest **p_isr = &new->req;
2974
2975		/* validity check */
2976		if (PFKEY_EXTLEN(xpl) < sizeof(*xpl)) {
2977			plog(ASL_LEVEL_ERR,
2978				"invalid msg length.\n");
2979			return -1;
2980		}
2981
2982		tlen = PFKEY_EXTLEN(xpl) - sizeof(*xpl);
2983		xisr = (struct sadb_x_ipsecrequest *)(xpl + 1);
2984
2985		while (tlen > 0) {
2986
2987			/* length check */
2988			if (xisr->sadb_x_ipsecrequest_len < sizeof(*xisr)) {
2989				plog(ASL_LEVEL_ERR,
2990					"invalid msg length.\n");
2991				return -1;
2992			}
2993
2994			/* allocate request buffer */
2995			*p_isr = newipsecreq();
2996			if (*p_isr == NULL) {
2997				plog(ASL_LEVEL_ERR,
2998					"failed to get new ipsecreq.\n");
2999				return -1;
3000			}
3001
3002			/* set values */
3003			(*p_isr)->next = NULL;
3004
3005			switch (xisr->sadb_x_ipsecrequest_proto) {
3006			case IPPROTO_ESP:
3007			case IPPROTO_AH:
3008			case IPPROTO_IPCOMP:
3009				break;
3010			default:
3011				plog(ASL_LEVEL_ERR,
3012					"invalid proto type: %u\n",
3013					xisr->sadb_x_ipsecrequest_proto);
3014				return -1;
3015			}
3016			(*p_isr)->saidx.proto = xisr->sadb_x_ipsecrequest_proto;
3017
3018			switch (xisr->sadb_x_ipsecrequest_mode) {
3019			case IPSEC_MODE_TRANSPORT:
3020			case IPSEC_MODE_TUNNEL:
3021				break;
3022			case IPSEC_MODE_ANY:
3023			default:
3024				plog(ASL_LEVEL_ERR,
3025					"invalid mode: %u\n",
3026					xisr->sadb_x_ipsecrequest_mode);
3027				return -1;
3028			}
3029			(*p_isr)->saidx.mode = xisr->sadb_x_ipsecrequest_mode;
3030
3031			switch (xisr->sadb_x_ipsecrequest_level) {
3032			case IPSEC_LEVEL_DEFAULT:
3033			case IPSEC_LEVEL_USE:
3034			case IPSEC_LEVEL_REQUIRE:
3035				break;
3036			case IPSEC_LEVEL_UNIQUE:
3037				(*p_isr)->saidx.reqid =
3038					xisr->sadb_x_ipsecrequest_reqid;
3039				break;
3040
3041			default:
3042				plog(ASL_LEVEL_ERR,
3043					"invalid level: %u\n",
3044					xisr->sadb_x_ipsecrequest_level);
3045				return -1;
3046			}
3047			(*p_isr)->level = xisr->sadb_x_ipsecrequest_level;
3048
3049			/* set IP addresses if there */
3050			if (xisr->sadb_x_ipsecrequest_len > sizeof(*xisr)) {
3051				struct sockaddr *paddr;
3052
3053				paddr = (struct sockaddr *)(xisr + 1);
3054				bcopy(paddr, &(*p_isr)->saidx.src,
3055					sysdep_sa_len(paddr));
3056
3057				paddr = (struct sockaddr *)((caddr_t)paddr
3058							+ sysdep_sa_len(paddr));
3059				bcopy(paddr, &(*p_isr)->saidx.dst,
3060					sysdep_sa_len(paddr));
3061			}
3062
3063			(*p_isr)->sp = new;
3064
3065			/* initialization for the next. */
3066			p_isr = &(*p_isr)->next;
3067			tlen -= xisr->sadb_x_ipsecrequest_len;
3068
3069			/* validity check */
3070			if (tlen < 0) {
3071				plog(ASL_LEVEL_ERR,
3072					"becoming tlen < 0\n");
3073			}
3074
3075			xisr = ALIGNED_CAST(struct sadb_x_ipsecrequest *)((caddr_t)xisr
3076			                 + xisr->sadb_x_ipsecrequest_len);
3077		}
3078	    }
3079		break;
3080	default:
3081		plog(ASL_LEVEL_ERR,
3082			"invalid policy type.\n");
3083		return -1;
3084	}
3085
3086#ifdef HAVE_PFKEY_POLICY_PRIORITY
3087	KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
3088			saddr + 1,
3089			daddr + 1,
3090			saddr->sadb_address_prefixlen,
3091			daddr->sadb_address_prefixlen,
3092			saddr->sadb_address_proto,
3093			xpl->sadb_x_policy_priority,
3094			&new->spidx);
3095#else
3096	KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
3097			saddr + 1,
3098			daddr + 1,
3099			saddr->sadb_address_prefixlen,
3100			daddr->sadb_address_prefixlen,
3101			saddr->sadb_address_proto,
3102			&new->spidx);
3103#endif
3104
3105	inssp(new);
3106
3107	return 0;
3108}
3109
3110/* proto/mode/src->dst spi */
3111const char *
3112sadbsecas2str(src, dst, proto, spi, mode)
3113	struct sockaddr_storage *src, *dst;
3114	int proto;
3115	u_int32_t spi;
3116	int mode;
3117{
3118	static char buf[256];
3119	u_int doi_proto, doi_mode = 0;
3120	char *p;
3121	int blen, i;
3122
3123	doi_proto = pfkey2ipsecdoi_proto(proto);
3124	if (doi_proto == ~0)
3125		return NULL;
3126	if (mode) {
3127		doi_mode = pfkey2ipsecdoi_mode(mode);
3128		if (doi_mode == ~0)
3129			return NULL;
3130	}
3131
3132	blen = sizeof(buf) - 1;
3133	p = buf;
3134
3135	i = snprintf(p, blen, "%s%s%s ",
3136		s_ipsecdoi_proto(doi_proto),
3137		mode ? "/" : "",
3138		mode ? s_ipsecdoi_encmode(doi_mode) : "");
3139	if (i < 0 || i >= blen)
3140		return NULL;
3141	p += i;
3142	blen -= i;
3143
3144	i = snprintf(p, blen, "%s->", saddr2str((struct sockaddr *)src));
3145	if (i < 0 || i >= blen)
3146		return NULL;
3147	p += i;
3148	blen -= i;
3149
3150	i = snprintf(p, blen, "%s ", saddr2str((struct sockaddr *)dst));
3151	if (i < 0 || i >= blen)
3152		return NULL;
3153	p += i;
3154	blen -= i;
3155
3156	if (spi) {
3157		snprintf(p, blen, "spi=%lu(0x%lx)", (unsigned long)ntohl(spi),
3158		    (unsigned long)ntohl(spi));
3159	}
3160
3161	return buf;
3162}
3163