1 /*      $KAME: isakmp_quick.c,v 1.95 2003/10/21 07:18:03 itojun 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 #ifdef HAVE_CONFIG_H
  33 #  include <config.h>
  34 #endif
  35 
  36 #include <sys/types.h>
  37 #include <sys/param.h>
  38 #include <sys/socket.h>
  39 
  40 #if 0
  41 #include <netkey/key_var.h>
  42 #endif
  43 #include <netinet/in.h>
  44 
  45 #include <stdlib.h>
  46 #include <stdio.h>
  47 #include <string.h>
  48 #include <errno.h>
  49 #if TIME_WITH_SYS_TIME
  50 # include <sys/time.h>
  51 # include <time.h>
  52 #else
  53 # if HAVE_SYS_TIME_H
  54 #  include <sys/time.h>
  55 # else
  56 #  include <time.h>
  57 # endif
  58 #endif
  59 
  60 #ifdef HAVE_NETINET6_IPSEC_H
  61 # include <netinet6/ipsec.h>
  62 #else
  63 # ifdef HAVE_NETIPSEC_IPSEC_H
  64 #  include <netipsec/ipsec.h>
  65 # else
  66 #  ifndef sun   /* XXX KEBE SAYS OpenSolaris */
  67 #    include <linux/ipsec.h>
  68 #  endif
  69 # endif
  70 #endif
  71 
  72 #ifdef sun      /* XXX KEBE SAYS OpenSolaris */
  73 #define IPSEC_ULPROTO_ANY 0
  74 #endif
  75 
  76 #include "racoon.h"
  77 
  78 #include "var.h"
  79 /* #include "vmbuf.h" */
  80 /* #include "schedule.h" */
  81 /* #include "misc.h" */
  82 #include "plog.h"
  83 #include "debug.h"
  84 
  85 /* #include "localconf.h" */
  86 #include "remoteconf.h"
  87 #include "isakmp.h"
  88 #include "isakmp_var.h"
  89 #include "isakmp_impl.h"
  90 #include "ikev1_impl.h"
  91 #include "isakmp_inf.h"
  92 #include "isakmp_quick.h"
  93 #include "oakley.h"
  94 #include "handler.h"
  95 #include "ipsec_doi.h"
  96 #include "crypto_impl.h"
  97 #include "pfkey.h"
  98 /* #include "policy.h" */
  99 #include "algorithm.h"
 100 #include "sockmisc.h"
 101 #include "proposal.h"
 102 /* #include "sainfo.h" */
 103 /* #include "admin.h" */
 104 #include "strnames.h"
 105 
 106 #ifdef sun
 107 #include "ikev1_natt.h"
 108 #define IPSECDOI_PREFIX_HOST 32 /* Hack for port of NAT-OA from ipsec-tools. */
 109 #endif
 110 
 111 #include "ike_conf.h"
 112 
 113 /* quick mode */
 114 static rc_vchar_t *quick_ir1mx (struct ph2handle *, rc_vchar_t *, rc_vchar_t *);
 115 static int get_sainfo_r (struct ph2handle *);
 116 static int get_proposal_r (struct ph2handle *);
 117 #ifdef INET6
 118 static uint32_t setscopeid (struct sockaddr *, struct sockaddr *)
 119         GCC_ATTRIBUTE((unused));
 120 #endif
 121 
 122 /* called from scheduler */
 123 void
 124 pfkey_timeover_stub(p)
 125         void *p;
 126 {
 127         void pfkey_timeover();
 128 
 129         pfkey_timeover((struct ph2handle *)p);
 130 }
 131 
 132 void
 133 pfkey_timeover(struct ph2handle *iph2)
 134 {
 135         plog(PLOG_PROTOERR, PLOGLOC, 0,
 136                 "%s give up to get IPsec-SA due to time up to wait.\n",
 137                 rcs_sa2str_wop(iph2->dst));
 138         SCHED_KILL(iph2->sce);
 139 
 140         /* If initiator side, send error to kernel by SADB_ACQUIRE. */
 141         if (iph2->side == INITIATOR)
 142                 pk_sendeacquire(iph2);
 143 
 144         unbindph12(iph2);
 145         remph2(iph2);
 146         delph2(iph2);
 147 
 148         return;
 149 }
 150 
 151 /* %%%
 152  * Quick Mode
 153  */
 154 /*
 155  * begin Quick Mode as initiator.  send pfkey getspi message to kernel.
 156  */
 157 int
 158 quick_i1prep(struct ph2handle *iph2, rc_vchar_t *msg /* must be null pointer */)
 159 {
 160         int error = ISAKMP_INTERNAL_ERROR;
 161 
 162         /* validity check */
 163         if (iph2->status != PHASE2ST_STATUS2) {
 164                 plog(PLOG_INTERR, PLOGLOC, NULL,
 165                         "status mismatched %d.\n", iph2->status);
 166                 goto end;
 167         }
 168 
 169         iph2->msgid = isakmp_newmsgid2(iph2->ph1);
 170         iph2->ivm = oakley_newiv2(iph2->ph1, iph2->msgid);
 171         if (iph2->ivm == NULL)
 172                 return 0;
 173 
 174         iph2->status = PHASE2ST_GETSPISENT;
 175 
 176 #if 0
 177         /* don't anything if local test mode. */
 178         if (f_local) {
 179                 error = 0;
 180                 goto end;
 181         }
 182 #endif
 183 
 184         /* send getspi message */
 185         if (pk_sendgetspi(iph2) < 0)
 186                 goto end;
 187 
 188         plog(PLOG_DEBUG, PLOGLOC, NULL, "pfkey getspi sent.\n");
 189 
 190         iph2->sce = sched_new(ikev1_ipsec_sa_nego_time_limit(iph2->ph1->rmconf),
 191                 pfkey_timeover_stub, iph2);
 192 
 193         error = 0;
 194 
 195 end:
 196         return error;
 197 }
 198 
 199 /*
 200  * send to responder
 201  *      HDR*, HASH(1), SA, Ni [, KE ] [, IDi2, IDr2 ] [, NAT-OAi, NAT-OAr ]
 202  */
 203 int
 204 quick_i1send(struct ph2handle *iph2, rc_vchar_t *msg /* must be null pointer */)
 205 {
 206         rc_vchar_t *body = NULL;
 207         rc_vchar_t *hash = NULL;
 208         struct isakmp_gen *gen;
 209         char *p;
 210         int tlen;
 211         int error = ISAKMP_INTERNAL_ERROR;
 212         int pfsgroup, idci, idcr;
 213         int np;
 214         struct ipsecdoi_id_b *id, *id_p;
 215 #ifdef sun
 216         int natoa = ISAKMP_NPTYPE_NONE;
 217         rc_vchar_t *nat_oai = NULL;
 218         rc_vchar_t *nat_oar = NULL;
 219 #endif
 220 
 221         /* validity check */
 222         if (msg != NULL) {
 223                 plog(PLOG_INTERR, PLOGLOC, NULL,
 224                         "msg has to be NULL in this function.\n");
 225                 goto end;
 226         }
 227         if (iph2->status != PHASE2ST_GETSPIDONE) {
 228                 plog(PLOG_INTERR, PLOGLOC, NULL,
 229                         "status mismatched %d.\n", iph2->status);
 230                 goto end;
 231         }
 232 
 233         /* create SA payload for my proposal */
 234         if (ipsecdoi_setph2proposal(iph2) < 0)
 235                 goto end;
 236 
 237         /* generate NONCE value */
 238         iph2->nonce = eay_set_random(ikev1_nonce_size(iph2->ph1->rmconf));
 239         if (iph2->nonce == NULL)
 240                 goto end;
 241 
 242         /*
 243          * DH value calculation is kicked out into cfparse.y.
 244          * because pfs group can not be negotiated, it's only to be checked
 245          * acceptable.
 246          */
 247         /* generate KE value if need */
 248         pfsgroup = iph2->proposal->pfs_group;
 249         if (pfsgroup) {
 250                 /* DH group settting if PFS is required. */
 251                 if (oakley_setdhgroup(pfsgroup, &iph2->pfsgrp) < 0) {
 252                         plog(PLOG_INTERR, PLOGLOC, NULL,
 253                                 "failed to set DH value.\n");
 254                         goto end;
 255                 }
 256                 if (oakley_dh_generate(iph2->pfsgrp,
 257                                 &iph2->dhpub, &iph2->dhpriv) < 0) {
 258                         goto end;
 259                 }
 260         }
 261 
 262         /* generate ID value */
 263         if (ipsecdoi_setid2(iph2) < 0) {
 264                 plog(PLOG_INTERR, PLOGLOC, NULL,
 265                         "failed to get ID.\n");
 266                 goto end;
 267         }
 268         plog(PLOG_DEBUG, PLOGLOC, NULL, "IDci:\n");
 269         plogdump(PLOG_DEBUG, PLOGLOC, 0, iph2->id->v, iph2->id->l);
 270         plog(PLOG_DEBUG, PLOGLOC, NULL, "IDcr:");
 271         plogdump(PLOG_DEBUG, PLOGLOC, 0, iph2->id_p->v, iph2->id_p->l);
 272 
 273         /*
 274          * we do not attach IDci nor IDcr, under the following condition:
 275          * - all proposals are transport mode
 276          * - no MIP6 or proxy
 277          * - id payload suggests to encrypt all the traffic (no specific
 278          *   protocol type)
 279          */
 280         id = (struct ipsecdoi_id_b *)iph2->id->v;
 281         id_p = (struct ipsecdoi_id_b *)iph2->id_p->v;
 282         if (id->proto_id == 0
 283          && id_p->proto_id == 0
 284          && id->port == 0
 285          && id_p->port == 0
 286          && iph2->selector->pl != 0
 287          && (iph2->selector->pl->my_sa_ipaddr != 0
 288            || iph2->selector->pl->peers_sa_ipaddr != 0)
 289          && ipsecdoi_transportmode(iph2->proposal)) {
 290                 idci = idcr = 0;
 291         } else
 292                 idci = idcr = 1;
 293 
 294 #ifdef sun
 295         /*
 296          * RFC3947 5.2. if we propose UDP-Encapsulated-Transport
 297          * we should send NAT-OA
 298          *
 299          * XXX KEBE ASKS if we should send it for tunnel mode anyway, like
 300          * we do with in.iked?
 301          */
 302         if (ipsecdoi_transportmode(iph2->proposal)
 303             && (iph2->ph1->natt_flags & NAT_DETECTED)) {
 304                 natoa = iph2->ph1->natt_options->payload_nat_oa;
 305 
 306                 nat_oai = ipsecdoi_sockaddr2id(iph2->src,
 307                     IPSECDOI_PREFIX_HOST, IPSEC_ULPROTO_ANY);
 308                 nat_oar = ipsecdoi_sockaddr2id(iph2->dst,
 309                     IPSECDOI_PREFIX_HOST, IPSEC_ULPROTO_ANY);
 310 
 311                 if (nat_oai == NULL || nat_oar == NULL) {
 312                         plog(PLOG_INTERR, PLOGLOC, NULL,
 313                             "failed to generate NAT-OA payload.\n");
 314                         goto end;
 315                 }
 316 
 317                 plog(PLOG_INFO, PLOGLOC, NULL, "Using NAT-OA.\n");
 318                 plog(PLOG_DEBUG, PLOGLOC, NULL, "NAT-OAi:\n");
 319                 plogdump(PLOG_DEBUG, PLOGLOC, 0, nat_oai->v, nat_oai->l);
 320                 plog(PLOG_DEBUG, PLOGLOC, NULL, "NAT-OAr:\n");
 321                 plogdump(PLOG_DEBUG, PLOGLOC, 0, nat_oar->v, nat_oar->l);
 322         } else {
 323                 plog(PLOG_INFO, PLOGLOC, NULL, "Not using NAT-OA.\n");
 324                 plog(PLOG_INFO, PLOGLOC, NULL, "transportmode == %d, "
 325                     "natt_flags == 0x%x\n",
 326                     ipsecdoi_transportmode(iph2->proposal),
 327                     iph2->ph1->natt_flags & NAT_DETECTED);
 328                 natoa = ISAKMP_NPTYPE_NONE;
 329         }
 330 #endif
 331 
 332         /* create SA;NONCE payload, and KE if need, and IDii, IDir. */
 333         tlen = + sizeof(*gen) + iph2->sa->l
 334                 + sizeof(*gen) + iph2->nonce->l;
 335         if (pfsgroup)
 336                 tlen += (sizeof(*gen) + iph2->dhpub->l);
 337         if (idci)
 338                 tlen += sizeof(*gen) + iph2->id->l;
 339         if (idcr)
 340                 tlen += sizeof(*gen) + iph2->id_p->l;
 341 #ifdef sun
 342         if (natoa != ISAKMP_NPTYPE_NONE)
 343                 tlen += 2 * sizeof(*gen) + nat_oai->l + nat_oar->l;
 344 #endif
 345 
 346         body = rc_vmalloc(tlen);
 347         if (body == NULL) {
 348                 plog(PLOG_INTERR, PLOGLOC, NULL,
 349                         "failed to get buffer to send.\n");
 350                 goto end;
 351         }
 352 
 353         p = body->v;
 354 
 355         /* add SA payload */
 356         p = set_isakmp_payload(p, iph2->sa, ISAKMP_NPTYPE_NONCE);
 357 
 358         /* add NONCE payload */
 359         if (pfsgroup)
 360                 np = ISAKMP_NPTYPE_KE;
 361         else if (idci || idcr)
 362                 np = ISAKMP_NPTYPE_ID;
 363         else
 364                 np = natoa;
 365         p = set_isakmp_payload(p, iph2->nonce, np);
 366 
 367         /* add KE payload if need. */
 368         np = (idci || idcr) ? ISAKMP_NPTYPE_ID : natoa;
 369         if (pfsgroup)
 370                 p = set_isakmp_payload(p, iph2->dhpub, np);
 371 
 372         /* IDci */
 373         np = (idcr) ? ISAKMP_NPTYPE_ID : natoa;
 374         if (idci)
 375                 p = set_isakmp_payload(p, iph2->id, np);
 376 
 377         /* IDcr */
 378         if (idcr)
 379                 p = set_isakmp_payload(p, iph2->id_p, natoa);
 380 
 381 #ifdef sun
 382         /* NAT-OA */
 383         if (natoa != ISAKMP_NPTYPE_NONE) {
 384                 p = set_isakmp_payload(p, nat_oai, natoa);
 385                 p = set_isakmp_payload(p, nat_oar, ISAKMP_NPTYPE_NONE);
 386         }
 387 #endif
 388 
 389         /* generate HASH(1) */
 390         hash = oakley_compute_hash1(iph2->ph1, iph2->msgid, body);
 391         if (hash == NULL)
 392                 goto end;
 393 
 394         /* send isakmp payload */
 395         iph2->sendbuf = quick_ir1mx(iph2, body, hash);
 396         if (iph2->sendbuf == NULL)
 397                 goto end;
 398 
 399         /* send the packet, add to the schedule to resend */
 400         iph2->retry_counter = ikev1_max_retry_to_send(iph2->ph1->rmconf);
 401         if (isakmp_ph2resend(iph2) == -1)
 402                 goto end;
 403 
 404         /* change status of isakmp status entry */
 405         iph2->status = PHASE2ST_MSG1SENT;
 406 
 407         error = 0;
 408 
 409 end:
 410         if (body != NULL)
 411                 rc_vfree(body);
 412         if (hash != NULL)
 413                 rc_vfree(hash);
 414         if (nat_oai != NULL)
 415                 rc_vfree(nat_oai);
 416         if (nat_oar != NULL)
 417                 rc_vfree(nat_oar);
 418 
 419         return error;
 420 }
 421 
 422 /*
 423  * receive from responder
 424  *      HDR*, HASH(2), SA, Nr [, KE ] [, IDi2, IDr2 ] [, NAT-OAi, NAT-OAr ]
 425  */
 426 int
 427 quick_i2recv(struct ph2handle *iph2, rc_vchar_t *msg0)
 428 {
 429         rc_vchar_t *msg = NULL;
 430         rc_vchar_t *hbuf = NULL;        /* for hash computing. */
 431         rc_vchar_t *pbuf = NULL;        /* for payload parsing */
 432         rc_vchar_t *idci = NULL;
 433         rc_vchar_t *idcr = NULL;
 434         struct isakmp_parse_t *pa;
 435         struct isakmp *isakmp = (struct isakmp *)msg0->v;
 436         struct isakmp_pl_hash *hash = NULL;
 437         char *p;
 438         int tlen;
 439         int error = ISAKMP_INTERNAL_ERROR;
 440 
 441         /* validity check */
 442         if (iph2->status != PHASE2ST_MSG1SENT) {
 443                 plog(PLOG_INTERR, PLOGLOC, NULL,
 444                         "status mismatched %d.\n", iph2->status);
 445                 goto end;
 446         }
 447 
 448         /* decrypt packet */
 449         if (!ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E)) {
 450                 isakmp_log(0, 0, iph2->ph1->remote, 0,
 451                            PLOG_PROTOERR, PLOGLOC,
 452                            "Packet wasn't encrypted.\n");
 453                 goto end;
 454         }
 455         msg = oakley_do_decrypt(iph2->ph1, msg0, iph2->ivm->iv, iph2->ivm->ive);
 456         if (msg == NULL)
 457                 goto end;
 458 
 459         /* create buffer for validating HASH(2) */
 460         /*
 461          * ordering rule:
 462          *      1. the first one must be HASH
 463          *      2. the second one must be SA (added in isakmp-oakley-05!)
 464          *      3. two IDs must be considered as IDci, then IDcr
 465          */
 466         pbuf = isakmp_parse(msg);
 467         if (pbuf == NULL)
 468                 goto end;
 469         pa = (struct isakmp_parse_t *)pbuf->v;
 470 
 471         /* HASH payload is fixed postion */
 472         if (pa->type != ISAKMP_NPTYPE_HASH) {
 473                 isakmp_log(0, 0, iph2->ph1->remote, 0,
 474                            PLOG_PROTOERR, PLOGLOC,
 475                            "received invalid next payload type %d, "
 476                            "expecting %d.\n",
 477                            pa->type, ISAKMP_NPTYPE_HASH);
 478                 goto end;
 479         }
 480         hash = (struct isakmp_pl_hash *)pa->ptr;
 481         pa++;
 482 
 483         /*
 484          * this restriction was introduced in isakmp-oakley-05.
 485          * we do not check this for backward compatibility.
 486          * TODO: command line/config file option to enable/disable this code
 487          */
 488         /* HASH payload is fixed postion */
 489         if (pa->type != ISAKMP_NPTYPE_SA) {
 490                 isakmp_log(0, 0, iph2->ph1->remote, 0,
 491                            PLOG_PROTOWARN, PLOGLOC,
 492                            "received invalid next payload type %d, "
 493                            "expecting %d.\n",
 494                            pa->type, ISAKMP_NPTYPE_HASH);
 495         }
 496 
 497         /* allocate buffer for computing HASH(2) */
 498         tlen = iph2->nonce->l
 499                 + get_uint32(&isakmp->len) - sizeof(*isakmp);
 500         hbuf = rc_vmalloc(tlen);
 501         if (hbuf == NULL) {
 502                 plog(PLOG_INTERR, PLOGLOC, NULL,
 503                         "failed to get hash buffer.\n");
 504                 goto end;
 505         }
 506         p = hbuf->v + iph2->nonce->l;  /* retain the space for Ni_b */
 507 
 508         /*
 509          * parse the payloads.
 510          * copy non-HASH payloads into hbuf, so that we can validate HASH.
 511          */
 512         iph2->sa_ret = NULL;
 513         tlen = 0;       /* count payload length except of HASH payload. */
 514         for (; pa->type; pa++) {
 515 
 516                 /* copy to buffer for HASH */
 517                 /* Don't modify the payload */
 518                 memcpy(p, pa->ptr, pa->len);
 519 
 520                 switch (pa->type) {
 521                 case ISAKMP_NPTYPE_SA:
 522                         if (iph2->sa_ret != NULL) {
 523                                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
 524                                         "Ignored, multiple SA "
 525                                         "isn't supported.\n");
 526                                 break;
 527                         }
 528                         if (isakmp_p2ph(&iph2->sa_ret, pa->ptr) < 0)
 529                                 goto end;
 530                         break;
 531 
 532                 case ISAKMP_NPTYPE_NONCE:
 533                         if (isakmp_p2ph(&iph2->nonce_p, pa->ptr) < 0)
 534                                 goto end;
 535                         break;
 536 
 537                 case ISAKMP_NPTYPE_KE:
 538                         if (isakmp_p2ph(&iph2->dhpub_p, pa->ptr) < 0)
 539                                 goto end;
 540                         break;
 541 
 542                 case ISAKMP_NPTYPE_ID:
 543                         if (idci == NULL) {
 544                                 if (isakmp_p2ph(&idci, pa->ptr) < 0)
 545                                         goto end;
 546                         } else if (idcr == NULL) {
 547                                 if (isakmp_p2ph(&idcr, pa->ptr) < 0)
 548                                         goto end;
 549                         } else {
 550                         }
 551                         break;
 552 
 553                 case ISAKMP_NPTYPE_N:
 554                         isakmp_check_notify(pa->ptr, iph2->ph1);
 555                         break;
 556 
 557 #ifdef ENABLE_NATT
 558                 case ISAKMP_NPTYPE_NATOA_DRAFT:
 559                 case ISAKMP_NPTYPE_NATOA_RFC:
 560 #ifdef sun
 561                         /* DON'T ignore original source/destination. */
 562                 {
 563                         struct sockaddr_storage addr;
 564                         struct sockaddr *daddr;
 565                         uint8_t prefix;
 566                         uint16_t ul_proto;
 567                         rc_vchar_t *vp = NULL;
 568 
 569                         if (isakmp_p2ph(&vp, pa->ptr) < 0)
 570                                 goto end;
 571 
 572                         error = ipsecdoi_id2sockaddr(vp,
 573                             (struct sockaddr *) &addr,
 574                             &prefix, &ul_proto);
 575 
 576                         rc_vfree(vp);
 577 
 578                         if (error)
 579                                 goto end;
 580 
 581                         daddr = rcs_sadup((struct sockaddr *) &addr);
 582                         if (daddr == NULL)
 583                                 goto end;
 584 
 585                         if (iph2->natoa_src == NULL)
 586                                 iph2->natoa_src = daddr;
 587                         else if (iph2->natoa_dst == NULL)
 588                                 iph2->natoa_dst = daddr;
 589                         else {
 590                                 racoon_free(daddr);
 591                                 goto end;
 592                         }
 593                 }
 594 #else
 595                         /* Ignore original source/destination messages */
 596 #endif
 597                         break;
 598 #endif
 599 
 600                 default:
 601                         /* don't send information, see ident_r1recv() */
 602                         isakmp_log(0, 0, iph2->ph1->remote, 0,
 603                                    PLOG_PROTOERR, PLOGLOC,
 604                                    "ignore the packet, "
 605                                    "received unexpecting payload type %d.\n",
 606                                    pa->type);
 607                         goto end;
 608                 }
 609 
 610                 p += pa->len;
 611 
 612                 /* compute true length of payload. */
 613                 tlen += pa->len;
 614         }
 615 
 616         /* payload existency check */
 617         if (hash == NULL || iph2->sa_ret == NULL || iph2->nonce_p == NULL) {
 618                 isakmp_log(0, 0, iph2->ph1->remote, 0,
 619                            PLOG_PROTOERR, PLOGLOC,
 620                            "few isakmp message received.\n");
 621                 goto end;
 622         }
 623 
 624        /* identity check */
 625        if (idci != NULL) {
 626                struct sockaddr_storage proposed_addr, got_addr;
 627                uint8_t proposed_prefix, got_prefix;
 628                uint16_t proposed_ulproto, got_ulproto;
 629 
 630                error = ipsecdoi_id2sockaddr(iph2->id,
 631                                        (struct sockaddr *) &proposed_addr,
 632                                        &proposed_prefix, &proposed_ulproto);
 633                if (error)
 634                        goto end;
 635                
 636                error = ipsecdoi_id2sockaddr(idci,
 637                                        (struct sockaddr *) &got_addr,
 638                                        &got_prefix, &got_ulproto);
 639                if (error)
 640                        goto end;
 641 
 642                if (proposed_prefix != got_prefix
 643                 || proposed_ulproto != got_ulproto) {
 644                        plog(PLOG_DEBUG, PLOGLOC, NULL,
 645                                "IDci prefix/ulproto does not match proposal.\n");
 646                        error = ISAKMP_NTYPE_ATTRIBUTES_NOT_SUPPORTED;
 647                        goto end;
 648                }
 649 
 650                if (rcs_cmpsa((struct sockaddr *) &proposed_addr,
 651                                   (struct sockaddr *) &got_addr) == 0) {
 652                        plog(PLOG_DEBUG, PLOGLOC, NULL,
 653                                "IDci matches proposal.\n");
 654 #ifdef ENABLE_NATT
 655                } else if (iph2->natoa_src != NULL
 656                        && rcs_cmpsa_wop(iph2->natoa_src,
 657                                       (struct sockaddr *) &got_addr) == 0
 658                        && extract_port((struct sockaddr *) &proposed_addr) ==
 659                           extract_port((struct sockaddr *) &got_addr)) {
 660                        plog(PLOG_DEBUG, PLOGLOC, NULL,
 661                                "IDci matches NAT-OAi.\n");
 662 #endif
 663                } else {
 664                        plog(PLOG_INTERR, PLOGLOC, NULL,
 665                                "mismatched IDci was returned.\n");
 666                        error = ISAKMP_NTYPE_ATTRIBUTES_NOT_SUPPORTED;
 667                        goto end;
 668                }
 669        }
 670        if (idcr != NULL) {
 671                struct sockaddr_storage proposed_addr, got_addr;
 672                uint8_t proposed_prefix, got_prefix;
 673                uint16_t proposed_ulproto, got_ulproto;
 674 
 675                error = ipsecdoi_id2sockaddr(iph2->id_p,
 676                                        (struct sockaddr *) &proposed_addr,
 677                                        &proposed_prefix, &proposed_ulproto);
 678                if (error)
 679                        goto end;
 680 
 681                error = ipsecdoi_id2sockaddr(idcr,
 682                                        (struct sockaddr *) &got_addr,
 683                                        &got_prefix, &got_ulproto);
 684                if (error)
 685                        goto end;
 686 
 687                if (proposed_prefix != got_prefix
 688                 || proposed_ulproto != got_ulproto) {
 689                        plog(PLOG_DEBUG, PLOGLOC, NULL,
 690                                "IDcr prefix/ulproto does not match proposal.\n");
 691                        error = ISAKMP_NTYPE_ATTRIBUTES_NOT_SUPPORTED;
 692                        goto end;
 693                }
 694 
 695                if (rcs_cmpsa((struct sockaddr *) &proposed_addr,
 696                                   (struct sockaddr *) &got_addr) == 0) {
 697                        plog(PLOG_DEBUG, PLOGLOC, NULL,
 698                                "IDcr matches proposal.\n");
 699 #ifdef ENABLE_NATT
 700                } else if (iph2->natoa_dst != NULL
 701                        && rcs_cmpsa_wop(iph2->natoa_dst,
 702                                       (struct sockaddr *) &got_addr) == 0
 703                        && extract_port((struct sockaddr *) &proposed_addr) ==
 704                           extract_port((struct sockaddr *) &got_addr)) {
 705                        plog(PLOG_DEBUG, PLOGLOC, NULL,
 706                                "IDcr matches NAT-OAr.\n");
 707 #endif
 708                } else {
 709                        plog(PLOG_INTERR, PLOGLOC, NULL,
 710                                "mismatched IDcr was returned.\n");
 711                        error = ISAKMP_NTYPE_ATTRIBUTES_NOT_SUPPORTED;
 712                        goto end;
 713                }
 714        }
 715 
 716         /* Fixed buffer for calculating HASH */
 717         memcpy(hbuf->v, iph2->nonce->v, iph2->nonce->l);
 718         plog(PLOG_DEBUG, PLOGLOC, NULL,
 719                 "HASH allocated:hbuf->l=%d actual:tlen=%d\n",
 720                 hbuf->l, tlen + iph2->nonce->l);
 721         /* adjust buffer length for HASH */
 722         hbuf->l = iph2->nonce->l + tlen;
 723 
 724         /* validate HASH(2) */
 725     {
 726         char *r_hash;
 727         rc_vchar_t *my_hash = NULL;
 728         int result;
 729 
 730         r_hash = (char *)hash + sizeof(*hash);
 731 
 732         plog(PLOG_DEBUG, PLOGLOC, NULL, "HASH(2) received:");
 733         plogdump(PLOG_DEBUG, PLOGLOC, 0, r_hash, get_uint16(&hash->h.len) - sizeof(*hash));
 734 
 735         my_hash = oakley_compute_hash1(iph2->ph1, iph2->msgid, hbuf);
 736         if (my_hash == NULL)
 737                 goto end;
 738 
 739         result = memcmp(my_hash->v, r_hash, my_hash->l);
 740         rc_vfree(my_hash);
 741 
 742         if (result) {
 743                 isakmp_log(0, 0, iph2->ph1->remote, 0,
 744                            PLOG_PROTOERR, PLOGLOC,
 745                            "HASH(2) mismatch.\n");
 746                 error = ISAKMP_NTYPE_INVALID_HASH_INFORMATION;
 747                 goto end;
 748         }
 749     }
 750 
 751         /* validity check SA payload sent from responder */
 752         if (ipsecdoi_checkph2proposal(iph2) < 0) {
 753                 error = ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN;
 754                 goto end;
 755         }
 756 
 757         /* change status of isakmp status entry */
 758         iph2->status = PHASE2ST_STATUS6;
 759 
 760         error = 0;
 761 
 762 end:
 763         if (hbuf)
 764                 rc_vfree(hbuf);
 765         if (pbuf)
 766                 rc_vfree(pbuf);
 767         if (msg)
 768                 rc_vfree(msg);
 769         if (idci)
 770                 rc_vfree(idci);
 771         if (idcr)
 772                 rc_vfree(idcr);
 773 
 774         if (error) {
 775                 VPTRINIT(iph2->sa_ret);
 776                 VPTRINIT(iph2->nonce_p);
 777                 VPTRINIT(iph2->dhpub_p);
 778                 VPTRINIT(iph2->id);
 779                 VPTRINIT(iph2->id_p);
 780 #ifdef ENABLE_NATT
 781                 if (iph2->natoa_src) {
 782                         racoon_free(iph2->natoa_src);
 783                         iph2->natoa_src = NULL;
 784                 }
 785                 if (iph2->natoa_dst) {
 786                         racoon_free(iph2->natoa_dst);
 787                         iph2->natoa_dst = NULL;
 788                 }
 789 #endif
 790         }
 791 
 792         return error;
 793 }
 794 
 795 static int
 796 fill_in_ipsec_sas(struct ph2handle *iph2)
 797 {
 798         /*
 799          * NOTE:  The OpenSolaris kernel can queue up packets on a larval SA
 800          * such that when the SA is filled-in via SADB_UPDATE, these packets
 801          * can be immediately processed.  If the reply packet is generated
 802          * in-kernel (e.g. ICMP_ECHO processing), an additonal ACQUIRE can
 803          * be sent if there is not a corresponding outbound SA waiting in
 804          * the wings.  We therefore perform SADB_ADD first so that if an
 805          * outbound SA is needed immediately during SADB_UPDATE processing,
 806          * it is ready.
 807          */
 808 
 809         plog(PLOG_DEBUG, PLOGLOC, NULL, "call pk_sendadd\n");
 810         if (pk_sendadd(iph2) < 0) {
 811                 plog(PLOG_INTERR, PLOGLOC, NULL, "pfkey add failed.\n");
 812                 return (-1);
 813         }
 814         plog(PLOG_DEBUG, PLOGLOC, NULL, "pfkey add sent.\n");
 815 
 816         plog(PLOG_DEBUG, PLOGLOC, NULL, "call pk_sendupdate\n");
 817         if (pk_sendupdate(iph2) < 0) {
 818                 plog(PLOG_INTERR, PLOGLOC, NULL, "pfkey update failed.\n");
 819                 return (-1);
 820         }
 821         plog(PLOG_DEBUG, PLOGLOC, NULL, "pfkey update sent.\n");
 822 
 823         return (0);
 824 }
 825 
 826 /*
 827  * send to responder
 828  *      HDR*, HASH(3)
 829  */
 830 int
 831 quick_i2send(struct ph2handle *iph2, rc_vchar_t *msg0)
 832 {
 833         rc_vchar_t *msg = NULL;
 834         rc_vchar_t *buf = NULL;
 835         rc_vchar_t *hash = NULL;
 836         char *p = NULL;
 837         int tlen;
 838         int error = ISAKMP_INTERNAL_ERROR;
 839 
 840         /* validity check */
 841         if (iph2->status != PHASE2ST_STATUS6) {
 842                 plog(PLOG_INTERR, PLOGLOC, NULL,
 843                         "status mismatched %d.\n", iph2->status);
 844                 goto end;
 845         }
 846 
 847         /* generate HASH(3) */
 848     {
 849         rc_vchar_t *tmp = NULL;
 850 
 851         plog(PLOG_DEBUG, PLOGLOC, NULL, "HASH(3) generate\n");
 852 
 853         tmp = rc_vmalloc(iph2->nonce->l + iph2->nonce_p->l);
 854         if (tmp == NULL) { 
 855                 plog(PLOG_INTERR, PLOGLOC, NULL,
 856                         "failed to get hash buffer.\n");
 857                 goto end;
 858         }
 859         memcpy(tmp->v, iph2->nonce->v, iph2->nonce->l);
 860         memcpy(tmp->v + iph2->nonce->l, iph2->nonce_p->v, iph2->nonce_p->l);
 861 
 862         hash = oakley_compute_hash3(iph2->ph1, iph2->msgid, tmp);
 863         rc_vfree(tmp);
 864 
 865         if (hash == NULL)
 866                 goto end;
 867     }
 868 
 869         /* create buffer for isakmp payload */
 870         tlen = sizeof(struct isakmp)
 871                 + sizeof(struct isakmp_gen) + hash->l;
 872         buf = rc_vmalloc(tlen);
 873         if (buf == NULL) { 
 874                 plog(PLOG_INTERR, PLOGLOC, NULL,
 875                         "failed to get buffer to send.\n");
 876                 goto end;
 877         }
 878 
 879         /* create isakmp header */
 880         p = set_isakmp_header2(buf, iph2, ISAKMP_NPTYPE_HASH);
 881         if (p == NULL)
 882                 goto end;
 883 
 884         /* add HASH(3) payload */
 885         p = set_isakmp_payload(p, hash, ISAKMP_NPTYPE_NONE);
 886 
 887 #ifdef HAVE_PRINT_ISAKMP_C
 888         isakmp_printpacket(buf, iph2->ph1->local, iph2->ph1->remote, 1);
 889 #endif
 890 
 891         /* encoding */
 892         iph2->sendbuf = oakley_do_encrypt(iph2->ph1, buf, iph2->ivm->ive, iph2->ivm->iv);
 893         if (iph2->sendbuf == NULL)
 894                 goto end;
 895 
 896         /* if there is commit bit, need resending */
 897         if (ISSET(iph2->flags, ISAKMP_FLAG_C)) {
 898                 /* send the packet, add to the schedule to resend */
 899                 iph2->retry_counter = ikev1_max_retry_to_send(iph2->ph1->rmconf);
 900                 if (isakmp_ph2resend(iph2) == -1)
 901                         goto end;
 902         } else {
 903                 /* send the packet */
 904                 if (isakmp_send(iph2->ph1, iph2->sendbuf) < 0)
 905                         goto end;
 906         }
 907 
 908         /* the sending message is added to the received-list. */
 909         if (add_recvdpkt(iph2->ph1->remote, iph2->ph1->local,
 910                         iph2->sendbuf, msg0, iph2->ph1->rmconf) == -1) {
 911                 plog(PLOG_INTERR , PLOGLOC, NULL,
 912                         "failed to add a response packet to the tree.\n");
 913                 goto end;
 914         }
 915 
 916         /* compute both of KEYMATs */
 917         if (oakley_compute_keymat(iph2, INITIATOR) < 0)
 918                 goto end;
 919 
 920         iph2->status = PHASE2ST_ADDSA;
 921 
 922 #if 0
 923         /* don't anything if local test mode. */
 924         if (f_local) {
 925                 error = 0;
 926                 goto end;
 927         }
 928 #endif
 929         
 930         /* if there is commit bit don't set up SA now. */
 931         if (ISSET(iph2->flags, ISAKMP_FLAG_C)) {
 932                 iph2->status = PHASE2ST_COMMIT;
 933                 error = 0;
 934                 goto end;
 935         }
 936 
 937         plog(PLOG_DEBUG, PLOGLOC, NULL, "call fill_in_ipsec_sas");
 938         error = fill_in_ipsec_sas(iph2);
 939 
 940 end:
 941         if (buf != NULL)
 942                 rc_vfree(buf);
 943         if (msg != NULL)
 944                 rc_vfree(msg);
 945         if (hash != NULL)
 946                 rc_vfree(hash);
 947 
 948         return error;
 949 }
 950 
 951 /*
 952  * receive from responder
 953  *      HDR#*, HASH(4), notify
 954  */
 955 int
 956 quick_i3recv(struct ph2handle *iph2, rc_vchar_t *msg0)
 957 {
 958         rc_vchar_t *msg = NULL;
 959         rc_vchar_t *pbuf = NULL;        /* for payload parsing */
 960         struct isakmp_parse_t *pa;
 961         struct isakmp_pl_hash *hash = NULL;
 962         rc_vchar_t *notify = NULL;
 963         int error = ISAKMP_INTERNAL_ERROR;
 964 
 965         /* validity check */
 966         if (iph2->status != PHASE2ST_COMMIT) {
 967                 plog(PLOG_INTERR, PLOGLOC, NULL,
 968                         "status mismatched %d.\n", iph2->status);
 969                 goto end;
 970         }
 971 
 972         /* decrypt packet */
 973         if (!ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E)) {
 974                 isakmp_log(0, 0, iph2->ph1->remote, 0,
 975                            PLOG_PROTOERR, PLOGLOC,
 976                            "Packet wasn't encrypted.\n");
 977                 goto end;
 978         }
 979         msg = oakley_do_decrypt(iph2->ph1, msg0, iph2->ivm->iv, iph2->ivm->ive);
 980         if (msg == NULL)
 981                 goto end;
 982 
 983         /* validate the type of next payload */
 984         pbuf = isakmp_parse(msg);
 985         if (pbuf == NULL)
 986                 goto end;
 987 
 988         for (pa = (struct isakmp_parse_t *)pbuf->v;
 989              pa->type != ISAKMP_NPTYPE_NONE;
 990              pa++) {
 991 
 992                 switch (pa->type) {
 993                 case ISAKMP_NPTYPE_HASH:
 994                         hash = (struct isakmp_pl_hash *)pa->ptr;
 995                         break;
 996                 case ISAKMP_NPTYPE_N:
 997                         if (notify != NULL) {
 998                                 plog(PLOG_INTWARN, PLOGLOC, NULL,
 999                                      "Ignoring multiple notifications\n");
1000                                 break;
1001                         }
1002                         isakmp_check_notify(pa->ptr, iph2->ph1);
1003                         notify = rc_vmalloc(pa->len);
1004                         if (notify == NULL) {
1005                                 plog(PLOG_INTERR, PLOGLOC, NULL,
1006                                         "failed to get notify buffer.\n");
1007                                 goto end;
1008                         }
1009                         memcpy(notify->v, pa->ptr, notify->l);
1010                         break;
1011                 default:
1012                         /* don't send information, see ident_r1recv() */
1013                         isakmp_log(0, 0, iph2->ph1->remote, 0,
1014                                    PLOG_PROTOERR, PLOGLOC,
1015                                    "ignore the packet, "
1016                                    "received unexpecting payload type %d.\n",
1017                                    pa->type);
1018                         goto end;
1019                 }
1020         }
1021 
1022         /* payload existency check */
1023         if (hash == NULL) {
1024                 isakmp_log(0, 0, iph2->ph1->remote, 0,
1025                            PLOG_PROTOERR, PLOGLOC,
1026                            "few isakmp message received.\n");
1027                 goto end;
1028         }
1029 
1030         /* validate HASH(4) */
1031     {
1032         char *r_hash;
1033         rc_vchar_t *my_hash = NULL;
1034         rc_vchar_t *tmp = NULL;
1035         int result;
1036 
1037         r_hash = (char *)hash + sizeof(*hash);
1038 
1039         plog(PLOG_DEBUG, PLOGLOC, NULL, "HASH(4) validate:");
1040         plogdump(PLOG_DEBUG, PLOGLOC, 0, r_hash, get_uint16(&hash->h.len) - sizeof(*hash));
1041 
1042         my_hash = oakley_compute_hash1(iph2->ph1, iph2->msgid, notify);
1043         rc_vfree(tmp);
1044         if (my_hash == NULL)
1045                 goto end;
1046 
1047         result = memcmp(my_hash->v, r_hash, my_hash->l);
1048         rc_vfree(my_hash);
1049 
1050         if (result) {
1051                 isakmp_log(0, 0, iph2->ph1->remote, 0,
1052                            PLOG_PROTOERR, PLOGLOC,
1053                            "HASH(4) mismatch.\n");
1054                 error = ISAKMP_NTYPE_INVALID_HASH_INFORMATION;
1055                 goto end;
1056         }
1057     }
1058 
1059         iph2->status = PHASE2ST_ADDSA;
1060         iph2->flags ^= ISAKMP_FLAG_C;        /* reset bit */
1061 
1062 #if 0
1063         /* don't anything if local test mode. */
1064         if (f_local) {
1065                 error = 0;
1066                 goto end;
1067         }
1068 #endif
1069 
1070         plog(PLOG_DEBUG, PLOGLOC, NULL, "call fill_in_ipsec_sas");
1071         error = fill_in_ipsec_sas(iph2);
1072 
1073 end:
1074         if (msg != NULL)
1075                 rc_vfree(msg);
1076         if (pbuf != NULL)
1077                 rc_vfree(pbuf);
1078         if (notify != NULL)
1079                 rc_vfree(notify);
1080 
1081         return error;
1082 }
1083 
1084 /*
1085  * receive from initiator
1086  *      HDR*, HASH(1), SA, Ni [, KE ] [, IDi2, IDr2 ] [, NAT-OAi, NAT-OAr ]
1087  */
1088 int
1089 quick_r1recv(struct ph2handle *iph2, rc_vchar_t *msg0)
1090 {
1091         rc_vchar_t *msg = NULL;
1092         rc_vchar_t *hbuf = NULL;        /* for hash computing. */
1093         rc_vchar_t *pbuf = NULL;        /* for payload parsing */
1094         struct isakmp_parse_t *pa;
1095         struct isakmp *isakmp = (struct isakmp *)msg0->v;
1096         struct isakmp_pl_hash *hash = NULL;
1097         char *p;
1098         int tlen;
1099         int f_id_order; /* for ID payload detection */
1100         int error = ISAKMP_INTERNAL_ERROR;
1101 
1102         /* validity check */
1103         if (iph2->status != PHASE2ST_START) {
1104                 plog(PLOG_INTERR, PLOGLOC, NULL,
1105                         "status mismatched %d.\n", iph2->status);
1106                 goto end;
1107         }
1108 
1109         /* decrypting */
1110         if (!ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E)) {
1111                 isakmp_log(0, 0, iph2->ph1->remote, 0,
1112                            PLOG_PROTOERR, PLOGLOC,
1113                            "Packet wasn't encrypted.\n");
1114                 error = ISAKMP_NTYPE_PAYLOAD_MALFORMED;
1115                 goto end;
1116         }
1117         /* decrypt packet */
1118         msg = oakley_do_decrypt(iph2->ph1, msg0, iph2->ivm->iv, iph2->ivm->ive);
1119         if (msg == NULL)
1120                 goto end;
1121 
1122         /* create buffer for using to validate HASH(1) */
1123         /*
1124          * ordering rule:
1125          *      1. the first one must be HASH
1126          *      2. the second one must be SA (added in isakmp-oakley-05!)
1127          *      3. two IDs must be considered as IDci, then IDcr
1128          */
1129         pbuf = isakmp_parse(msg);
1130         if (pbuf == NULL)
1131                 goto end;
1132         pa = (struct isakmp_parse_t *)pbuf->v;
1133 
1134         /* HASH payload is fixed postion */
1135         if (pa->type != ISAKMP_NPTYPE_HASH) {
1136                 isakmp_log(0, 0, iph2->ph1->remote, 0,
1137                            PLOG_PROTOERR, PLOGLOC,
1138                            "received invalid next payload type %d, "
1139                            "expecting %d.\n",
1140                            pa->type, ISAKMP_NPTYPE_HASH);
1141                 error = ISAKMP_NTYPE_BAD_PROPOSAL_SYNTAX;
1142                 goto end;
1143         }
1144         hash = (struct isakmp_pl_hash *)pa->ptr;
1145         pa++;
1146 
1147         /*
1148          * this restriction was introduced in isakmp-oakley-05.
1149          * we do not check this for backward compatibility.
1150          * TODO: command line/config file option to enable/disable this code
1151          */
1152         /* HASH payload is fixed postion */
1153         if (pa->type != ISAKMP_NPTYPE_SA) {
1154                 isakmp_log(0, 0, iph2->ph1->remote, 0,
1155                            PLOG_PROTOERR, PLOGLOC,
1156                            "received invalid next payload type %d, "
1157                            "expecting %d.\n",
1158                            pa->type, ISAKMP_NPTYPE_HASH);
1159                 error = ISAKMP_NTYPE_BAD_PROPOSAL_SYNTAX;
1160         }
1161 
1162         /* allocate buffer for computing HASH(1) */
1163         tlen = get_uint32(&isakmp->len) - sizeof(*isakmp);
1164         hbuf = rc_vmalloc(tlen);
1165         if (hbuf == NULL) {
1166                 plog(PLOG_INTERR, PLOGLOC, NULL,
1167                         "failed to get hash buffer.\n");
1168                 goto end;
1169         }
1170         p = hbuf->v;
1171 
1172         /*
1173          * parse the payloads.
1174          * copy non-HASH payloads into hbuf, so that we can validate HASH.
1175          */
1176         iph2->sa = NULL;     /* we don't support multi SAs. */
1177         iph2->nonce_p = NULL;
1178         iph2->dhpub_p = NULL;
1179         iph2->id_p = NULL;
1180         iph2->id = NULL;
1181         tlen = 0;       /* count payload length except of HASH payload. */
1182 
1183         /*
1184          * IDi2 MUST be immediatelly followed by IDr2.  We allowed the
1185          * illegal case, but logged.  First ID payload is to be IDi2.
1186          * And next ID payload is to be IDr2.
1187          */
1188         f_id_order = 0;
1189 
1190         for (; pa->type; pa++) {
1191 
1192                 /* copy to buffer for HASH */
1193                 /* Don't modify the payload */
1194                 memcpy(p, pa->ptr, pa->len);
1195 
1196                 if (pa->type != ISAKMP_NPTYPE_ID)
1197                         f_id_order = 0;
1198 
1199                 switch (pa->type) {
1200                 case ISAKMP_NPTYPE_SA:
1201                         if (iph2->sa != NULL) {
1202                                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1203                                         "Multi SAs isn't supported.\n");
1204                                 goto end;
1205                         }
1206                         if (isakmp_p2ph(&iph2->sa, pa->ptr) < 0)
1207                                 goto end;
1208                         break;
1209 
1210                 case ISAKMP_NPTYPE_NONCE:
1211                         if (isakmp_p2ph(&iph2->nonce_p, pa->ptr) < 0)
1212                                 goto end;
1213                         break;
1214 
1215                 case ISAKMP_NPTYPE_KE:
1216                         if (isakmp_p2ph(&iph2->dhpub_p, pa->ptr) < 0)
1217                                 goto end;
1218                         break;
1219 
1220                 case ISAKMP_NPTYPE_ID:
1221                         if (iph2->id_p == NULL) {
1222                                 /* for IDci */
1223                                 f_id_order++;
1224 
1225                                 if (isakmp_p2ph(&iph2->id_p, pa->ptr) < 0)
1226                                         goto end;
1227 
1228                         } else if (iph2->id == NULL) {
1229                                 /* for IDcr */
1230                                 if (f_id_order == 0) {
1231                                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
1232                                                 "IDr2 payload is not "
1233                                                 "immediatelly followed "
1234                                                 "by IDi2. We allowed.\n");
1235                                         /* XXX we allowed in this case. */
1236                                 }
1237 
1238                                 if (isakmp_p2ph(&iph2->id, pa->ptr) < 0)
1239                                         goto end;
1240                         } else {
1241                                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1242                                         "received too many ID payloads.\n");
1243                                 plogdump(PLOG_PROTOERR, PLOGLOC, 0, iph2->id->v, iph2->id->l);
1244                                 error = ISAKMP_NTYPE_INVALID_ID_INFORMATION;
1245                                 goto end;
1246                         }
1247                         break;
1248 
1249                 case ISAKMP_NPTYPE_N:
1250                         isakmp_check_notify(pa->ptr, iph2->ph1);
1251                         break;
1252 
1253 #ifdef ENABLE_NATT
1254                 case ISAKMP_NPTYPE_NATOA_DRAFT:
1255                 case ISAKMP_NPTYPE_NATOA_RFC:
1256 #ifdef sun
1257                 {
1258                         struct sockaddr_storage addr;
1259                         struct sockaddr *daddr;
1260                         uint8_t prefix;
1261                         uint16_t ul_proto;
1262                         rc_vchar_t *vp = NULL;
1263 
1264                         if (isakmp_p2ph(&vp, pa->ptr) < 0)
1265                                 goto end;
1266 
1267                         error = ipsecdoi_id2sockaddr(vp,
1268                             (struct sockaddr *) &addr,
1269                             &prefix, &ul_proto);
1270 
1271                         rc_vfree(vp);
1272 
1273                         if (error)
1274                                 goto end;
1275 
1276                         daddr = rcs_sadup((struct sockaddr *) &addr);
1277                         if (daddr == NULL)
1278                                 goto end;
1279 
1280                         if (iph2->natoa_dst == NULL)
1281                                 iph2->natoa_dst = daddr;
1282                         else if (iph2->natoa_src == NULL)
1283                                 iph2->natoa_src = daddr;
1284                         else {
1285                                 racoon_free(daddr);
1286                                 goto end;
1287                         }
1288                 }
1289 #else
1290                         /* Ignore original source/destination messages */
1291 #endif
1292                         break;
1293 #endif
1294 
1295                 default:
1296                         isakmp_log(0, 0, iph2->ph1->remote, 0,
1297                                    PLOG_PROTOERR, PLOGLOC,
1298                                    "ignore the packet, "
1299                                    "received unexpecting payload type %d.\n",
1300                                    pa->type);
1301                         error = ISAKMP_NTYPE_PAYLOAD_MALFORMED;
1302                         goto end;
1303                 }
1304 
1305                 p += pa->len;
1306 
1307                 /* compute true length of payload. */
1308                 tlen += pa->len;
1309         }
1310 
1311         /* payload existency check */
1312         if (hash == NULL || iph2->sa == NULL || iph2->nonce_p == NULL) {
1313                 isakmp_log(0, 0, iph2->ph1->remote, 0,
1314                            PLOG_PROTOERR, PLOGLOC,
1315                            "few isakmp message received.\n");
1316                 error = ISAKMP_NTYPE_PAYLOAD_MALFORMED;
1317                 goto end;
1318         }
1319 
1320         if (iph2->id_p) {
1321                 plog(PLOG_DEBUG, PLOGLOC, NULL, "received IDci2:");
1322                 plogdump(PLOG_DEBUG, PLOGLOC, 0, iph2->id_p->v, iph2->id_p->l);
1323         }
1324         if (iph2->id) {
1325                 plog(PLOG_DEBUG, PLOGLOC, NULL, "received IDcr2:");
1326                 plogdump(PLOG_DEBUG, PLOGLOC, 0, iph2->id->v, iph2->id->l);
1327         }
1328 
1329         /* adjust buffer length for HASH */
1330         hbuf->l = tlen;
1331 
1332         /* validate HASH(1) */
1333     {
1334         char *r_hash;
1335         rc_vchar_t *my_hash = NULL;
1336         int result;
1337 
1338         r_hash = (caddr_t)hash + sizeof(*hash);
1339 
1340         plog(PLOG_DEBUG, PLOGLOC, NULL, "HASH(1) validate:");
1341         plogdump(PLOG_DEBUG, PLOGLOC, 0, r_hash, get_uint16(&hash->h.len) - sizeof(*hash));
1342 
1343         my_hash = oakley_compute_hash1(iph2->ph1, iph2->msgid, hbuf);
1344         if (my_hash == NULL)
1345                 goto end;
1346 
1347         result = memcmp(my_hash->v, r_hash, my_hash->l);
1348         rc_vfree(my_hash);
1349 
1350         if (result) {
1351                 isakmp_log(0, 0, iph2->ph1->remote, 0,
1352                            PLOG_DEBUG, PLOGLOC,
1353                            "HASH(1) mismatch.\n");
1354                 error = ISAKMP_NTYPE_INVALID_HASH_INFORMATION;
1355                 goto end;
1356         }
1357     }
1358 
1359 #ifndef sun
1360         /* get sainfo */
1361         error = get_sainfo_r(iph2);
1362         if (error) {
1363                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1364                         "failed to get sainfo.\n");
1365                 goto end;
1366         }
1367 
1368         /* check the existence of ID payload and create responder's proposal */
1369         error = get_proposal_r(iph2);
1370         switch (error) {
1371 #ifdef notyet
1372         case -2:
1373                 /* generate a policy template from peer's proposal */
1374                 if (set_proposal_from_proposal(iph2)) {
1375                         plog(PLOG_INTERR, PLOGLOC, NULL,
1376                                 "failed to generate a proposal template "
1377                                 "from client's proposal.\n");
1378                         return ISAKMP_INTERNAL_ERROR;
1379                 }
1380                 /*FALLTHROUGH*/
1381 #endif
1382         case 0:
1383                 /* select single proposal or reject it. */
1384                 if (ipsecdoi_selectph2proposal(iph2) < 0) {
1385                         error = ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN;
1386                         goto end;
1387                 }
1388                 break;
1389         default:
1390                 plog(PLOG_INTERR, PLOGLOC, NULL,
1391                         "failed to get proposal for responder.\n");
1392                 goto end;
1393         }
1394 
1395         /* check KE and attribute of PFS */
1396         if (iph2->dhpub_p != NULL && iph2->approval->pfs_group == 0) {
1397                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1398                         "no PFS is specified, but peer sends KE.\n");
1399                 error = ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN;
1400                 goto end;
1401         }
1402         if (iph2->dhpub_p == NULL && iph2->approval->pfs_group != 0) {
1403                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
1404                         "PFS is specified, but peer doesn't sends KE.\n");
1405                 error = ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN;
1406                 goto end;
1407         }
1408         /* change status of isakmp status entry */
1409         iph2->status = PHASE2ST_STATUS2;
1410 
1411 #endif /* sun/OpenSolaris */
1412 
1413         /*
1414          * save the packet from the initiator in order to resend the
1415          * responder's first packet against this packet.
1416          */
1417         iph2->msg1 = rc_vdup(msg0);
1418 
1419         error = 0;
1420 
1421 end:
1422         if (hbuf)
1423                 rc_vfree(hbuf);
1424         if (msg)
1425                 rc_vfree(msg);
1426         if (pbuf)
1427                 rc_vfree(pbuf);
1428 
1429         if (error) {
1430                 VPTRINIT(iph2->sa);
1431                 VPTRINIT(iph2->nonce_p);
1432                 VPTRINIT(iph2->dhpub_p);
1433                 VPTRINIT(iph2->id);
1434                 VPTRINIT(iph2->id_p);
1435 #ifdef ENABLE_NATT
1436                 if (iph2->natoa_src) {
1437                         racoon_free(iph2->natoa_src);
1438                         iph2->natoa_src = NULL;
1439                 }
1440                 if (iph2->natoa_dst) {
1441                         racoon_free(iph2->natoa_dst);
1442                         iph2->natoa_dst = NULL;
1443                 }
1444 #endif
1445         }
1446 
1447         return error;
1448 }
1449 
1450 /*
1451  * call pfkey_getspi.
1452  */
1453 int
1454 quick_r1prep(struct ph2handle *iph2, rc_vchar_t *msg)
1455 {
1456         int error = ISAKMP_INTERNAL_ERROR;
1457 
1458         /* validity check */
1459         if (iph2->status != PHASE2ST_STATUS2) {
1460                 plog(PLOG_INTERR, PLOGLOC, NULL,
1461                         "status mismatched %d.\n", iph2->status);
1462                 goto end;
1463         }
1464 
1465         iph2->status = PHASE2ST_GETSPISENT;
1466 
1467         /* send getspi message */
1468         if (pk_sendgetspi(iph2) < 0)
1469                 goto end;
1470 
1471         plog(PLOG_DEBUG, PLOGLOC, NULL, "pfkey getspi sent.\n");
1472 
1473         iph2->sce = sched_new(ikev1_ipsec_sa_nego_time_limit(iph2->ph1->rmconf),
1474                 pfkey_timeover_stub, iph2);
1475 
1476         error = 0;
1477 
1478 end:
1479         return error;
1480 }
1481 
1482 /*
1483  * send to initiator
1484  *      HDR*, HASH(2), SA, Nr [, KE ] [, IDi2, IDr2 ] [, NAT-OAi, NAT-OAr ]
1485  */
1486 int
1487 quick_r2send(struct ph2handle *iph2, rc_vchar_t *msg)
1488 {
1489         rc_vchar_t *body = NULL;
1490         rc_vchar_t *hash = NULL;
1491         struct isakmp_gen *gen;
1492         char *p;
1493         int tlen;
1494         int error = ISAKMP_INTERNAL_ERROR;
1495         int natoa = ISAKMP_NPTYPE_NONE;
1496         int pfsgroup;
1497         uint8_t *np_p = NULL;
1498 #ifdef ENABLE_NATT
1499         rc_vchar_t *nat_oai = NULL;
1500         rc_vchar_t *nat_oar = NULL;
1501 #endif
1502 
1503         /* validity check */
1504         if (msg != NULL) {
1505                 plog(PLOG_INTERR, PLOGLOC, NULL,
1506                         "msg has to be NULL in this function.\n");
1507                 goto end;
1508         }
1509         if (iph2->status != PHASE2ST_GETSPIDONE) {
1510                 plog(PLOG_INTERR, PLOGLOC, NULL,
1511                         "status mismatched %d.\n", iph2->status);
1512                 goto end;
1513         }
1514 
1515         /* update responders SPI */
1516         if (ipsecdoi_updatespi(iph2) < 0) {
1517                 plog(PLOG_INTERR, PLOGLOC, NULL, "failed to update spi.\n");
1518                 goto end;
1519         }
1520 
1521         /* generate NONCE value */
1522         iph2->nonce = eay_set_random(ikev1_nonce_size(iph2->ph1->rmconf));
1523         if (iph2->nonce == NULL)
1524                 goto end;
1525 
1526         /* generate KE value if need */
1527         pfsgroup = iph2->approval->pfs_group;
1528         if (iph2->dhpub_p != NULL && pfsgroup != 0) {
1529                 /* DH group settting if PFS is required. */
1530                 if (oakley_setdhgroup(pfsgroup, &iph2->pfsgrp) < 0) {
1531                         plog(PLOG_INTERR, PLOGLOC, NULL,
1532                                 "failed to set DH value.\n");
1533                         goto end;
1534                 }
1535                 /* generate DH public value */
1536                 if (oakley_dh_generate(iph2->pfsgrp,
1537                                 &iph2->dhpub, &iph2->dhpriv) < 0) {
1538                         goto end;
1539                 }
1540         }
1541 
1542 #ifdef ENABLE_NATT
1543         /*
1544          * RFC3947 5.2. if we chose UDP-Encapsulated-Transport
1545          * we should send NAT-OA
1546          */
1547         if (ipsecdoi_transportmode(iph2->proposal)
1548             && (iph2->ph1->natt_flags & NAT_DETECTED)) {
1549                 natoa = iph2->ph1->natt_options->payload_nat_oa;
1550                 
1551                 nat_oai = ipsecdoi_sockaddr2id(iph2->dst,
1552                     IPSECDOI_PREFIX_HOST, IPSEC_ULPROTO_ANY);
1553                 nat_oar = ipsecdoi_sockaddr2id(iph2->src,
1554                     IPSECDOI_PREFIX_HOST, IPSEC_ULPROTO_ANY);
1555                 
1556                 if (nat_oai == NULL || nat_oar == NULL) {
1557                         plog(PLOG_INTERR, PLOGLOC, NULL,
1558                             "failed to generate NAT-OA payload.\n");
1559                         goto end;
1560                 }
1561 
1562                 plog(PLOG_DEBUG, PLOGLOC, NULL, "NAT-OAi:\n");
1563                 plogdump(PLOG_DEBUG, PLOGLOC, 0, nat_oai->v, nat_oai->l);
1564                 plog(PLOG_DEBUG, PLOGLOC, 0, NULL, "NAT-OAr:\n");
1565                 plogdump(PLOG_DEBUG, PLOGLOC, 0, nat_oar->v, nat_oar->l);
1566         }
1567 #endif
1568 
1569         /* create SA;NONCE payload, and KE and ID if need */
1570         tlen = sizeof(*gen) + iph2->sa_ret->l
1571                 + sizeof(*gen) + iph2->nonce->l;
1572         if (iph2->dhpub_p != NULL && pfsgroup != 0)
1573                 tlen += (sizeof(*gen) + iph2->dhpub->l);
1574         if (iph2->id_p != NULL)
1575                 tlen += (sizeof(*gen) + iph2->id_p->l
1576                         + sizeof(*gen) + iph2->id->l);
1577 
1578 #ifdef ENABLE_NATT
1579        if (natoa != ISAKMP_NPTYPE_NONE)
1580                tlen += 2 * sizeof(*gen) + nat_oai->l + nat_oar->l;
1581 #endif
1582 
1583         body = rc_vmalloc(tlen);
1584         if (body == NULL) { 
1585                 plog(PLOG_INTERR, PLOGLOC, NULL,
1586                         "failed to get buffer to send.\n");
1587                 goto end;
1588         }
1589         p = body->v;
1590 
1591         /* make SA payload */ 
1592         p = set_isakmp_payload(body->v, iph2->sa_ret, ISAKMP_NPTYPE_NONCE);
1593 
1594         /* add NONCE payload */
1595         np_p = &((struct isakmp_gen *)p)->np;    /* XXX */
1596         p = set_isakmp_payload(p, iph2->nonce,
1597                 (iph2->dhpub_p != NULL && pfsgroup != 0)
1598                                 ? ISAKMP_NPTYPE_KE
1599                                 : (iph2->id_p != NULL
1600                                         ? ISAKMP_NPTYPE_ID
1601                                         : natoa));
1602 
1603         /* add KE payload if need. */
1604         if (iph2->dhpub_p != NULL && pfsgroup != 0) {
1605                 np_p = &((struct isakmp_gen *)p)->np;    /* XXX */
1606                 p = set_isakmp_payload(p, iph2->dhpub,
1607                         (iph2->id_p == NULL)
1608                                 ? natoa
1609                                 : ISAKMP_NPTYPE_ID);
1610         }
1611 
1612         /* add ID payloads received. */
1613         if (iph2->id_p != NULL) {
1614                 /* IDci */
1615                 p = set_isakmp_payload(p, iph2->id_p, ISAKMP_NPTYPE_ID);
1616                 /* IDcr */
1617                 np_p = &((struct isakmp_gen *)p)->np;    /* XXX */
1618                 p = set_isakmp_payload(p, iph2->id, natoa);
1619         }
1620 #ifdef ENABLE_NATT
1621         /* NAT-OA */
1622         if (natoa != ISAKMP_NPTYPE_NONE) {
1623                 p = set_isakmp_payload(p, nat_oai, natoa);
1624                 p = set_isakmp_payload(p, nat_oar, ISAKMP_NPTYPE_NONE);
1625         }
1626 #endif
1627 
1628         /* add a RESPONDER-LIFETIME notify payload if needed */
1629     {
1630         rc_vchar_t *data = NULL;
1631         struct saprop *pp = iph2->approval;
1632         struct saproto *pr;
1633 
1634         if (pp->claim & IPSECDOI_ATTR_SA_LD_TYPE_SEC) {
1635                 uint32_t v = htonl((uint32_t)pp->lifetime);
1636                 data = isakmp_add_attr_l(data, IPSECDOI_ATTR_SA_LD_TYPE,
1637                                         IPSECDOI_ATTR_SA_LD_TYPE_SEC);
1638                 if (!data)
1639                         goto end;
1640                 data = isakmp_add_attr_v(data, IPSECDOI_ATTR_SA_LD,
1641                                         (caddr_t)&v, sizeof(v));
1642                 if (!data)
1643                         goto end;
1644         }
1645         if (pp->claim & IPSECDOI_ATTR_SA_LD_TYPE_KB) {
1646                 uint32_t v = htonl((uint32_t)pp->lifebyte);
1647                 data = isakmp_add_attr_l(data, IPSECDOI_ATTR_SA_LD_TYPE,
1648                                         IPSECDOI_ATTR_SA_LD_TYPE_KB);
1649                 if (!data)
1650                         goto end;
1651                 data = isakmp_add_attr_v(data, IPSECDOI_ATTR_SA_LD,
1652                                         (caddr_t)&v, sizeof(v));
1653                 if (!data)
1654                         goto end;
1655         }
1656 
1657         /*
1658          * XXX Is there only single RESPONDER-LIFETIME payload in a IKE message
1659          * in the case of SA bundle ?
1660          */
1661         if (data) {
1662                 for (pr = pp->head; pr; pr = pr->next) {
1663                         body = isakmp_add_pl_n(body, &np_p,
1664                                         ISAKMP_NTYPE_RESPONDER_LIFETIME, pr, data);
1665                         if (!body) {
1666                                 rc_vfree(data);
1667                                 return error;   /* XXX */
1668                         }
1669                 }
1670                 rc_vfree(data);
1671         }
1672     }
1673 
1674         /* generate HASH(2) */
1675     {
1676         rc_vchar_t *tmp;
1677 
1678         tmp = rc_vmalloc(iph2->nonce_p->l + body->l);
1679         if (tmp == NULL) { 
1680                 plog(PLOG_INTERR, PLOGLOC, NULL,
1681                         "failed to get hash buffer.\n");
1682                 goto end;
1683         }
1684         memcpy(tmp->v, iph2->nonce_p->v, iph2->nonce_p->l);
1685         memcpy(tmp->v + iph2->nonce_p->l, body->v, body->l);
1686 
1687         hash = oakley_compute_hash1(iph2->ph1, iph2->msgid, tmp);
1688         rc_vfree(tmp);
1689 
1690         if (hash == NULL)
1691                 goto end;
1692     }
1693 
1694         /* send isakmp payload */
1695         iph2->sendbuf = quick_ir1mx(iph2, body, hash);
1696         if (iph2->sendbuf == NULL)
1697                 goto end;
1698 
1699         /* send the packet, add to the schedule to resend */
1700         iph2->retry_counter = ikev1_max_retry_to_send(iph2->ph1->rmconf);
1701         if (isakmp_ph2resend(iph2) == -1)
1702                 goto end;
1703 
1704         /* the sending message is added to the received-list. */
1705         if (add_recvdpkt(iph2->ph1->remote, iph2->ph1->local, iph2->sendbuf, iph2->msg1, iph2->ph1->rmconf) == -1) {
1706                 plog(PLOG_INTERR , PLOGLOC, NULL,
1707                         "failed to add a response packet to the tree.\n");
1708                 goto end;
1709         }
1710 
1711         /* change status of isakmp status entry */
1712         iph2->status = PHASE2ST_MSG1SENT;
1713 
1714         error = 0;
1715 
1716 end:
1717         if (body != NULL)
1718                 rc_vfree(body);
1719         if (hash != NULL)
1720                 rc_vfree(hash);
1721 #ifdef ENABLE_NATT
1722         if (nat_oai != NULL)
1723                 rc_vfree(nat_oai);
1724         if (nat_oar != NULL)
1725                 rc_vfree(nat_oar);
1726 #endif
1727 
1728         return error;
1729 }
1730 
1731 /*
1732  * receive from initiator
1733  *      HDR*, HASH(3)
1734  */
1735 int
1736 quick_r3recv(struct ph2handle *iph2, rc_vchar_t *msg0)
1737 {
1738         rc_vchar_t *msg = NULL;
1739         rc_vchar_t *pbuf = NULL;        /* for payload parsing */
1740         struct isakmp_parse_t *pa;
1741         struct isakmp_pl_hash *hash = NULL;
1742         int error = ISAKMP_INTERNAL_ERROR;
1743 
1744         /* validity check */
1745         if (iph2->status != PHASE2ST_MSG1SENT) {
1746                 plog(PLOG_INTERR, PLOGLOC, NULL,
1747                         "status mismatched %d.\n", iph2->status);
1748                 goto end;
1749         }
1750 
1751         /* decrypt packet */
1752         if (!ISSET(((struct isakmp *)msg0->v)->flags, ISAKMP_FLAG_E)) {
1753                 isakmp_log(0, 0, iph2->ph1->remote, 0,
1754                            PLOG_PROTOERR, PLOGLOC,
1755                            "Packet wasn't encrypted.\n");
1756                 goto end;
1757         }
1758         msg = oakley_do_decrypt(iph2->ph1, msg0, iph2->ivm->iv, iph2->ivm->ive);
1759         if (msg == NULL)
1760                 goto end;
1761 
1762         /* validate the type of next payload */
1763         pbuf = isakmp_parse(msg);
1764         if (pbuf == NULL)
1765                 goto end;
1766 
1767         for (pa = (struct isakmp_parse_t *)pbuf->v;
1768              pa->type != ISAKMP_NPTYPE_NONE;
1769              pa++) {
1770 
1771                 switch (pa->type) {
1772                 case ISAKMP_NPTYPE_HASH:
1773                         hash = (struct isakmp_pl_hash *)pa->ptr;
1774                         break;
1775                 case ISAKMP_NPTYPE_N:
1776                         isakmp_check_notify(pa->ptr, iph2->ph1);
1777                         break;
1778                 default:
1779                         /* don't send information, see ident_r1recv() */
1780                         isakmp_log(0, 0, iph2->ph1->remote, 0,
1781                                    PLOG_PROTOERR, PLOGLOC,
1782                                    "ignore the packet, "
1783                                    "received unexpecting payload type %d.\n",
1784                                    pa->type);
1785                         goto end;
1786                 }
1787         }
1788 
1789         /* payload existency check */
1790         if (hash == NULL) {
1791                 isakmp_log(0, 0, iph2->ph1->remote, 0,
1792                            PLOG_PROTOERR, PLOGLOC,
1793                            "few isakmp message received.\n");
1794                 goto end;
1795         }
1796 
1797         /* validate HASH(3) */
1798         /* HASH(3) = prf(SKEYID_a, 0 | M-ID | Ni_b | Nr_b) */
1799     {
1800         char *r_hash;
1801         rc_vchar_t *my_hash = NULL;
1802         rc_vchar_t *tmp = NULL;
1803         int result;
1804 
1805         r_hash = (char *)hash + sizeof(*hash);
1806 
1807         plog(PLOG_DEBUG, PLOGLOC, NULL, "HASH(3) validate:");
1808         plogdump(PLOG_DEBUG, PLOGLOC, 0, r_hash, get_uint16(&hash->h.len) - sizeof(*hash));
1809 
1810         tmp = rc_vmalloc(iph2->nonce_p->l + iph2->nonce->l);
1811         if (tmp == NULL) { 
1812                 plog(PLOG_INTERR, PLOGLOC, NULL,
1813                         "failed to get hash buffer.\n");
1814                 goto end;
1815         }
1816         memcpy(tmp->v, iph2->nonce_p->v, iph2->nonce_p->l);
1817         memcpy(tmp->v + iph2->nonce_p->l, iph2->nonce->v, iph2->nonce->l);
1818 
1819         my_hash = oakley_compute_hash3(iph2->ph1, iph2->msgid, tmp);
1820         rc_vfree(tmp);
1821         if (my_hash == NULL)
1822                 goto end;
1823 
1824         result = memcmp(my_hash->v, r_hash, my_hash->l);
1825         rc_vfree(my_hash);
1826 
1827         if (result) {
1828                 isakmp_log(0, 0, iph2->ph1->remote, 0,
1829                            PLOG_PROTOERR, PLOGLOC,
1830                            "HASH(3) mismatch.\n");
1831                 error = ISAKMP_NTYPE_INVALID_HASH_INFORMATION;
1832                 goto end;
1833         }
1834     }
1835 
1836         /* if there is commit bit, don't set up SA now. */
1837         if (ISSET(iph2->flags, ISAKMP_FLAG_C)) {
1838                 iph2->status = PHASE2ST_COMMIT;
1839         } else
1840                 iph2->status = PHASE2ST_STATUS6;
1841 
1842         error = 0;
1843 
1844 end:
1845         if (pbuf != NULL)
1846                 rc_vfree(pbuf);
1847         if (msg != NULL)
1848                 rc_vfree(msg);
1849 
1850         return error;
1851 }
1852 
1853 /*
1854  * send to initiator
1855  *      HDR#*, HASH(4), notify
1856  */
1857 int
1858 quick_r3send(struct ph2handle *iph2, rc_vchar_t *msg0)
1859 {
1860         rc_vchar_t *buf = NULL;
1861         rc_vchar_t *myhash = NULL;
1862         struct isakmp_pl_n *n;
1863         rc_vchar_t *notify = NULL;
1864         char *p;
1865         int tlen;
1866         int error = ISAKMP_INTERNAL_ERROR;
1867 
1868         /* validity check */
1869         if (iph2->status != PHASE2ST_COMMIT) {
1870                 plog(PLOG_INTERR, PLOGLOC, NULL,
1871                         "status mismatched %d.\n", iph2->status);
1872                 goto end;
1873         }
1874 
1875         /* generate HASH(4) */
1876         /* XXX What can I do in the case of multiple different SA */
1877         plog(PLOG_DEBUG, PLOGLOC, NULL, "HASH(4) generate\n");
1878 
1879         /* XXX What should I do if there are multiple SAs ? */
1880         tlen = sizeof(struct isakmp_pl_n) + iph2->approval->head->spisize;
1881         notify = rc_vmalloc(tlen);
1882         if (notify == NULL) { 
1883                 plog(PLOG_INTERR, PLOGLOC, NULL,
1884                         "failed to get notify buffer.\n");
1885                 goto end;
1886         }
1887         n = (struct isakmp_pl_n *)notify->v;
1888         n->h.np = ISAKMP_NPTYPE_NONE;
1889         put_uint16(&n->h.len, tlen);
1890         put_uint32(&n->doi, IPSEC_DOI);
1891         n->proto_id = iph2->approval->head->proto_id;
1892         n->spi_size = sizeof(iph2->approval->head->spisize);
1893         put_uint16(&n->type, ISAKMP_NTYPE_CONNECTED);
1894         memcpy(n + 1, &iph2->approval->head->spi, iph2->approval->head->spisize);
1895 
1896         myhash = oakley_compute_hash1(iph2->ph1, iph2->msgid, notify);
1897         if (myhash == NULL)
1898                 goto end;
1899 
1900         /* create buffer for isakmp payload */
1901         tlen = sizeof(struct isakmp)
1902                 + sizeof(struct isakmp_gen) + myhash->l
1903                 + notify->l;
1904         buf = rc_vmalloc(tlen);
1905         if (buf == NULL) { 
1906                 plog(PLOG_INTERR, PLOGLOC, NULL,
1907                         "failed to get buffer to send.\n");
1908                 goto end;
1909         }
1910 
1911         /* create isakmp header */
1912         p = set_isakmp_header2(buf, iph2, ISAKMP_NPTYPE_HASH);
1913         if (p == NULL)
1914                 goto end;
1915 
1916         /* add HASH(4) payload */
1917         p = set_isakmp_payload(p, myhash, ISAKMP_NPTYPE_N);
1918 
1919         /* add notify payload */
1920         memcpy(p, notify->v, notify->l);
1921 
1922 #ifdef HAVE_PRINT_ISAKMP_C
1923         isakmp_printpacket(buf, iph2->ph1->local, iph2->ph1->remote, 1);
1924 #endif
1925 
1926         /* encoding */
1927         iph2->sendbuf = oakley_do_encrypt(iph2->ph1, buf, iph2->ivm->ive, iph2->ivm->iv);
1928         if (iph2->sendbuf == NULL)
1929                 goto end;
1930 
1931         /* send the packet */
1932         if (isakmp_send(iph2->ph1, iph2->sendbuf) < 0)
1933                 goto end;
1934 
1935         /* the sending message is added to the received-list. */
1936         if (add_recvdpkt(iph2->ph1->remote, iph2->ph1->local, iph2->sendbuf, msg0, iph2->ph1->rmconf) == -1) {
1937                 plog(PLOG_INTERR , PLOGLOC, NULL,
1938                         "failed to add a response packet to the tree.\n");
1939                 goto end;
1940         }
1941 
1942         iph2->status = PHASE2ST_COMMIT;
1943 
1944         error = 0;
1945 
1946 end:
1947         if (buf != NULL)
1948                 rc_vfree(buf);
1949         if (myhash != NULL)
1950                 rc_vfree(myhash);
1951         if (notify != NULL)
1952                 rc_vfree(notify);
1953 
1954         return error;
1955 }
1956 
1957 
1958 /*
1959  * set SA to kernel.
1960  */
1961 int
1962 quick_r3prep(struct ph2handle *iph2, rc_vchar_t *msg0)
1963 {
1964         rc_vchar_t *msg = NULL;
1965         int lifetime;
1966         int error = ISAKMP_INTERNAL_ERROR;
1967 
1968         /* validity check */
1969         if (iph2->status != PHASE2ST_STATUS6) {
1970                 plog(PLOG_INTERR, PLOGLOC, NULL,
1971                         "status mismatched %d.\n", iph2->status);
1972                 goto end;
1973         }
1974 
1975         /* compute both of KEYMATs */
1976         if (oakley_compute_keymat(iph2, RESPONDER) < 0)
1977                 goto end;
1978 
1979         iph2->status = PHASE2ST_ADDSA;
1980         iph2->flags ^= ISAKMP_FLAG_C;        /* reset bit */
1981 
1982         /* generate policy */
1983         if (rcs_is_addr_rw(iph2->selector->pl->peers_sa_ipaddr)) {
1984                 IPSEC_CONF(lifetime, iph2->selector->pl->ips,
1985                            ipsec_sa_lifetime_time, 0);
1986                 if (ike_spmif_post_policy_add(iph2->selector,
1987                                               ike_ipsec_mode(iph2->selector->pl),
1988                                               lifetime, iph2->src, iph2->dst,
1989                                               iph2->ph1->rmconf) < 0) {
1990                         plog(PLOG_INTERR, PLOGLOC, NULL,
1991                              "generate policy failed.\n");
1992                         goto end;
1993                 }
1994         }
1995 
1996         plog(PLOG_DEBUG, PLOGLOC, NULL, "call fill_in_ipsec_sas");
1997         error = fill_in_ipsec_sas(iph2);
1998 
1999 end:
2000         if (msg != NULL)
2001                 rc_vfree(msg);
2002 
2003         return error;
2004 }
2005 
2006 
2007 /*
2008  * create HASH, body (SA, NONCE) payload with isakmp header.
2009  */
2010 static rc_vchar_t *
2011 quick_ir1mx(struct ph2handle *iph2, rc_vchar_t *body, rc_vchar_t *hash)
2012 {
2013         struct isakmp *isakmp;
2014         rc_vchar_t *buf = NULL, *new = NULL;
2015         char *p;
2016         int tlen;
2017         struct isakmp_gen *gen;
2018         int error = ISAKMP_INTERNAL_ERROR;
2019 
2020         /* create buffer for isakmp payload */
2021         tlen = sizeof(*isakmp)
2022                 + sizeof(*gen) + hash->l
2023                 + body->l;
2024         buf = rc_vmalloc(tlen);
2025         if (buf == NULL) { 
2026                 plog(PLOG_INTERR, PLOGLOC, NULL,
2027                         "failed to get buffer to send.\n");
2028                 goto end;
2029         }
2030 
2031         /* re-set encryption flag, for serurity. */
2032         iph2->flags |= ISAKMP_FLAG_E;
2033 
2034         /* set isakmp header */
2035         p = set_isakmp_header2(buf, iph2, ISAKMP_NPTYPE_HASH);
2036         if (p == NULL)
2037                 goto end;
2038 
2039         /* add HASH payload */
2040         /* XXX is next type always SA ? */
2041         p = set_isakmp_payload(p, hash, ISAKMP_NPTYPE_SA);
2042 
2043         /* add body payload */
2044         memcpy(p, body->v, body->l);
2045 
2046 #ifdef HAVE_PRINT_ISAKMP_C
2047         isakmp_printpacket(buf, iph2->ph1->local, iph2->ph1->remote, 1);
2048 #endif
2049 
2050         /* encoding */
2051         new = oakley_do_encrypt(iph2->ph1, buf, iph2->ivm->ive, iph2->ivm->iv);
2052         if (new == NULL)
2053                 goto end;
2054 
2055         rc_vfree(buf);
2056 
2057         buf = new;
2058 
2059         error = 0;
2060 
2061 end:
2062         if (error && buf != NULL) {
2063                 rc_vfree(buf);
2064                 buf = NULL;
2065         }
2066 
2067         return buf;
2068 }
2069 
2070 /*
2071  * get remote's sainfo.
2072  * NOTE: this function is for responder.
2073  */
2074 static int
2075 get_sainfo_r(struct ph2handle *iph2)
2076 {
2077         rc_vchar_t *idsrc = NULL, *iddst = NULL;
2078         int prefixlen;
2079         int error = ISAKMP_INTERNAL_ERROR;
2080 
2081         if (iph2->id == NULL) {
2082                 struct sockaddr *sa;
2083 
2084                 switch (iph2->src->sa_family) {
2085                 case AF_INET:
2086                         prefixlen = sizeof(struct in_addr) << 3;
2087                         break;
2088                 case AF_INET6:
2089                         prefixlen = sizeof(struct in6_addr) << 3;
2090                         break;
2091                 default:
2092                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
2093                                 "invalid family: %d\n", iph2->src->sa_family);
2094                         goto end;
2095                 }
2096                 sa = rcs_sadup(iph2->src);
2097                 set_port(sa, 0);
2098                 idsrc = ipsecdoi_sockaddr2id(sa, prefixlen,
2099                                         IPSEC_ULPROTO_ANY);
2100                 rc_free(sa);
2101         } else {
2102                 idsrc = rc_vdup(iph2->id);
2103         }
2104         if (idsrc == NULL) {
2105                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2106                         "failed to set ID for source.\n");
2107                 goto end;
2108         }
2109 
2110         if (iph2->id_p == NULL) {
2111                 struct sockaddr *sa;
2112 
2113                 switch (iph2->dst->sa_family) {
2114                 case AF_INET:
2115                         prefixlen = sizeof(struct in_addr) << 3;
2116                         break;
2117                 case AF_INET6:
2118                         prefixlen = sizeof(struct in6_addr) << 3;
2119                         break;
2120                 default:
2121                         plog(PLOG_PROTOERR, PLOGLOC, NULL,
2122                                 "invalid family: %d\n", iph2->dst->sa_family);
2123                         goto end;
2124                 }
2125                 sa = rcs_sadup(iph2->dst);
2126                 set_port(sa, 0);
2127                 iddst = ipsecdoi_sockaddr2id(sa, prefixlen,
2128                                         IPSEC_ULPROTO_ANY);
2129                 rc_free(sa);
2130         } else {
2131                 iddst = rc_vdup(iph2->id_p);
2132         }
2133         if (iddst == NULL) {
2134                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2135                         "failed to set ID for destination.\n");
2136                 goto end;
2137         }
2138 
2139         iph2->selector = ike_conf_find_ikev1sel_by_id(idsrc, iddst);
2140         if (! iph2->selector) {
2141                 plog(PLOG_INTERR, PLOGLOC, 0,
2142                      "can't find matching selector\n");
2143                 goto end;
2144         }
2145 
2146 #if 0
2147         iph2->sainfo = getsainfo(idsrc, iddst, iph2->ph1->id_p);
2148         if (iph2->sainfo == NULL) {
2149                 plog(PLOG_INTERR, PLOGLOC, NULL,
2150                         "failed to get sainfo.\n");
2151                 goto end;
2152         }
2153 
2154         plog(PLOG_DEBUG, PLOGLOC, NULL,
2155                 "get sa info: %s\n", sainfo2str(iph2->sainfo));
2156 #endif
2157 
2158         error = 0;
2159 end:
2160         if (idsrc)
2161                 rc_vfree(idsrc);
2162         if (iddst)
2163                 rc_vfree(iddst);
2164 
2165         return error;
2166 }
2167 
2168 
2169 /*
2170  * Copy both IP addresses in ID payloads into [src,dst]_id if both ID types
2171  * are IP address and same address family.
2172  * Then get remote's policy from SPD copied from kernel.
2173  * If the type of ID payload is address or subnet type, then the index is
2174  * made from the payload.  If there is no ID payload, or the type of ID
2175  * payload is NOT address type, then the index is made from the address
2176  * pair of phase 1.
2177  * NOTE: This function is only for responder.
2178  */
2179 static int
2180 get_proposal_r(struct ph2handle *iph2)
2181 {
2182         struct rcf_selector *selector;
2183         struct rcf_policy *p;
2184 
2185         /* check the existence of ID payload */
2186         if ((iph2->id_p != NULL && iph2->id == NULL)
2187          || (iph2->id_p == NULL && iph2->id != NULL)) {
2188                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2189                         "Both IDs wasn't found in payload.\n");
2190                 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
2191         }
2192 
2193         if (iph2->src_id || iph2->dst_id) {
2194                 plog(PLOG_INTERR, PLOGLOC, 0,
2195                      "ph2handle has ID[src, dst] already\n");
2196                 return ISAKMP_INTERNAL_ERROR;
2197         }
2198 
2199         selector = iph2->selector;
2200         p = selector->pl;
2201         if (!p) {
2202                 plog(PLOG_INTERR, PLOGLOC, 0,
2203                      "selector (index %s) does not have policy\n",
2204                      rc_vmem2str(selector->sl_index));
2205                 return ISAKMP_INTERNAL_ERROR;
2206         }
2207 
2208         if (set_proposal_from_policy(iph2, iph2->ph1->rmconf, p)) {
2209                 plog(PLOG_INTERR, PLOGLOC, 0,
2210                      "failed to create saprop.\n");
2211                 return ISAKMP_INTERNAL_ERROR;
2212         }
2213 
2214         return 0;
2215 #if 0
2216         struct policyindex spidx;
2217         struct secpolicy *sp_in, *sp_out;
2218         int idi2type = 0;       /* switch whether copy IDs into id[src,dst]. */
2219         int error = ISAKMP_INTERNAL_ERROR;
2220 
2221         /* check the existence of ID payload */
2222         if ((iph2->id_p != NULL && iph2->id == NULL)
2223          || (iph2->id_p == NULL && iph2->id != NULL)) {
2224                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2225                         "Both IDs wasn't found in payload.\n");
2226                 return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
2227         }
2228 
2229         /* make sure if id[src,dst] is null. */
2230         if (iph2->src_id || iph2->dst_id) {
2231                 plog(PLOG_PROTOERR, PLOGLOC, NULL,
2232                         "Why do ID[src,dst] exist already.\n");
2233                 return ISAKMP_INTERNAL_ERROR;
2234         }
2235 
2236         memset(&spidx, 0, sizeof(spidx));
2237 
2238 #define _XIDT(d) ((struct ipsecdoi_id_b *)(d)->v)->type
2239 
2240         /* make a spidx; a key to search SPD */
2241         spidx.dir = IPSEC_DIR_INBOUND;
2242         spidx.ul_proto = 0;
2243 
2244         /*
2245          * make destination address in spidx from either ID payload
2246          * or phase 1 address into a address in spidx.
2247          */
2248         if (iph2->id != NULL
2249          && (_XIDT(iph2->id) == IPSECDOI_ID_IPV4_ADDR
2250           || _XIDT(iph2->id) == IPSECDOI_ID_IPV6_ADDR
2251           || _XIDT(iph2->id) == IPSECDOI_ID_IPV4_ADDR_SUBNET
2252           || _XIDT(iph2->id) == IPSECDOI_ID_IPV6_ADDR_SUBNET)) {
2253                 /* get a destination address of a policy */
2254                 error = ipsecdoi_id2sockaddr(iph2->id,
2255                                 (struct sockaddr *)&spidx.dst,
2256                                 &spidx.prefd, &spidx.ul_proto);
2257                 if (error)
2258                         return error;
2259 
2260 #ifdef INET6
2261                 /*
2262                  * get scopeid from the SA address.
2263                  * note that the phase 1 source address is used as
2264                  * a destination address to search for a inbound policy entry
2265                  * because rcoon is responder.
2266                  */
2267                 if (_XIDT(iph2->id) == IPSECDOI_ID_IPV6_ADDR) {
2268                         error = setscopeid((struct sockaddr *)&spidx.dst,
2269                                             iph2->src);
2270                         if (error)
2271                                 return error;
2272                 }
2273 #endif
2274 
2275                 if (_XIDT(iph2->id) == IPSECDOI_ID_IPV4_ADDR
2276                  || _XIDT(iph2->id) == IPSECDOI_ID_IPV6_ADDR)
2277                         idi2type = _XIDT(iph2->id);
2278 
2279         } else {
2280 
2281                 plog(PLOG_DEBUG, PLOGLOC, NULL,
2282                         "get a destination address of SP index "
2283                         "from phase1 address "
2284                         "due to no ID payloads found "
2285                         "OR because ID type is not address.\n");
2286 
2287                 /*
2288                  * copy the SOURCE address of IKE into the DESTINATION address
2289                  * of the key to search the SPD because the direction of policy
2290                  * is inbound.
2291                  */
2292                 memcpy(&spidx.dst, iph2->src, iph2->src->sa_len);
2293                 switch (spidx.dst.ss_family) {
2294                 case AF_INET:
2295                         spidx.prefd = sizeof(struct in_addr) << 3;
2296                         break;
2297 #ifdef INET6
2298                 case AF_INET6:
2299                         spidx.prefd = sizeof(struct in6_addr) << 3;
2300                         break;
2301 #endif
2302                 default:
2303                         spidx.prefd = 0;
2304                         break;
2305                 }
2306         }
2307 
2308         /* make source address in spidx */
2309         if (iph2->id_p != NULL
2310          && (_XIDT(iph2->id_p) == IPSECDOI_ID_IPV4_ADDR
2311           || _XIDT(iph2->id_p) == IPSECDOI_ID_IPV6_ADDR
2312           || _XIDT(iph2->id_p) == IPSECDOI_ID_IPV4_ADDR_SUBNET
2313           || _XIDT(iph2->id_p) == IPSECDOI_ID_IPV6_ADDR_SUBNET)) {
2314                 /* get a source address of inbound SA */
2315                 error = ipsecdoi_id2sockaddr(iph2->id_p,
2316                                 (struct sockaddr *)&spidx.src,
2317                                 &spidx.prefs, &spidx.ul_proto);
2318                 if (error)
2319                         return error;
2320 
2321 #ifdef INET6
2322                 /*
2323                  * get scopeid from the SA address.
2324                  * for more detail, see above of this function.
2325                  */
2326                 if (_XIDT(iph2->id_p) == IPSECDOI_ID_IPV6_ADDR) {
2327                         error = setscopeid((struct sockaddr *)&spidx.src,
2328                                             iph2->dst);
2329                         if (error)
2330                                 return error;
2331                 }
2332 #endif
2333 
2334                 /* make id[src,dst] if both ID types are IP address and same */
2335                 if (_XIDT(iph2->id_p) == idi2type
2336                  && spidx.dst.ss_family == spidx.src.ss_family) {
2337                         iph2->src_id = rcs_sadup((struct sockaddr *)&spidx.dst);
2338                         iph2->dst_id = rcs_sadup((struct sockaddr *)&spidx.src);
2339                 }
2340 
2341         } else {
2342                 plog(PLOG_DEBUG, PLOGLOC, NULL,
2343                         "get a source address of SP index "
2344                         "from phase1 address "
2345                         "due to no ID payloads found "
2346                         "OR because ID type is not address.\n");
2347 
2348                 /* see above comment. */
2349                 memcpy(&spidx.src, iph2->dst, iph2->dst->sa_len);
2350                 switch (spidx.src.ss_family) {
2351                 case AF_INET:
2352                         spidx.prefs = sizeof(struct in_addr) << 3;
2353                         break;
2354 #ifdef INET6
2355                 case AF_INET6:
2356                         spidx.prefs = sizeof(struct in6_addr) << 3;
2357                         break;
2358 #endif
2359                 default:
2360                         spidx.prefs = 0;
2361                         break;
2362                 }
2363         }
2364 
2365 #undef _XIDT
2366 
2367         plog(PLOG_DEBUG, PLOGLOC, NULL,
2368                 "get a src address from ID payload "
2369                 "%s prefixlen=%u ul_proto=%u\n",
2370              rcs_sa2str((struct sockaddr *)&spidx.src),
2371                 spidx.prefs, spidx.ul_proto);
2372         plog(PLOG_DEBUG, PLOGLOC, NULL,
2373                 "get dst address from ID payload "
2374                 "%s prefixlen=%u ul_proto=%u\n",
2375                 rcs_sa2str((struct sockaddr *)&spidx.dst),
2376                 spidx.prefd, spidx.ul_proto);
2377 
2378         /*
2379          * convert the ul_proto if it is 0
2380          * because 0 in ID payload means a wild card.
2381          */
2382         if (spidx.ul_proto == 0)
2383                 spidx.ul_proto = IPSEC_ULPROTO_ANY;
2384 
2385         /* get inbound policy */
2386         sp_in = getsp_r(&spidx);
2387         if (sp_in == NULL) {
2388                 if (iph2->ph1->rmconf->gen_policy) {
2389                         plog(PLOG_INFO, PLOGLOC, NULL,
2390                                 "no policy found, "
2391                                 "try to generate the policy : %s\n",
2392                                 spidx2str(&spidx));
2393                         iph2->spidx_gen = racoon_malloc(sizeof(spidx));
2394                         if (!iph2->spidx_gen) {
2395                                 plog(PLOG_INTERR, PLOGLOC, NULL,
2396                                         "buffer allocation failed.\n");
2397                                 return ISAKMP_INTERNAL_ERROR;
2398                         }
2399                         memcpy(iph2->spidx_gen, &spidx, sizeof(spidx));
2400                         return -2;      /* special value */
2401                 }
2402                 plog(PLOG_INTERR, PLOGLOC, NULL,
2403                         "no policy found: %s\n", spidx2str(&spidx));
2404                 return ISAKMP_INTERNAL_ERROR;
2405         }
2406         /* Refresh existing generated policies
2407          */
2408         if (iph2->ph1->rmconf->gen_policy) {
2409                 plog(LLV_INFO, LOCATION, NULL,
2410                          "Update the generated policy : %s\n",
2411                          spidx2str(&spidx));
2412                 iph2->spidx_gen = racoon_malloc(sizeof(spidx));
2413                 if (!iph2->spidx_gen) {
2414                         plog(PLOG_INTERR, PLOGLOC, NULL,
2415                                  "buffer allocation failed.\n");
2416                         return ISAKMP_INTERNAL_ERROR;
2417                 }
2418                 memcpy(iph2->spidx_gen, &spidx, sizeof(spidx));
2419         }
2420 
2421         /* get outbound policy */
2422     {
2423         struct sockaddr_storage addr;
2424         uint8_t pref;
2425 
2426         spidx.dir = IPSEC_DIR_OUTBOUND;
2427         addr = spidx.src;
2428         spidx.src = spidx.dst;
2429         spidx.dst = addr;
2430         pref = spidx.prefs;
2431         spidx.prefs = spidx.prefd;
2432         spidx.prefd = pref;
2433 
2434         sp_out = getsp_r(&spidx);
2435         if (!sp_out) {
2436                 plog(PLOG_INTWARN, PLOGLOC, NULL,
2437                         "no outbound policy found: %s\n",
2438                         spidx2str(&spidx));
2439         }
2440     }
2441 
2442         plog(PLOG_DEBUG, PLOGLOC, NULL,
2443                 "suitable SP found:%s\n", spidx2str(&spidx));
2444 
2445         /*
2446          * In the responder side, the inbound policy should be using IPsec.
2447          * outbound policy is not checked currently.
2448          */
2449         if (sp_in->policy != IPSEC_POLICY_IPSEC) {
2450                 plog(PLOG_INTERR, PLOGLOC, NULL,
2451                         "policy found, but no IPsec required: %s\n",
2452                         spidx2str(&spidx));
2453                 return ISAKMP_INTERNAL_ERROR;
2454         }
2455 
2456         /* set new proposal derived from a policy into the iph2->proposal. */
2457         if (set_proposal_from_policy(iph2, sp_in, sp_out) < 0) {
2458                 plog(PLOG_INTERR, PLOGLOC, NULL,
2459                         "failed to create saprop.\n");
2460                 return ISAKMP_INTERNAL_ERROR;
2461         }
2462 
2463         return 0;
2464 #endif /* 0 */
2465 }
2466 
2467 #ifdef INET6
2468 static uint32_t
2469 setscopeid(struct sockaddr *sp_addr0, struct sockaddr *sa_addr0)
2470 {
2471         struct sockaddr_in6 *sp_addr, *sa_addr;
2472     
2473         sp_addr = (struct sockaddr_in6 *)sp_addr0;
2474         sa_addr = (struct sockaddr_in6 *)sa_addr0;
2475 
2476         if (!IN6_IS_ADDR_LINKLOCAL(&sp_addr->sin6_addr)
2477          && !IN6_IS_ADDR_SITELOCAL(&sp_addr->sin6_addr)
2478          && !IN6_IS_ADDR_MULTICAST(&sp_addr->sin6_addr))
2479                 return 0;
2480 
2481         /* this check should not be here ? */
2482         if (sa_addr->sin6_family != AF_INET6) {
2483                 plog(PLOG_INTERR, PLOGLOC, NULL,
2484                         "can't get scope ID: family mismatch\n");
2485                 return -1;
2486         }
2487 
2488         if (!IN6_IS_ADDR_LINKLOCAL(&sa_addr->sin6_addr)) {
2489                 plog(PLOG_INTERR, PLOGLOC, NULL,
2490                         "scope ID is not supported except of lladdr.\n");
2491                 return -1;
2492         }
2493 
2494         sp_addr->sin6_scope_id = sa_addr->sin6_scope_id;
2495 
2496         return 0;
2497 }
2498 #endif