1 /* $Id: isakmp_inf.c,v 1.18 2008/07/07 09:36:08 fukumoto Exp $ */
   2 
   3 /*
   4  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
   5  * All rights reserved.
   6  * 
   7  * Redistribution and use in source and binary forms, with or without
   8  * modification, are permitted provided that the following conditions
   9  * are met:
  10  * 1. Redistributions of source code must retain the above copyright
  11  *    notice, this list of conditions and the following disclaimer.
  12  * 2. Redistributions in binary form must reproduce the above copyright
  13  *    notice, this list of conditions and the following disclaimer in the
  14  *    documentation and/or other materials provided with the distribution.
  15  * 3. Neither the name of the project nor the names of its contributors
  16  *    may be used to endorse or promote products derived from this software
  17  *    without specific prior written permission.
  18  * 
  19  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
  20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
  23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  29  * SUCH DAMAGE.
  30  */
  31 
  32 #include <config.h>
  33 
  34 #include <sys/types.h>
  35 #include <sys/param.h>
  36 #include <sys/socket.h>
  37 
  38 #include <netinet/in.h>
  39 #include <sys/queue.h>
  40 
  41 #ifdef HAVE_NETINET6_IPSEC_H
  42 # include <netinet6/ipsec.h>
  43 #else
  44 # ifdef HAVE_NETIPSEC_IPSEC_H
  45 #  include <netipsec/ipsec.h>
  46 # else
  47 #  ifndef sun   /* XXX KEBE SAYS OpenSolaris */
  48 #    include <linux/ipsec.h>
  49 #  endif
  50 # endif
  51 #endif
  52 
  53 #include <stdlib.h>
  54 #include <stdio.h>
  55 #include <string.h>
  56 #include <errno.h>
  57 #if TIME_WITH_SYS_TIME
  58 # include <sys/time.h>
  59 # include <time.h>
  60 #else
  61 # if HAVE_SYS_TIME_H
  62 #  include <sys/time.h>
  63 # else
  64 #  include <time.h>
  65 # endif
  66 #endif
  67 #ifdef ENABLE_HYBRID
  68 #include <resolv.h>
  69 #endif
  70 
  71 #include "racoon.h"
  72 
  73 /* #include "libpfkey.h" */
  74 
  75 #include "var.h"
  76 /* #include "vmbuf.h" */
  77 /* #include "schedule.h" */
  78 #include "str2val.h"
  79 /* #include "misc.h" */
  80 #include "plog.h"
  81 #include "debug.h"
  82 
  83 /* #include "localconf.h" */
  84 #include "remoteconf.h"
  85 #include "proposal.h"
  86 #include "sockmisc.h"
  87 #include "evt.h"
  88 #include "isakmp.h"
  89 #include "isakmp_var.h"
  90 #include "isakmp_impl.h"
  91 #include "ikev1_impl.h"
  92 #ifdef ENABLE_HYBRID
  93 #include "isakmp_xauth.h"
  94 #include "isakmp_unity.h"
  95 #include "isakmp_cfg.h" 
  96 #endif
  97 #include "isakmp_inf.h"
  98 #include "oakley.h"
  99 #include "ipsec_doi.h"
 100 #include "handler.h"
 101 #include "crypto_impl.h"
 102 #include "pfkey.h"
 103 /* #include "policy.h" */
 104 #include "algorithm.h"
 105 /* #include "admin.h" */
 106 #include "strnames.h"
 107 #ifdef ENABLE_NATT
 108 #include "ikev1_natt.h"
 109 #endif
 110 
 111 #include "ike_conf.h"
 112 
 113 /* information exchange */
 114 static int isakmp_info_recv_n (struct ph1handle *, rc_vchar_t *);
 115 static int isakmp_info_recv_d (struct ph1handle *, rc_vchar_t *);
 116 
 117 
 118 static int isakmp_info_recv_r_u (struct ph1handle *,
 119         struct isakmp_pl_ru *, uint32_t);
 120 static int isakmp_info_recv_r_u_ack (struct ph1handle *,
 121         struct isakmp_pl_ru *, uint32_t);
 122 static void isakmp_info_send_r_u (void *);
 123 
 124 /* static void purge_isakmp_spi (int, isakmp_index_t *, size_t); */
 125 static void info_recv_initialcontact (struct ph1handle *);
 126 
 127 /* %%%
 128  * Information Exchange
 129  */
 130 /*
 131  * receive Information
 132  */
 133 int
 134 isakmp_info_recv(struct ph1handle *iph1, rc_vchar_t *msg0)
 135 {
 136         rc_vchar_t *msg = NULL;
 137         struct isakmp *isakmp;
 138         struct isakmp_gen *gen;
 139         void *p;
 140         rc_vchar_t *hash, *payload;
 141         struct isakmp_gen *nd;
 142         uint8_t np;
 143         int encrypted;
 144 
 145         plog(PLOG_DEBUG, PLOGLOC, NULL, "receive Information.\n");
 146 
 147         encrypted = ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E);
 148 
 149         /* Use new IV to decrypt Informational message. */
 150         if (encrypted) {
 151                 struct isakmp_ivm *ivm;
 152 
 153                 if (iph1->ivm == NULL) {
 154                         plog(PLOG_INTERR, PLOGLOC, NULL, "iph1->ivm == NULL\n");
 155                         return -1;
 156                 }
 157 
 158                 /* compute IV */
 159                 ivm = oakley_newiv2(iph1, ((struct isakmp *)msg0->v)->msgid);
 160                 if (ivm == NULL)
 161                         return -1;
 162 
 163                 msg = oakley_do_decrypt(iph1, msg0, ivm->iv, ivm->ive);
 164                 oakley_delivm(ivm);
 165                 if (msg == NULL)
 166                         return -1;
 167 
 168         } else
 169                 msg = rc_vdup(msg0);
 170 
 171         /* Safety check */
 172         if (msg->l < sizeof(*isakmp) + sizeof(*gen)) {
 173                 plog(PLOG_PROTOERR, PLOGLOC, NULL, 
 174                         "ignore information because the "
 175                         "message is way too short\n");
 176                 goto end;
 177         }
 178 
 179         isakmp = (struct isakmp *)msg->v;
 180         gen = (struct isakmp_gen *)((caddr_t)isakmp + sizeof(struct isakmp));
 181         np = gen->np;
 182 
 183         if (encrypted) {
 184                 if (isakmp->np != ISAKMP_NPTYPE_HASH) {
 185                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
 186                             "ignore information because the "
 187                             "message has no hash payload.\n");
 188                         goto end;
 189                 }
 190 
 191                 if (iph1->status != PHASE1ST_ESTABLISHED) {
 192                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
 193                             "ignore information because ISAKMP-SA "
 194                             "has not been established yet.\n");
 195                         goto end;
 196                 }
 197                 
 198                 /* Safety check */
 199                 if (msg->l < sizeof(*isakmp) + get_uint16(&gen->len) + sizeof(*nd)) {
 200                         plog(PLOG_PROTOERR, PLOGLOC, NULL, 
 201                                 "ignore information because the "
 202                                 "message is too short\n");
 203                         goto end;
 204                 }
 205 
 206                 p = (caddr_t) gen + sizeof(struct isakmp_gen);
 207                 nd = (struct isakmp_gen *) ((caddr_t) gen + get_uint16(&gen->len));
 208 
 209                 /* nd length check */
 210                 if (get_uint16(&nd->len) > msg->l - (sizeof(struct isakmp) +
 211                     get_uint16(&gen->len))) {
 212                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
 213                                  "too long payload length (broken message?)\n");
 214                         goto end;
 215                 }
 216 
 217                 if (get_uint16(&nd->len) < sizeof(*nd)) {
 218                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
 219                                 "too short payload length (broken message?)\n");
 220                         goto end;
 221                 }
 222 
 223                 payload = rc_vmalloc(get_uint16(&nd->len));
 224                 if (payload == NULL) {
 225                         plog(PLOG_INTERR, PLOGLOC, NULL,
 226                             "cannot allocate memory\n");
 227                         goto end;
 228                 }
 229 
 230                 memcpy(payload->v, (caddr_t) nd, get_uint16(&nd->len));
 231 
 232                 /* compute HASH */
 233                 hash = oakley_compute_hash1(iph1, isakmp->msgid, payload);
 234                 if (hash == NULL) {
 235                         plog(PLOG_INTERR, PLOGLOC, NULL,
 236                             "cannot compute hash\n");
 237 
 238                         rc_vfree(payload);
 239                         goto end;
 240                 }
 241                 
 242                 if (get_uint16(&gen->len) - sizeof(struct isakmp_gen) != hash->l) {
 243                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
 244                             "ignore information due to hash length mismatch\n");
 245 
 246                         rc_vfree(hash);
 247                         rc_vfree(payload);
 248                         goto end;
 249                 }
 250 
 251                 if (memcmp(p, hash->v, hash->l) != 0) {
 252                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
 253                             "ignore information due to hash mismatch\n");
 254 
 255                         rc_vfree(hash);
 256                         rc_vfree(payload);
 257                         goto end;
 258                 }
 259 
 260                 plog(PLOG_DEBUG, PLOGLOC, NULL, "hash validated.\n");
 261 
 262                 rc_vfree(hash);
 263                 rc_vfree(payload);
 264         } else {
 265                 /* make sure the packet was encrypted after the beginning of phase 1. */
 266                 switch (iph1->etype) {
 267                 case ISAKMP_ETYPE_AGG:
 268                 case ISAKMP_ETYPE_BASE:
 269                 case ISAKMP_ETYPE_IDENT:
 270                         if ((iph1->side == INITIATOR && iph1->status < PHASE1ST_MSG3SENT)
 271                          || (iph1->side == RESPONDER && iph1->status < PHASE1ST_MSG2SENT)) {
 272                                 break;
 273                         }
 274                         /*FALLTHRU*/
 275                 default:
 276                         plog(PLOG_PROTOERR, PLOGLOC, 0,
 277                                 "received %s payload is not encrypted\n",
 278                                 s_isakmp_nptype(isakmp->np));
 279                         goto end;
 280                 }
 281         }
 282 
 283         switch (np) {
 284         case ISAKMP_NPTYPE_N:
 285                 if ( encrypted )
 286                         isakmp_info_recv_n(iph1, msg);
 287                 else 
 288                         plog(PLOG_PROTOWARN, PLOGLOC, 0,
 289                              "received unencrypted Notify payload, ignored\n");
 290                 break;
 291         case ISAKMP_NPTYPE_D:
 292                 if ( encrypted )
 293                         isakmp_info_recv_d(iph1, msg);
 294                 else
 295                         plog(PLOG_PROTOWARN, PLOGLOC, 0,
 296                              "received unencrypted Delete payload, ignored\n");
 297                 break;
 298         case ISAKMP_NPTYPE_NONCE:
 299                 /* XXX to be 6.4.2 ike-01.txt */
 300                 /* XXX IV is to be synchronized. */
 301                 plog(PLOG_PROTOERR, PLOGLOC, 0,
 302                         "ignore Acknowledged Informational\n");
 303                 break;
 304         default:
 305                 /* don't send information, see isakmp_ident_r1() */
 306                 plog(PLOG_PROTOERR, PLOGLOC, 0,
 307                         "reject the packet, "
 308                         "received unexpected payload type %s.\n",
 309                         s_isakmp_nptype(gen->np));
 310                 goto end;
 311         }
 312 
 313     end:
 314         if (msg != NULL)
 315                 rc_vfree(msg);
 316         return 0;
 317 }
 318 
 319 /*
 320  * send Delete payload (for ISAKMP SA) in Informational exchange.
 321  */
 322 int
 323 isakmp_info_send_d1(struct ph1handle *iph1)
 324 {
 325         struct isakmp_pl_d *d;
 326         rc_vchar_t *payload = NULL;
 327         int tlen;
 328         int error = 0;
 329 
 330         if (iph1->status != PHASE2ST_ESTABLISHED)
 331                 return 0;
 332 
 333         /* create delete payload */
 334 
 335         /* send SPIs of inbound SAs. */
 336         /* XXX should send outbound SAs's ? */
 337         tlen = sizeof(*d) + sizeof(isakmp_index_t);
 338         payload = rc_vmalloc(tlen);
 339         if (payload == NULL) {
 340                 plog(PLOG_INTERR, PLOGLOC, NULL, 
 341                         "failed to get buffer for payload.\n");
 342                 return errno;
 343         }
 344 
 345         d = (struct isakmp_pl_d *)payload->v;
 346         d->h.np = ISAKMP_NPTYPE_NONE;
 347         put_uint16(&d->h.len, tlen);
 348         put_uint32(&d->doi, IPSEC_DOI);
 349         d->proto_id = IPSECDOI_PROTO_ISAKMP;
 350         d->spi_size = sizeof(isakmp_index_t);
 351         put_uint16(&d->num_spi, 1);
 352         memcpy(d + 1, &iph1->index, sizeof(isakmp_index_t));
 353 
 354         error = isakmp_info_send_common(iph1, payload,
 355                                         ISAKMP_NPTYPE_D, 0);
 356         rc_vfree(payload);
 357 
 358         return error;
 359 }
 360 
 361 /*
 362  * send Delete payload (for IPsec SA) in Informational exchange, based on
 363  * pfkey msg.  It sends always single SPI.
 364  */
 365 int
 366 isakmp_info_send_d2(struct ph2handle *iph2)
 367 {
 368         struct ph1handle *iph1;
 369         struct saproto *pr;
 370         struct isakmp_pl_d *d;
 371         rc_vchar_t *payload = NULL;
 372         int tlen;
 373         int error = 0;
 374         uint8_t *spi;
 375 
 376         if (iph2->status != PHASE2ST_ESTABLISHED)
 377                 return 0;
 378 
 379         /*
 380          * don't send delete information if there is no phase 1 handler.
 381          * It's nonsensical to negotiate phase 1 to send the information.
 382          */
 383         iph1 = getph1byaddr(iph2->src, iph2->dst); 
 384         if (iph1 == NULL)
 385                 return 0;
 386 
 387         /* create delete payload */
 388         for (pr = iph2->approval->head; pr != NULL; pr = pr->next) {
 389 
 390                 /* send SPIs of inbound SAs. */
 391                 /*
 392                  * XXX should I send outbound SAs's ?
 393                  * I send inbound SAs's SPI only at the moment because I can't
 394                  * decode any more if peer send encoded packet without aware of
 395                  * deletion of SA.  Outbound SAs don't come under the situation.
 396                  */
 397                 tlen = sizeof(*d) + pr->spisize;
 398                 payload = rc_vmalloc(tlen);
 399                 if (payload == NULL) {
 400                         plog(PLOG_INTERR, PLOGLOC, NULL, 
 401                                 "failed to get buffer for payload.\n");
 402                         return errno;
 403                 }
 404 
 405                 d = (struct isakmp_pl_d *)payload->v;
 406                 d->h.np = ISAKMP_NPTYPE_NONE;
 407                 put_uint16(&d->h.len, tlen);
 408                 put_uint32(&d->doi, IPSEC_DOI);
 409                 d->proto_id = pr->proto_id;
 410                 d->spi_size = pr->spisize;
 411                 put_uint16(&d->num_spi, 1);
 412                 /*
 413                  * XXX SPI bits are left-filled, for use with IPComp.
 414                  * we should be switching to variable-length spi field...
 415                  */
 416                 spi = (uint8_t *)&pr->spi;
 417                 spi += sizeof(pr->spi);
 418                 spi -= pr->spisize;
 419                 memcpy(d + 1, spi, pr->spisize);
 420 
 421                 error = isakmp_info_send_common(iph1, payload,
 422                                                 ISAKMP_NPTYPE_D, 0);
 423                 rc_vfree(payload);
 424         }
 425 
 426         return error;
 427 }
 428 
 429 /*
 430  * send Notification payload (for without ISAKMP SA) in Informational exchange
 431  */
 432 int
 433 isakmp_info_send_nx(struct isakmp *isakmp, struct sockaddr *remote, struct sockaddr *local, 
 434                     int type, rc_vchar_t *data)
 435 {
 436         struct ph1handle *iph1 = NULL;
 437         struct rcf_remote *rmconf;
 438         rc_vchar_t *payload = NULL;
 439         int tlen;
 440         int error = -1;
 441         struct isakmp_pl_n *n;
 442         int spisiz = 0;         /* see below */
 443 
 444         /* search appropreate configuration */
 445         rmconf = getrmconf(remote);
 446         if (rmconf == NULL) {
 447                 plog(PLOG_INTERR, PLOGLOC, 0,
 448                         "no configuration found for peer address.\n");
 449                 goto end;
 450         }
 451 
 452         /* add new entry to isakmp status table. */
 453         iph1 = newph1();
 454         if (iph1 == NULL)
 455                 return -1;
 456 
 457         memcpy(&iph1->index.i_ck, &isakmp->i_ck, sizeof(isakmp_cookie_t));
 458         isakmp_newcookie((char *)&iph1->index.r_ck, remote, local);
 459         iph1->status = PHASE1ST_START;
 460         iph1->rmconf = rmconf;
 461         iph1->side = INITIATOR;
 462         iph1->version = isakmp->v;
 463         iph1->flags = 0;
 464         iph1->msgid = 0;     /* XXX */
 465 #ifdef ENABLE_HYBRID
 466         if ((iph1->mode_cfg = isakmp_cfg_mkstate()) == NULL) {
 467                 error = -1;
 468                 goto end;
 469         }
 470 #endif
 471 #ifdef ENABLE_FRAG
 472         iph1->frag = 0;
 473         iph1->frag_chain = NULL;
 474 #endif
 475         iph1->proposal = ikev1_conf_to_isakmpsa(rmconf);
 476 
 477         /* copy remote address */
 478         if (copy_ph1addresses(iph1, rmconf, remote, local) < 0) {
 479                 error = -1;
 480                 goto end;
 481         }
 482 
 483         tlen = sizeof(*n) + spisiz;
 484         if (data)
 485                 tlen += data->l;
 486         payload = rc_vmalloc(tlen);
 487         if (payload == NULL) { 
 488                 plog(PLOG_INTERR, PLOGLOC, NULL,
 489                         "failed to get buffer to send.\n");
 490                 error = -1;
 491                 goto end;
 492         }
 493 
 494         n = (struct isakmp_pl_n *)payload->v;
 495         n->h.np = ISAKMP_NPTYPE_NONE;
 496         put_uint16(&n->h.len, tlen);
 497         put_uint32(&n->doi, IPSEC_DOI);
 498         n->proto_id = IPSECDOI_KEY_IKE;
 499         n->spi_size = spisiz;
 500         put_uint16(&n->type, type);
 501         if (spisiz)
 502                 memset(n + 1, 0, spisiz);       /*XXX*/
 503         if (data)
 504                 memcpy((caddr_t)(n + 1) + spisiz, data->v, data->l);
 505 
 506         error = isakmp_info_send_common(iph1, payload, ISAKMP_NPTYPE_N, 0);
 507         rc_vfree(payload);
 508 
 509     end:
 510         if (iph1 != NULL)
 511                 delph1(iph1);
 512 
 513         return error;
 514 }
 515 
 516 /*
 517  * send Notification payload (for ISAKMP SA) in Informational exchange
 518  */
 519 int
 520 isakmp_info_send_n1(struct ph1handle *iph1, int type, rc_vchar_t *data)
 521 {
 522         rc_vchar_t *payload = NULL;
 523         int tlen;
 524         int error = 0;
 525         struct isakmp_pl_n *n;
 526         int spisiz;
 527 
 528         /*
 529          * note on SPI size: which description is correct?  I have chosen
 530          * this to be 0.
 531          *
 532          * RFC2408 3.1, 2nd paragraph says: ISAKMP SA is identified by
 533          * Initiator/Responder cookie and SPI has no meaning, SPI size = 0.
 534          * RFC2408 3.1, first paragraph on page 40: ISAKMP SA is identified
 535          * by cookie and SPI has no meaning, 0 <= SPI size <= 16.
 536          * RFC2407 4.6.3.3, INITIAL-CONTACT is required to set to 16.
 537          */
 538         if (type == ISAKMP_NTYPE_INITIAL_CONTACT)
 539                 spisiz = sizeof(isakmp_index_t);
 540         else
 541                 spisiz = 0;
 542 
 543         tlen = sizeof(*n) + spisiz;
 544         if (data)
 545                 tlen += data->l;
 546         payload = rc_vmalloc(tlen);
 547         if (payload == NULL) { 
 548                 plog(PLOG_INTERR, PLOGLOC, NULL,
 549                         "failed to get buffer to send.\n");
 550                 return errno;
 551         }
 552 
 553         n = (struct isakmp_pl_n *)payload->v;
 554         n->h.np = ISAKMP_NPTYPE_NONE;
 555         put_uint16(&n->h.len, tlen);
 556         put_uint32(&n->doi, ikev1_doitype(iph1->rmconf));
 557         n->proto_id = IPSECDOI_PROTO_ISAKMP; /* XXX to be configurable ? */
 558         n->spi_size = spisiz;
 559         put_uint16(&n->type, type);
 560         if (spisiz)
 561                 memcpy(n + 1, &iph1->index, sizeof(isakmp_index_t));
 562         if (data)
 563                 memcpy((caddr_t)(n + 1) + spisiz, data->v, data->l);
 564 
 565         error = isakmp_info_send_common(iph1, payload, ISAKMP_NPTYPE_N, iph1->flags);
 566         rc_vfree(payload);
 567 
 568         return error;
 569 }
 570 
 571 /*
 572  * send Notification payload (for IPsec SA) in Informational exchange
 573  */
 574 int
 575 isakmp_info_send_n2(struct ph2handle *iph2, int type, rc_vchar_t *data)
 576 {
 577         struct ph1handle *iph1 = iph2->ph1;
 578         rc_vchar_t *payload = NULL;
 579         int tlen;
 580         int error = 0;
 581         struct isakmp_pl_n *n;
 582         struct saproto *pr;
 583 
 584         if (!iph2->approval)
 585                 return EINVAL;
 586 
 587         pr = iph2->approval->head;
 588 
 589         /* XXX must be get proper spi */
 590         tlen = sizeof(*n) + pr->spisize;
 591         if (data)
 592                 tlen += data->l;
 593         payload = rc_vmalloc(tlen);
 594         if (payload == NULL) { 
 595                 plog(PLOG_INTERR, PLOGLOC, NULL,
 596                         "failed to get buffer to send.\n");
 597                 return errno;
 598         }
 599 
 600         n = (struct isakmp_pl_n *)payload->v;
 601         n->h.np = ISAKMP_NPTYPE_NONE;
 602         put_uint16(&n->h.len, tlen);
 603         put_uint32(&n->doi, IPSEC_DOI);          /* IPSEC DOI (1) */
 604         n->proto_id = pr->proto_id;               /* IPSEC AH/ESP/whatever*/
 605         n->spi_size = pr->spisize;
 606         put_uint16(&n->type, type);
 607         memcpy((uint8_t *)(n + 1), &pr->spi, pr->spisize);
 608         if (data)
 609                 memcpy((caddr_t)(n + 1) + pr->spisize, data->v, data->l);
 610 
 611         iph2->flags |= ISAKMP_FLAG_E;        /* XXX Should we do FLAG_A ? */
 612         error = isakmp_info_send_common(iph1, payload, ISAKMP_NPTYPE_N, iph2->flags);
 613         rc_vfree(payload);
 614 
 615         return error;
 616 }
 617 
 618 /*
 619  * send Information
 620  * When ph1->skeyid_a == NULL, send message without encoding.
 621  */
 622 int
 623 isakmp_info_send_common(struct ph1handle *iph1, rc_vchar_t *payload, uint32_t np, int flags)
 624 {
 625         struct ph2handle *iph2 = NULL;
 626         rc_vchar_t *hash = NULL;
 627         struct isakmp *isakmp;
 628         struct isakmp_gen *gen;
 629         char *p;
 630         int tlen;
 631         int error = -1;
 632 
 633         /* add new entry to isakmp status table */
 634         iph2 = newph2();
 635         if (iph2 == NULL)
 636                 goto end;
 637 
 638         iph2->dst = rcs_sadup(iph1->remote);
 639         if (iph2->dst == NULL) {
 640                 delph2(iph2);
 641                 goto end;
 642         }
 643 
 644         iph2->src = rcs_sadup(iph1->local);
 645         if (iph2->src == NULL) {
 646                 delph2(iph2);
 647                 goto end;
 648         }
 649 
 650         iph2->ph1 = iph1;
 651         iph2->side = INITIATOR;
 652         iph2->status = PHASE2ST_START;
 653         iph2->msgid = isakmp_newmsgid2(iph1);
 654 
 655         /* get IV and HASH(1) if skeyid_a was generated. */
 656         if (iph1->skeyid_a != NULL) {
 657                 iph2->ivm = oakley_newiv2(iph1, iph2->msgid);
 658                 if (iph2->ivm == NULL) {
 659                         delph2(iph2);
 660                         goto end;
 661                 }
 662 
 663                 /* generate HASH(1) */
 664                 hash = oakley_compute_hash1(iph2->ph1, iph2->msgid, payload);
 665                 if (hash == NULL) {
 666                         delph2(iph2);
 667                         goto end;
 668                 }
 669 
 670                 /* initialized total buffer length */
 671                 tlen = hash->l;
 672                 tlen += sizeof(*gen);
 673         } else {
 674                 /* IKE-SA is not established */
 675                 hash = NULL;
 676 
 677                 /* initialized total buffer length */
 678                 tlen = 0;
 679         }
 680         if ((flags & ISAKMP_FLAG_A) == 0)
 681                 iph2->flags = (hash == NULL ? 0 : ISAKMP_FLAG_E);
 682         else
 683                 iph2->flags = (hash == NULL ? 0 : ISAKMP_FLAG_A);
 684 
 685         insph2(iph2);
 686         bindph12(iph1, iph2);
 687 
 688         tlen += sizeof(*isakmp) + payload->l;
 689 
 690         /* create buffer for isakmp payload */
 691         iph2->sendbuf = rc_vmalloc(tlen);
 692         if (iph2->sendbuf == NULL) { 
 693                 plog(PLOG_INTERR, PLOGLOC, NULL,
 694                         "failed to get buffer to send.\n");
 695                 goto err;
 696         }
 697 
 698         /* create isakmp header */
 699         isakmp = (struct isakmp *)iph2->sendbuf->v;
 700         memcpy(&isakmp->i_ck, &iph1->index.i_ck, sizeof(isakmp_cookie_t));
 701         memcpy(&isakmp->r_ck, &iph1->index.r_ck, sizeof(isakmp_cookie_t));
 702         isakmp->np = hash == NULL ? (np & 0xff) : ISAKMP_NPTYPE_HASH;
 703         isakmp->v = iph1->version;
 704         isakmp->etype = ISAKMP_ETYPE_INFO;
 705         isakmp->flags = iph2->flags;
 706         memcpy(&isakmp->msgid, &iph2->msgid, sizeof(isakmp->msgid));
 707         put_uint32(&isakmp->len, tlen);
 708         p = (char *)(isakmp + 1);
 709 
 710         /* create HASH payload */
 711         if (hash != NULL) {
 712                 gen = (struct isakmp_gen *)p;
 713                 gen->np = np & 0xff;
 714                 put_uint16(&gen->len, sizeof(*gen) + hash->l);
 715                 p += sizeof(*gen);
 716                 memcpy(p, hash->v, hash->l);
 717                 p += hash->l;
 718         }
 719 
 720         /* add payload */
 721         memcpy(p, payload->v, payload->l);
 722         p += payload->l;
 723 
 724 #ifdef HAVE_PRINT_ISAKMP_C
 725         isakmp_printpacket(iph2->sendbuf, iph1->local, iph1->remote, 1);
 726 #endif
 727 
 728         /* encoding */
 729         if (ISSET(isakmp->flags, ISAKMP_FLAG_E)) {
 730                 rc_vchar_t *tmp;
 731 
 732                 tmp = oakley_do_encrypt(iph2->ph1, iph2->sendbuf, iph2->ivm->ive,
 733                                 iph2->ivm->iv);
 734                 VPTRINIT(iph2->sendbuf);
 735                 if (tmp == NULL)
 736                         goto err;
 737                 iph2->sendbuf = tmp;
 738         }
 739 
 740         /* HDR*, HASH(1), N */
 741         if (isakmp_send(iph2->ph1, iph2->sendbuf) < 0) {
 742                 VPTRINIT(iph2->sendbuf);
 743                 goto err;
 744         }
 745 
 746         plog(PLOG_DEBUG, PLOGLOC, NULL,
 747                 "sendto Information %s.\n", s_isakmp_nptype(np));
 748 
 749         /*
 750          * don't resend notify message because peer can use Acknowledged
 751          * Informational if peer requires the reply of the notify message.
 752          */
 753 
 754         /* XXX If Acknowledged Informational required, don't delete ph2handle */
 755         error = 0;
 756         VPTRINIT(iph2->sendbuf);
 757         goto err;       /* XXX */
 758 
 759 end:
 760         if (hash)
 761                 rc_vfree(hash);
 762         return error;
 763 
 764 err:
 765         unbindph12(iph2);
 766         remph2(iph2);
 767         delph2(iph2);
 768         goto end;
 769 }
 770 
 771 /*
 772  * add a notify payload to buffer by reallocating buffer.
 773  * If buf == NULL, the function only create a notify payload.
 774  *
 775  * XXX Which is SPI to be included, inbound or outbound ?
 776  */
 777 rc_vchar_t *
 778 isakmp_add_pl_n(rc_vchar_t *buf0, uint8_t **np_p, int type, 
 779                 struct saproto *pr, rc_vchar_t *data)
 780 {
 781         rc_vchar_t *buf = NULL;
 782         struct isakmp_pl_n *n;
 783         int tlen;
 784         int oldlen = 0;
 785 
 786         if (*np_p)
 787                 **np_p = ISAKMP_NPTYPE_N;
 788 
 789         tlen = sizeof(*n) + pr->spisize;
 790 
 791         if (data)
 792                 tlen += data->l;
 793         if (buf0) {
 794                 oldlen = buf0->l;
 795                 buf = rc_vrealloc(buf0, buf0->l + tlen);
 796         } else
 797                 buf = rc_vmalloc(tlen);
 798         if (!buf) {
 799                 plog(PLOG_INTERR, PLOGLOC, NULL,
 800                         "failed to get a payload buffer.\n");
 801                 return NULL;
 802         }
 803 
 804         n = (struct isakmp_pl_n *)(buf->v + oldlen);
 805         n->h.np = ISAKMP_NPTYPE_NONE;
 806         put_uint16(&n->h.len, tlen);
 807         put_uint32(&n->doi, IPSEC_DOI);          /* IPSEC DOI (1) */
 808         n->proto_id = pr->proto_id;               /* IPSEC AH/ESP/whatever*/
 809         n->spi_size = pr->spisize;
 810         put_uint16(&n->type, type);
 811         memcpy((uint8_t *)(n + 1), &pr->spi, pr->spisize);
 812         if (data)
 813                 memcpy((caddr_t)(n + 1) + pr->spisize, data->v, data->l);
 814 
 815         /* save the pointer of next payload type */
 816         *np_p = &n->h.np;
 817 
 818         return buf;
 819 }
 820 
 821 /*
 822  * handling to receive Notification payload
 823  */
 824 static int
 825 isakmp_info_recv_n(struct ph1handle *iph1, rc_vchar_t *msg)
 826 {
 827         struct isakmp_pl_n *n = NULL;
 828         unsigned int type;
 829         rc_vchar_t *pbuf;
 830         struct isakmp_parse_t *pa, *pap;
 831         char *spi;
 832 
 833         if (!(pbuf = isakmp_parse(msg)))
 834                 return -1;
 835         pa = (struct isakmp_parse_t *)pbuf->v;
 836         for (pap = pa; pap->type; pap++) {
 837                 switch (pap->type) {
 838                 case ISAKMP_NPTYPE_HASH:
 839                         /* do something here */
 840                         break;
 841                 case ISAKMP_NPTYPE_NONCE:
 842                         /* send to ack */
 843                         break;
 844                 case ISAKMP_NPTYPE_N:
 845                         n = (struct isakmp_pl_n *)pap->ptr;
 846                         break;
 847                 default:
 848                         rc_vfree(pbuf);
 849                         return -1;
 850                 }
 851         }
 852         rc_vfree(pbuf);
 853         if (!n)
 854                 return -1;
 855 
 856         type = get_uint16(&n->type);
 857 
 858         switch (type) {
 859         case ISAKMP_NTYPE_CONNECTED:
 860         case ISAKMP_NTYPE_RESPONDER_LIFETIME:
 861         case ISAKMP_NTYPE_REPLAY_STATUS:
 862                 /* do something */
 863                 break;
 864         case ISAKMP_NTYPE_INITIAL_CONTACT:
 865                 info_recv_initialcontact(iph1);
 866                 break;
 867         case ISAKMP_NTYPE_R_U_THERE:
 868                 isakmp_info_recv_r_u(iph1, (struct isakmp_pl_ru *)n,
 869                                      ((struct isakmp *)msg->v)->msgid);
 870                 break;
 871         case ISAKMP_NTYPE_R_U_THERE_ACK:
 872                 isakmp_info_recv_r_u_ack(iph1, (struct isakmp_pl_ru *)n,
 873                                          ((struct isakmp *)msg->v)->msgid);
 874                 break;
 875 
 876         default:
 877             {
 878                 uint32_t msgid = ((struct isakmp *)msg->v)->msgid;
 879                 struct ph2handle *iph2;
 880 
 881                 /* XXX there is a potential of dos attack. */
 882                 if (msgid == 0) {
 883                         /* delete ph1 */
 884                         plog(PLOG_PROTOERR, PLOGLOC, 0,
 885                                 "delete phase1 handle.\n");
 886                         return -1;
 887                 } else {
 888                         iph2 = getph2bymsgid(iph1, msgid);
 889                         if (iph2 == NULL) {
 890                                 plog(PLOG_PROTOERR, PLOGLOC, 0,
 891                                     "unknown notify message (%d), "
 892                                     "no phase2 handle found.\n", type);
 893                         } else {
 894                                 /* delete ph2 */
 895                                 unbindph12(iph2);
 896                                 remph2(iph2);
 897                                 delph2(iph2);
 898                         }
 899                 }
 900             }
 901                 break;
 902         }
 903 
 904         /* get spi and allocate */
 905         if (get_uint16(&n->h.len) < sizeof(*n) + n->spi_size) {
 906                 plog(PLOG_PROTOERR, PLOGLOC, 0,
 907                         "invalid spi_size in notification payload.\n");
 908                 return -1;
 909         }
 910         spi = val2str((char *)(n + 1), n->spi_size);
 911 
 912         plog(PLOG_DEBUG, PLOGLOC, 0,
 913                 "notification message %d:%s, "
 914                 "doi=%d proto_id=%d spi=%s(size=%d).\n",
 915                 type, s_isakmp_notify_msg(type),
 916                 get_uint32(&n->doi), n->proto_id, spi, n->spi_size);
 917 
 918         racoon_free(spi);
 919 
 920         return(0);
 921 }
 922 
 923 #if 0
 924 static void
 925 purge_isakmp_spi(proto, spi, n)
 926         int proto;
 927         isakmp_index_t *spi;    /*network byteorder*/
 928         size_t n;
 929 {
 930         struct ph1handle *iph1;
 931         size_t i;
 932 
 933         for (i = 0; i < n; i++) {
 934                 iph1 = getph1byindex(&spi[i]);
 935                 if (!iph1)
 936                         continue;
 937 
 938                 plog(PLOG_INFO, PLOGLOC, NULL,
 939                         "purged ISAKMP-SA proto_id=%s spi=%s.\n",
 940                         s_ipsecdoi_proto(proto),
 941                         isakmp_pindex(&spi[i], 0));
 942 
 943                 if (iph1->sce)
 944                         SCHED_KILL(iph1->sce);
 945                 iph1->status = PHASE1ST_EXPIRED;
 946                 iph1->sce = sched_new(1, isakmp_ph1delete_stub, iph1);
 947         }
 948 }
 949 #endif
 950 
 951 
 952 /*
 953  * delete all phase2 sa relatived to the destination address.
 954  * Don't delete Phase 1 handlers on INITIAL-CONTACT, and don't ignore
 955  * an INITIAL-CONTACT if we have contacted the peer.  This matches the
 956  * Sun IKE behavior, and makes rekeying work much better when the peer
 957  * restarts.
 958  */
 959 static void
 960 info_recv_initialcontact(struct ph1handle *iph1)
 961 {
 962         plog(PLOG_INFO, PLOGLOC, 0,
 963              "INITIALCONTACT processing unimplemented");
 964 
 965 #ifdef notyet
 966         struct ph2handle *ph2;
 967         struct ph2handle *next_ph2;
 968         struct saprop *pp;
 969         struct saproto *pr;
 970 
 971         plog(PLOG_INFO, PLOGLOC, 0,
 972              "processing INITIALCONTACT for %s->%s\n",
 973              rcs_sa2str(iph1->local), rcs_sa2str(iph1->remote));
 974 
 975         for (ph2 = LIST_FIRST(&ph2tree); ph2; ph2 = next_ph2) {
 976                 next_ph2 = LIST_NEXT(ph2, chain);
 977 
 978 #ifdef ENABLE_NATT
 979                 /* 
 980                  * XXX RFC 3947 says that whe MUST NOT use IP+port to find old SAs
 981                  * from this peer !
 982                  */
 983                 if(iph1->natt_flags & NAT_DETECTED){
 984                         if (CMPSADDR(iph1->local, ph2->src) == 0 &&
 985                                 CMPSADDR(iph1->remote, ph2->dst) == 0)
 986                                 ;
 987                         else if (CMPSADDR(iph1->remote, ph2->src) == 0 &&
 988                                          CMPSADDR(iph1->local, ph2->dst) == 0)
 989                                 ;
 990                         else
 991                                 continue;
 992                 } else
 993 #endif
 994                 /* If there is no NAT-T, we don't have to check addr + port...
 995                  * XXX what about a configuration with a remote peers which is not
 996                  * NATed, but which NATs some other peers ?
 997                  * Here, the INITIAl-CONTACT would also flush all those NATed peers !!
 998                  */
 999                 if (rcs_cmpsa_wop(iph1->local, ph2->src) == 0 &&
1000                     rcs_cmpsa_wop(iph1->remote, ph2->dst) == 0)
1001                         ;
1002                 else if (rcs_cmpsa_wop(iph1->remote, ph2->src) == 0 &&
1003                     rcs_cmpsa_wop(iph1->local, ph2->dst) == 0)
1004                         ;
1005                 else
1006                         continue;
1007 
1008                 pp = ph2->approval;
1009                 if (! pp) {
1010                         TRACE((PLOGLOC, "no negotiated protocols, skipping\n"));
1011                         continue;
1012                 }
1013 
1014                 for (pr = pp->head; pr; pr = pr->next) {
1015                         plog(PLOG_INFO, PLOGLOC, NULL,
1016                              "purging proto=%d spi=%lu outbound.\n",
1017                              pr->proto_id, ntohl(pr->spi_p));
1018                         delete_ipsec_sa(&ph2->sadb_request,
1019                                         ph2->src, ph2->dst,
1020                                         pr->proto_id, pr->spi_p);
1021                         plog(PLOG_INFO, PLOGLOC, NULL,
1022                              "purging proto=%d spi=%lu inbound.\n",
1023                              pr->proto_id, ntohl(pr->spi));
1024                         delete_ipsec_sa(&ph2->sadb_request,
1025                                         ph2->dst, ph2->src,
1026                                         pr->proto_id, pr->spi);
1027                 }
1028 
1029                 destroy_ph2(ph2);
1030         }
1031 #endif
1032 }
1033 
1034 /*
1035  * handling to receive Deletion payload
1036  */
1037 static int
1038 isakmp_info_recv_d(struct ph1handle *iph1, rc_vchar_t *msg)
1039 {
1040         struct isakmp_pl_d *d;
1041         int tlen, num_spi;
1042         rc_vchar_t *pbuf;
1043         struct isakmp_parse_t *pa, *pap;
1044         int protected = 0;
1045         union {
1046                 uint32_t spi32;
1047                 uint16_t spi16[2];
1048         } spi;
1049 
1050         /* validate the type of next payload */
1051         if (!(pbuf = isakmp_parse(msg)))
1052                 return -1;
1053         pa = (struct isakmp_parse_t *)pbuf->v;
1054         for (pap = pa; pap->type; pap++) {
1055                 switch (pap->type) {
1056                 case ISAKMP_NPTYPE_D:
1057                         break;
1058                 case ISAKMP_NPTYPE_HASH:
1059                         if (pap == pa) {
1060                                 protected++;
1061                                 break;
1062                         }
1063                         plog(PLOG_PROTOERR, PLOGLOC, 0,
1064                                 "received next payload type %d "
1065                                 "in wrong place (must be the first payload).\n",
1066                                 pap->type);
1067                         rc_vfree(pbuf);
1068                         return -1;
1069                 default:
1070                         /* don't send information, see isakmp_ident_r1() */
1071                         plog(PLOG_PROTOERR, PLOGLOC, 0,
1072                                 "reject the packet, "
1073                                 "received unexpecting payload type %d.\n",
1074                                 pap->type);
1075                         rc_vfree(pbuf);
1076                         return 0;
1077                 }
1078         }
1079 
1080         if (!protected) {
1081                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1082                         "delete payload is not proteted, "
1083                         "ignored.\n");
1084                 rc_vfree(pbuf);
1085                 return -1;
1086         }
1087 
1088         /* process a delete payload */
1089         for (pap = pa; pap->type; pap++) {
1090                 if (pap->type != ISAKMP_NPTYPE_D)
1091                         continue;
1092 
1093                 d = (struct isakmp_pl_d *)pap->ptr;
1094 
1095                 if (get_uint32(&d->doi) != IPSEC_DOI) {
1096                         plog(PLOG_PROTOERR, PLOGLOC, 0,
1097                                 "delete payload with invalid doi:%d.\n",
1098                                 get_uint32(&d->doi));
1099 #ifdef ENABLE_HYBRID
1100                         /*
1101                          * At deconnexion time, Cisco VPN client does this
1102                          * with a zero DOI. Don't give up in that situation.
1103                          */
1104                         if (((iph1->mode_cfg->flags &
1105                             ISAKMP_CFG_VENDORID_UNITY) == 0) || (d->doi != 0))
1106                                 continue;
1107 #else
1108                         continue;
1109  #endif
1110  }
1111  
1112                 num_spi = get_uint16(&d->num_spi);
1113                 tlen = get_uint16(&d->h.len) - sizeof(struct isakmp_pl_d);
1114 
1115                 if (tlen != num_spi * d->spi_size) {
1116                         plog(PLOG_PROTOERR, PLOGLOC, 0,
1117                                 "deletion payload with invalid length.\n");
1118                         rc_vfree(pbuf);
1119                         return -1;
1120                 }
1121 
1122                 switch (d->proto_id) {
1123                 case IPSECDOI_PROTO_ISAKMP:
1124                         if (d->spi_size != sizeof(isakmp_index_t)) {
1125                                 plog(PLOG_PROTOERR, PLOGLOC, 0,
1126                                         "delete payload with strange spi "
1127                                         "size %d(proto_id:%d)\n",
1128                                         d->spi_size, d->proto_id);
1129                                 continue;
1130                         }
1131 
1132                         if (iph1->scr)
1133                                 SCHED_KILL(iph1->scr);
1134 
1135                         purge_remote(iph1);
1136                         break;
1137 
1138                 case IPSECDOI_PROTO_IPSEC_AH:
1139                 case IPSECDOI_PROTO_IPSEC_ESP:
1140                         if (d->spi_size != sizeof(uint32_t)) {
1141                                 plog(PLOG_PROTOERR, PLOGLOC, 0,
1142                                         "delete payload with strange spi "
1143                                         "size %d(proto_id:%d)\n",
1144                                         d->spi_size, d->proto_id);
1145                                 continue;
1146                         }
1147                         EVT_PUSH(iph1->local, iph1->remote, 
1148                             EVTT_PEER_DELETE, NULL);
1149                         purge_ipsec_spi(iph1, iph1->remote, d->proto_id,
1150                             (uint32_t *)(d + 1), num_spi);
1151                         break;
1152 
1153                 case IPSECDOI_PROTO_IPCOMP:
1154                         /* need to handle both 16bit/32bit SPI */
1155                         memset(&spi, 0, sizeof(spi));
1156                         if (d->spi_size == sizeof(spi.spi16[1])) {
1157                                 memcpy(&spi.spi16[1], d + 1,
1158                                     sizeof(spi.spi16[1]));
1159                         } else if (d->spi_size == sizeof(spi.spi32))
1160                                 memcpy(&spi.spi32, d + 1, sizeof(spi.spi32));
1161                         else {
1162                                 plog(PLOG_PROTOERR, PLOGLOC, 0,
1163                                         "delete payload with strange spi "
1164                                         "size %d(proto_id:%d)\n",
1165                                         d->spi_size, d->proto_id);
1166                                 continue;
1167                         }
1168                         purge_ipsec_spi(iph1, iph1->remote, d->proto_id,
1169                             &spi.spi32, num_spi);
1170                         break;
1171 
1172                 default:
1173                         plog(PLOG_PROTOERR, PLOGLOC, 0,
1174                                 "deletion message received, "
1175                                 "invalid proto_id: %d\n",
1176                                 d->proto_id);
1177                         continue;
1178                 }
1179 
1180                 plog(PLOG_DEBUG, PLOGLOC, NULL, "purged SAs.\n");
1181         }
1182 
1183         rc_vfree(pbuf);
1184 
1185         return 0;
1186 }
1187 
1188 void
1189 isakmp_check_notify(struct isakmp_gen *gen,             /* points to Notify payload */
1190                     struct ph1handle *iph1)
1191 {
1192         struct isakmp_pl_n *notify = (struct isakmp_pl_n *)gen;
1193 
1194         plog(PLOG_DEBUG, PLOGLOC, 0,
1195                 "Notify Message received\n");
1196 
1197         switch (get_uint16(&notify->type)) {
1198         case ISAKMP_NTYPE_CONNECTED:
1199         case ISAKMP_NTYPE_RESPONDER_LIFETIME:
1200         case ISAKMP_NTYPE_REPLAY_STATUS:
1201         case ISAKMP_NTYPE_HEARTBEAT:
1202 #ifdef ENABLE_HYBRID
1203         case ISAKMP_NTYPE_UNITY_HEARTBEAT:
1204 #endif
1205                 plog(PLOG_PROTOWARN, PLOGLOC, 0,
1206                         "ignore %s notification.\n",
1207                         s_isakmp_notify_msg(get_uint16(&notify->type)));
1208                 break;
1209         case ISAKMP_NTYPE_INITIAL_CONTACT:
1210                 plog(PLOG_PROTOWARN, PLOGLOC, 0,
1211                         "ignore INITIAL-CONTACT notification, "
1212                         "because it is only accepted after phase1.\n");
1213                 break;
1214         default:
1215                 isakmp_info_send_n1(iph1, ISAKMP_NTYPE_INVALID_PAYLOAD_TYPE, NULL);
1216                 plog(PLOG_PROTOERR, PLOGLOC, 0,
1217                         "received unknown notification type %s.\n",
1218                         s_isakmp_notify_msg(get_uint16(&notify->type)));
1219         }
1220 
1221         return;
1222 }
1223 
1224 
1225 static int
1226 isakmp_info_recv_r_u (struct ph1handle *iph1, struct isakmp_pl_ru *ru, uint32_t msgid)
1227 {
1228         struct isakmp_pl_ru *ru_ack;
1229         rc_vchar_t *payload = NULL;
1230         int tlen;
1231         int error = 0;
1232 
1233         plog(PLOG_DEBUG, PLOGLOC, 0,
1234                  "DPD R-U-There received\n");
1235 
1236         /* XXX should compare cookies with iph1->index?
1237            Or is this already done by calling function?  */
1238         tlen = sizeof(*ru_ack);
1239         payload = rc_vmalloc(tlen);
1240         if (payload == NULL) { 
1241                 plog(PLOG_INTERR, PLOGLOC, NULL,
1242                         "failed to get buffer to send.\n");
1243                 return errno;
1244         }
1245 
1246         ru_ack = (struct isakmp_pl_ru *)payload->v;
1247         ru_ack->h.np = ISAKMP_NPTYPE_NONE;
1248         put_uint16(&ru_ack->h.len, tlen);
1249         put_uint32(&ru_ack->doi, IPSEC_DOI);
1250         put_uint16(&ru_ack->type, ISAKMP_NTYPE_R_U_THERE_ACK);
1251         ru_ack->proto_id = IPSECDOI_PROTO_ISAKMP; /* XXX ? */
1252         ru_ack->spi_size = sizeof(isakmp_index_t);
1253         memcpy(ru_ack->i_ck, ru->i_ck, sizeof(isakmp_cookie_t));
1254         memcpy(ru_ack->r_ck, ru->r_ck, sizeof(isakmp_cookie_t));  
1255         ru_ack->data = ru->data;
1256 
1257         /* XXX Should we do FLAG_A ?  */
1258         error = isakmp_info_send_common(iph1, payload, ISAKMP_NPTYPE_N,
1259                                         ISAKMP_FLAG_E);
1260         rc_vfree(payload);
1261 
1262         plog(PLOG_DEBUG, PLOGLOC, NULL, "received a valid R-U-THERE, ACK sent\n");
1263 
1264         /* Should we mark tunnel as active ? */
1265         return error;
1266 }
1267 
1268 static int
1269 isakmp_info_recv_r_u_ack (struct ph1handle *iph1, 
1270                           struct isakmp_pl_ru *ru, uint32_t msgid)
1271 {
1272 
1273         plog(PLOG_DEBUG, PLOGLOC, 0,
1274                  "DPD R-U-There-Ack received\n");
1275 
1276         /* XXX Maintain window of acceptable sequence numbers ?
1277          * => ru->data <= iph2->dpd_seq &&
1278          *    ru->data >= iph2->dpd_seq - iph2->dpd_fails ? */
1279         if (get_uint32(&ru->data) != iph1->dpd_seq-1) {
1280                 plog(PLOG_PROTOERR, PLOGLOC, 0,
1281                          "Wrong DPD sequence number (%d, %d expected).\n", 
1282                          get_uint32(&ru->data), iph1->dpd_seq-1);
1283                 return 0;
1284         }
1285 
1286         if (memcmp(ru->i_ck, iph1->index.i_ck, sizeof(isakmp_cookie_t)) ||
1287             memcmp(ru->r_ck, iph1->index.r_ck, sizeof(isakmp_cookie_t))) {
1288                 plog(PLOG_PROTOERR, PLOGLOC, 0,
1289                          "Cookie mismatch in DPD ACK!.\n");
1290                 return 0;
1291         }
1292 
1293         iph1->dpd_fails = 0;
1294 
1295         /* Useless ??? */
1296         iph1->dpd_lastack = time(NULL);
1297         plog(PLOG_DEBUG, PLOGLOC, NULL, "received an R-U-THERE-ACK\n");
1298 
1299         return 0;
1300 }
1301 
1302 
1303 
1304 
1305 /*
1306  * send Delete payload (for ISAKMP SA) in Informational exchange.
1307  */
1308 static void
1309 isakmp_info_send_r_u(void *arg)
1310 {
1311         struct ph2handle *iph2 = arg;
1312         struct ph1handle *iph1;
1313 
1314         /* create R-U-THERE payload */
1315         struct isakmp_pl_ru *ru;
1316         rc_vchar_t *payload = NULL;
1317         int tlen;
1318         int error = 0;
1319 
1320         plog(PLOG_DEBUG, PLOGLOC, 0, "DPD monitoring....\n");
1321 
1322         iph1 = getph1byaddr(iph2->src, iph2->dst);
1323         if (!iph1) {
1324                 plog(PLOG_DEBUG, PLOGLOC, 0, "can't find iph1\n");
1325                 return;
1326         }
1327         SCHED_KILL(iph1->dpd_r_u);
1328 
1329         if (iph1->dpd_fails >= ikev1_dpd_maxfails(iph1->rmconf)) {
1330                 EVT_PUSH(iph1->local, iph1->remote, EVTT_DPD_TIMEOUT, NULL);
1331                 purge_remote(iph1);
1332                 plog(PLOG_DEBUG, PLOGLOC, 0,
1333                          "DPD: remote seems to be dead\n");
1334 
1335                 /* Do not reschedule here: phase1 is deleted,
1336                  * DPD will be reactivated when a new ph1 will be negociated
1337                  */
1338                 return;
1339         }
1340 
1341         /* Check recent activity to avoid useless sends... */
1342         if (iph2->status != PHASE2ST_ESTABLISHED)
1343                 return;
1344 
1345         /* 
1346          * DPD is necessary only when peer is idle AND
1347          * self has packets to send
1348          */
1349         if (iph2->prev_peercount != iph2->cur_peercount ||
1350             iph2->prev_selfcount == iph2->cur_selfcount) {
1351                 isakmp_sched_r_u(iph2, 0);
1352                 return;
1353         }
1354 
1355         /* XXX: why do we have a NULL LIST_FIRST even when a Phase2 exists ??? */
1356 #if 0
1357         if (LIST_FIRST(&iph1->ph2tree) == NULL){
1358                 /* XXX: No Ph2 => no need to test ph1 ?
1359                  */
1360                 /* Reschedule the r_u_there....
1361                    XXX: reschedule when a new ph2 ?
1362                  */
1363                 isakmp_sched_r_u(iph2, 0);
1364                 plog(PLOG_DEBUG, PLOGLOC, 0,
1365                          "no phase2 handler, rescheduling send_r_u (%d).\n", iph1->rmconf->dpd_interval);
1366                 return 0;
1367         }
1368 #endif
1369 
1370         tlen = sizeof(*ru);
1371         payload = rc_vmalloc(tlen);
1372         if (payload == NULL) {
1373                 plog(PLOG_INTERR, PLOGLOC, NULL, 
1374                          "failed to get buffer for payload.\n");
1375                 return;
1376         }
1377         ru = (struct isakmp_pl_ru *)payload->v;
1378         ru->h.np = ISAKMP_NPTYPE_NONE;
1379         put_uint16(&ru->h.len, tlen);
1380         put_uint32(&ru->doi, IPSEC_DOI);
1381         put_uint16(&ru->type, ISAKMP_NTYPE_R_U_THERE);
1382         ru->proto_id = IPSECDOI_PROTO_ISAKMP; /* XXX ?*/
1383         ru->spi_size = sizeof(isakmp_index_t);
1384 
1385         memcpy(ru->i_ck, iph1->index.i_ck, sizeof(isakmp_cookie_t));
1386         memcpy(ru->r_ck, iph1->index.r_ck, sizeof(isakmp_cookie_t));
1387 
1388         if (iph1->dpd_seq == 0){
1389                 /* generate a random seq which is not too big */
1390                 iph1->dpd_seq = eay_random_uint32() & 0x0fff;
1391         }
1392 
1393         put_uint32(&ru->data, iph1->dpd_seq);
1394 
1395         error = isakmp_info_send_common(iph1, payload, ISAKMP_NPTYPE_N, 0);
1396         rc_vfree(payload);
1397 
1398         plog(PLOG_DEBUG, PLOGLOC, 0,
1399                  "DPD R-U-There sent (%d)\n", error);
1400 
1401         /* will be decreased if ACK received... */
1402         iph1->dpd_fails++;
1403 
1404         /* XXX should be increased only when ACKed ? */
1405         iph1->dpd_seq++;
1406 
1407         /* Reschedule the r_u_there with a short delay,
1408          * will be deleted/rescheduled if ACK received before */
1409         if (iph1->dpd_lastack < time(NULL) - ikev1_dpd_interval(iph1->rmconf)) {
1410                 isakmp_sched_r_u(iph2, 1);
1411         } else {
1412                 isakmp_sched_r_u(iph2, 0);
1413         }
1414 
1415         plog(PLOG_DEBUG, PLOGLOC, 0,
1416              "rescheduling send_r_u (%d).\n", ikev1_dpd_retry(iph1->rmconf));
1417 }
1418 
1419 /* Schedule a new R-U-THERE */
1420 int
1421 isakmp_sched_r_u(struct ph2handle *iph2, int retry)
1422 {
1423         struct ph1handle *iph1;
1424 
1425         if(iph2 == NULL)
1426                 return 1;
1427         iph1 = getph1byaddr(iph2->src, iph2->dst);
1428         if (!iph1 || !iph1->rmconf)
1429                 return 1;
1430 
1431         if (iph2->status != PHASE2ST_ESTABLISHED) {
1432                 return 0;
1433         }
1434 
1435         if(iph1->dpd_support == 0 ||
1436            ikev1_dpd_interval(iph1->rmconf) == 0)
1437                 return 0;
1438 
1439         pk_sendget(iph2, 0);
1440         pk_sendget(iph2, 1);
1441 
1442         if(retry)
1443                 iph1->dpd_r_u = sched_new(ikev1_dpd_retry(iph1->rmconf),
1444                                           isakmp_info_send_r_u, iph2);
1445         else
1446                 sched_new(ikev1_dpd_interval(iph1->rmconf),
1447                           isakmp_info_send_r_u, iph2);
1448 
1449         return 0;
1450 }