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