No empty .Rs/.Re
[netbsd-mini2440.git] / crypto / dist / ipsec-tools / src / racoon / isakmp_inf.c
blob1846ef170b4c5364c234eafeab3c7b2336d91763
1 /* $NetBSD: isakmp_inf.c,v 1.40 2009/07/03 06:40:10 tteras Exp $ */
3 /* Id: isakmp_inf.c,v 1.44 2006/05/06 20:45:52 manubsd Exp */
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.
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.
34 #include "config.h"
36 #include <sys/types.h>
37 #include <sys/param.h>
38 #include <sys/socket.h>
40 #include <net/pfkeyv2.h>
41 #include <netinet/in.h>
42 #include <sys/queue.h>
43 #include PATH_IPSEC_H
45 #include <stdlib.h>
46 #include <stdio.h>
47 #include <string.h>
48 #include <errno.h>
49 #if TIME_WITH_SYS_TIME
50 # include <sys/time.h>
51 # include <time.h>
52 #else
53 # if HAVE_SYS_TIME_H
54 # include <sys/time.h>
55 # else
56 # include <time.h>
57 # endif
58 #endif
59 #ifdef ENABLE_HYBRID
60 #include <resolv.h>
61 #endif
63 #include "libpfkey.h"
65 #include "var.h"
66 #include "vmbuf.h"
67 #include "schedule.h"
68 #include "str2val.h"
69 #include "misc.h"
70 #include "plog.h"
71 #include "debug.h"
73 #include "localconf.h"
74 #include "remoteconf.h"
75 #include "sockmisc.h"
76 #include "handler.h"
77 #include "policy.h"
78 #include "proposal.h"
79 #include "isakmp_var.h"
80 #include "evt.h"
81 #include "isakmp.h"
82 #ifdef ENABLE_HYBRID
83 #include "isakmp_xauth.h"
84 #include "isakmp_unity.h"
85 #include "isakmp_cfg.h"
86 #endif
87 #include "isakmp_inf.h"
88 #include "oakley.h"
89 #include "ipsec_doi.h"
90 #include "crypto_openssl.h"
91 #include "pfkey.h"
92 #include "policy.h"
93 #include "algorithm.h"
94 #include "proposal.h"
95 #include "admin.h"
96 #include "strnames.h"
97 #ifdef ENABLE_NATT
98 #include "nattraversal.h"
99 #endif
101 /* information exchange */
102 static int isakmp_info_recv_n (struct ph1handle *, struct isakmp_pl_n *, u_int32_t, int);
103 static int isakmp_info_recv_d (struct ph1handle *, struct isakmp_pl_d *, u_int32_t, int);
105 #ifdef ENABLE_DPD
106 static int isakmp_info_recv_r_u __P((struct ph1handle *,
107 struct isakmp_pl_ru *, u_int32_t));
108 static int isakmp_info_recv_r_u_ack __P((struct ph1handle *,
109 struct isakmp_pl_ru *, u_int32_t));
110 static void isakmp_info_send_r_u __P((struct sched *));
111 #endif
113 static void purge_isakmp_spi __P((int, isakmp_index *, size_t));
115 /* \f%%%
116 * Information Exchange
119 * receive Information
122 isakmp_info_recv(iph1, msg0)
123 struct ph1handle *iph1;
124 vchar_t *msg0;
126 vchar_t *msg = NULL;
127 vchar_t *pbuf = NULL;
128 u_int32_t msgid = 0;
129 int error = -1;
130 struct isakmp *isakmp;
131 struct isakmp_gen *gen;
132 struct isakmp_parse_t *pa, *pap;
133 void *p;
134 vchar_t *hash, *payload;
135 struct isakmp_gen *nd;
136 u_int8_t np;
137 int encrypted;
139 plog(LLV_DEBUG, LOCATION, NULL, "receive Information.\n");
141 encrypted = ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E);
142 msgid = ((struct isakmp *)msg0->v)->msgid;
144 /* Use new IV to decrypt Informational message. */
145 if (encrypted) {
146 struct isakmp_ivm *ivm;
148 if (iph1->ivm == NULL) {
149 plog(LLV_ERROR, LOCATION, NULL, "iph1->ivm == NULL\n");
150 return -1;
153 /* compute IV */
154 ivm = oakley_newiv2(iph1, ((struct isakmp *)msg0->v)->msgid);
155 if (ivm == NULL)
156 return -1;
158 msg = oakley_do_decrypt(iph1, msg0, ivm->iv, ivm->ive);
159 oakley_delivm(ivm);
160 if (msg == NULL)
161 return -1;
163 } else
164 msg = vdup(msg0);
166 /* Safety check */
167 if (msg->l < sizeof(*isakmp) + sizeof(*gen)) {
168 plog(LLV_ERROR, LOCATION, NULL,
169 "ignore information because the "
170 "message is way too short - %zu byte(s).\n",
171 msg->l);
172 goto end;
175 isakmp = (struct isakmp *)msg->v;
176 gen = (struct isakmp_gen *)((caddr_t)isakmp + sizeof(struct isakmp));
177 np = gen->np;
179 if (encrypted) {
180 if (isakmp->np != ISAKMP_NPTYPE_HASH) {
181 plog(LLV_ERROR, LOCATION, NULL,
182 "ignore information because the "
183 "message has no hash payload.\n");
184 goto end;
187 if (iph1->status != PHASE1ST_ESTABLISHED &&
188 iph1->status != PHASE1ST_DYING) {
189 plog(LLV_ERROR, LOCATION, NULL,
190 "ignore information because ISAKMP-SA "
191 "has not been established yet.\n");
192 goto end;
195 /* Safety check */
196 if (msg->l < sizeof(*isakmp) + ntohs(gen->len) + sizeof(*nd)) {
197 plog(LLV_ERROR, LOCATION, NULL,
198 "ignore information because the "
199 "message is too short - %zu byte(s).\n",
200 msg->l);
201 goto end;
204 p = (caddr_t) gen + sizeof(struct isakmp_gen);
205 nd = (struct isakmp_gen *) ((caddr_t) gen + ntohs(gen->len));
207 /* nd length check */
208 if (ntohs(nd->len) > msg->l - (sizeof(struct isakmp) +
209 ntohs(gen->len))) {
210 plog(LLV_ERROR, LOCATION, NULL,
211 "too long payload length (broken message?)\n");
212 goto end;
215 if (ntohs(nd->len) < sizeof(*nd)) {
216 plog(LLV_ERROR, LOCATION, NULL,
217 "too short payload length (broken message?)\n");
218 goto end;
221 payload = vmalloc(ntohs(nd->len));
222 if (payload == NULL) {
223 plog(LLV_ERROR, LOCATION, NULL,
224 "cannot allocate memory\n");
225 goto end;
228 memcpy(payload->v, (caddr_t) nd, ntohs(nd->len));
230 /* compute HASH */
231 hash = oakley_compute_hash1(iph1, isakmp->msgid, payload);
232 if (hash == NULL) {
233 plog(LLV_ERROR, LOCATION, NULL,
234 "cannot compute hash\n");
236 vfree(payload);
237 goto end;
240 if (ntohs(gen->len) - sizeof(struct isakmp_gen) != hash->l) {
241 plog(LLV_ERROR, LOCATION, NULL,
242 "ignore information due to hash length mismatch\n");
244 vfree(hash);
245 vfree(payload);
246 goto end;
249 if (memcmp(p, hash->v, hash->l) != 0) {
250 plog(LLV_ERROR, LOCATION, NULL,
251 "ignore information due to hash mismatch\n");
253 vfree(hash);
254 vfree(payload);
255 goto end;
258 plog(LLV_DEBUG, LOCATION, NULL, "hash validated.\n");
260 vfree(hash);
261 vfree(payload);
262 } else {
263 /* make sure the packet was encrypted after the beginning of phase 1. */
264 switch (iph1->etype) {
265 case ISAKMP_ETYPE_AGG:
266 case ISAKMP_ETYPE_BASE:
267 case ISAKMP_ETYPE_IDENT:
268 if ((iph1->side == INITIATOR && iph1->status < PHASE1ST_MSG3SENT)
269 || (iph1->side == RESPONDER && iph1->status < PHASE1ST_MSG2SENT)) {
270 break;
272 /*FALLTHRU*/
273 default:
274 plog(LLV_ERROR, LOCATION, iph1->remote,
275 "%s message must be encrypted\n",
276 s_isakmp_nptype(np));
277 error = 0;
278 goto end;
282 if (!(pbuf = isakmp_parse(msg))) {
283 error = -1;
284 goto end;
287 error = 0;
288 for (pa = (struct isakmp_parse_t *)pbuf->v; pa->type; pa++) {
289 switch (pa->type) {
290 case ISAKMP_NPTYPE_HASH:
291 /* Handled above */
292 break;
293 case ISAKMP_NPTYPE_N:
294 error = isakmp_info_recv_n(iph1,
295 (struct isakmp_pl_n *)pa->ptr,
296 msgid, encrypted);
297 break;
298 case ISAKMP_NPTYPE_D:
299 error = isakmp_info_recv_d(iph1,
300 (struct isakmp_pl_d *)pa->ptr,
301 msgid, encrypted);
302 break;
303 case ISAKMP_NPTYPE_NONCE:
304 /* XXX to be 6.4.2 ike-01.txt */
305 /* XXX IV is to be synchronized. */
306 plog(LLV_ERROR, LOCATION, iph1->remote,
307 "ignore Acknowledged Informational\n");
308 break;
309 default:
310 /* don't send information, see isakmp_ident_r1() */
311 error = 0;
312 plog(LLV_ERROR, LOCATION, iph1->remote,
313 "reject the packet, "
314 "received unexpected payload type %s.\n",
315 s_isakmp_nptype(gen->np));
317 if (error < 0)
318 break;
320 end:
321 if (msg != NULL)
322 vfree(msg);
323 if (pbuf != NULL)
324 vfree(pbuf);
325 return error;
330 * log unhandled / unallowed Notification payload
333 isakmp_log_notify(iph1, notify, exchange)
334 struct ph1handle *iph1;
335 struct isakmp_pl_n *notify;
336 const char *exchange;
338 u_int type;
339 char *nraw, *ndata, *nhex;
340 size_t l;
342 type = ntohs(notify->type);
343 if (ntohs(notify->h.len) < sizeof(*notify) + notify->spi_size) {
344 plog(LLV_ERROR, LOCATION, iph1->remote,
345 "invalid spi_size in %s notification in %s.\n",
346 s_isakmp_notify_msg(type), exchange);
347 return -1;
350 plog(LLV_ERROR, LOCATION, iph1->remote,
351 "notification %s received in %s.\n",
352 s_isakmp_notify_msg(type), exchange);
354 nraw = ((char*) notify) + sizeof(*notify) + notify->spi_size;
355 l = ntohs(notify->h.len) - sizeof(*notify) - notify->spi_size;
356 if (l > 0) {
357 if (type >= ISAKMP_NTYPE_MINERROR &&
358 type <= ISAKMP_NTYPE_MAXERROR) {
359 ndata = binsanitize(nraw, l);
360 if (ndata != NULL) {
361 plog(LLV_ERROR, LOCATION, iph1->remote,
362 "error message: '%s'.\n",
363 ndata);
364 racoon_free(ndata);
365 } else {
366 plog(LLV_ERROR, LOCATION, iph1->remote,
367 "Cannot allocate memory\n");
369 } else {
370 nhex = val2str(nraw, l);
371 if (nhex != NULL) {
372 plog(LLV_ERROR, LOCATION, iph1->remote,
373 "notification payload: %s.\n",
374 nhex);
375 racoon_free(nhex);
376 } else {
377 plog(LLV_ERROR, LOCATION, iph1->remote,
378 "Cannot allocate memory\n");
383 return 0;
388 * handling of Notification payload
390 static int
391 isakmp_info_recv_n(iph1, notify, msgid, encrypted)
392 struct ph1handle *iph1;
393 struct isakmp_pl_n *notify;
394 u_int32_t msgid;
395 int encrypted;
397 u_int type;
399 type = ntohs(notify->type);
400 switch (type) {
401 case ISAKMP_NTYPE_CONNECTED:
402 case ISAKMP_NTYPE_RESPONDER_LIFETIME:
403 case ISAKMP_NTYPE_REPLAY_STATUS:
404 #ifdef ENABLE_HYBRID
405 case ISAKMP_NTYPE_UNITY_HEARTBEAT:
406 #endif
407 /* do something */
408 break;
409 case ISAKMP_NTYPE_INITIAL_CONTACT:
410 if (encrypted)
411 return isakmp_info_recv_initialcontact(iph1, NULL);
412 break;
413 #ifdef ENABLE_DPD
414 case ISAKMP_NTYPE_R_U_THERE:
415 if (encrypted)
416 return isakmp_info_recv_r_u(iph1,
417 (struct isakmp_pl_ru *)notify, msgid);
418 break;
419 case ISAKMP_NTYPE_R_U_THERE_ACK:
420 if (encrypted)
421 return isakmp_info_recv_r_u_ack(iph1,
422 (struct isakmp_pl_ru *)notify, msgid);
423 break;
424 #endif
427 /* If we receive a error notification we should delete the related
428 * phase1 / phase2 handle, and send an event to racoonctl.
429 * However, since phase1 error notifications are not encrypted and
430 * can not be authenticated, it would allow a DoS attack possibility
431 * to handle them.
432 * Phase2 error notifications should be encrypted, so we could handle
433 * those, but it needs implementing (the old code didn't implement
434 * that either).
435 * So we are good to just log the messages here.
437 if (encrypted)
438 isakmp_log_notify(iph1, notify, "informational exchange");
439 else
440 isakmp_log_notify(iph1, notify, "unencrypted informational exchange");
442 return 0;
446 * handling of Deletion payload
448 static int
449 isakmp_info_recv_d(iph1, delete, msgid, encrypted)
450 struct ph1handle *iph1;
451 struct isakmp_pl_d *delete;
452 u_int32_t msgid;
453 int encrypted;
455 int tlen, num_spi;
456 vchar_t *pbuf;
457 int protected = 0;
458 struct ph1handle *del_ph1;
459 struct ph2handle *iph2;
460 union {
461 u_int32_t spi32;
462 u_int16_t spi16[2];
463 } spi;
465 if (ntohl(delete->doi) != IPSEC_DOI) {
466 plog(LLV_ERROR, LOCATION, iph1->remote,
467 "delete payload with invalid doi:%d.\n",
468 ntohl(delete->doi));
469 #ifdef ENABLE_HYBRID
471 * At deconnexion time, Cisco VPN client does this
472 * with a zero DOI. Don't give up in that situation.
474 if (((iph1->mode_cfg->flags &
475 ISAKMP_CFG_VENDORID_UNITY) == 0) || (delete->doi != 0))
476 return 0;
477 #else
478 return 0;
479 #endif
482 num_spi = ntohs(delete->num_spi);
483 tlen = ntohs(delete->h.len) - sizeof(struct isakmp_pl_d);
485 if (tlen != num_spi * delete->spi_size) {
486 plog(LLV_ERROR, LOCATION, iph1->remote,
487 "deletion payload with invalid length.\n");
488 return 0;
491 plog(LLV_DEBUG, LOCATION, iph1->remote,
492 "delete payload for protocol %s\n",
493 s_ipsecdoi_proto(delete->proto_id));
495 if(!iph1->rmconf->weak_phase1_check && !encrypted) {
496 plog(LLV_WARNING, LOCATION, iph1->remote,
497 "Ignoring unencrypted delete payload "
498 "(check the weak_phase1_check option)\n");
499 return 0;
502 switch (delete->proto_id) {
503 case IPSECDOI_PROTO_ISAKMP:
504 if (delete->spi_size != sizeof(isakmp_index)) {
505 plog(LLV_ERROR, LOCATION, iph1->remote,
506 "delete payload with strange spi "
507 "size %d(proto_id:%d)\n",
508 delete->spi_size, delete->proto_id);
509 return 0;
512 del_ph1=getph1byindex((isakmp_index *)(delete + 1));
513 if(del_ph1 != NULL){
515 evt_phase1(iph1, EVT_PHASE1_PEER_DELETED, NULL);
516 sched_cancel(&del_ph1->scr);
519 * Do not delete IPsec SAs when receiving an IKE delete notification.
520 * Just delete the IKE SA.
522 isakmp_ph1expire(del_ph1);
524 break;
526 case IPSECDOI_PROTO_IPSEC_AH:
527 case IPSECDOI_PROTO_IPSEC_ESP:
528 if (delete->spi_size != sizeof(u_int32_t)) {
529 plog(LLV_ERROR, LOCATION, iph1->remote,
530 "delete payload with strange spi "
531 "size %d(proto_id:%d)\n",
532 delete->spi_size, delete->proto_id);
533 return 0;
535 purge_ipsec_spi(iph1->remote, delete->proto_id,
536 (u_int32_t *)(delete + 1), num_spi);
537 break;
539 case IPSECDOI_PROTO_IPCOMP:
540 /* need to handle both 16bit/32bit SPI */
541 memset(&spi, 0, sizeof(spi));
542 if (delete->spi_size == sizeof(spi.spi16[1])) {
543 memcpy(&spi.spi16[1], delete + 1,
544 sizeof(spi.spi16[1]));
545 } else if (delete->spi_size == sizeof(spi.spi32))
546 memcpy(&spi.spi32, delete + 1, sizeof(spi.spi32));
547 else {
548 plog(LLV_ERROR, LOCATION, iph1->remote,
549 "delete payload with strange spi "
550 "size %d(proto_id:%d)\n",
551 delete->spi_size, delete->proto_id);
552 return 0;
554 purge_ipsec_spi(iph1->remote, delete->proto_id,
555 &spi.spi32, num_spi);
556 break;
558 default:
559 plog(LLV_ERROR, LOCATION, iph1->remote,
560 "deletion message received, "
561 "invalid proto_id: %d\n",
562 delete->proto_id);
563 return 0;
566 plog(LLV_DEBUG, LOCATION, NULL, "purged SAs.\n");
568 return 0;
572 * send Delete payload (for ISAKMP SA) in Informational exchange.
575 isakmp_info_send_d1(iph1)
576 struct ph1handle *iph1;
578 struct isakmp_pl_d *d;
579 vchar_t *payload = NULL;
580 int tlen;
581 int error = 0;
583 if (iph1->status != PHASE2ST_ESTABLISHED)
584 return 0;
586 /* create delete payload */
588 /* send SPIs of inbound SAs. */
589 /* XXX should send outbound SAs's ? */
590 tlen = sizeof(*d) + sizeof(isakmp_index);
591 payload = vmalloc(tlen);
592 if (payload == NULL) {
593 plog(LLV_ERROR, LOCATION, NULL,
594 "failed to get buffer for payload.\n");
595 return errno;
598 d = (struct isakmp_pl_d *)payload->v;
599 d->h.np = ISAKMP_NPTYPE_NONE;
600 d->h.len = htons(tlen);
601 d->doi = htonl(IPSEC_DOI);
602 d->proto_id = IPSECDOI_PROTO_ISAKMP;
603 d->spi_size = sizeof(isakmp_index);
604 d->num_spi = htons(1);
605 memcpy(d + 1, &iph1->index, sizeof(isakmp_index));
607 error = isakmp_info_send_common(iph1, payload,
608 ISAKMP_NPTYPE_D, 0);
609 vfree(payload);
611 return error;
615 * send Delete payload (for IPsec SA) in Informational exchange, based on
616 * pfkey msg. It sends always single SPI.
619 isakmp_info_send_d2(iph2)
620 struct ph2handle *iph2;
622 struct ph1handle *iph1;
623 struct saproto *pr;
624 struct isakmp_pl_d *d;
625 vchar_t *payload = NULL;
626 int tlen;
627 int error = 0;
628 u_int8_t *spi;
630 if (iph2->status != PHASE2ST_ESTABLISHED)
631 return 0;
634 * don't send delete information if there is no phase 1 handler.
635 * It's nonsensical to negotiate phase 1 to send the information.
637 iph1 = getph1byaddr(iph2->src, iph2->dst, 0);
638 if (iph1 == NULL){
639 plog(LLV_DEBUG2, LOCATION, NULL,
640 "No ph1 handler found, could not send DELETE_SA\n");
641 return 0;
644 /* create delete payload */
645 for (pr = iph2->approval->head; pr != NULL; pr = pr->next) {
647 /* send SPIs of inbound SAs. */
649 * XXX should I send outbound SAs's ?
650 * I send inbound SAs's SPI only at the moment because I can't
651 * decode any more if peer send encoded packet without aware of
652 * deletion of SA. Outbound SAs don't come under the situation.
654 tlen = sizeof(*d) + pr->spisize;
655 payload = vmalloc(tlen);
656 if (payload == NULL) {
657 plog(LLV_ERROR, LOCATION, NULL,
658 "failed to get buffer for payload.\n");
659 return errno;
662 d = (struct isakmp_pl_d *)payload->v;
663 d->h.np = ISAKMP_NPTYPE_NONE;
664 d->h.len = htons(tlen);
665 d->doi = htonl(IPSEC_DOI);
666 d->proto_id = pr->proto_id;
667 d->spi_size = pr->spisize;
668 d->num_spi = htons(1);
670 * XXX SPI bits are left-filled, for use with IPComp.
671 * we should be switching to variable-length spi field...
673 spi = (u_int8_t *)&pr->spi;
674 spi += sizeof(pr->spi);
675 spi -= pr->spisize;
676 memcpy(d + 1, spi, pr->spisize);
678 error = isakmp_info_send_common(iph1, payload,
679 ISAKMP_NPTYPE_D, 0);
680 vfree(payload);
683 return error;
687 * send Notification payload (for without ISAKMP SA) in Informational exchange
690 isakmp_info_send_nx(isakmp, remote, local, type, data)
691 struct isakmp *isakmp;
692 struct sockaddr *remote, *local;
693 int type;
694 vchar_t *data;
696 struct ph1handle *iph1 = NULL;
697 vchar_t *payload = NULL;
698 int tlen;
699 int error = -1;
700 struct isakmp_pl_n *n;
701 int spisiz = 0; /* see below */
703 /* add new entry to isakmp status table. */
704 iph1 = newph1();
705 if (iph1 == NULL)
706 return -1;
708 memcpy(&iph1->index.i_ck, &isakmp->i_ck, sizeof(cookie_t));
709 isakmp_newcookie((char *)&iph1->index.r_ck, remote, local);
710 iph1->status = PHASE1ST_START;
711 iph1->side = INITIATOR;
712 iph1->version = isakmp->v;
713 iph1->flags = 0;
714 iph1->msgid = 0; /* XXX */
715 #ifdef ENABLE_HYBRID
716 if ((iph1->mode_cfg = isakmp_cfg_mkstate()) == NULL)
717 goto end;
718 #endif
719 #ifdef ENABLE_FRAG
720 iph1->frag = 0;
721 iph1->frag_chain = NULL;
722 #endif
724 /* copy remote address */
725 if (copy_ph1addresses(iph1, NULL, remote, local) < 0)
726 goto end;
728 tlen = sizeof(*n) + spisiz;
729 if (data)
730 tlen += data->l;
731 payload = vmalloc(tlen);
732 if (payload == NULL) {
733 plog(LLV_ERROR, LOCATION, NULL,
734 "failed to get buffer to send.\n");
735 goto end;
738 n = (struct isakmp_pl_n *)payload->v;
739 n->h.np = ISAKMP_NPTYPE_NONE;
740 n->h.len = htons(tlen);
741 n->doi = htonl(IPSEC_DOI);
742 n->proto_id = IPSECDOI_KEY_IKE;
743 n->spi_size = spisiz;
744 n->type = htons(type);
745 if (spisiz)
746 memset(n + 1, 0, spisiz); /* XXX spisiz is always 0 */
747 if (data)
748 memcpy((caddr_t)(n + 1) + spisiz, data->v, data->l);
750 error = isakmp_info_send_common(iph1, payload, ISAKMP_NPTYPE_N, 0);
751 vfree(payload);
753 end:
754 if (iph1 != NULL)
755 delph1(iph1);
757 return error;
761 * send Notification payload (for ISAKMP SA) in Informational exchange
764 isakmp_info_send_n1(iph1, type, data)
765 struct ph1handle *iph1;
766 int type;
767 vchar_t *data;
769 vchar_t *payload = NULL;
770 int tlen;
771 int error = 0;
772 struct isakmp_pl_n *n;
773 int spisiz;
776 * note on SPI size: which description is correct? I have chosen
777 * this to be 0.
779 * RFC2408 3.1, 2nd paragraph says: ISAKMP SA is identified by
780 * Initiator/Responder cookie and SPI has no meaning, SPI size = 0.
781 * RFC2408 3.1, first paragraph on page 40: ISAKMP SA is identified
782 * by cookie and SPI has no meaning, 0 <= SPI size <= 16.
783 * RFC2407 4.6.3.3, INITIAL-CONTACT is required to set to 16.
785 if (type == ISAKMP_NTYPE_INITIAL_CONTACT)
786 spisiz = sizeof(isakmp_index);
787 else
788 spisiz = 0;
790 tlen = sizeof(*n) + spisiz;
791 if (data)
792 tlen += data->l;
793 payload = vmalloc(tlen);
794 if (payload == NULL) {
795 plog(LLV_ERROR, LOCATION, NULL,
796 "failed to get buffer to send.\n");
797 return errno;
800 n = (struct isakmp_pl_n *)payload->v;
801 n->h.np = ISAKMP_NPTYPE_NONE;
802 n->h.len = htons(tlen);
803 n->doi = htonl(iph1->rmconf->doitype);
804 n->proto_id = IPSECDOI_PROTO_ISAKMP; /* XXX to be configurable ? */
805 n->spi_size = spisiz;
806 n->type = htons(type);
807 if (spisiz)
808 memcpy(n + 1, &iph1->index, sizeof(isakmp_index));
809 if (data)
810 memcpy((caddr_t)(n + 1) + spisiz, data->v, data->l);
812 error = isakmp_info_send_common(iph1, payload, ISAKMP_NPTYPE_N, iph1->flags);
813 vfree(payload);
815 return error;
819 * send Notification payload (for IPsec SA) in Informational exchange
822 isakmp_info_send_n2(iph2, type, data)
823 struct ph2handle *iph2;
824 int type;
825 vchar_t *data;
827 struct ph1handle *iph1 = iph2->ph1;
828 vchar_t *payload = NULL;
829 int tlen;
830 int error = 0;
831 struct isakmp_pl_n *n;
832 struct saproto *pr;
834 if (!iph2->approval)
835 return EINVAL;
837 pr = iph2->approval->head;
839 /* XXX must be get proper spi */
840 tlen = sizeof(*n) + pr->spisize;
841 if (data)
842 tlen += data->l;
843 payload = vmalloc(tlen);
844 if (payload == NULL) {
845 plog(LLV_ERROR, LOCATION, NULL,
846 "failed to get buffer to send.\n");
847 return errno;
850 n = (struct isakmp_pl_n *)payload->v;
851 n->h.np = ISAKMP_NPTYPE_NONE;
852 n->h.len = htons(tlen);
853 n->doi = htonl(IPSEC_DOI); /* IPSEC DOI (1) */
854 n->proto_id = pr->proto_id; /* IPSEC AH/ESP/whatever*/
855 n->spi_size = pr->spisize;
856 n->type = htons(type);
857 *(u_int32_t *)(n + 1) = pr->spi;
858 if (data)
859 memcpy((caddr_t)(n + 1) + pr->spisize, data->v, data->l);
861 iph2->flags |= ISAKMP_FLAG_E; /* XXX Should we do FLAG_A ? */
862 error = isakmp_info_send_common(iph1, payload, ISAKMP_NPTYPE_N, iph2->flags);
863 vfree(payload);
865 return error;
869 * send Information
870 * When ph1->skeyid_a == NULL, send message without encoding.
873 isakmp_info_send_common(iph1, payload, np, flags)
874 struct ph1handle *iph1;
875 vchar_t *payload;
876 u_int32_t np;
877 int flags;
879 struct ph2handle *iph2 = NULL;
880 vchar_t *hash = NULL;
881 struct isakmp *isakmp;
882 struct isakmp_gen *gen;
883 char *p;
884 int tlen;
885 int error = -1;
887 /* add new entry to isakmp status table */
888 iph2 = newph2();
889 if (iph2 == NULL)
890 goto end;
892 iph2->dst = dupsaddr(iph1->remote);
893 if (iph2->dst == NULL) {
894 delph2(iph2);
895 goto end;
897 iph2->src = dupsaddr(iph1->local);
898 if (iph2->src == NULL) {
899 delph2(iph2);
900 goto end;
902 iph2->side = INITIATOR;
903 iph2->status = PHASE2ST_START;
904 iph2->msgid = isakmp_newmsgid2(iph1);
906 /* get IV and HASH(1) if skeyid_a was generated. */
907 if (iph1->skeyid_a != NULL) {
908 iph2->ivm = oakley_newiv2(iph1, iph2->msgid);
909 if (iph2->ivm == NULL) {
910 delph2(iph2);
911 goto end;
914 /* generate HASH(1) */
915 hash = oakley_compute_hash1(iph1, iph2->msgid, payload);
916 if (hash == NULL) {
917 delph2(iph2);
918 goto end;
921 /* initialized total buffer length */
922 tlen = hash->l;
923 tlen += sizeof(*gen);
924 } else {
925 /* IKE-SA is not established */
926 hash = NULL;
928 /* initialized total buffer length */
929 tlen = 0;
931 if ((flags & ISAKMP_FLAG_A) == 0)
932 iph2->flags = (hash == NULL ? 0 : ISAKMP_FLAG_E);
933 else
934 iph2->flags = (hash == NULL ? 0 : ISAKMP_FLAG_A);
936 insph2(iph2);
937 bindph12(iph1, iph2);
939 tlen += sizeof(*isakmp) + payload->l;
941 /* create buffer for isakmp payload */
942 iph2->sendbuf = vmalloc(tlen);
943 if (iph2->sendbuf == NULL) {
944 plog(LLV_ERROR, LOCATION, NULL,
945 "failed to get buffer to send.\n");
946 goto err;
949 /* create isakmp header */
950 isakmp = (struct isakmp *)iph2->sendbuf->v;
951 memcpy(&isakmp->i_ck, &iph1->index.i_ck, sizeof(cookie_t));
952 memcpy(&isakmp->r_ck, &iph1->index.r_ck, sizeof(cookie_t));
953 isakmp->np = hash == NULL ? (np & 0xff) : ISAKMP_NPTYPE_HASH;
954 isakmp->v = iph1->version;
955 isakmp->etype = ISAKMP_ETYPE_INFO;
956 isakmp->flags = iph2->flags;
957 memcpy(&isakmp->msgid, &iph2->msgid, sizeof(isakmp->msgid));
958 isakmp->len = htonl(tlen);
959 p = (char *)(isakmp + 1);
961 /* create HASH payload */
962 if (hash != NULL) {
963 gen = (struct isakmp_gen *)p;
964 gen->np = np & 0xff;
965 gen->len = htons(sizeof(*gen) + hash->l);
966 p += sizeof(*gen);
967 memcpy(p, hash->v, hash->l);
968 p += hash->l;
971 /* add payload */
972 memcpy(p, payload->v, payload->l);
973 p += payload->l;
975 #ifdef HAVE_PRINT_ISAKMP_C
976 isakmp_printpacket(iph2->sendbuf, iph1->local, iph1->remote, 1);
977 #endif
979 /* encoding */
980 if (ISSET(isakmp->flags, ISAKMP_FLAG_E)) {
981 vchar_t *tmp;
983 tmp = oakley_do_encrypt(iph2->ph1, iph2->sendbuf, iph2->ivm->ive,
984 iph2->ivm->iv);
985 VPTRINIT(iph2->sendbuf);
986 if (tmp == NULL)
987 goto err;
988 iph2->sendbuf = tmp;
991 /* HDR*, HASH(1), N */
992 if (isakmp_send(iph2->ph1, iph2->sendbuf) < 0) {
993 VPTRINIT(iph2->sendbuf);
994 goto err;
997 plog(LLV_DEBUG, LOCATION, NULL,
998 "sendto Information %s.\n", s_isakmp_nptype(np));
1001 * don't resend notify message because peer can use Acknowledged
1002 * Informational if peer requires the reply of the notify message.
1005 /* XXX If Acknowledged Informational required, don't delete ph2handle */
1006 error = 0;
1007 VPTRINIT(iph2->sendbuf);
1008 goto err; /* XXX */
1010 end:
1011 if (hash)
1012 vfree(hash);
1013 return error;
1015 err:
1016 remph2(iph2);
1017 delph2(iph2);
1018 goto end;
1022 * add a notify payload to buffer by reallocating buffer.
1023 * If buf == NULL, the function only create a notify payload.
1025 * XXX Which is SPI to be included, inbound or outbound ?
1027 vchar_t *
1028 isakmp_add_pl_n(buf0, np_p, type, pr, data)
1029 vchar_t *buf0;
1030 u_int8_t **np_p;
1031 int type;
1032 struct saproto *pr;
1033 vchar_t *data;
1035 vchar_t *buf = NULL;
1036 struct isakmp_pl_n *n;
1037 int tlen;
1038 int oldlen = 0;
1040 if (*np_p)
1041 **np_p = ISAKMP_NPTYPE_N;
1043 tlen = sizeof(*n) + pr->spisize;
1045 if (data)
1046 tlen += data->l;
1047 if (buf0) {
1048 oldlen = buf0->l;
1049 buf = vrealloc(buf0, buf0->l + tlen);
1050 } else
1051 buf = vmalloc(tlen);
1052 if (!buf) {
1053 plog(LLV_ERROR, LOCATION, NULL,
1054 "failed to get a payload buffer.\n");
1055 return NULL;
1058 n = (struct isakmp_pl_n *)(buf->v + oldlen);
1059 n->h.np = ISAKMP_NPTYPE_NONE;
1060 n->h.len = htons(tlen);
1061 n->doi = htonl(IPSEC_DOI); /* IPSEC DOI (1) */
1062 n->proto_id = pr->proto_id; /* IPSEC AH/ESP/whatever*/
1063 n->spi_size = pr->spisize;
1064 n->type = htons(type);
1065 *(u_int32_t *)(n + 1) = pr->spi; /* XXX */
1066 if (data)
1067 memcpy((caddr_t)(n + 1) + pr->spisize, data->v, data->l);
1069 /* save the pointer of next payload type */
1070 *np_p = &n->h.np;
1072 return buf;
1075 static void
1076 purge_isakmp_spi(proto, spi, n)
1077 int proto;
1078 isakmp_index *spi; /*network byteorder*/
1079 size_t n;
1081 struct ph1handle *iph1;
1082 size_t i;
1084 for (i = 0; i < n; i++) {
1085 iph1 = getph1byindex(&spi[i]);
1086 if (!iph1)
1087 continue;
1089 plog(LLV_INFO, LOCATION, NULL,
1090 "purged ISAKMP-SA proto_id=%s spi=%s.\n",
1091 s_ipsecdoi_proto(proto),
1092 isakmp_pindex(&spi[i], 0));
1094 iph1->status = PHASE1ST_EXPIRED;
1095 sched_schedule(&iph1->sce, 1, isakmp_ph1delete_stub);
1101 void
1102 purge_ipsec_spi(dst0, proto, spi, n)
1103 struct sockaddr *dst0;
1104 int proto;
1105 u_int32_t *spi; /*network byteorder*/
1106 size_t n;
1108 vchar_t *buf = NULL;
1109 struct sadb_msg *msg, *next, *end;
1110 struct sadb_sa *sa;
1111 struct sadb_lifetime *lt;
1112 struct sockaddr *src, *dst;
1113 struct ph2handle *iph2;
1114 u_int64_t created;
1115 size_t i;
1116 caddr_t mhp[SADB_EXT_MAX + 1];
1118 plog(LLV_DEBUG2, LOCATION, NULL,
1119 "purge_ipsec_spi:\n");
1120 plog(LLV_DEBUG2, LOCATION, NULL, "dst0: %s\n", saddr2str(dst0));
1121 plog(LLV_DEBUG2, LOCATION, NULL, "SPI: %08X\n", ntohl(spi[0]));
1123 buf = pfkey_dump_sadb(ipsecdoi2pfkey_proto(proto));
1124 if (buf == NULL) {
1125 plog(LLV_DEBUG, LOCATION, NULL,
1126 "pfkey_dump_sadb returned nothing.\n");
1127 return;
1130 msg = (struct sadb_msg *)buf->v;
1131 end = (struct sadb_msg *)(buf->v + buf->l);
1133 while (msg < end) {
1134 if ((msg->sadb_msg_len << 3) < sizeof(*msg))
1135 break;
1136 next = (struct sadb_msg *)((caddr_t)msg + (msg->sadb_msg_len << 3));
1137 if (msg->sadb_msg_type != SADB_DUMP) {
1138 msg = next;
1139 continue;
1142 if (pfkey_align(msg, mhp) || pfkey_check(mhp)) {
1143 plog(LLV_ERROR, LOCATION, NULL,
1144 "pfkey_check (%s)\n", ipsec_strerror());
1145 msg = next;
1146 continue;
1149 sa = (struct sadb_sa *)(mhp[SADB_EXT_SA]);
1150 if (!sa
1151 || !mhp[SADB_EXT_ADDRESS_SRC]
1152 || !mhp[SADB_EXT_ADDRESS_DST]) {
1153 msg = next;
1154 continue;
1156 pk_fixup_sa_addresses(mhp);
1157 src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
1158 dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
1159 lt = (struct sadb_lifetime*)mhp[SADB_EXT_LIFETIME_HARD];
1160 if(lt != NULL)
1161 created = lt->sadb_lifetime_addtime;
1162 else
1163 created = 0;
1165 if (sa->sadb_sa_state != SADB_SASTATE_MATURE
1166 && sa->sadb_sa_state != SADB_SASTATE_DYING) {
1167 msg = next;
1168 continue;
1171 plog(LLV_DEBUG2, LOCATION, NULL, "src: %s\n", saddr2str(src));
1172 plog(LLV_DEBUG2, LOCATION, NULL, "dst: %s\n", saddr2str(dst));
1174 /* XXX n^2 algorithm, inefficient */
1176 /* don't delete inbound SAs at the moment */
1177 /* XXX should we remove SAs with opposite direction as well? */
1178 if (cmpsaddr(dst0, dst)) {
1179 msg = next;
1180 continue;
1183 for (i = 0; i < n; i++) {
1184 plog(LLV_DEBUG, LOCATION, NULL,
1185 "check spi(packet)=%u spi(db)=%u.\n",
1186 ntohl(spi[i]), ntohl(sa->sadb_sa_spi));
1187 if (spi[i] != sa->sadb_sa_spi)
1188 continue;
1190 pfkey_send_delete(lcconf->sock_pfkey,
1191 msg->sadb_msg_satype,
1192 IPSEC_MODE_ANY,
1193 src, dst, sa->sadb_sa_spi);
1196 * delete a relative phase 2 handler.
1197 * continue to process if no relative phase 2 handler
1198 * exists.
1200 iph2 = getph2bysaidx(src, dst, proto, spi[i]);
1201 if(iph2 != NULL){
1202 delete_spd(iph2, created);
1203 remph2(iph2);
1204 delph2(iph2);
1207 plog(LLV_INFO, LOCATION, NULL,
1208 "purged IPsec-SA proto_id=%s spi=%u.\n",
1209 s_ipsecdoi_proto(proto),
1210 ntohl(spi[i]));
1213 msg = next;
1216 if (buf)
1217 vfree(buf);
1221 * delete all phase2 sa relatived to the destination address
1222 * (except the phase2 within which the INITIAL-CONTACT was received).
1223 * Don't delete Phase 1 handlers on INITIAL-CONTACT, and don't ignore
1224 * an INITIAL-CONTACT if we have contacted the peer. This matches the
1225 * Sun IKE behavior, and makes rekeying work much better when the peer
1226 * restarts.
1229 isakmp_info_recv_initialcontact(iph1, protectedph2)
1230 struct ph1handle *iph1;
1231 struct ph2handle *protectedph2;
1233 vchar_t *buf = NULL;
1234 struct sadb_msg *msg, *next, *end;
1235 struct sadb_sa *sa;
1236 struct sockaddr *src, *dst;
1237 caddr_t mhp[SADB_EXT_MAX + 1];
1238 int proto_id, i;
1239 struct ph2handle *iph2;
1240 #if 0
1241 char *loc, *rem;
1242 #endif
1244 plog(LLV_INFO, LOCATION, iph1->remote, "received INITIAL-CONTACT\n");
1246 if (f_local)
1247 return 0;
1249 #if 0
1250 loc = racoon_strdup(saddrwop2str(iph1->local));
1251 rem = racoon_strdup(saddrwop2str(iph1->remote));
1252 STRDUP_FATAL(loc);
1253 STRDUP_FATAL(rem);
1256 * Purge all IPSEC-SAs for the peer. We can do this
1257 * the easy way (using a PF_KEY SADB_DELETE extension)
1258 * or we can do it the hard way.
1260 for (i = 0; i < pfkey_nsatypes; i++) {
1261 proto_id = pfkey2ipsecdoi_proto(pfkey_satypes[i].ps_satype);
1263 plog(LLV_INFO, LOCATION, NULL,
1264 "purging %s SAs for %s -> %s\n",
1265 pfkey_satypes[i].ps_name, loc, rem);
1266 if (pfkey_send_delete_all(lcconf->sock_pfkey,
1267 pfkey_satypes[i].ps_satype, IPSEC_MODE_ANY,
1268 iph1->local, iph1->remote) == -1) {
1269 plog(LLV_ERROR, LOCATION, NULL,
1270 "delete_all %s -> %s failed for %s (%s)\n",
1271 loc, rem,
1272 pfkey_satypes[i].ps_name, ipsec_strerror());
1273 goto the_hard_way;
1276 deleteallph2(iph1->local, iph1->remote, proto_id);
1278 plog(LLV_INFO, LOCATION, NULL,
1279 "purging %s SAs for %s -> %s\n",
1280 pfkey_satypes[i].ps_name, rem, loc);
1281 if (pfkey_send_delete_all(lcconf->sock_pfkey,
1282 pfkey_satypes[i].ps_satype, IPSEC_MODE_ANY,
1283 iph1->remote, iph1->local) == -1) {
1284 plog(LLV_ERROR, LOCATION, NULL,
1285 "delete_all %s -> %s failed for %s (%s)\n",
1286 rem, loc,
1287 pfkey_satypes[i].ps_name, ipsec_strerror());
1288 goto the_hard_way;
1291 deleteallph2(iph1->remote, iph1->local, proto_id);
1294 racoon_free(loc);
1295 racoon_free(rem);
1296 return 0;
1298 the_hard_way:
1299 racoon_free(loc);
1300 racoon_free(rem);
1301 #endif
1303 buf = pfkey_dump_sadb(SADB_SATYPE_UNSPEC);
1304 if (buf == NULL) {
1305 plog(LLV_DEBUG, LOCATION, NULL,
1306 "pfkey_dump_sadb returned nothing.\n");
1307 return 0;
1310 msg = (struct sadb_msg *)buf->v;
1311 end = (struct sadb_msg *)(buf->v + buf->l);
1313 for (; msg < end; msg = next) {
1314 if ((msg->sadb_msg_len << 3) < sizeof(*msg))
1315 break;
1317 next = (struct sadb_msg *)((caddr_t)msg + (msg->sadb_msg_len << 3));
1318 if (msg->sadb_msg_type != SADB_DUMP)
1319 continue;
1321 if (pfkey_align(msg, mhp) || pfkey_check(mhp)) {
1322 plog(LLV_ERROR, LOCATION, NULL,
1323 "pfkey_check (%s)\n", ipsec_strerror());
1324 continue;
1327 if (mhp[SADB_EXT_SA] == NULL
1328 || mhp[SADB_EXT_ADDRESS_SRC] == NULL
1329 || mhp[SADB_EXT_ADDRESS_DST] == NULL)
1330 continue;
1332 sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
1333 pk_fixup_sa_addresses(mhp);
1334 src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
1335 dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
1337 if (sa->sadb_sa_state != SADB_SASTATE_MATURE
1338 && sa->sadb_sa_state != SADB_SASTATE_DYING)
1339 continue;
1342 * RFC2407 4.6.3.3 INITIAL-CONTACT is the message that
1343 * announces the sender of the message was rebooted.
1344 * it is interpreted to delete all SAs which source address
1345 * is the sender of the message.
1346 * racoon only deletes SA which is matched both the
1347 * source address and the destination accress.
1351 * Check that the IP and port match. But this is not optimal,
1352 * since NAT-T can make the peer have multiple different
1353 * ports. Correct thing to do is delete all entries with
1354 * same identity. -TT
1356 if ((cmpsaddr(iph1->local, src) != 0 ||
1357 cmpsaddr(iph1->remote, dst) != 0) &&
1358 (cmpsaddr(iph1->local, dst) != 0 ||
1359 cmpsaddr(iph1->remote, src) != 0))
1360 continue;
1363 * Make sure this is an SATYPE that we manage.
1364 * This is gross; too bad we couldn't do it the
1365 * easy way.
1367 for (i = 0; i < pfkey_nsatypes; i++) {
1368 if (pfkey_satypes[i].ps_satype ==
1369 msg->sadb_msg_satype)
1370 break;
1372 if (i == pfkey_nsatypes)
1373 continue;
1375 plog(LLV_INFO, LOCATION, NULL,
1376 "purging spi=%u.\n", ntohl(sa->sadb_sa_spi));
1377 pfkey_send_delete(lcconf->sock_pfkey,
1378 msg->sadb_msg_satype,
1379 IPSEC_MODE_ANY, src, dst, sa->sadb_sa_spi);
1382 * delete a relative phase 2 handler.
1383 * continue to process if no relative phase 2 handler
1384 * exists.
1386 proto_id = pfkey2ipsecdoi_proto(msg->sadb_msg_satype);
1387 iph2 = getph2bysaidx(src, dst, proto_id, sa->sadb_sa_spi);
1388 if (iph2 && iph2 != protectedph2) {
1389 delete_spd(iph2, 0);
1390 remph2(iph2);
1391 delph2(iph2);
1395 vfree(buf);
1396 return 0;
1400 #ifdef ENABLE_DPD
1401 static int
1402 isakmp_info_recv_r_u (iph1, ru, msgid)
1403 struct ph1handle *iph1;
1404 struct isakmp_pl_ru *ru;
1405 u_int32_t msgid;
1407 struct isakmp_pl_ru *ru_ack;
1408 vchar_t *payload = NULL;
1409 int tlen;
1410 int error = 0;
1412 plog(LLV_DEBUG, LOCATION, iph1->remote,
1413 "DPD R-U-There received\n");
1415 /* XXX should compare cookies with iph1->index?
1416 Or is this already done by calling function? */
1417 tlen = sizeof(*ru_ack);
1418 payload = vmalloc(tlen);
1419 if (payload == NULL) {
1420 plog(LLV_ERROR, LOCATION, NULL,
1421 "failed to get buffer to send.\n");
1422 return errno;
1425 ru_ack = (struct isakmp_pl_ru *)payload->v;
1426 ru_ack->h.np = ISAKMP_NPTYPE_NONE;
1427 ru_ack->h.len = htons(tlen);
1428 ru_ack->doi = htonl(IPSEC_DOI);
1429 ru_ack->type = htons(ISAKMP_NTYPE_R_U_THERE_ACK);
1430 ru_ack->proto_id = IPSECDOI_PROTO_ISAKMP; /* XXX ? */
1431 ru_ack->spi_size = sizeof(isakmp_index);
1432 memcpy(ru_ack->i_ck, ru->i_ck, sizeof(cookie_t));
1433 memcpy(ru_ack->r_ck, ru->r_ck, sizeof(cookie_t));
1434 ru_ack->data = ru->data;
1436 /* XXX Should we do FLAG_A ? */
1437 error = isakmp_info_send_common(iph1, payload, ISAKMP_NPTYPE_N,
1438 ISAKMP_FLAG_E);
1439 vfree(payload);
1441 plog(LLV_DEBUG, LOCATION, NULL, "received a valid R-U-THERE, ACK sent\n");
1443 /* Should we mark tunnel as active ? */
1444 return error;
1447 static int
1448 isakmp_info_recv_r_u_ack (iph1, ru, msgid)
1449 struct ph1handle *iph1;
1450 struct isakmp_pl_ru *ru;
1451 u_int32_t msgid;
1454 plog(LLV_DEBUG, LOCATION, iph1->remote,
1455 "DPD R-U-There-Ack received\n");
1457 /* XXX Maintain window of acceptable sequence numbers ?
1458 * => ru->data <= iph2->dpd_seq &&
1459 * ru->data >= iph2->dpd_seq - iph2->dpd_fails ? */
1460 if (ntohl(ru->data) != iph1->dpd_seq-1) {
1461 plog(LLV_ERROR, LOCATION, iph1->remote,
1462 "Wrong DPD sequence number (%d, %d expected).\n",
1463 ntohl(ru->data), iph1->dpd_seq-1);
1464 return 0;
1467 if (memcmp(ru->i_ck, iph1->index.i_ck, sizeof(cookie_t)) ||
1468 memcmp(ru->r_ck, iph1->index.r_ck, sizeof(cookie_t))) {
1469 plog(LLV_ERROR, LOCATION, iph1->remote,
1470 "Cookie mismatch in DPD ACK!.\n");
1471 return 0;
1474 iph1->dpd_fails = 0;
1475 sched_cancel(&iph1->dpd_r_u);
1476 isakmp_sched_r_u(iph1, 0);
1478 plog(LLV_DEBUG, LOCATION, NULL, "received an R-U-THERE-ACK\n");
1480 return 0;
1487 * send DPD R-U-THERE payload in Informational exchange.
1489 static void
1490 isakmp_info_send_r_u(sc)
1491 struct sched *sc;
1493 struct ph1handle *iph1 = container_of(sc, struct ph1handle, dpd_r_u);
1495 /* create R-U-THERE payload */
1496 struct isakmp_pl_ru *ru;
1497 vchar_t *payload = NULL;
1498 int tlen;
1499 int error = 0;
1501 plog(LLV_DEBUG, LOCATION, iph1->remote, "DPD monitoring....\n");
1503 if (iph1->dpd_fails >= iph1->rmconf->dpd_maxfails) {
1505 plog(LLV_INFO, LOCATION, iph1->remote,
1506 "DPD: remote (ISAKMP-SA spi=%s) seems to be dead.\n",
1507 isakmp_pindex(&iph1->index, 0));
1509 evt_phase1(iph1, EVT_PHASE1_DPD_TIMEOUT, NULL);
1510 purge_remote(iph1);
1512 /* Do not reschedule here: phase1 is deleted,
1513 * DPD will be reactivated when a new ph1 will be negociated
1515 return;
1518 /* TODO: check recent activity to avoid useless sends... */
1520 tlen = sizeof(*ru);
1521 payload = vmalloc(tlen);
1522 if (payload == NULL) {
1523 plog(LLV_ERROR, LOCATION, NULL,
1524 "failed to get buffer for payload.\n");
1525 return;
1527 ru = (struct isakmp_pl_ru *)payload->v;
1528 ru->h.np = ISAKMP_NPTYPE_NONE;
1529 ru->h.len = htons(tlen);
1530 ru->doi = htonl(IPSEC_DOI);
1531 ru->type = htons(ISAKMP_NTYPE_R_U_THERE);
1532 ru->proto_id = IPSECDOI_PROTO_ISAKMP; /* XXX ?*/
1533 ru->spi_size = sizeof(isakmp_index);
1535 memcpy(ru->i_ck, iph1->index.i_ck, sizeof(cookie_t));
1536 memcpy(ru->r_ck, iph1->index.r_ck, sizeof(cookie_t));
1538 if (iph1->dpd_seq == 0){
1539 /* generate a random seq which is not too big */
1540 srand(time(NULL));
1541 iph1->dpd_seq = rand() & 0x0fff;
1544 ru->data = htonl(iph1->dpd_seq);
1546 error = isakmp_info_send_common(iph1, payload, ISAKMP_NPTYPE_N, 0);
1547 vfree(payload);
1549 plog(LLV_DEBUG, LOCATION, iph1->remote,
1550 "DPD R-U-There sent (%d)\n", error);
1552 /* will be decreased if ACK received... */
1553 iph1->dpd_fails++;
1555 /* XXX should be increased only when ACKed ? */
1556 iph1->dpd_seq++;
1558 /* Reschedule the r_u_there with a short delay,
1559 * will be deleted/rescheduled if ACK received before */
1560 isakmp_sched_r_u(iph1, 1);
1562 plog(LLV_DEBUG, LOCATION, iph1->remote,
1563 "rescheduling send_r_u (%d).\n", iph1->rmconf->dpd_retry);
1566 /* Schedule a new R-U-THERE */
1568 isakmp_sched_r_u(iph1, retry)
1569 struct ph1handle *iph1;
1570 int retry;
1572 if(iph1 == NULL ||
1573 iph1->rmconf == NULL)
1574 return 1;
1577 if(iph1->dpd_support == 0 ||
1578 iph1->rmconf->dpd_interval == 0)
1579 return 0;
1581 if(retry)
1582 sched_schedule(&iph1->dpd_r_u, iph1->rmconf->dpd_retry,
1583 isakmp_info_send_r_u);
1584 else
1585 sched_schedule(&iph1->dpd_r_u, iph1->rmconf->dpd_interval,
1586 isakmp_info_send_r_u);
1588 return 0;
1590 #endif