1/*	$NetBSD: isakmp_inf.c,v 1.14.4.8 2007/08/01 11:52:20 vanhu Exp $	*/
2
3/* Id: isakmp_inf.c,v 1.44 2006/05/06 20:45:52 manubsd Exp */
4
5/*
6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the project nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include "config.h"
35#include "racoon_types.h"
36
37#include <sys/types.h>
38#include <sys/param.h>
39#include <sys/socket.h>
40
41#include <net/pfkeyv2.h>
42#include <netinet/in.h>
43#include <sys/queue.h>
44#ifndef HAVE_NETINET6_IPSEC
45#include <netinet/ipsec.h>
46#else
47#include <netinet6/ipsec.h>
48#endif
49
50#include <stdlib.h>
51#include <stdio.h>
52#include <string.h>
53#include <errno.h>
54#if TIME_WITH_SYS_TIME
55# include <sys/time.h>
56# include <time.h>
57#else
58# if HAVE_SYS_TIME_H
59#  include <sys/time.h>
60# else
61#  include <time.h>
62# endif
63#endif
64#ifdef ENABLE_HYBRID
65#include <resolv.h>
66#endif
67
68#include "libpfkey.h"
69
70#include "var.h"
71#include "vmbuf.h"
72#include "schedule.h"
73#include "str2val.h"
74#include "misc.h"
75#include "plog.h"
76#include "debug.h"
77#include "fsm.h"
78#include "session.h"
79#include "ike_session.h"
80
81#include "localconf.h"
82#include "remoteconf.h"
83#include "sockmisc.h"
84#include "handler.h"
85#include "policy.h"
86#include "proposal.h"
87#include "isakmp_var.h"
88#include "isakmp.h"
89#ifdef ENABLE_HYBRID
90#include "isakmp_xauth.h"
91#include "isakmp_unity.h"
92#include "isakmp_cfg.h"
93#endif
94#include "isakmp_inf.h"
95#include "ikev2_info_rfc.h"
96#include "oakley.h"
97#include "ipsec_doi.h"
98#include "crypto_openssl.h"
99#include "pfkey.h"
100#include "policy.h"
101#include "algorithm.h"
102#include "proposal.h"
103#include "strnames.h"
104#ifdef ENABLE_NATT
105#include "nattraversal.h"
106#endif
107#include "vpn_control_var.h"
108#include "vpn_control.h"
109#include "ike_session.h"
110#include "ipsecSessionTracer.h"
111#include "ipsecMessageTracer.h"
112
113/* information exchange */
114static int isakmp_info_recv_n (phase1_handle_t *, struct isakmp_pl_n *, u_int32_t, int);
115static int isakmp_info_recv_d (phase1_handle_t *, struct isakmp_pl_d *, u_int32_t, int);
116
117#ifdef ENABLE_DPD
118static int isakmp_info_recv_r_u (phase1_handle_t *, struct isakmp_pl_ru *, u_int32_t);
119static int isakmp_info_recv_r_u_ack (phase1_handle_t *, struct isakmp_pl_ru *, u_int32_t);
120#endif
121
122#ifdef ENABLE_VPNCONTROL_PORT
123static int isakmp_info_recv_lb (phase1_handle_t *, struct isakmp_pl_lb *lb, int);
124#endif
125
126static int
127isakmp_ph1_responder_lifetime (phase1_handle_t *iph1, struct isakmp_pl_resp_lifetime *notify)
128{
129    char *spi;
130
131    if (ntohs(notify->h.len) < sizeof(*notify) + notify->spi_size) {
132        plog(ASL_LEVEL_ERR,
133             "invalid spi_size in notification payload.\n");
134        return -1;
135    }
136    spi = val2str((char *)(notify + 1), notify->spi_size);
137
138    plog(ASL_LEVEL_DEBUG,
139         "notification message ISAKMP-SA RESPONDER-LIFETIME, "
140         "doi=%d proto_id=%d spi=%s(size=%d).\n",
141         ntohl(notify->doi), notify->proto_id, spi, notify->spi_size);
142
143    /* TODO */
144    #if 0
145        struct isakmp_pl_attr *attrpl;
146        int                    len = ntohs(notify->h.len) - (sizeof(*notify) + notify->spi_size);
147
148        attrpl = (struct isakmp_pl_attr *)((char *)(notify + 1) + notify->spi_size);
149        while (len > 0) {
150        }
151    #endif
152
153    racoon_free(spi);
154    return 0;
155}
156
157static int
158isakmp_ph2_responder_lifetime (phase2_handle_t *iph2, struct isakmp_pl_resp_lifetime *notify)
159{
160    char *spi;
161
162    if (ntohs(notify->h.len) < sizeof(*notify) + notify->spi_size) {
163        plog(ASL_LEVEL_ERR,
164             "invalid spi_size in notification payload.\n");
165        return -1;
166    }
167    spi = val2str((char *)(notify + 1), notify->spi_size);
168
169    plog(ASL_LEVEL_DEBUG,
170         "notification message IPSEC-SA RESPONDER-LIFETIME, "
171         "doi=%d proto_id=%d spi=%s(size=%d).\n",
172         ntohl(notify->doi), notify->proto_id, spi, notify->spi_size);
173
174    /* TODO */
175
176    racoon_free(spi);
177    return 0;
178}
179
180/* %%%
181 * Information Exchange
182 */
183/*
184 * receive Information
185 */
186int
187isakmp_info_recv(phase1_handle_t *iph1, vchar_t *msg0)
188{
189	vchar_t *msg = NULL;
190	vchar_t *pbuf = NULL;
191	u_int32_t msgid = 0;
192	int error = -1;
193	struct isakmp *isakmp;
194	struct isakmp_gen *gen;
195    struct isakmp_parse_t *pa;
196	void *p;
197	vchar_t *hash, *payload;
198	struct isakmp_gen *nd;
199	u_int8_t np;
200	int encrypted;
201	int flag = 0;
202
203	plog(ASL_LEVEL_DEBUG, "receive Information.\n");
204
205	encrypted = ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E);
206	msgid = ((struct isakmp *)msg0->v)->msgid;
207
208	/* Use new IV to decrypt Informational message. */
209	if (encrypted) {
210		struct isakmp_ivm *ivm;
211
212		if (iph1->ivm == NULL) {
213			plog(ASL_LEVEL_ERR, "iph1->ivm == NULL\n");
214			IPSECSESSIONTRACEREVENT(iph1->parent_session,
215									IPSECSESSIONEVENTCODE_IKE_PACKET_RX_FAIL,
216									CONSTSTR("Information message"),
217									CONSTSTR("Failed to process Information Message (no IV)"));
218			return -1;
219		}
220
221		/* compute IV */
222		ivm = oakley_newiv2(iph1, ((struct isakmp *)msg0->v)->msgid);
223		if (ivm == NULL) {
224			plog(ASL_LEVEL_ERR,
225				 "failed to compute IV\n");
226			IPSECSESSIONTRACEREVENT(iph1->parent_session,
227									IPSECSESSIONEVENTCODE_IKE_PACKET_RX_FAIL,
228									CONSTSTR("Information message"),
229									CONSTSTR("Failed to process Information Message (can't compute IV)"));
230			return -1;
231		}
232
233		msg = oakley_do_decrypt(iph1, msg0, ivm->iv, ivm->ive);
234		oakley_delivm(ivm);
235		if (msg == NULL) {
236			plog(ASL_LEVEL_ERR,
237				 "failed to decrypt packet\n");
238			IPSECSESSIONTRACEREVENT(iph1->parent_session,
239									IPSECSESSIONEVENTCODE_IKE_PACKET_RX_FAIL,
240									CONSTSTR("Information message"),
241									CONSTSTR("Failed to decrypt Information message"));
242			return -1;
243		}
244
245	} else
246		msg = vdup(msg0);
247
248	/* Safety check */
249	if (msg->l < sizeof(*isakmp) + sizeof(*gen)) {
250		plog(ASL_LEVEL_ERR,
251			"ignore information because the "
252			"message is way too short\n");
253		goto end;
254	}
255
256	isakmp = (struct isakmp *)msg->v;
257	gen = (struct isakmp_gen *)((caddr_t)isakmp + sizeof(struct isakmp));
258	np = gen->np;
259
260	if (encrypted) {
261		if (isakmp->np != ISAKMP_NPTYPE_HASH) {
262			plog(ASL_LEVEL_ERR,
263			    "ignore information because the "
264			    "message has no hash payload.\n");
265			goto end;
266		}
267
268		if (!FSM_STATE_IS_ESTABLISHED(iph1->status) &&
269            (!iph1->approval || !iph1->skeyid_a)) {
270			plog(ASL_LEVEL_ERR,
271			    "ignore information because ISAKMP-SA "
272			    "has not been established yet.\n");
273			goto end;
274		}
275
276		/* Safety check */
277		if (msg->l < sizeof(*isakmp) + ntohs(gen->len) + sizeof(*nd)) {
278			plog(ASL_LEVEL_ERR,
279				"ignore information because the "
280				"message is too short\n");
281			goto end;
282		}
283
284		p = (caddr_t) gen + sizeof(struct isakmp_gen);
285		nd = (struct isakmp_gen *) ((caddr_t) gen + ntohs(gen->len));
286
287		/* nd length check */
288		if (ntohs(nd->len) > msg->l - (sizeof(struct isakmp) +
289		    ntohs(gen->len))) {
290			plog(ASL_LEVEL_ERR,
291				 "too long payload length (broken message?)\n");
292			goto end;
293		}
294
295		if (ntohs(nd->len) < sizeof(*nd)) {
296			plog(ASL_LEVEL_ERR,
297				"too short payload length (broken message?)\n");
298			goto end;
299		}
300
301		payload = vmalloc(ntohs(nd->len));
302		if (payload == NULL) {
303			plog(ASL_LEVEL_ERR,
304			    "cannot allocate memory\n");
305			goto end;
306		}
307
308		memcpy(payload->v, (caddr_t) nd, ntohs(nd->len));
309
310		/* compute HASH */
311		hash = oakley_compute_hash1(iph1, isakmp->msgid, payload);
312		if (hash == NULL) {
313			plog(ASL_LEVEL_ERR,
314			    "cannot compute hash\n");
315
316			vfree(payload);
317			goto end;
318		}
319
320		if (ntohs(gen->len) - sizeof(struct isakmp_gen) != hash->l) {
321			plog(ASL_LEVEL_ERR,
322			    "ignore information due to hash length mismatch\n");
323
324			vfree(hash);
325			vfree(payload);
326			goto end;
327		}
328
329		if (memcmp(p, hash->v, hash->l) != 0) {
330			plog(ASL_LEVEL_ERR,
331			    "ignore information due to hash mismatch\n");
332
333			vfree(hash);
334			vfree(payload);
335			goto end;
336		}
337
338		plog(ASL_LEVEL_DEBUG, "hash validated.\n");
339
340		vfree(hash);
341		vfree(payload);
342	} else {
343		/* make sure phase 1 was not yet at encrypted state */
344		switch (iph1->etype) {
345		case ISAKMP_ETYPE_AGG:
346            // %%%%% should also check for unity/mode cfg - last pkt is encrypted in such cases
347            if (!FSM_STATE_IS_ESTABLISHED(iph1->status) &&
348                ((iph1->side == INITIATOR && iph1->status == IKEV1_STATE_AGG_I_MSG3SENT) ||
349                 (iph1->side == RESPONDER && iph1->status == IKEV1_STATE_AGG_R_MSG3RCVD))) {
350                    break;
351                }
352		case ISAKMP_ETYPE_IDENT:
353            if (!FSM_STATE_IS_ESTABLISHED(iph1->status) &&
354                ((iph1->side == INITIATOR && (iph1->status == IKEV1_STATE_IDENT_I_MSG5SENT
355                                               || iph1->status == IKEV1_STATE_IDENT_I_MSG6RCVD)) ||
356                 (iph1->side == RESPONDER && (iph1->status == IKEV1_STATE_IDENT_R_MSG5RCVD)))) {
357				break;
358			}
359			/*FALLTHRU*/
360		default:
361			plog(ASL_LEVEL_ERR,
362				"%s message must be encrypted\n",
363				s_isakmp_nptype(np));
364			error = 0;
365			goto end;
366		}
367	}
368
369	if (!(pbuf = isakmp_parse(msg))) {
370		plog(ASL_LEVEL_ERR,
371			 "failed to parse msg");
372		error = -1;
373		goto end;
374	}
375
376	error = 0;
377	for (pa = ALIGNED_CAST(struct isakmp_parse_t *)pbuf->v; pa->type; pa++) {    // Wcast-align fix (void*) - aligned buffer of aligned (unpacked) structs
378		switch (pa->type) {
379		case ISAKMP_NPTYPE_HASH:
380			/* Handled above */
381			break;
382		case ISAKMP_NPTYPE_N:
383			error = isakmp_info_recv_n(iph1,
384				(struct isakmp_pl_n *)pa->ptr,
385				msgid, encrypted);
386			break;
387		case ISAKMP_NPTYPE_D:
388			error = isakmp_info_recv_d(iph1,
389				(struct isakmp_pl_d *)pa->ptr,
390				msgid, encrypted);
391			break;
392		case ISAKMP_NPTYPE_NONCE:
393			/* XXX to be 6.4.2 ike-01.txt */
394			/* XXX IV is to be synchronized. */
395			plog(ASL_LEVEL_ERR,
396				"ignore Acknowledged Informational\n");
397			break;
398		default:
399			/* don't send information, see isakmp_ident_r1() */
400			error = 0;
401			plog(ASL_LEVEL_ERR,
402				"reject the packet, "
403				"received unexpected payload type %s.\n",
404				s_isakmp_nptype(gen->np));
405		}
406		if(error < 0) {
407			break;
408		} else {
409			flag |= error;
410		}
411	}
412	IPSECSESSIONTRACEREVENT(iph1->parent_session,
413							IPSECSESSIONEVENTCODE_IKE_PACKET_RX_SUCC,
414							CONSTSTR("Information message"),
415							CONSTSTR(NULL));
416
417end:
418	if (error) {
419		IPSECSESSIONTRACEREVENT(iph1->parent_session,
420								IPSECSESSIONEVENTCODE_IKE_PACKET_RX_FAIL,
421								CONSTSTR("Information message"),
422								CONSTSTR("Failed to process Information Message"));
423	}
424	if (msg != NULL)
425		vfree(msg);
426	if (pbuf != NULL)
427		vfree(pbuf);
428	return error;
429}
430
431/*
432 * handling of Notification payload
433 */
434static int
435isakmp_info_recv_n(phase1_handle_t *iph1, struct isakmp_pl_n *notify, u_int32_t msgid, int encrypted)
436{
437	u_int type;
438	vchar_t *ndata;
439	char *nraw;
440	size_t l;
441	char *spi;
442
443	type = ntohs(notify->type);
444
445	switch (type) {
446	case ISAKMP_NTYPE_CONNECTED:
447	case ISAKMP_NTYPE_REPLAY_STATUS:
448#ifdef ENABLE_HYBRID
449	case ISAKMP_NTYPE_UNITY_HEARTBEAT:
450#endif
451		/* do something */
452		break;
453    case ISAKMP_NTYPE_RESPONDER_LIFETIME:
454        if (encrypted) {
455            return(isakmp_ph1_responder_lifetime(iph1,
456                                                 (struct isakmp_pl_resp_lifetime *)notify));
457        }
458        break;
459	case ISAKMP_NTYPE_INITIAL_CONTACT:
460		if (encrypted) {
461			info_recv_initialcontact(iph1);
462			return 0;
463		}
464		break;
465#ifdef ENABLE_DPD
466	case ISAKMP_NTYPE_R_U_THERE:
467		if (encrypted)
468			return isakmp_info_recv_r_u(iph1,
469				(struct isakmp_pl_ru *)notify, msgid);
470		break;
471	case ISAKMP_NTYPE_R_U_THERE_ACK:
472		if (encrypted)
473			return isakmp_info_recv_r_u_ack(iph1,
474				(struct isakmp_pl_ru *)notify, msgid);
475		break;
476#endif
477#ifdef ENABLE_VPNCONTROL_PORT
478	case ISAKMP_NTYPE_LOAD_BALANCE:
479		isakmp_info_recv_lb(iph1, (struct isakmp_pl_lb *)notify, encrypted);
480		break;
481#endif
482
483	default:
484	    {
485		/* XXX there is a potential of dos attack. */
486		if(type >= ISAKMP_NTYPE_MINERROR &&
487		   type <= ISAKMP_NTYPE_MAXERROR) {
488			if (msgid == 0) {
489				/* don't think this realy deletes ph1 ? */
490				plog(ASL_LEVEL_ERR,
491					"Delete Phase 1 handle.\n");
492				return -1;
493			} else {
494				if (ike_session_getph2bymsgid(iph1, msgid) == NULL) {
495					plog(ASL_LEVEL_ERR,
496						"Fatal %s notify messsage, "
497						"Phase 1 should be deleted.\n",
498						s_isakmp_notify_msg(type));
499				} else {
500					plog(ASL_LEVEL_ERR,
501						"Fatal %s notify messsage, "
502						"Phase 2 should be deleted.\n",
503						s_isakmp_notify_msg(type));
504				}
505			}
506		} else {
507			plog(ASL_LEVEL_ERR,
508				"Unhandled notify message %s, "
509				"no Phase 2 handle found.\n",
510				s_isakmp_notify_msg(type));
511		}
512	    }
513	    break;
514	}
515
516	/* get spi if specified and allocate */
517	if(notify->spi_size > 0) {
518		if (ntohs(notify->h.len) < sizeof(*notify) + notify->spi_size) {
519			plog(ASL_LEVEL_ERR,
520				"Invalid spi_size in notification payload.\n");
521			return -1;
522		}
523		spi = val2str((char *)(notify + 1), notify->spi_size);
524
525		plog(ASL_LEVEL_DEBUG,
526			"Notification message %d:%s, "
527			"doi=%d proto_id=%d spi=%s(size=%d).\n",
528			type, s_isakmp_notify_msg(type),
529			ntohl(notify->doi), notify->proto_id, spi, notify->spi_size);
530
531		racoon_free(spi);
532	}
533
534	/* Send the message data to the logs */
535	if(type >= ISAKMP_NTYPE_MINERROR &&
536	   type <= ISAKMP_NTYPE_MAXERROR) {
537		l = ntohs(notify->h.len) - sizeof(*notify) - notify->spi_size;
538		if (l > 0) {
539			nraw = (char*)notify;
540			nraw += sizeof(*notify) + notify->spi_size;
541			if ((ndata = vmalloc(l)) != NULL) {
542				memcpy(ndata->v, nraw, ndata->l);
543				plog(ASL_LEVEL_ERR,
544				    "Message: '%s'.\n",
545				    binsanitize(ndata->v, ndata->l));
546				vfree(ndata);
547			} else {
548				plog(ASL_LEVEL_ERR,
549				    "Cannot allocate memory\n");
550			}
551		}
552	}
553	return 0;
554}
555
556#ifdef ENABLE_VPNCONTROL_PORT
557static void
558isakmp_info_vpncontrol_notify_ike_failed (phase1_handle_t *iph1, int isakmp_info_initiator, int type, vchar_t *data)
559{
560	u_int32_t address;
561	u_int32_t fail_reason;
562
563	/* notify the API that we have received the delete */
564	if (iph1->remote->ss_family == AF_INET)
565		address = ((struct sockaddr_in *)(iph1->remote))->sin_addr.s_addr;
566	else
567		address = 0;
568
569	if (isakmp_info_initiator == FROM_REMOTE) {
570		int premature = oakley_find_status_in_certchain(iph1->cert, CERT_STATUS_PREMATURE);
571		int expired = oakley_find_status_in_certchain(iph1->cert, CERT_STATUS_EXPIRED);
572
573		if (premature) {
574			fail_reason = VPNCTL_NTYPE_LOCAL_CERT_PREMATURE;
575            plog(ASL_LEVEL_NOTICE, ">>> Server reports client's certificate is pre-mature\n");
576		} else if (expired) {
577			fail_reason = VPNCTL_NTYPE_LOCAL_CERT_EXPIRED;
578            plog(ASL_LEVEL_NOTICE, ">>> Server reports client's certificate is expired\n");
579		} else {
580			fail_reason = type;
581		}
582		vpncontrol_notify_ike_failed(fail_reason, isakmp_info_initiator, address, 0, NULL);
583		return;
584	} else {
585		/* FROM_LOCAL */
586		if (type == ISAKMP_INTERNAL_ERROR ||
587			type <= ISAKMP_NTYPE_UNEQUAL_PAYLOAD_LENGTHS) {
588			int premature = oakley_find_status_in_certchain(iph1->cert_p, CERT_STATUS_PREMATURE);
589			int expired = oakley_find_status_in_certchain(iph1->cert_p, CERT_STATUS_EXPIRED);
590			int subjname = oakley_find_status_in_certchain(iph1->cert_p, CERT_STATUS_INVALID_SUBJNAME);
591			int subjaltname = oakley_find_status_in_certchain(iph1->cert_p, CERT_STATUS_INVALID_SUBJALTNAME);
592
593			if (premature) {
594				fail_reason = VPNCTL_NTYPE_PEER_CERT_PREMATURE;
595                plog(ASL_LEVEL_NOTICE, ">>> Server's certificate is pre-mature\n");
596			} else if (expired) {
597				fail_reason = VPNCTL_NTYPE_PEER_CERT_EXPIRED;
598                plog(ASL_LEVEL_NOTICE, ">>> Server's certificate is expired\n");
599			} else if (subjname) {
600				fail_reason = VPNCTL_NTYPE_PEER_CERT_INVALID_SUBJNAME;
601                plog(ASL_LEVEL_NOTICE, ">>> Server's certificate subject name not valid\n");
602			} else if (subjaltname) {
603				fail_reason = VPNCTL_NTYPE_PEER_CERT_INVALID_SUBJALTNAME;
604                plog(ASL_LEVEL_NOTICE, ">>> Server's certificate subject alternate name not valid\n");
605			} else {
606				fail_reason = type;
607			}
608			(void)vpncontrol_notify_ike_failed(fail_reason, isakmp_info_initiator, address,
609											   (data ? data->l : 0), (u_int8_t *)(data ? data->v : NULL));
610			return;
611		}
612	}
613}
614#endif /* ENABLE_VPNCONTROL_PORT */
615
616/*
617 * handling of Deletion payload
618 */
619static int
620isakmp_info_recv_d(phase1_handle_t *iph1, struct isakmp_pl_d *delete, u_int32_t msgid, int encrypted)
621{
622	int tlen, num_spi;
623	phase1_handle_t *del_ph1;
624	union {
625		u_int32_t spi32;
626		u_int16_t spi16[2];
627	} spi;
628
629	if (ntohl(delete->doi) != IPSEC_DOI) {
630		plog(ASL_LEVEL_ERR,
631			"delete payload with invalid doi:%d.\n",
632			ntohl(delete->doi));
633#ifdef ENABLE_HYBRID
634		/*
635		 * At deconnexion time, Cisco VPN client does this
636		 * with a zero DOI. Don't give up in that situation.
637		 */
638		if (((iph1->mode_cfg->flags &
639		    ISAKMP_CFG_VENDORID_UNITY) == 0) || (delete->doi != 0))
640			return 0;
641#else
642		return 0;
643#endif
644	}
645
646	num_spi = ntohs(delete->num_spi);
647	tlen = ntohs(delete->h.len) - sizeof(struct isakmp_pl_d);
648
649	if (tlen != num_spi * delete->spi_size) {
650		plog(ASL_LEVEL_ERR,
651			"deletion payload with invalid length.\n");
652		return 0;
653	}
654
655	plog(ASL_LEVEL_DEBUG,
656		"delete payload for protocol %s\n",
657		s_ipsecdoi_proto(delete->proto_id));
658
659	if(!iph1->rmconf->weak_phase1_check && !encrypted) {
660		plog(ASL_LEVEL_WARNING,
661			"Ignoring unencrypted delete payload "
662			"(check the weak_phase1_check option)\n");
663		return 0;
664	}
665
666	switch (delete->proto_id) {
667	case IPSECDOI_PROTO_ISAKMP:
668		if (delete->spi_size != sizeof(isakmp_index)) {
669			plog(ASL_LEVEL_ERR,
670				"delete payload with strange spi "
671				"size %d(proto_id:%d)\n",
672				delete->spi_size, delete->proto_id);
673			return 0;
674		}
675
676		del_ph1 = ike_session_getph1byindex(iph1->parent_session, (isakmp_index *)(delete + 1));
677		if(del_ph1 != NULL){
678
679            // hack: start a rekey now, if one was pending (only for client).
680            if (del_ph1->sce_rekey &&
681                del_ph1->parent_session &&
682                del_ph1->parent_session->is_client &&
683                del_ph1->parent_session->established) {
684                isakmp_ph1rekeyexpire(del_ph1, FALSE);
685            }
686
687			if (del_ph1->scr)
688				SCHED_KILL(del_ph1->scr);
689
690			/*
691			 * Do not delete IPsec SAs when receiving an IKE delete notification.
692			 * Just delete the IKE SA.
693			 */
694#ifdef ENABLE_VPNCONTROL_PORT
695			if (del_ph1->started_by_api || (del_ph1->is_rekey && del_ph1->parent_session && del_ph1->parent_session->is_client)) {
696				if (ike_session_islast_ph1(del_ph1)) {
697					isakmp_info_vpncontrol_notify_ike_failed(del_ph1, FROM_REMOTE, VPNCTL_NTYPE_PH1_DELETE, NULL);
698				}
699			}
700#endif
701			if (del_ph1->rmconf->natt_multiple_user &&
702				del_ph1->parent_session->is_l2tpvpn_ipsec) {
703				plog(ASL_LEVEL_DEBUG, "Ignoring IKE delete from peer for L2TP server\n");
704				break;
705			}
706			isakmp_ph1expire(del_ph1);
707		}
708		break;
709
710	case IPSECDOI_PROTO_IPSEC_AH:
711	case IPSECDOI_PROTO_IPSEC_ESP:
712		if (delete->spi_size != sizeof(u_int32_t)) {
713			plog(ASL_LEVEL_ERR,
714				"delete payload with strange spi "
715				"size %d(proto_id:%d)\n",
716				delete->spi_size, delete->proto_id);
717			return 0;
718		}
719		if (iph1->rmconf->natt_multiple_user &&
720			iph1->parent_session->is_l2tpvpn_ipsec) {
721			plog(ASL_LEVEL_DEBUG, "Ignoring SA delete from peer for L2TP server\n");
722			break;
723		}
724		purge_ipsec_spi(iph1->remote, delete->proto_id,
725		    ALIGNED_CAST(u_int32_t *)(delete + 1), num_spi, NULL, NULL);     // Wcast-align fix (void*) - delete payload is aligned
726		break;
727
728	case IPSECDOI_PROTO_IPCOMP:
729		/* need to handle both 16bit/32bit SPI */
730		memset(&spi, 0, sizeof(spi));
731		if (delete->spi_size == sizeof(spi.spi16[1])) {
732			memcpy(&spi.spi16[1], delete + 1,
733			    sizeof(spi.spi16[1]));
734		} else if (delete->spi_size == sizeof(spi.spi32))
735			memcpy(&spi.spi32, delete + 1, sizeof(spi.spi32));
736		else {
737			plog(ASL_LEVEL_ERR,
738				"delete payload with strange spi "
739				"size %d(proto_id:%d)\n",
740				delete->spi_size, delete->proto_id);
741			return 0;
742		}
743		purge_ipsec_spi(iph1->remote, delete->proto_id,
744		    &spi.spi32, num_spi, NULL, NULL);
745		break;
746
747	default:
748		plog(ASL_LEVEL_ERR,
749			"deletion message received, "
750			"invalid proto_id: %d\n",
751			delete->proto_id);
752		return 0;
753	}
754
755	plog(ASL_LEVEL_DEBUG, "purged SAs.\n");
756
757	return 0;
758}
759
760/*
761 * send Delete payload (for ISAKMP SA) in Informational exchange.
762 */
763int
764isakmp_info_send_d1(phase1_handle_t *iph1)
765{
766	struct isakmp_pl_d *d;
767	vchar_t *payload = NULL;
768	int tlen;
769	int error = 0;
770
771	if (!FSM_STATE_IS_ESTABLISHED(iph1->status))
772		return 0;
773
774	/* create delete payload */
775
776	/* send SPIs of inbound SAs. */
777	/* XXX should send outbound SAs's ? */
778	tlen = sizeof(*d) + sizeof(isakmp_index);
779	payload = vmalloc(tlen);
780	if (payload == NULL) {
781		plog(ASL_LEVEL_ERR,
782			"failed to get buffer for payload.\n");
783		return errno;
784	}
785
786	d = (struct isakmp_pl_d *)payload->v;
787	d->h.np = ISAKMP_NPTYPE_NONE;
788	d->h.len = htons(tlen);
789	d->doi = htonl(IPSEC_DOI);
790	d->proto_id = IPSECDOI_PROTO_ISAKMP;
791	d->spi_size = sizeof(isakmp_index);
792	d->num_spi = htons(1);
793	memcpy(d + 1, &iph1->index, sizeof(isakmp_index));
794
795	error = isakmp_info_send_common(iph1, payload,
796					ISAKMP_NPTYPE_D, 0);
797	vfree(payload);
798	if (error) {
799		IPSECSESSIONTRACEREVENT(iph1->parent_session,
800								IPSECSESSIONEVENTCODE_IKEV1_INFO_NOTICE_TX_FAIL,
801								CONSTSTR("Delete ISAKMP-SA"),
802								CONSTSTR("Failed to transmit Delete-ISAKMP-SA message"));
803	} else {
804		IPSECSESSIONTRACEREVENT(iph1->parent_session,
805								IPSECSESSIONEVENTCODE_IKEV1_INFO_NOTICE_TX_SUCC,
806								CONSTSTR("Delete ISAKMP-SA"),
807								CONSTSTR(NULL));
808	}
809
810	return error;
811}
812
813/*
814 * send Delete payload (for IPsec SA) in Informational exchange, based on
815 * pfkey msg.  It sends always single SPI.
816 */
817int
818isakmp_info_send_d2(phase2_handle_t *iph2)
819{
820	phase1_handle_t *iph1;
821	struct saproto *pr;
822	struct isakmp_pl_d *d;
823	vchar_t *payload = NULL;
824	int tlen;
825	int error = 0;
826	u_int8_t *spi;
827
828	if (!FSM_STATE_IS_ESTABLISHED(iph2->status))
829		return 0;
830
831	/*
832	 * don't send delete information if there is no phase 1 handler.
833	 * It's nonsensical to negotiate phase 1 to send the information.
834	 */
835    iph1 = ike_session_get_established_ph1(iph2->parent_session);
836    if (!iph1) {
837        iph1 = ike_session_getph1byaddr(iph2->parent_session, iph2->src, iph2->dst);
838    }
839	if (iph1 == NULL){
840		IPSECSESSIONTRACEREVENT(iph2->parent_session,
841								IPSECSESSIONEVENTCODE_IKE_PACKET_TX_FAIL,
842								CONSTSTR("Information message"),
843								CONSTSTR("Failed to transmit Information message"));
844		IPSECSESSIONTRACEREVENT(iph2->parent_session,
845								IPSECSESSIONEVENTCODE_IKEV1_INFO_NOTICE_TX_FAIL,
846								CONSTSTR("Delete IPSEC-SA"),
847								CONSTSTR("Failed to transmit Delete-IPSEC-SA message"));
848		plog(ASL_LEVEL_DEBUG,
849			 "No ph1 handler found, could not send DELETE_SA\n");
850		return 0;
851	}
852
853	/* create delete payload */
854	for (pr = iph2->approval->head; pr != NULL; pr = pr->next) {
855
856		/* send SPIs of inbound SAs. */
857		/*
858		 * XXX should I send outbound SAs's ?
859		 * I send inbound SAs's SPI only at the moment because I can't
860		 * decode any more if peer send encoded packet without aware of
861		 * deletion of SA.  Outbound SAs don't come under the situation.
862		 */
863		tlen = sizeof(*d) + pr->spisize;
864		payload = vmalloc(tlen);
865		if (payload == NULL) {
866			IPSECSESSIONTRACEREVENT(iph2->parent_session,
867									IPSECSESSIONEVENTCODE_IKE_PACKET_TX_FAIL,
868									CONSTSTR("Information message"),
869									CONSTSTR("Failed to transmit Information message"));
870			IPSECSESSIONTRACEREVENT(iph2->parent_session,
871									IPSECSESSIONEVENTCODE_IKEV1_INFO_NOTICE_TX_FAIL,
872									CONSTSTR("Delete IPSEC-SA"),
873									CONSTSTR("Failed to transmit Delete-IPSEC-SA message"));
874			plog(ASL_LEVEL_ERR,
875				"failed to get buffer for payload.\n");
876			return errno;
877		}
878
879		d = (struct isakmp_pl_d *)payload->v;
880		d->h.np = ISAKMP_NPTYPE_NONE;
881		d->h.len = htons(tlen);
882		d->doi = htonl(IPSEC_DOI);
883		d->proto_id = pr->proto_id;
884		d->spi_size = pr->spisize;
885		d->num_spi = htons(1);
886		/*
887		 * XXX SPI bits are left-filled, for use with IPComp.
888		 * we should be switching to variable-length spi field...
889		 */
890		spi = (u_int8_t *)&pr->spi;
891		spi += sizeof(pr->spi);
892		spi -= pr->spisize;
893		memcpy(d + 1, spi, pr->spisize);
894
895		error = isakmp_info_send_common(iph1, payload,
896						ISAKMP_NPTYPE_D, 0);
897		vfree(payload);
898		if (error) {
899			IPSECSESSIONTRACEREVENT(iph2->parent_session,
900									IPSECSESSIONEVENTCODE_IKEV1_INFO_NOTICE_TX_FAIL,
901									CONSTSTR("Delete IPSEC-SA"),
902									CONSTSTR("Failed to transmit Delete-IPSEC-SA"));
903		} else {
904			IPSECSESSIONTRACEREVENT(iph2->parent_session,
905									IPSECSESSIONEVENTCODE_IKEV1_INFO_NOTICE_TX_SUCC,
906									CONSTSTR("Delete IPSEC-SA"),
907									CONSTSTR(NULL));
908		}
909	}
910
911	return error;
912}
913
914/*
915 * send Notification payload (without ISAKMP SA) in an Informational exchange
916 */
917int
918isakmp_info_send_nx(struct isakmp *isakmp, struct sockaddr_storage *remote, struct sockaddr_storage *local,
919                    int type, vchar_t *data)
920{
921	phase1_handle_t *iph1 = NULL;
922	struct remoteconf *rmconf;
923	vchar_t *payload = NULL;
924	int tlen;
925	int error = -1;
926	struct isakmp_pl_n *n;
927	int spisiz = 0;		/* see below */
928    ike_session_t *sess = ike_session_get_session(local, remote, FALSE, NULL);
929
930	/* search appropreate configuration */
931	rmconf = getrmconf(remote);
932	if (rmconf == NULL) {
933		IPSECSESSIONTRACEREVENT(sess,
934								IPSECSESSIONEVENTCODE_IKE_PACKET_TX_FAIL,
935								CONSTSTR("Information message"),
936								CONSTSTR("Failed to transmit Information message (no remote configuration)"));
937		plog(ASL_LEVEL_ERR,
938			"no configuration found for peer address.\n");
939		goto end;
940	}
941
942	/* add new entry to isakmp status table. */
943	iph1 = ike_session_newph1(ISAKMP_VERSION_NUMBER_IKEV1);
944	if (iph1 == NULL) {
945		IPSECSESSIONTRACEREVENT(sess,
946								IPSECSESSIONEVENTCODE_IKE_PACKET_TX_FAIL,
947								CONSTSTR("Information message"),
948								CONSTSTR("Failed to transmit Information message (no new Phase 1)"));
949		plog(ASL_LEVEL_ERR,
950			 "failed to allocate ph1");
951		return -1;
952	}
953
954	memcpy(&iph1->index.i_ck, &isakmp->i_ck, sizeof(cookie_t));
955	isakmp_newcookie((char *)&iph1->index.r_ck, remote, local);
956	fsm_set_state(&iph1->status, IKEV1_STATE_INFO);
957	iph1->rmconf = rmconf;
958    retain_rmconf(iph1->rmconf);
959	iph1->side = INITIATOR;
960	iph1->version = isakmp->v;
961	iph1->flags = 0;
962	iph1->msgid = 0;	/* XXX */
963#ifdef ENABLE_HYBRID
964	if ((iph1->mode_cfg = isakmp_cfg_mkstate()) == NULL) {
965		error = -1;
966		goto end;
967	}
968#endif
969#ifdef ENABLE_FRAG
970	iph1->frag = 0;
971	iph1->frag_chain = NULL;
972#endif
973
974	/* copy remote address */
975	if (copy_ph1addresses(iph1, rmconf, remote, local) < 0) {
976		IPSECSESSIONTRACEREVENT(sess,
977								IPSECSESSIONEVENTCODE_IKE_PACKET_TX_FAIL,
978								CONSTSTR("Information message"),
979								CONSTSTR("Failed to transmit Information Message (can't copy Phase 1 addresses)"));
980		plog(ASL_LEVEL_ERR,
981			 "failed to copy ph1 addresses");
982		error = -1;
983		iph1 = NULL; /* deleted in copy_ph1addresses */
984		goto end;
985	}
986
987	tlen = sizeof(*n) + spisiz;
988	if (data)
989		tlen += data->l;
990	payload = vmalloc(tlen);
991	if (payload == NULL) {
992		IPSECSESSIONTRACEREVENT(sess,
993								IPSECSESSIONEVENTCODE_IKE_PACKET_TX_FAIL,
994								CONSTSTR("Information message"),
995								CONSTSTR("Failed to transmit Information Message (can't allocate payload)"));
996		plog(ASL_LEVEL_ERR,
997			"failed to get buffer to send.\n");
998		error = -1;
999		goto end;
1000	}
1001
1002	n = (struct isakmp_pl_n *)payload->v;
1003	n->h.np = ISAKMP_NPTYPE_NONE;
1004	n->h.len = htons(tlen);
1005	n->doi = htonl(IPSEC_DOI);
1006	n->proto_id = IPSECDOI_KEY_IKE;
1007	n->spi_size = spisiz;
1008	n->type = htons(type);
1009	if (spisiz)
1010		memset(n + 1, 0, spisiz);	/* XXX spisiz is always 0 */
1011	if (data)
1012		memcpy((caddr_t)(n + 1) + spisiz, data->v, data->l);
1013
1014#ifdef ENABLE_VPNCONTROL_PORT
1015	isakmp_info_vpncontrol_notify_ike_failed(iph1, FROM_LOCAL, type, data);
1016#endif
1017    if (ike_session_link_phase1(sess, iph1))
1018        fatal_error(-1);
1019
1020	error = isakmp_info_send_common(iph1, payload, ISAKMP_NPTYPE_N, 0);
1021	vfree(payload);
1022	if (error) {
1023		IPSECSESSIONTRACEREVENT(sess,
1024								IPSECSESSIONEVENTCODE_IKEV1_INFO_NOTICE_TX_FAIL,
1025								CONSTSTR("Without ISAKMP-SA"),
1026								CONSTSTR("Failed to transmit Without-ISAKMP-SA message"));
1027	} else {
1028		IPSECSESSIONTRACEREVENT(sess,
1029								IPSECSESSIONEVENTCODE_IKEV1_INFO_NOTICE_TX_SUCC,
1030								CONSTSTR("Without ISAKMP-SA"),
1031								CONSTSTR(NULL));
1032	}
1033
1034    end:
1035	if (iph1 != NULL)
1036		ike_session_unlink_phase1(iph1);
1037
1038	return error;
1039}
1040
1041/*
1042 * send Notification payload (with ISAKMP SA) in an Informational exchange
1043 */
1044int
1045isakmp_info_send_n1(phase1_handle_t *iph1, int type, vchar_t *data)
1046{
1047	vchar_t *payload = NULL;
1048	int tlen;
1049	int error = 0;
1050	struct isakmp_pl_n *n;
1051	int spisiz;
1052
1053	/*
1054	 * note on SPI size: which description is correct?  I have chosen
1055	 * this to be 0.
1056	 *
1057	 * RFC2408 3.1, 2nd paragraph says: ISAKMP SA is identified by
1058	 * Initiator/Responder cookie and SPI has no meaning, SPI size = 0.
1059	 * RFC2408 3.1, first paragraph on page 40: ISAKMP SA is identified
1060	 * by cookie and SPI has no meaning, 0 <= SPI size <= 16.
1061	 * RFC2407 4.6.3.3, INITIAL-CONTACT is required to set to 16.
1062	 */
1063	if (type == ISAKMP_NTYPE_INITIAL_CONTACT ||
1064			type == ISAKMP_NTYPE_LOAD_BALANCE)
1065		spisiz = sizeof(isakmp_index);
1066	else
1067		spisiz = 0;
1068
1069	tlen = sizeof(*n) + spisiz;
1070	if (data)
1071		tlen += data->l;
1072	payload = vmalloc(tlen);
1073	if (payload == NULL) {
1074		IPSECSESSIONTRACEREVENT(iph1->parent_session,
1075								IPSECSESSIONEVENTCODE_IKEV1_INFO_NOTICE_TX_FAIL,
1076								CONSTSTR("ISAKMP-SA"),
1077								CONSTSTR("Failed to transmit ISAKMP-SA message (can't allocate payload)"));
1078		plog(ASL_LEVEL_ERR,
1079			"failed to get buffer to send.\n");
1080		return errno;
1081	}
1082
1083	n = (struct isakmp_pl_n *)payload->v;
1084	n->h.np = ISAKMP_NPTYPE_NONE;
1085	n->h.len = htons(tlen);
1086	n->doi = htonl(iph1->rmconf->doitype);
1087	n->proto_id = IPSECDOI_PROTO_ISAKMP; /* XXX to be configurable ? */
1088	n->spi_size = spisiz;
1089	n->type = htons(type);
1090	if (spisiz)
1091		memcpy(n + 1, &iph1->index, sizeof(isakmp_index));
1092	if (data)
1093		memcpy((caddr_t)(n + 1) + spisiz, data->v, data->l);
1094
1095#ifdef ENABLE_VPNCONTROL_PORT
1096	isakmp_info_vpncontrol_notify_ike_failed(iph1, FROM_LOCAL, type, data);
1097#endif
1098
1099	error = isakmp_info_send_common(iph1, payload, ISAKMP_NPTYPE_N, iph1->flags);
1100	vfree(payload);
1101	if (error) {
1102		IPSECSESSIONTRACEREVENT(iph1->parent_session,
1103								IPSECSESSIONEVENTCODE_IKEV1_INFO_NOTICE_TX_FAIL,
1104								CONSTSTR("ISAKMP-SA"),
1105								CONSTSTR("Can't transmit ISAKMP-SA message"));
1106	} else {
1107		IPSECSESSIONTRACEREVENT(iph1->parent_session,
1108								IPSECSESSIONEVENTCODE_IKEV1_INFO_NOTICE_TX_SUCC,
1109								CONSTSTR("ISAKMP-SA"),
1110								CONSTSTR(NULL));
1111	}
1112
1113	return error;
1114}
1115
1116/*
1117 * send Notification payload (with IPsec SA) in an Informational exchange
1118 */
1119int
1120isakmp_info_send_n2(phase2_handle_t *iph2, int type, vchar_t *data)
1121{
1122	phase1_handle_t *iph1 = iph2->ph1;
1123	vchar_t *payload = NULL;
1124	int tlen;
1125	int error = 0;
1126	struct isakmp_pl_n *n;
1127	struct saproto *pr;
1128
1129	if (!iph2->approval)
1130		return EINVAL;
1131
1132	pr = iph2->approval->head;
1133
1134	/* XXX must be get proper spi */
1135	tlen = sizeof(*n) + pr->spisize;
1136	if (data)
1137		tlen += data->l;
1138	payload = vmalloc(tlen);
1139	if (payload == NULL) {
1140		IPSECSESSIONTRACEREVENT(iph2->parent_session,
1141								IPSECSESSIONEVENTCODE_IKEV1_INFO_NOTICE_TX_FAIL,
1142								CONSTSTR("IPSEC-SA"),
1143								CONSTSTR("Failed to transmit IPSEC-SA message (can't allocate payload)"));
1144		plog(ASL_LEVEL_ERR,
1145			"failed to get buffer to send.\n");
1146		return errno;
1147	}
1148
1149	n = (struct isakmp_pl_n *)payload->v;
1150	n->h.np = ISAKMP_NPTYPE_NONE;
1151	n->h.len = htons(tlen);
1152	n->doi = htonl(IPSEC_DOI);		/* IPSEC DOI (1) */
1153	n->proto_id = pr->proto_id;		/* IPSEC AH/ESP/whatever*/
1154	n->spi_size = pr->spisize;
1155	n->type = htons(type);
1156    memcpy(n + 1, &pr->spi, sizeof(u_int32_t));         // Wcast-align fix - copy instead of assign
1157	if (data)
1158		memcpy((caddr_t)(n + 1) + pr->spisize, data->v, data->l);
1159
1160	iph2->flags |= ISAKMP_FLAG_E;	/* XXX Should we do FLAG_A ? */
1161	error = isakmp_info_send_common(iph1, payload, ISAKMP_NPTYPE_N, iph2->flags);
1162	vfree(payload);
1163	if (error) {
1164		IPSECSESSIONTRACEREVENT(iph2->parent_session,
1165								IPSECSESSIONEVENTCODE_IKEV1_INFO_NOTICE_TX_FAIL,
1166								CONSTSTR("IPSEC-SA"),
1167								CONSTSTR("Failed to transmit IPSEC-SA message"));
1168	} else {
1169		IPSECSESSIONTRACEREVENT(iph2->parent_session,
1170								IPSECSESSIONEVENTCODE_IKEV1_INFO_NOTICE_TX_SUCC,
1171								CONSTSTR("IPSEC-SA"),
1172								CONSTSTR(NULL));
1173	}
1174
1175	return error;
1176}
1177
1178/*
1179 * send Information
1180 * When ph1->skeyid_a == NULL, send message without encoding.
1181 */
1182int
1183isakmp_info_send_common(phase1_handle_t *iph1, vchar_t *payload, u_int32_t np, int flags)
1184{
1185	phase2_handle_t *iph2 = NULL;
1186	vchar_t *hash = NULL;
1187	struct isakmp *isakmp;
1188	struct isakmp_gen *gen;
1189	char *p;
1190	int tlen;
1191	int error = -1;
1192
1193	/* add new entry to isakmp status table */
1194	iph2 = ike_session_newph2(ISAKMP_VERSION_NUMBER_IKEV1, PHASE2_TYPE_INFO);
1195	if (iph2 == NULL) {
1196		plog(ASL_LEVEL_ERR,
1197			 "failed to allocate ph2");
1198		goto end;
1199	}
1200
1201	iph2->dst = dupsaddr(iph1->remote);
1202	if (iph2->dst == NULL) {
1203		plog(ASL_LEVEL_ERR,
1204			 "failed to duplicate remote address");
1205		ike_session_delph2(iph2);
1206		goto end;
1207	}
1208	iph2->src = dupsaddr(iph1->local);
1209	if (iph2->src == NULL) {
1210		plog(ASL_LEVEL_ERR,
1211			 "failed to duplicate local address");
1212		ike_session_delph2(iph2);
1213		goto end;
1214	}
1215	switch (iph1->remote->ss_family) {
1216	case AF_INET:
1217#if (!defined(ENABLE_NATT)) || (defined(BROKEN_NATT))
1218		((struct sockaddr_in *)iph2->dst)->sin_port = 0;
1219		((struct sockaddr_in *)iph2->src)->sin_port = 0;
1220#endif
1221		break;
1222#ifdef INET6
1223	case AF_INET6:
1224#if (!defined(ENABLE_NATT)) || (defined(BROKEN_NATT))
1225		((struct sockaddr_in6 *)iph2->dst)->sin6_port = 0;
1226		((struct sockaddr_in6 *)iph2->src)->sin6_port = 0;
1227#endif
1228		break;
1229#endif
1230	default:
1231		plog(ASL_LEVEL_ERR,
1232			"invalid family: %d\n", iph1->remote->ss_family);
1233		ike_session_delph2(iph2);
1234		goto end;
1235	}
1236	iph2->side = INITIATOR;
1237	fsm_set_state(&iph2->status, IKEV1_STATE_INFO);
1238	iph2->msgid = isakmp_newmsgid2(iph1);
1239
1240	/* get IV and HASH(1) if skeyid_a was generated. */
1241	if (iph1->skeyid_a != NULL) {
1242		iph2->ivm = oakley_newiv2(iph1, iph2->msgid);
1243		if (iph2->ivm == NULL) {
1244			plog(ASL_LEVEL_ERR,
1245				 "failed to generate IV");
1246			ike_session_delph2(iph2);
1247			goto end;
1248		}
1249
1250		/* generate HASH(1) */
1251		hash = oakley_compute_hash1(iph1, iph2->msgid, payload);
1252		if (hash == NULL) {
1253			plog(ASL_LEVEL_ERR,
1254				 "failed to generate HASH");
1255			ike_session_delph2(iph2);
1256			goto end;
1257		}
1258
1259		/* initialized total buffer length */
1260		tlen = hash->l;
1261		tlen += sizeof(*gen);
1262	} else {
1263		/* IKE-SA is not established */
1264		hash = NULL;
1265
1266		/* initialized total buffer length */
1267		tlen = 0;
1268	}
1269	if ((flags & ISAKMP_FLAG_A) == 0)
1270		iph2->flags = (hash == NULL ? 0 : ISAKMP_FLAG_E);
1271	else
1272		iph2->flags = (hash == NULL ? 0 : ISAKMP_FLAG_A);
1273
1274	ike_session_link_ph2_to_ph1(iph1, iph2);
1275
1276	tlen += sizeof(*isakmp) + payload->l;
1277
1278	/* create buffer for isakmp payload */
1279	iph2->sendbuf = vmalloc(tlen);
1280	if (iph2->sendbuf == NULL) {
1281		plog(ASL_LEVEL_ERR,
1282			"failed to get buffer to send.\n");
1283		goto err;
1284	}
1285
1286	/* create isakmp header */
1287	isakmp = (struct isakmp *)iph2->sendbuf->v;
1288	memcpy(&isakmp->i_ck, &iph1->index.i_ck, sizeof(cookie_t));
1289	memcpy(&isakmp->r_ck, &iph1->index.r_ck, sizeof(cookie_t));
1290	isakmp->np = hash == NULL ? (np & 0xff) : ISAKMP_NPTYPE_HASH;
1291	isakmp->v = iph1->version;
1292	isakmp->etype = ISAKMP_ETYPE_INFO;
1293	isakmp->flags = iph2->flags;
1294	memcpy(&isakmp->msgid, &iph2->msgid, sizeof(isakmp->msgid));
1295	isakmp->len   = htonl(tlen);
1296	p = (char *)(isakmp + 1);
1297
1298	/* create HASH payload */
1299	if (hash != NULL) {
1300		gen = (struct isakmp_gen *)p;
1301		gen->np = np & 0xff;
1302		gen->len = htons(sizeof(*gen) + hash->l);
1303		p += sizeof(*gen);
1304		memcpy(p, hash->v, hash->l);
1305		p += hash->l;
1306	}
1307
1308	/* add payload */
1309	memcpy(p, payload->v, payload->l);
1310	p += payload->l;
1311
1312#ifdef HAVE_PRINT_ISAKMP_C
1313	isakmp_printpacket(iph2->sendbuf, iph1->local, iph1->remote, 1);
1314#endif
1315
1316	/* encoding */
1317	if (ISSET(isakmp->flags, ISAKMP_FLAG_E)) {
1318		vchar_t *tmp;
1319
1320		tmp = oakley_do_encrypt(iph2->ph1, iph2->sendbuf, iph2->ivm->ive,
1321				iph2->ivm->iv);
1322		VPTRINIT(iph2->sendbuf);
1323		if (tmp == NULL) {
1324			plog(ASL_LEVEL_ERR,
1325				 "failed to encrypt packet");
1326			goto err;
1327		}
1328		iph2->sendbuf = tmp;
1329	}
1330
1331	/* HDR*, HASH(1), N */
1332	if (isakmp_send(iph2->ph1, iph2->sendbuf) < 0) {
1333		plog(ASL_LEVEL_ERR,
1334			 "failed to send packet");
1335		VPTRINIT(iph2->sendbuf);
1336		goto err;
1337	}
1338
1339	plog(ASL_LEVEL_DEBUG,
1340		"sendto Information %s.\n", s_isakmp_nptype(np));
1341
1342	/*
1343	 * don't resend notify message because peer can use Acknowledged
1344	 * Informational if peer requires the reply of the notify message.
1345	 */
1346
1347	/* XXX If Acknowledged Informational required, don't delete ph2handle */
1348	error = 0;
1349	VPTRINIT(iph2->sendbuf);
1350	IPSECSESSIONTRACEREVENT(iph1->parent_session,
1351							IPSECSESSIONEVENTCODE_IKE_PACKET_TX_SUCC,
1352							CONSTSTR("Information message"),
1353							CONSTSTR(NULL));
1354
1355	goto err;	/* XXX */
1356
1357end:
1358	if (error) {
1359		IPSECSESSIONTRACEREVENT(iph1->parent_session,
1360								IPSECSESSIONEVENTCODE_IKE_PACKET_TX_FAIL,
1361								CONSTSTR("Information message"),
1362								CONSTSTR("Failed to transmit Information message"));
1363	}
1364	if (hash)
1365		vfree(hash);
1366	return error;
1367
1368err:
1369	ike_session_unlink_phase2(iph2);
1370	goto end;
1371}
1372
1373/*
1374 * add a notify payload to buffer by reallocating buffer.
1375 * If buf == NULL, the function only create a notify payload.
1376 *
1377 * XXX Which is SPI to be included, inbound or outbound ?
1378 */
1379vchar_t *
1380isakmp_add_pl_n(vchar_t *buf0, u_int8_t **np_p, int type, struct saproto *pr, vchar_t *data)
1381{
1382	vchar_t *buf = NULL;
1383	struct isakmp_pl_n *n;
1384	int tlen;
1385	int oldlen = 0;
1386
1387	if (*np_p)
1388		**np_p = ISAKMP_NPTYPE_N;
1389
1390	tlen = sizeof(*n) + pr->spisize;
1391
1392	if (data)
1393		tlen += data->l;
1394	if (buf0) {
1395		oldlen = buf0->l;
1396		buf = vrealloc(buf0, buf0->l + tlen);
1397	} else
1398		buf = vmalloc(tlen);
1399	if (!buf) {
1400		plog(ASL_LEVEL_ERR,
1401			"failed to get a payload buffer.\n");
1402		return NULL;
1403	}
1404
1405	n = (struct isakmp_pl_n *)(buf->v + oldlen);
1406	n->h.np = ISAKMP_NPTYPE_NONE;
1407	n->h.len = htons(tlen);
1408	n->doi = htonl(IPSEC_DOI);		/* IPSEC DOI (1) */
1409	n->proto_id = pr->proto_id;		/* IPSEC AH/ESP/whatever*/
1410	n->spi_size = pr->spisize;
1411	n->type = htons(type);
1412    memcpy(n + 1, &pr->spi, sizeof(u_int32_t));			// Wcast-align fix - copy instead of assign with cast
1413	if (data)
1414		memcpy((caddr_t)(n + 1) + pr->spisize, data->v, data->l);
1415
1416	/* save the pointer of next payload type */
1417	*np_p = &n->h.np;
1418
1419	return buf;
1420}
1421
1422
1423void
1424purge_ipsec_spi(struct sockaddr_storage *dst0, int proto, u_int32_t *spi /*network byteorder*/, size_t n, u_int32_t *inbound_spi, size_t *max_inbound_spi)
1425{
1426	vchar_t *buf = NULL;
1427	struct sadb_msg *msg, *next, *end;
1428	struct sadb_sa *sa;
1429	struct sadb_lifetime *lt;
1430	struct sockaddr_storage *src, *dst;
1431	phase2_handle_t *iph2;
1432	u_int64_t created;
1433	size_t i, j = 0;
1434	caddr_t mhp[SADB_EXT_MAX + 1];
1435
1436	buf = pfkey_dump_sadb(ipsecdoi2pfkey_proto(proto));
1437	if (buf == NULL) {
1438		plog(ASL_LEVEL_DEBUG,
1439			"pfkey_dump_sadb returned nothing.\n");
1440		return;
1441	}
1442
1443	msg = ALIGNED_CAST(struct sadb_msg *)buf->v;
1444	end = ALIGNED_CAST(struct sadb_msg *)(buf->v + buf->l);
1445
1446	while (msg < end) {
1447		if ((msg->sadb_msg_len << 3) < sizeof(*msg))
1448			break;
1449		next = ALIGNED_CAST(struct sadb_msg *)((caddr_t)msg + (msg->sadb_msg_len << 3));
1450		if (msg->sadb_msg_type != SADB_DUMP) {
1451			msg = next;
1452			continue;
1453		}
1454
1455		if (pfkey_align(msg, mhp) || pfkey_check(mhp)) {
1456			plog(ASL_LEVEL_ERR,
1457				"pfkey_check (%s)\n", ipsec_strerror());
1458			msg = next;
1459			continue;
1460		}
1461
1462		sa = ALIGNED_CAST(struct sadb_sa *)(mhp[SADB_EXT_SA]);       // Wcast-align fix (void*) - buffer of pointers to aligned structs
1463		if (!sa
1464		 || !mhp[SADB_EXT_ADDRESS_SRC]
1465		 || !mhp[SADB_EXT_ADDRESS_DST]) {
1466			msg = next;
1467			continue;
1468		}
1469		src =  ALIGNED_CAST(struct sockaddr_storage*)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);     // Wcast-align fix (void*) - buffer of pointers to aligned structs
1470		dst = ALIGNED_CAST(struct sockaddr_storage*)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
1471		lt = ALIGNED_CAST(struct sadb_lifetime*)mhp[SADB_EXT_LIFETIME_HARD];
1472		if(lt != NULL)
1473			created = lt->sadb_lifetime_addtime;
1474		else
1475			created = 0;
1476
1477		if (sa->sadb_sa_state != SADB_SASTATE_MATURE
1478		 && sa->sadb_sa_state != SADB_SASTATE_DYING) {
1479			msg = next;
1480			continue;
1481		}
1482
1483		/* XXX n^2 algorithm, inefficient */
1484
1485		/* don't delete inbound SAs at the moment (just save them in inbound_spi) */
1486		/* XXX should we remove SAs with opposite direction as well? */
1487		if (CMPSADDR2(dst0, dst)) {
1488			msg = next;
1489			continue;
1490		}
1491
1492		for (i = 0; i < n; i++) {
1493			u_int32_t *i_spi;
1494
1495			if (spi[i] != sa->sadb_sa_spi)
1496				continue;
1497
1498			/*
1499			 * delete a relative phase 2 handler.
1500			 * continue to process if no relative phase 2 handler
1501			 * exists.
1502			 */
1503			if (inbound_spi && max_inbound_spi && j < *max_inbound_spi) {
1504				i_spi = &inbound_spi[j];
1505			} else {
1506				i_spi = NULL;
1507			}
1508			iph2 = ike_session_getph2bysaidx2(src, dst, proto, spi[i], i_spi);
1509
1510            pfkey_send_delete(lcconf->sock_pfkey,
1511                              msg->sadb_msg_satype,
1512                              IPSEC_MODE_ANY,
1513                              src, dst, sa->sadb_sa_spi);
1514
1515			if(iph2 != NULL){
1516				delete_spd(iph2);
1517				ike_session_unlink_phase2(iph2);
1518				if (i_spi) {
1519					j++;
1520				}
1521			}
1522
1523			plog(ASL_LEVEL_INFO, "Purged IPsec-SA proto_id=%s spi=%u.\n",
1524                s_ipsecdoi_proto(proto),
1525                ntohl(spi[i]));
1526		}
1527
1528		msg = next;
1529	}
1530
1531	if (max_inbound_spi) {
1532		*max_inbound_spi = j;
1533	}
1534
1535	if (buf)
1536		vfree(buf);
1537}
1538
1539/*
1540 * delete all phase2 sa relatived to the destination address.
1541 * Don't delete Phase 1 handlers on INITIAL-CONTACT, and don't ignore
1542 * an INITIAL-CONTACT if we have contacted the peer.  This matches the
1543 * Sun IKE behavior, and makes rekeying work much better when the peer
1544 * restarts.
1545 */
1546void
1547info_recv_initialcontact(phase1_handle_t *iph1)
1548{
1549	vchar_t *buf = NULL;
1550	struct sadb_msg *msg, *next, *end;
1551	struct sadb_sa *sa;
1552	struct sockaddr_storage *src, *dst;
1553	caddr_t mhp[SADB_EXT_MAX + 1];
1554	int proto_id, i;
1555	phase2_handle_t *iph2;
1556#if 0
1557	char *loc, *rem;
1558#endif
1559
1560	if (f_local)
1561		return;
1562
1563	// TODO: make sure that is_rekey is cleared for this. and session indicates the same
1564#if 0
1565	loc = racoon_strdup(saddrwop2str(iph1->local));
1566	rem = racoon_strdup(saddrwop2str(iph1->remote));
1567	STRDUP_FATAL(loc);
1568	STRDUP_FATAL(rem);
1569
1570	/*
1571	 * Purge all IPSEC-SAs for the peer.  We can do this
1572	 * the easy way (using a PF_KEY SADB_DELETE extension)
1573	 * or we can do it the hard way.
1574	 */
1575	for (i = 0; i < pfkey_nsatypes; i++) {
1576		proto_id = pfkey2ipsecdoi_proto(pfkey_satypes[i].ps_satype);
1577
1578		plog(ASL_LEVEL_INFO,
1579		    "purging %s SAs for %s -> %s\n",
1580		    pfkey_satypes[i].ps_name, loc, rem);
1581		if (pfkey_send_delete_all(lcconf->sock_pfkey,
1582		    pfkey_satypes[i].ps_satype, IPSEC_MODE_ANY,
1583		    iph1->local, iph1->remote) == -1) {
1584			plog(ASL_LEVEL_ERR,
1585			    "delete_all %s -> %s failed for %s (%s)\n",
1586			    loc, rem,
1587			    pfkey_satypes[i].ps_name, ipsec_strerror());
1588			goto the_hard_way;
1589		}
1590
1591		ike_session_deleteallph2(iph1->local, iph1->remote, proto_id);
1592
1593		plog(ASL_LEVEL_INFO,
1594		    "purging %s SAs for %s -> %s\n",
1595		    pfkey_satypes[i].ps_name, rem, loc);
1596		if (pfkey_send_delete_all(lcconf->sock_pfkey,
1597		    pfkey_satypes[i].ps_satype, IPSEC_MODE_ANY,
1598		    iph1->remote, iph1->local) == -1) {
1599			plog(ASL_LEVEL_ERR,
1600			    "delete_all %s -> %s failed for %s (%s)\n",
1601			    rem, loc,
1602			    pfkey_satypes[i].ps_name, ipsec_strerror());
1603			goto the_hard_way;
1604		}
1605
1606		ike_session_deleteallph2(iph1->remote, iph1->local, proto_id);
1607	}
1608
1609	racoon_free(loc);
1610	racoon_free(rem);
1611	return;
1612
1613 the_hard_way:
1614	racoon_free(loc);
1615	racoon_free(rem);
1616#endif
1617
1618	buf = pfkey_dump_sadb(SADB_SATYPE_UNSPEC);
1619	if (buf == NULL) {
1620		plog(ASL_LEVEL_DEBUG,
1621			"pfkey_dump_sadb returned nothing.\n");
1622		return;
1623	}
1624
1625	msg = ALIGNED_CAST(struct sadb_msg *)buf->v;
1626	end = ALIGNED_CAST(struct sadb_msg *)(buf->v + buf->l);
1627
1628	while (msg < end) {
1629		if ((msg->sadb_msg_len << 3) < sizeof(*msg))
1630			break;
1631		next = ALIGNED_CAST(struct sadb_msg *)((caddr_t)msg + (msg->sadb_msg_len << 3));
1632		if (msg->sadb_msg_type != SADB_DUMP) {
1633			msg = next;
1634			continue;
1635		}
1636
1637		if (pfkey_align(msg, mhp) || pfkey_check(mhp)) {
1638			plog(ASL_LEVEL_ERR,
1639				"pfkey_check (%s)\n", ipsec_strerror());
1640			msg = next;
1641			continue;
1642		}
1643
1644		if (mhp[SADB_EXT_SA] == NULL
1645		 || mhp[SADB_EXT_ADDRESS_SRC] == NULL
1646		 || mhp[SADB_EXT_ADDRESS_DST] == NULL) {
1647			msg = next;
1648			continue;
1649		}
1650		sa = ALIGNED_CAST(struct sadb_sa *)mhp[SADB_EXT_SA];                 // Wcast-align fix (void*) - buffer of pointers to aligned structs
1651		src = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
1652		dst = ALIGNED_CAST(struct sockaddr_storage *)PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
1653
1654		if (sa->sadb_sa_state != SADB_SASTATE_MATURE
1655		 && sa->sadb_sa_state != SADB_SASTATE_DYING) {
1656			msg = next;
1657			continue;
1658		}
1659
1660		/*
1661		 * RFC2407 4.6.3.3 INITIAL-CONTACT is the message that
1662		 * announces the sender of the message was rebooted.
1663		 * it is interpreted to delete all SAs which source address
1664		 * is the sender of the message.
1665		 * racoon only deletes SA which is matched both the
1666		 * source address and the destination accress.
1667		 */
1668#ifdef ENABLE_NATT
1669		/*
1670		 * XXX RFC 3947 says that whe MUST NOT use IP+port to find old SAs
1671		 * from this peer !
1672		 */
1673		if(iph1->natt_flags & NAT_DETECTED){
1674			if (CMPSADDR(iph1->local, src) == 0 &&
1675				CMPSADDR(iph1->remote, dst) == 0)
1676				;
1677			else if (CMPSADDR(iph1->remote, src) == 0 &&
1678					 CMPSADDR(iph1->local, dst) == 0)
1679				;
1680			else {
1681				msg = next;
1682				continue;
1683			}
1684		} else
1685#endif
1686		/* If there is no NAT-T, we don't have to check addr + port...
1687		 * XXX what about a configuration with a remote peers which is not
1688		 * NATed, but which NATs some other peers ?
1689		 * Here, the INITIAl-CONTACT would also flush all those NATed peers !!
1690		 */
1691		if (cmpsaddrwop(iph1->local, src) == 0 &&
1692		    cmpsaddrwop(iph1->remote, dst) == 0)
1693			;
1694		else if (cmpsaddrwop(iph1->remote, src) == 0 &&
1695		    cmpsaddrwop(iph1->local, dst) == 0)
1696			;
1697		else {
1698			msg = next;
1699			continue;
1700		}
1701
1702		/*
1703		 * Make sure this is an SATYPE that we manage.
1704		 * This is gross; too bad we couldn't do it the
1705		 * easy way.
1706		 */
1707		for (i = 0; i < pfkey_nsatypes; i++) {
1708			if (pfkey_satypes[i].ps_satype ==
1709			    msg->sadb_msg_satype)
1710				break;
1711		}
1712		if (i == pfkey_nsatypes) {
1713			msg = next;
1714			continue;
1715		}
1716
1717		plog(ASL_LEVEL_INFO,
1718			"purging spi=%u.\n", ntohl(sa->sadb_sa_spi));
1719		pfkey_send_delete(lcconf->sock_pfkey,
1720			msg->sadb_msg_satype,
1721			IPSEC_MODE_ANY, src, dst, sa->sadb_sa_spi);
1722
1723		/*
1724		 * delete a relative phase 2 handler.
1725		 * continue to process if no relative phase 2 handler
1726		 * exists.
1727		 */
1728		proto_id = pfkey2ipsecdoi_proto(msg->sadb_msg_satype);
1729		iph2 = ike_session_getph2bysaidx(src, dst, proto_id, sa->sadb_sa_spi);
1730		if (iph2) {
1731			delete_spd(iph2);
1732			ike_session_unlink_phase2(iph2);
1733		}
1734
1735		msg = next;
1736	}
1737
1738	vfree(buf);
1739}
1740
1741void
1742isakmp_check_notify(struct isakmp_gen *gen /* points to Notify payload */, phase1_handle_t *iph1)
1743{
1744	struct isakmp_pl_n *notify = (struct isakmp_pl_n *)gen;
1745
1746	plog(ASL_LEVEL_DEBUG,
1747		"Notify Message received\n");
1748
1749	switch (ntohs(notify->type)) {
1750	case ISAKMP_NTYPE_CONNECTED:
1751	case ISAKMP_NTYPE_RESPONDER_LIFETIME:
1752	case ISAKMP_NTYPE_REPLAY_STATUS:
1753	case ISAKMP_NTYPE_HEARTBEAT:
1754#ifdef ENABLE_HYBRID
1755	case ISAKMP_NTYPE_UNITY_HEARTBEAT:
1756#endif
1757		plog(ASL_LEVEL_WARNING,
1758			"Ignore %s notification.\n",
1759			s_isakmp_notify_msg(ntohs(notify->type)));
1760		break;
1761	case ISAKMP_NTYPE_INITIAL_CONTACT:
1762		plog(ASL_LEVEL_WARNING,
1763			"Ignore INITIAL-CONTACT notification, "
1764			"because it is only accepted after Phase 1.\n");
1765		break;
1766	case ISAKMP_NTYPE_LOAD_BALANCE:
1767		plog(ASL_LEVEL_WARNING,
1768			"Ignore LOAD-BALANCE notification, "
1769			"because it is only accepted after Phase 1.\n");
1770		break;
1771	default:
1772		isakmp_info_send_n1(iph1, ISAKMP_NTYPE_INVALID_PAYLOAD_TYPE, NULL);
1773		plog(ASL_LEVEL_ERR,
1774			"Received unknown notification type %s.\n",
1775			s_isakmp_notify_msg(ntohs(notify->type)));
1776	}
1777
1778	return;
1779}
1780
1781void
1782isakmp_check_ph2_notify(struct isakmp_gen *gen /* points to Notify payload */, phase2_handle_t *iph2)
1783{
1784	struct isakmp_pl_n *notify = (struct isakmp_pl_n *)gen;
1785
1786	plog(ASL_LEVEL_DEBUG,
1787         "Phase 2 Notify Message received\n");
1788
1789	switch (ntohs(notify->type)) {
1790        case ISAKMP_NTYPE_RESPONDER_LIFETIME:
1791            return((void)isakmp_ph2_responder_lifetime(iph2,
1792                                                       (struct isakmp_pl_resp_lifetime *)notify));
1793            break;
1794        case ISAKMP_NTYPE_CONNECTED:
1795        case ISAKMP_NTYPE_REPLAY_STATUS:
1796        case ISAKMP_NTYPE_HEARTBEAT:
1797#ifdef ENABLE_HYBRID
1798        case ISAKMP_NTYPE_UNITY_HEARTBEAT:
1799#endif
1800            plog(ASL_LEVEL_WARNING,
1801                 "Ignore %s notification.\n",
1802                 s_isakmp_notify_msg(ntohs(notify->type)));
1803            break;
1804        case ISAKMP_NTYPE_INITIAL_CONTACT:
1805            plog(ASL_LEVEL_WARNING,
1806                 "Ignore INITIAL-CONTACT notification, "
1807                 "because it is only accepted after Phase 1.\n");
1808            break;
1809        case ISAKMP_NTYPE_LOAD_BALANCE:
1810            plog(ASL_LEVEL_WARNING,
1811                 "Ignore LOAD-BALANCE notification, "
1812                 "because it is only accepted after Phase 1.\n");
1813            break;
1814        default:
1815            isakmp_info_send_n1(iph2->ph1, ISAKMP_NTYPE_INVALID_PAYLOAD_TYPE, NULL);
1816            plog(ASL_LEVEL_ERR,
1817                 "Received unknown notification type %s.\n",
1818                 s_isakmp_notify_msg(ntohs(notify->type)));
1819	}
1820
1821	return;
1822}
1823
1824#ifdef ENABLE_VPNCONTROL_PORT
1825static int
1826isakmp_info_recv_lb(phase1_handle_t *iph1, struct isakmp_pl_lb *n, int encrypted)
1827{
1828
1829	if (iph1->side != INITIATOR)
1830	{
1831		plog(ASL_LEVEL_DEBUG,
1832			"LOAD-BALANCE notification ignored - we are not the initiator.\n");
1833		return 0;
1834	}
1835	if (iph1->remote->ss_family != AF_INET) {
1836		plog(ASL_LEVEL_DEBUG,
1837			"LOAD-BALANCE notification ignored - only supported for IPv4.\n");
1838		return 0;
1839	}
1840	if (!encrypted) {
1841		plog(ASL_LEVEL_DEBUG,
1842			"LOAD-BALANCE notification ignored - not protected.\n");
1843		return 0;
1844	}
1845	if (ntohs(n->h.len) != sizeof(struct isakmp_pl_lb)) {
1846		plog(ASL_LEVEL_DEBUG,
1847			"Invalid length of payload\n");
1848		return -1;
1849	}
1850	vpncontrol_notify_ike_failed(ISAKMP_NTYPE_LOAD_BALANCE, FROM_REMOTE,
1851		((struct sockaddr_in*)iph1->remote)->sin_addr.s_addr, 4, (u_int8_t*)(&(n->address)));
1852
1853	plog(ASL_LEVEL_NOTICE,
1854			"Received LOAD_BALANCE notification.\n");
1855
1856    if (((struct sockaddr_in*)iph1->remote)->sin_addr.s_addr != ntohl(n->address)) {
1857        plog(ASL_LEVEL_DEBUG,
1858             "Deleting old Phase 1 because of LOAD_BALANCE notification - redirect address=%x.\n",
1859             ntohl(n->address));
1860
1861        if (FSM_STATE_IS_ESTABLISHED(iph1->status)) {
1862            isakmp_info_send_d1(iph1);
1863        }
1864        isakmp_ph1expire(iph1);
1865    }
1866
1867	return 0;
1868}
1869#endif
1870
1871#ifdef ENABLE_DPD
1872static int
1873isakmp_info_recv_r_u (phase1_handle_t *iph1, struct isakmp_pl_ru *ru, u_int32_t msgid)
1874{
1875	struct isakmp_pl_ru *ru_ack;
1876	vchar_t *payload = NULL;
1877	int tlen;
1878	int error = 0;
1879
1880	plog(ASL_LEVEL_DEBUG,
1881		 "DPD R-U-There received\n");
1882
1883	/* XXX should compare cookies with iph1->index?
1884	   Or is this already done by calling function?  */
1885	tlen = sizeof(*ru_ack);
1886	payload = vmalloc(tlen);
1887	if (payload == NULL) {
1888		IPSECSESSIONTRACEREVENT(iph1->parent_session,
1889								IPSECSESSIONEVENTCODE_IKEV1_INFO_NOTICE_TX_FAIL,
1890								CONSTSTR("R-U-THERE? ACK"),
1891								CONSTSTR("Failed to transmit DPD response"));
1892		plog(ASL_LEVEL_ERR,
1893			"failed to get buffer to send.\n");
1894		return errno;
1895	}
1896
1897	ru_ack = (struct isakmp_pl_ru *)payload->v;
1898	ru_ack->h.np = ISAKMP_NPTYPE_NONE;
1899	ru_ack->h.len = htons(tlen);
1900	ru_ack->doi = htonl(IPSEC_DOI);
1901	ru_ack->type = htons(ISAKMP_NTYPE_R_U_THERE_ACK);
1902	ru_ack->proto_id = IPSECDOI_PROTO_ISAKMP; /* XXX ? */
1903	ru_ack->spi_size = sizeof(isakmp_index);
1904	memcpy(ru_ack->i_ck, ru->i_ck, sizeof(cookie_t));
1905	memcpy(ru_ack->r_ck, ru->r_ck, sizeof(cookie_t));
1906	ru_ack->data = ru->data;
1907
1908	/* XXX Should we do FLAG_A ?  */
1909	error = isakmp_info_send_common(iph1, payload, ISAKMP_NPTYPE_N,
1910					ISAKMP_FLAG_E);
1911	vfree(payload);
1912	if (error) {
1913		IPSECSESSIONTRACEREVENT(iph1->parent_session,
1914								IPSECSESSIONEVENTCODE_IKEV1_INFO_NOTICE_TX_FAIL,
1915								CONSTSTR("R-U-THERE? ACK"),
1916								CONSTSTR("Failed to transmit DPD ack"));
1917	} else {
1918		IPSECSESSIONTRACEREVENT(iph1->parent_session,
1919								IPSECSESSIONEVENTCODE_IKEV1_INFO_NOTICE_TX_SUCC,
1920								CONSTSTR("R-U-THERE? ACK"),
1921								CONSTSTR(NULL));
1922	}
1923
1924	plog(ASL_LEVEL_DEBUG, "received a valid R-U-THERE, ACK sent\n");
1925
1926	/* Should we mark tunnel as active ? */
1927	return error;
1928}
1929
1930static int
1931isakmp_info_recv_r_u_ack (phase1_handle_t *iph1, struct isakmp_pl_ru *ru, u_int32_t msgid)
1932{
1933
1934	plog(ASL_LEVEL_DEBUG,
1935		 "DPD R-U-There-Ack received\n");
1936
1937	/* XXX Maintain window of acceptable sequence numbers ?
1938	 * => ru->data <= iph2->dpd_seq &&
1939	 *    ru->data >= iph2->dpd_seq - iph2->dpd_fails ? */
1940	if (ntohl(ru->data) != iph1->dpd_seq) {
1941		plog(ASL_LEVEL_ERR,
1942			 "Wrong DPD sequence number (%d, %d expected).\n",
1943			 ntohl(ru->data), iph1->dpd_seq);
1944		return 0;
1945	}
1946
1947	if (memcmp(ru->i_ck, iph1->index.i_ck, sizeof(cookie_t)) ||
1948	    memcmp(ru->r_ck, iph1->index.r_ck, sizeof(cookie_t))) {
1949		plog(ASL_LEVEL_ERR,
1950			 "Cookie mismatch in DPD ACK!.\n");
1951		return 0;
1952	}
1953
1954	iph1->dpd_fails = 0;
1955
1956	iph1->dpd_seq++;
1957
1958	/* Useless ??? */
1959	iph1->dpd_lastack = time(NULL);
1960
1961	SCHED_KILL(iph1->dpd_r_u);
1962
1963	isakmp_sched_r_u(iph1, 0);
1964
1965	if (iph1->side == INITIATOR) {
1966		IPSECSESSIONTRACEREVENT(iph1->parent_session,
1967								IPSECSESSIONEVENTCODE_IKEV1_DPD_INIT_RESP,
1968								CONSTSTR("Initiator DPD Response"),
1969								CONSTSTR(NULL));
1970	} else {
1971		IPSECSESSIONTRACEREVENT(iph1->parent_session,
1972								IPSECSESSIONEVENTCODE_IKEV1_DPD_RESP_RESP,
1973								CONSTSTR("Responder DPD Response"),
1974								CONSTSTR(NULL));
1975	}
1976	plog(ASL_LEVEL_DEBUG, "received an R-U-THERE-ACK\n");
1977
1978#ifdef ENABLE_VPNCONTROL_PORT
1979	vpncontrol_notify_peer_resp_ph1(1, iph1);
1980#endif /* ENABLE_VPNCONTROL_PORT */
1981
1982	return 0;
1983}
1984
1985
1986/*
1987 * send Delete payload (for ISAKMP SA) in Informational exchange.
1988 */
1989void
1990isakmp_info_send_r_u(void *arg)
1991{
1992	phase1_handle_t *iph1 = arg;
1993
1994	/* create R-U-THERE payload */
1995	struct isakmp_pl_ru *ru;
1996	vchar_t *payload = NULL;
1997	int tlen;
1998	int error = 0;
1999
2000    if (!FSM_STATE_IS_ESTABLISHED(iph1->status)) {
2001        plog(ASL_LEVEL_DEBUG, "DPD r-u send aborted, invalid Phase 1 status %d....\n",
2002             iph1->status);
2003        return;
2004    }
2005
2006	if (iph1->dpd_fails >= iph1->rmconf->dpd_maxfails) {
2007		u_int32_t address;
2008
2009		IPSECSESSIONTRACEREVENT(iph1->parent_session,
2010								IPSECSESSIONEVENTCODE_IKEV1_DPD_MAX_RETRANSMIT,
2011								CONSTSTR("DPD maximum retransmits"),
2012								CONSTSTR("maxed-out of DPD requests without receiving an ack"));
2013
2014		if (iph1->remote->ss_family == AF_INET)
2015			address = ((struct sockaddr_in *)iph1->remote)->sin_addr.s_addr;
2016		else
2017			address = 0;
2018		(void)vpncontrol_notify_ike_failed(VPNCTL_NTYPE_PEER_DEAD, FROM_LOCAL, address, 0, NULL);
2019
2020		purge_remote(iph1);
2021		plog(ASL_LEVEL_DEBUG,
2022			 "DPD: remote seems to be dead\n");
2023
2024		/* Do not reschedule here: phase1 is deleted,
2025		 * DPD will be reactivated when a new ph1 will be negociated
2026		 */
2027		return;
2028	}
2029
2030	tlen = sizeof(*ru);
2031	payload = vmalloc(tlen);
2032	if (payload == NULL) {
2033		IPSECSESSIONTRACEREVENT(iph1->parent_session,
2034								IPSECSESSIONEVENTCODE_IKEV1_INFO_NOTICE_TX_FAIL,
2035								CONSTSTR("R-U-THERE?"),
2036								CONSTSTR("Failed to transmit DPD request"));
2037		plog(ASL_LEVEL_ERR,
2038			 "failed to get buffer for payload.\n");
2039		return;
2040	}
2041	ru = (struct isakmp_pl_ru *)payload->v;
2042	ru->h.np = ISAKMP_NPTYPE_NONE;
2043	ru->h.len = htons(tlen);
2044	ru->doi = htonl(IPSEC_DOI);
2045	ru->type = htons(ISAKMP_NTYPE_R_U_THERE);
2046	ru->proto_id = IPSECDOI_PROTO_ISAKMP; /* XXX ?*/
2047	ru->spi_size = sizeof(isakmp_index);
2048
2049	memcpy(ru->i_ck, iph1->index.i_ck, sizeof(cookie_t));
2050	memcpy(ru->r_ck, iph1->index.r_ck, sizeof(cookie_t));
2051
2052	if (iph1->dpd_seq == 0){
2053		/* generate a random seq which is not too big */
2054		srand(time(NULL));
2055		iph1->dpd_seq = rand() & 0x0fff;
2056	}
2057
2058	ru->data = htonl(iph1->dpd_seq);
2059
2060	error = isakmp_info_send_common(iph1, payload, ISAKMP_NPTYPE_N, 0);
2061	vfree(payload);
2062	if (error) {
2063		IPSECSESSIONTRACEREVENT(iph1->parent_session,
2064								IPSECSESSIONEVENTCODE_IKEV1_INFO_NOTICE_TX_FAIL,
2065								CONSTSTR("R-U-THERE?"),
2066								CONSTSTR("Failed to transmit DPD request"));
2067	} else {
2068		IPSECSESSIONTRACEREVENT(iph1->parent_session,
2069								IPSECSESSIONEVENTCODE_IKEV1_INFO_NOTICE_TX_SUCC,
2070								CONSTSTR("R-U-THERE?"),
2071								CONSTSTR(NULL));
2072	}
2073
2074	if (iph1->side == INITIATOR) {
2075		IPSECSESSIONTRACEREVENT(iph1->parent_session,
2076								iph1->dpd_fails? IPSECSESSIONEVENTCODE_IKEV1_DPD_INIT_RETRANSMIT : IPSECSESSIONEVENTCODE_IKEV1_DPD_INIT_REQ,
2077								CONSTSTR("Initiator DPD Request"),
2078								CONSTSTR(NULL));
2079	} else {
2080		IPSECSESSIONTRACEREVENT(iph1->parent_session,
2081								iph1->dpd_fails? IPSECSESSIONEVENTCODE_IKEV1_DPD_RESP_RETRANSMIT : IPSECSESSIONEVENTCODE_IKEV1_DPD_RESP_REQ,
2082								CONSTSTR("Responder DPD Request"),
2083								CONSTSTR(NULL));
2084	}
2085	plog(ASL_LEVEL_DEBUG,
2086		 "DPD R-U-There sent (%d)\n", error);
2087
2088	/* will be decreased if ACK received... */
2089	iph1->dpd_fails++;
2090
2091	/* Reschedule the r_u_there with a short delay,
2092	 * will be deleted/rescheduled if ACK received before */
2093	isakmp_sched_r_u(iph1, 1);
2094
2095	plog(ASL_LEVEL_DEBUG,
2096		 "rescheduling send_r_u (%d).\n", iph1->rmconf->dpd_retry);
2097}
2098
2099/*
2100 * monitor DPD (ALGORITHM_INBOUND_DETECT) Informational exchange.
2101 */
2102static void
2103isakmp_info_monitor_r_u_algo_inbound_detect (phase1_handle_t *iph1)
2104{
2105    if (!FSM_STATE_IS_ESTABLISHED(iph1->status)) {
2106        plog(ASL_LEVEL_DEBUG, "DPD monitoring (for ALGORITHM_INBOUND_DETECT) aborted, invalid Phase 1 status %d....\n",
2107             iph1->status);
2108        return;
2109    }
2110
2111	plog(ASL_LEVEL_DEBUG, "DPD monitoring (for ALGORITHM_INBOUND_DETECT) ....\n");
2112
2113    // check phase1 for ike packets received from peer
2114    if (iph1->peer_sent_ike) {
2115        // yes, reshedule check
2116        iph1->peer_sent_ike = 0;
2117
2118        /* ike packets received from peer... reschedule dpd */
2119        isakmp_sched_r_u(iph1, 0);
2120
2121        plog(ASL_LEVEL_DEBUG,
2122             "ike packets received from peer... reschedule monitor.\n");
2123
2124        return;
2125    }
2126
2127    // after ike packets, next we check if any data was received
2128    if (!iph1->parent_session->peer_sent_data_sc_dpd) {
2129        isakmp_info_send_r_u(iph1);
2130    } else {
2131        isakmp_sched_r_u(iph1, 0);
2132
2133        plog(ASL_LEVEL_DEBUG,
2134             "rescheduling DPD monitoring (for ALGORITHM_INBOUND_DETECT).\n");
2135    }
2136    iph1->parent_session->peer_sent_data_sc_dpd = 0;
2137}
2138
2139/*
2140 * monitor DPD (ALGORITHM_BLACKHOLE_DETECT) Informational exchange.
2141 */
2142static void
2143isakmp_info_monitor_r_u_algo_blackhole_detect (phase1_handle_t *iph1)
2144{
2145    if (!FSM_STATE_IS_ESTABLISHED(iph1->status)) {
2146        plog(ASL_LEVEL_DEBUG, "DPD monitoring (for ALGORITHM_BLACKHOLE_DETECT) aborted, invalid Phase 1 status %d....\n",
2147             iph1->status);
2148        return;
2149    }
2150
2151	plog(ASL_LEVEL_DEBUG, "DPD monitoring (for ALGORITHM_BLACKHOLE_DETECT) ....\n");
2152
2153    // check if data was sent but none was received
2154    if (iph1->parent_session->i_sent_data_sc_dpd &&
2155        !iph1->parent_session->peer_sent_data_sc_dpd) {
2156        isakmp_info_send_r_u(iph1);
2157    } else {
2158        isakmp_sched_r_u(iph1, 0);
2159
2160        plog(ASL_LEVEL_DEBUG,
2161             "rescheduling DPD monitoring (for ALGORITHM_BLACKHOLE_DETECT) i = %d, peer %d.\n",
2162             iph1->parent_session->i_sent_data_sc_dpd,
2163             iph1->parent_session->peer_sent_data_sc_dpd);
2164    }
2165    iph1->parent_session->i_sent_data_sc_dpd = 0;
2166    iph1->parent_session->peer_sent_data_sc_dpd = 0;
2167}
2168
2169/*
2170 * monitor DPD Informational exchange.
2171 */
2172static void
2173isakmp_info_monitor_r_u(void *arg)
2174{
2175	phase1_handle_t *iph1 = arg;
2176
2177    if (iph1 && iph1->rmconf) {
2178        if (iph1->rmconf->dpd_algo == DPD_ALGO_INBOUND_DETECT) {
2179            isakmp_info_monitor_r_u_algo_inbound_detect(iph1);
2180        } else if (iph1->rmconf->dpd_algo == DPD_ALGO_BLACKHOLE_DETECT) {
2181            isakmp_info_monitor_r_u_algo_blackhole_detect(iph1);
2182        } else {
2183            plog(ASL_LEVEL_DEBUG, "DPD monitoring aborted, invalid algorithm %d....\n",
2184                 iph1->rmconf->dpd_algo);
2185        }
2186    }
2187}
2188
2189/* Schedule a new R-U-THERE */
2190int
2191isakmp_sched_r_u(phase1_handle_t *iph1, int retry)
2192{
2193	if(iph1 == NULL ||
2194	   iph1->rmconf == NULL)
2195		return 1;
2196
2197
2198	if(iph1->dpd_support == 0 ||
2199	   iph1->rmconf->dpd_interval == 0)
2200		return 0;
2201
2202	if(retry) {
2203		iph1->dpd_r_u = sched_new(iph1->rmconf->dpd_retry,
2204								  isakmp_info_send_r_u, iph1);
2205	} else {
2206        if (iph1->rmconf->dpd_algo == DPD_ALGO_INBOUND_DETECT ||
2207            iph1->rmconf->dpd_algo == DPD_ALGO_BLACKHOLE_DETECT) {
2208            iph1->dpd_r_u = sched_new(iph1->rmconf->dpd_interval,
2209                                      isakmp_info_monitor_r_u, iph1);
2210        } else {
2211            iph1->dpd_r_u = sched_new(iph1->rmconf->dpd_interval,
2212                                      isakmp_info_send_r_u, iph1);
2213        }
2214    }
2215
2216	return 0;
2217}
2218
2219/*
2220 * punts dpd for later because of some activity that:
2221 * 1) implicitly does dpd (e.g. phase2 exchanges), or
2222 * 2) indicates liveness (e.g. received ike packets).
2223 */
2224void
2225isakmp_reschedule_info_monitor_if_pending (phase1_handle_t *iph1, char *reason)
2226{
2227    if (!iph1 ||
2228        !FSM_STATE_IS_ESTABLISHED(iph1->status) ||
2229        !iph1->dpd_support ||
2230        !iph1->rmconf->dpd_interval ||
2231        iph1->rmconf->dpd_algo == DPD_ALGO_DEFAULT) {
2232        return;
2233    }
2234
2235    if (!iph1->peer_sent_ike) {
2236        SCHED_KILL(iph1->dpd_r_u);
2237
2238        isakmp_sched_r_u(iph1, 0);
2239
2240        plog(ASL_LEVEL_DEBUG,
2241             "%s... rescheduling send_r_u.\n",
2242             reason);
2243    }
2244    iph1->peer_sent_ike++;
2245}
2246#endif
2247