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