1 /* $Id: ike_pfkey.c,v 1.79 2008/02/06 08:08:59 mk Exp $ */
   2 
   3 /*
   4  * Copyright (C) 2004 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 /*
  33  * IKE-PFKEY interface bridge
  34  */
  35 
  36 #include <config.h>
  37 
  38 #include <stdio.h>
  39 #include <string.h>
  40 #ifdef HAVE_INTTYPES_H
  41 #  include <inttypes.h>
  42 #endif
  43 #include <sys/types.h>
  44 #if TIME_WITH_SYS_TIME
  45 #  include <sys/time.h>
  46 #  include <time.h>
  47 #else
  48 #  if HAVE_SYS_TIME_H
  49 #    include <sys/time.h>
  50 #  else
  51 #    include <time.h>
  52 #  endif
  53 #endif
  54 #include <arpa/inet.h>
  55 
  56 #include "racoon.h"
  57 #include "ike_pfkey.h"
  58 #include "isakmp_impl.h"
  59 #include "ikev2_impl.h"
  60 #include "debug.h"
  61 #ifdef IKEV1
  62 # include "oakley.h"
  63 # include "ikev1_impl.h"
  64 # include "ikev1/handler.h"
  65 #endif
  66 
  67 extern int debug_pfkey;
  68 static void dump_param(char *, struct rcpfk_msg *);
  69 
  70 static int sadb_getspi(struct rcpfk_msg *);
  71 static int sadb_acquire_error(struct rcpfk_msg *);
  72 static int sadb_inverse_acquire(struct rcpfk_msg *);
  73 static int sadb_update(struct rcpfk_msg *);
  74 static int sadb_get(struct rcpfk_msg *);
  75 static int sadb_add(struct rcpfk_msg *);
  76 static int sadb_responder_error(struct rcpfk_msg *);
  77 static int sadb_delete(struct rcpfk_msg *);
  78 
  79 static int
  80 null_proc()
  81 {
  82         return 0;
  83 }
  84 
  85 /* sadb_initiator_request_method used in response to SADB_ACQUIRE */
  86 struct sadb_request_method sadb_initiator_request_method = {
  87         sadb_getspi,
  88         sadb_acquire_error,
  89         sadb_update,
  90         sadb_add,
  91         sadb_delete,
  92         sadb_get,
  93 #ifdef sun
  94         null_proc,
  95 #endif /* sun/OpenSolaris */
  96 };
  97 
  98 /* sadb_responder_request_method for use when receiving IKE_SA_INIT packet */
  99 struct sadb_request_method sadb_responder_request_method = {
 100         sadb_getspi,
 101         sadb_responder_error,
 102         sadb_update,
 103         sadb_add,
 104         sadb_delete,
 105         sadb_get,
 106 #ifdef sun
 107         sadb_inverse_acquire,
 108 #endif /* sun/OpenSolaris */
 109 };
 110 
 111 /* sadb_rekey_request_method for use when rekeying soft-expired IPsec SA */
 112 struct sadb_request_method sadb_rekey_request_method = {
 113         sadb_getspi,
 114         sadb_responder_error,
 115         sadb_update,
 116         sadb_add,
 117         sadb_delete,
 118         sadb_get,
 119 };
 120 
 121 /* sadb_null_method for informational exchange SA */
 122 struct sadb_request_method sadb_null_method = {
 123         null_proc, null_proc, null_proc, null_proc, null_proc, null_proc
 124 #ifdef sun
 125         , null_proc
 126 #endif /* sun/OpenSolaris */
 127 };
 128 
 129 /* sadb_force_initiate_method for use with isakmp_force_initiate() */
 130 struct sadb_request_method sadb_force_initiate_method = {
 131         sadb_getspi,
 132         sadb_responder_error,   /* to ignore error */
 133         sadb_update,
 134         sadb_add,
 135         sadb_delete,
 136         sadb_get,
 137 #ifdef sun
 138         null_proc,
 139 #endif /* sun/OpenSolaris */
 140 };
 141 
 142 static SADB_LIST_HEAD(sadb_request_list_head, sadb_request) sadb_request_list_head;
 143 
 144 static int pfkey_socket;
 145 static uint32_t my_sadb_seqnum;
 146 
 147 static int sadb_getspi_callback(struct rcpfk_msg *param);
 148 static int sadb_update_callback(struct rcpfk_msg *param);
 149 static int sadb_get_callback(struct rcpfk_msg *param);
 150 static int sadb_expire_callback(struct rcpfk_msg *param);
 151 static int sadb_acquire_callback(struct rcpfk_msg *param);
 152 static int sadb_delete_callback(struct rcpfk_msg *param);
 153 #ifdef SADB_X_MIGRATE
 154 static int sadb_x_migrate_callback(struct rcpfk_msg *param);
 155 #endif
 156 
 157 static struct rcpfk_cb ike_rcpfk_callback = {
 158         sadb_getspi_callback,
 159         sadb_update_callback,
 160         0,              /* sadb_add_callback, */
 161         sadb_expire_callback,
 162         sadb_acquire_callback,
 163         sadb_delete_callback,
 164         sadb_get_callback,
 165         0,              /* sadb_spdupdate_callback, */
 166         0,              /* sadb_spdadd_callback, */
 167         0,              /* sadb_spddelete_callback, */
 168         0,              /* sadb_spddelete2_callback, */
 169         0,              /* sadb_spdexpire_callbcak, */
 170         0,              /* sadb_spdget_callback */
 171         0,              /* sadb_spddump_callback */
 172 #ifdef SADB_X_MIGRATE
 173         sadb_x_migrate_callback,
 174 #endif
 175 };
 176 
 177 int
 178 sadb_init(void)
 179 {
 180         struct rcpfk_msg param;
 181 
 182         (void) memset(&param, 0, sizeof (param));
 183 
 184         SADB_LIST_INIT(&sadb_request_list_head);
 185         if (debug_pfkey)
 186                 return 0;
 187 
 188         param.flags = 0;
 189 
 190         if (rcpfk_init(&param, &ike_rcpfk_callback) != 0)
 191                 return -1;
 192         pfkey_socket = param.so;
 193         TRACE((PLOGLOC, "pfkey_socket: %d\n", pfkey_socket));
 194         return 0;
 195 }
 196 
 197 #ifdef DEBUG
 198 void
 199 sadb_list_dump(void)
 200 {
 201         struct sadb_request *req;
 202 
 203         plog(PLOG_DEBUG, PLOGLOC, 0, "sadb request list:\n");
 204         for (req = SADB_LIST_FIRST(&sadb_request_list_head);
 205              !SADB_LIST_END(req);
 206              req = SADB_LIST_NEXT(req)) {
 207                 plog(PLOG_DEBUG, PLOGLOC, 0,
 208                      "req %p method:%p seqno:%lx sa:%p\n",
 209                      req, req->method, (unsigned long)req->seqno,
 210                      req->sa);
 211         }
 212         plog(PLOG_DEBUG, PLOGLOC, 0, "end\n");
 213 }
 214 #endif
 215 
 216 int
 217 sadb_socket(void)
 218 {
 219         return pfkey_socket;
 220 }
 221 
 222 uint32_t
 223 sadb_new_seq(void)
 224 {
 225         return ++my_sadb_seqnum;
 226 }
 227 
 228 static void
 229 log_rcpfk_error(const char *msg, struct rcpfk_msg *param)
 230 {
 231         if (param->eno) {
 232                 isakmp_log(0, 0, 0, 0,
 233                            PLOG_INTERR, PLOGLOC,
 234                            "%s: %s\n", msg, param->estr);
 235         } else {
 236                 isakmp_log(0, 0, 0, 0,
 237                            PLOG_INTERR, PLOGLOC,
 238                            "%s: unknown error\n", msg);
 239         }
 240 }
 241 
 242 void
 243 sadb_poll(void)
 244 {
 245         struct rcpfk_msg rcpfk_param;
 246 
 247         (void) memset(&rcpfk_param, 0, sizeof (rcpfk_param));
 248         rcpfk_param.so = pfkey_socket;
 249         rcpfk_param.flags = 0;
 250         if (rcpfk_handler(&rcpfk_param) != 0) {
 251                 log_rcpfk_error("sadb_poll", &rcpfk_param);
 252         }
 253 }
 254 
 255 void
 256 sadb_request_initialize(struct sadb_request *req,
 257                         struct sadb_request_method *m,
 258                         struct sadb_response_method *r,
 259                         uint32_t seqno, void *sa)
 260 {
 261         req->method = m;
 262         req->callback = r;
 263         req->seqno = seqno;
 264         req->sa = sa;
 265         SADB_LIST_LINK(&sadb_request_list_head, req);
 266 }
 267 
 268 void
 269 sadb_request_finish(struct sadb_request *req)
 270 {
 271         TRACE((PLOGLOC, "%p\n", req));
 272         if (req->link.tqe_prev != 0) /* initialized? */
 273                 SADB_LIST_REMOVE(&sadb_request_list_head, req);
 274 }
 275 
 276 /*
 277  * Send a SADB_GETSPI message
 278  */
 279 static int
 280 sadb_getspi(struct rcpfk_msg *param)
 281 {
 282         int err;
 283 
 284         TRACE((PLOGLOC, "sadb_getspi: seq=%d, satype=%d\n",
 285                param->seq, param->satype));
 286 
 287         param->so = pfkey_socket;
 288         param->eno = 0;
 289         param->flags = 0;
 290         err = rcpfk_send_getspi(param);
 291         if (err)
 292                 log_rcpfk_error("sadb_getspi", param);
 293         return err;
 294 }
 295 
 296 /*
 297  * send SADB_ACQUIRE with error to inform kernel of SA creation failure
 298  */
 299 static int
 300 sadb_acquire_error(struct rcpfk_msg *param)
 301 {
 302         int err;
 303 
 304         TRACE((PLOGLOC,
 305                "sadb_acquire_error: seq=%d, satype=%d, errno=%d\n",
 306                param->seq, param->satype, param->eno));
 307 
 308         /* param: so, satype, seq, eno */
 309         param->so = pfkey_socket;
 310         param->flags = 0;
 311         err = rcpfk_send_acquire(param);
 312         if (err)
 313                 log_rcpfk_error("sadb_acquire_error", param);
 314         return err;
 315 }
 316 
 317 #ifdef sun
 318 static int
 319 sadb_inverse_acquire(struct rcpfk_msg *param)
 320 {
 321         int err;
 322 
 323         TRACE((PLOGLOC, "sadb_inverse_acquire: seq=%d\n", param->seq));
 324 
 325         /* param: so, satype, seq, eno */
 326         param->so = pfkey_socket;
 327         param->flags = 0;
 328         err = rcpfk_send_inverse_acquire(param);
 329         if (err)
 330                 log_rcpfk_error("sadb_inverse_acquire", param);
 331         return (err);
 332 }
 333 #endif /* sun/OpenSolaris */
 334 
 335 #define sa2str_chk(sa) (((sa) == NULL) ? "<none>" : rcs_sa2str(sa))
 336 
 337 static void
 338 sadb_log_add(char *op, struct rcpfk_msg *param)
 339 {
 340         if (param->satype == RCT_SATYPE_ESP) {
 341                 INFO((PLOGLOC,
 342                       "%s ul_proto=%d src=%s dst=%s "
 343 #ifdef sun
 344                       "isrc=%s idst=%s nlc=%s nrm=%s"
 345 #endif
 346                       "satype=%s samode=%s spi=0x%08x authtype=%s enctype=%s lifetime soft time=%"
 347                       PRIu64 " bytes=%" PRIu64 " hard time=%" PRIu64 " bytes=%" PRIu64 "\n",
 348                       op, param->ul_proto, rcs_sa2str(param->sa_src),
 349                       rcs_sa2str(param->sa_dst),
 350 #ifdef sun
 351                       sa2str_chk(param->sa_isrc), sa2str_chk(param->sa_idst),
 352                       sa2str_chk(param->sa_natlocal),
 353                       sa2str_chk(param->sa_natremote),
 354 #endif
 355                       rct2str(param->satype),
 356                       rct2str(param->samode), ntohl(param->spi),
 357                       rct2str(param->authtype), rct2str(param->enctype),
 358                       param->lft_soft_time, param->lft_soft_bytes,
 359                       param->lft_hard_time, param->lft_hard_bytes));
 360         } else {
 361                 INFO((PLOGLOC,
 362                       "%s ul_proto=%d src=%s dst=%s "
 363 #ifdef sun
 364                       "isrc=%s idst=%s nlc=%s nrm=%s"
 365 #endif
 366                       "satype=%s samode=%s spi=0x%08x authtype=%s lifetime soft time=%"
 367                       PRIu64 " bytes=%" PRIu64 " hard time=%" PRIu64 " bytes=%" PRIu64 "\n",
 368                       op, param->ul_proto, rcs_sa2str(param->sa_src),
 369                       rcs_sa2str(param->sa_dst),
 370 #ifdef sun
 371                       sa2str_chk(param->sa_isrc), sa2str_chk(param->sa_idst),
 372                       sa2str_chk(param->sa_natlocal),
 373                       sa2str_chk(param->sa_natremote),
 374 #endif
 375                       rct2str(param->satype),
 376                       rct2str(param->samode), ntohl(param->spi),
 377                       rct2str(param->authtype), param->lft_soft_time,
 378                       param->lft_soft_bytes, param->lft_hard_time,
 379                       param->lft_hard_bytes));
 380         }
 381 }
 382 
 383 /* send SADB_UPDATE */
 384 static int
 385 sadb_update(struct rcpfk_msg *param)
 386 {
 387         int err;
 388 
 389         sadb_log_add("SADB_UPDATE", param);
 390         IF_TRACE(dump_param("sadb_update", param));
 391 
 392         /* param:
 393          * so, satype, seq, spi, wsize, authtype, [enctype,] saflags, samode, reqid,
 394          * lft_hard_time, lft_hard_bytes, lft_soft_time, lft_soft_bytes,
 395          * sa_src, pref_src, sa_dst, pref_dst, ul_proto,
 396          * [enckey, enckeylen], authkey, authkeylen
 397          */
 398         param->so = pfkey_socket;
 399         param->eno = 0;
 400         err = rcpfk_send_update(param);
 401         if (err)
 402                 log_rcpfk_error("sadb_update", param);
 403         return err;
 404 }
 405 
 406 /* send SADB_ADD */
 407 static int
 408 sadb_add(struct rcpfk_msg *param)
 409 {
 410         int err;
 411 
 412         sadb_log_add("SADB_ADD", param);
 413         IF_TRACE(dump_param("sadb_add", param));
 414 
 415         param->so = pfkey_socket;
 416         param->eno = 0;
 417         err = rcpfk_send_add(param);
 418         if (err)
 419                 log_rcpfk_error("sadb_add", param);
 420         return err;
 421 }
 422 
 423 /* send SADB_GET */
 424 static int
 425 sadb_get(struct rcpfk_msg *param)
 426 {
 427         int err;
 428 
 429         IF_TRACE(dump_param("sadb_get", param));
 430 
 431         param->so = pfkey_socket;
 432         param->eno = 0;
 433         err = rcpfk_send_get(param);
 434         if (err)
 435                 log_rcpfk_error("sadb_get", param);
 436         return err;
 437 }
 438 
 439 /*
 440  * acquire_error for responder
 441  */
 442 static int
 443 sadb_responder_error(struct rcpfk_msg *param)
 444 {
 445         /* just ignore since there's no corresponding SADB_ACQUIRE */
 446         TRACE((PLOGLOC,
 447                "sadb_responder_error: seq=%d, satype=%d, spi=0x%08x, errno=%d\n",
 448                param->seq, param->satype, ntohl(param->spi), param->eno));
 449         return 0;
 450 }
 451 
 452 /*
 453  * send SADB_DELETE
 454  */
 455 static int
 456 sadb_delete(struct rcpfk_msg *rc)
 457 {
 458         int err;
 459 
 460         INFO((PLOGLOC,
 461               "SADB_DELETE ul_proto=%d src=%s dst=%s satype=%s spi=0x%08x\n",
 462               rc->ul_proto, rcs_sa2str(rc->sa_src), rcs_sa2str(rc->sa_dst),
 463               rct2str(rc->satype), ntohl(rc->spi)));
 464         TRACE((PLOGLOC,
 465                "sadb_delete: sa_src=%s, sa_dst=%s, satype=%d (%s), spi=0x%08x\n",
 466                rcs_sa2str(rc->sa_src), rcs_sa2str(rc->sa_dst), rc->satype,
 467                rct2str(rc->satype), ntohl(rc->spi)));
 468 
 469         /* param: so, satype, spi, sa_src, sa_dst, ul_proto */
 470         /* XXX
 471          *        pref_dst,pref_src must be <= addrlen, eventhough the values aren't used
 472          */
 473         rc->so = pfkey_socket;
 474         rc->eno = 0;
 475         rc->seq = 0;
 476         rc->pref_src = rc->pref_dst = 0;  /* ??? */
 477         rc->flags = 0;
 478         err = rcpfk_send_delete(rc);
 479         if (err)
 480                 log_rcpfk_error("sadb_delete", rc);
 481         return err;
 482 }
 483 
 484 /*
 485  * find sadb_request by seq
 486  */
 487 static struct sadb_request *
 488 sadb_find_by_seq(uint32_t seq)
 489 {
 490         struct sadb_request     *req;
 491 
 492         for (req = SADB_LIST_FIRST(&sadb_request_list_head);
 493              !SADB_LIST_END(req);
 494              req = SADB_LIST_NEXT(req)) {
 495                 if (req->seqno == seq)
 496                         return req;
 497         }
 498         return 0;
 499 }
 500 
 501 
 502 /*
 503  * receive SADB_GETSPI message from kernel
 504  */
 505 static int
 506 sadb_getspi_callback(struct rcpfk_msg *param)
 507 {
 508         /* param: seq, satype, spi, sa_src, sa_dst */
 509 
 510         struct sadb_request *req;
 511 
 512         TRACE((PLOGLOC,
 513                "sadb_getspi_callback: seq=%d, spi=0x%08x, satype=%d, sa_src=%s, sa_dst=%s\n",
 514                param->seq, ntohl(param->spi), param->satype,
 515                rcs_sa2str(param->sa_src), rcs_sa2str(param->sa_dst)));
 516 
 517         /* find sadb_request by param->seq */
 518         req = sadb_find_by_seq(param->seq);
 519         if (!req) {
 520 
 521                 /* couldn't find corresponding SA */
 522                 isakmp_log(0, 0, 0, 0,
 523                            PLOG_INTWARN, PLOGLOC,
 524                            "received PF_KEY SADB_GETSPI message (seq %u) does not have corresponding request. (ignored)\n",
 525                            param->seq);
 526                 return -1;
 527         }
 528 
 529         (*req->callback->getspi_response)(req, param->sa_src,
 530                                         param->sa_dst,
 531                                         (unsigned int)param->satype,
 532                                         ntohl(param->spi));
 533         return 0;
 534 }
 535 
 536 
 537 /* called when other KMd issued SADB_UPDATE */
 538 static int
 539 sadb_update_callback(struct rcpfk_msg *param)
 540 {
 541         /* param: seq, satype, spi, sa_src, sa_dst, samode */
 542         /* lifetime??? address(P)??? identity??? */
 543 
 544         struct sadb_request *req;
 545 
 546         TRACE((PLOGLOC,
 547                "sadb_update_callback: seq=%d, spi=0x%08x, satype=%d, sa_src=%s,"
 548                " sa_dst=%s, samode=%d\n",
 549                param->seq, ntohl(param->spi), param->satype,
 550                rcs_sa2str(param->sa_src), rcs_sa2str(param->sa_dst),
 551                param->samode));
 552 
 553         req = sadb_find_by_seq(param->seq);
 554         if (!req) {
 555 
 556                 /* couldn't find corresponding SA */
 557                 isakmp_log(0, 0, 0, 0,
 558                            PLOG_INTWARN, PLOGLOC,
 559                            "received PF_KEY SADB_UPDATE message (seq %u) does not have corresponding request. (ignored)\n",
 560                            param->seq);
 561                 return -1;
 562         }
 563 
 564         req->callback->update_response(req, 
 565                                        param->sa_src, param->sa_dst,
 566                                        (unsigned int)param->satype,
 567                                        (unsigned int)param->samode,
 568                                        ntohl(param->spi));
 569         return 0;
 570 }
 571 
 572 /* called when other KMd issued SADB_GET */
 573 static int
 574 sadb_get_callback(struct rcpfk_msg *param)
 575 {
 576         /* param: seq, satype, spi, sa_src, sa_dst, samode */
 577         /* lifetime address(P) identity */
 578 
 579         struct sadb_request *req;
 580 
 581         TRACE((PLOGLOC,
 582                "sadb_get_callback: seq=%d, spi=0x%08x, satype=%d, sa_src=%s,"
 583                " sa_dst=%s, samode=%d\n",
 584                param->seq, ntohl(param->spi), param->satype,
 585                rcs_sa2str(param->sa_src), rcs_sa2str(param->sa_dst),
 586                param->samode));
 587 
 588         req = sadb_find_by_seq(param->seq);
 589         if (!req) {
 590                 /* couldn't find corresponding SA */
 591                 isakmp_log(0, 0, 0, 0,
 592                            PLOG_INTWARN, PLOGLOC,
 593                            "received PF_KEY SADB_GET message (seq %u) does not have corresponding request. (ignored)\n",
 594                            param->seq);
 595                 return -1;
 596         }
 597 
 598         req->callback->get_response(req,
 599                                     param->sa_src,
 600                                     param->sa_dst,
 601                                     (unsigned int)param->satype,
 602                                     ntohl(param->spi),
 603                                     &param->lft_current_bytes);
 604         
 605         return 0;
 606 }
 607 
 608 
 609 #if 0
 610 /* not used */
 611 /* called when other KMd issued SADB_UDPATE */
 612 static int
 613 sadb_add_callback(struct rcpfk_msg *param)
 614 {
 615         /* param: seq, satype, spi, sa_src, sa_dst, samode */
 616         /* lifetime??? identity?? sensitivity?? */
 617 
 618         return 0;
 619 }
 620 #endif
 621 
 622 /*
 623  * called when kernel SA expires
 624  */
 625 static int
 626 sadb_expire_callback(struct rcpfk_msg *param)
 627 {
 628         /* param: seq, satype, spi, sa_src, sa_dst, samode, expired(hard?2:1) */
 629         /* lifetime(C)??? */
 630 
 631         struct sadb_request *req;
 632 
 633         plog(PLOG_INFO, PLOGLOC, 0,
 634              "received PFKEY_EXPIRE seq=%d sa_dst=%s spi=0x%08x satype=%s samode=%s expired=%d\n",
 635              param->seq, rcs_sa2str(param->sa_dst), ntohl(param->spi),
 636              rct2str(param->satype), rct2str(param->samode), param->expired);
 637 
 638         /* #ifdef __linux__ ??? */
 639         /* Linux/USAGI generates soft-expire regardless it was used or not */
 640         TRACE((PLOGLOC, "allocated: %" PRIu64 "\n", param->lft_current_alloc));
 641         if (param->expired == 1 && param->lft_current_alloc == 0) {
 642                 TRACE((PLOGLOC, "ignoring soft expire\n"));
 643                 return 0;
 644         }
 645         /* #endif */
 646 
 647         /* start rekeying */
 648         /* find sadb_request by spi, sa_dst */
 649         for (req = SADB_LIST_FIRST(&sadb_request_list_head);
 650              !SADB_LIST_END(req); req = SADB_LIST_NEXT(req)) {
 651                 if (req->callback->expired(req, param))
 652                         goto done;
 653         }
 654 
 655         /* couldn't find corresponding SA */
 656         isakmp_log(0, 0, 0, 0, PLOG_INTWARN, PLOGLOC,
 657                    "PF_KEY SADB_EXPIRE message does not have corresponding request. (ignored)\n");
 658 
 659       done:
 660         TRACE((PLOGLOC, "done.\n"));
 661         return 0;
 662 }
 663 
 664 
 665 /*
 666  * called when the kernel generates SADB_ACQUIRE message
 667  */
 668 static int
 669 sadb_acquire_callback(struct rcpfk_msg *param)
 670 {
 671         struct sadb_request *req;
 672         invacq_t *invacq;
 673         /* param: seq, satype, sa_src, sa_dst, samode, selid */
 674         /* address(P)??? pid?? identity??? proposal??? */
 675 
 676         TRACE((PLOGLOC,
 677                "sadb_acquire_callback: seq=%d satype=%d sa_src=%s sa_dst=%s samode=%d selid=%d\n",
 678                param->seq, param->satype, rcs_sa2str(param->sa_src),
 679                rcs_sa2str(param->sa_dst), param->samode, param->slid));
 680 
 681         req = sadb_find_by_seq(param->seq);
 682         if (req != NULL) {
 683                 /* Inverse-ACQUIRE. */
 684                 invacq = (invacq_t *)req->sa;
 685                 invacq->answer = param;
 686                 return (invacq->receiver(invacq));
 687         }
 688 
 689         if (param->eno != 0) {
 690                 /* inverse-ACQUIRE error with no outstanding request.  Drop. */
 691                 return (-1);
 692         }
 693 
 694         isakmp_initiate(&sadb_initiator_request_method, param);
 695         return 0;
 696 }
 697 
 698 /*
 699  * called when the kernel generates SADB_DELETE message
 700  */
 701 static int
 702 sadb_delete_callback(struct rcpfk_msg *param)
 703 {
 704         /* param: seq, satype, spi, sa_src, sa_dst, samode */
 705 
 706         /* similar to expire ? */
 707 
 708         plog(PLOG_INFO, PLOGLOC, 0,
 709              "received PFKEY_DELETE seq=%d satype=%s spi=0x%08x\n",
 710              param->seq, rct2str(param->satype), ntohl(param->spi));
 711         return 0;
 712 }
 713 
 714 #if 0
 715 /* not used */
 716 /* called when other KMd issued SADB_X_SPDUPDATE */
 717 static int
 718 sadb_spdupdate_callback(struct rcpfk_msg *param)
 719 {
 720         /* param: selid */
 721 
 722         return 0;
 723 }
 724 #endif
 725 
 726 #if 0
 727 /* not used */
 728 /* called when other KMd issued SADB_X_SPDADD */
 729 static int
 730 sadb_spdadd_callback(struct rcpfk_msg *param)
 731 {
 732         /* param: selid */
 733         return 0;
 734 }
 735 #endif
 736 
 737 #if 0
 738 /* called when other KMd issued SADB_X_SPDDELETE */
 739 static int
 740 sadb_spddelete_callback(struct rcpfk_msg *param)
 741 {
 742         /* param: selid */
 743         return 0;
 744 }
 745 #endif
 746 
 747 #if 0
 748 /* called when kernel SP expires */
 749 static int
 750 sadb_spdexpire_callback(struct rcpfk_msg *param)
 751 {
 752         /* param: selid */
 753         /* address(SD)? lifetime(CH)? */
 754 
 755         return 0;
 756 }
 757 #endif
 758 
 759 #ifdef SADB_X_MIGRATE
 760 #include <netinet/in.h>
 761 /* called when kernel issued SADB_X_MIGRATE */
 762 static int
 763 sadb_x_migrate_callback(struct rcpfk_msg *param)
 764 {
 765         struct rcf_selector *selector;
 766         struct rcf_policy *policy;
 767         struct ikev2_sa *ike_sa;
 768         struct ikev2_child_sa *child_sa;
 769 #ifdef IKEV1
 770         struct ph1handle *iph1;
 771         struct ph2handle *iph2;
 772         extern struct ph1handle *getph1bydstaddrwop(struct sockaddr *);
 773 #endif
 774         extern struct rcf_selector *rcf_selector_head;
 775 
 776         TRACE((PLOGLOC,
 777                "sadb_x_migrate_callback: dir=%s, sa_src=%s, sa_dst=%s, sa2_src=%s, sa2_dst=%s\n",
 778                rct2str(param->dir),  
 779                rcs_sa2str(param->sa_src), rcs_sa2str(param->sa_dst),
 780                rcs_sa2str(param->sa2_src), rcs_sa2str(param->sa2_dst)));
 781 
 782         if ((rcs_cmpsa(param->sa_src, param->sa2_src) == 0) &&
 783              (rcs_cmpsa(param->sa_dst, param->sa2_dst) == 0))
 784                 return 0;
 785         if (param->dir != RCT_DIR_OUTBOUND)
 786                 return 0;
 787 
 788         /* migrate the primary selector */
 789 
 790         for (selector = rcf_selector_head;
 791              selector != 0;
 792              selector = selector->next) {
 793                 if (selector->direction != RCT_DIR_OUTBOUND)
 794                         continue;
 795                 /* XXX match only on the reqid! */
 796                 if (param->reqid != selector->reqid)
 797                         continue;
 798                 policy = selector->pl;
 799                 if (policy->my_sa_ipaddr)
 800                         switch (param->sa_src->sa_family) {
 801                         case AF_INET:
 802                             if (policy->my_sa_ipaddr->type != RCT_ADDR_INET)
 803                                 break;
 804                             ((struct sockaddr_in *)policy->my_sa_ipaddr->a.ipaddr)->sin_addr =
 805                                 ((struct sockaddr_in *)param->sa2_src)->sin_addr;
 806                             break;
 807 #ifdef INET6
 808                         case AF_INET6:
 809                             if (policy->my_sa_ipaddr->type != RCT_ADDR_INET)
 810                                 break;
 811                             memcpy(&((struct sockaddr_in6 *)policy->my_sa_ipaddr->a.ipaddr)->sin6_addr, 
 812                                    &((struct sockaddr_in6 *)param->sa2_src)->sin6_addr,
 813                                    sizeof(struct in6_addr));
 814                             break;
 815 #endif
 816                         default:
 817                                 return -1;
 818                         }
 819                 if (policy->peers_sa_ipaddr)
 820                         switch (param->sa_dst->sa_family) {
 821                         case AF_INET:
 822                             if (policy->peers_sa_ipaddr->type != RCT_ADDR_INET)
 823                                 break;
 824                             ((struct sockaddr_in *)policy->peers_sa_ipaddr->a.ipaddr)->sin_addr =
 825                                 ((struct sockaddr_in *)param->sa2_dst)->sin_addr;
 826                             break;
 827 #ifdef INET6
 828                         case AF_INET6:
 829                             if (policy->peers_sa_ipaddr->type != RCT_ADDR_INET)
 830                                 break;
 831                             memcpy(&((struct sockaddr_in6 *)policy->peers_sa_ipaddr->a.ipaddr)->sin6_addr, 
 832                                    &((struct sockaddr_in6 *)param->sa2_dst)->sin6_addr,
 833                                    sizeof(struct in6_addr));
 834                             break;
 835 #endif
 836                         default:
 837                                 return -1;
 838                         }
 839                 plog(PLOG_INFO, PLOGLOC, 0,
 840                      "move selector(%p) with sl_index(%s)\n",
 841                      selector, rc_vmem2str(selector->sl_index));
 842         }
 843 
 844         /* migrate the IKE SA */
 845 
 846         ike_sa = ikev2_find_sa_by_addr(param->sa_dst);
 847         if (ike_sa == NULL)
 848                 goto v1;
 849         plog(PLOG_INFO, PLOGLOC, 0, "move ikev2_sa(%p): from %s -> %s\n",
 850              ike_sa, rcs_sa2str(ike_sa->local), rcs_sa2str(ike_sa->remote));
 851           
 852         switch (ike_sa->remote->sa_family) {
 853         case AF_INET:
 854                 ((struct sockaddr_in *)ike_sa->local)->sin_addr =
 855                         ((struct sockaddr_in *)param->sa2_src)->sin_addr;
 856                 ((struct sockaddr_in *)ike_sa->remote)->sin_addr =
 857                         ((struct sockaddr_in *)param->sa2_dst)->sin_addr;
 858 #ifdef INET6
 859         case AF_INET6:
 860                 memcpy(&((struct sockaddr_in6 *)ike_sa->local)->sin6_addr, 
 861                        &((struct sockaddr_in6 *)param->sa2_src)->sin6_addr,
 862                        sizeof(struct in6_addr));
 863                 memcpy(&((struct sockaddr_in6 *)ike_sa->remote)->sin6_addr,
 864                        &((struct sockaddr_in6 *)param->sa2_dst)->sin6_addr,
 865                        sizeof(struct in6_addr));
 866                 break;
 867 #endif
 868         default:
 869                 return -1;
 870         }
 871         plog(PLOG_INFO, PLOGLOC, 0, "move ikev2_sa(%p): to %s -> %s\n",
 872              ike_sa, rcs_sa2str(ike_sa->local), rcs_sa2str(ike_sa->remote));
 873         
 874         /* migrate children */
 875 
 876         for (child_sa = IKEV2_CHILD_LIST_FIRST(&ike_sa->children);
 877              !IKEV2_CHILD_LIST_END(child_sa);
 878              child_sa = IKEV2_CHILD_LIST_NEXT(child_sa)) {
 879                 if (!child_sa->selector)
 880                         continue;
 881                 if (param->reqid != child_sa->selector->reqid)
 882                         continue;
 883                 switch (ike_sa->remote->sa_family) {
 884                 case AF_INET:
 885                   if (child_sa->local)
 886                     ((struct sockaddr_in *)child_sa->local)->sin_addr =
 887                       ((struct sockaddr_in *)ike_sa->local)->sin_addr;
 888                   if (child_sa->remote)
 889                     ((struct sockaddr_in *)child_sa->remote)->sin_addr =
 890                       ((struct sockaddr_in *)ike_sa->remote)->sin_addr;
 891 
 892                   policy = child_sa->selector->pl;
 893                   if (policy->my_sa_ipaddr) {
 894                     if (policy->my_sa_ipaddr->type != RCT_ADDR_INET) {
 895                       TRACE((PLOGLOC, "unexpected type\n"));
 896                       continue;
 897                     }
 898                     ((struct sockaddr_in *)policy->my_sa_ipaddr->a.ipaddr)->sin_addr =
 899                       ((struct sockaddr_in *)ike_sa->local)->sin_addr;
 900                   }
 901                   if (policy->peers_sa_ipaddr) {
 902                     if (policy->peers_sa_ipaddr->type != RCT_ADDR_INET) {
 903                       TRACE((PLOGLOC, "unexpected type\n"));
 904                       continue;
 905                     }
 906                     ((struct sockaddr_in *)policy->peers_sa_ipaddr->a.ipaddr)->sin_addr =
 907                       ((struct sockaddr_in *)ike_sa->local)->sin_addr;
 908                   }
 909                   break;
 910 #ifdef INET6
 911                 case AF_INET6:
 912                   if (child_sa->local)
 913                     memcpy(&((struct sockaddr_in6 *)child_sa->local)->sin6_addr,
 914                            &((struct sockaddr_in6 *)ike_sa->local)->sin6_addr,
 915                            sizeof(struct in6_addr));
 916                   if (child_sa->remote)
 917                     memcpy(&((struct sockaddr_in6 *)child_sa->remote)->sin6_addr,
 918                            &((struct sockaddr_in6 *)ike_sa->remote)->sin6_addr,
 919                            sizeof(struct in6_addr));
 920 
 921                   policy = child_sa->selector->pl;
 922                   if (policy->my_sa_ipaddr) {
 923                     if (policy->my_sa_ipaddr->type != RCT_ADDR_INET) {
 924                       TRACE((PLOGLOC, "unexpected type\n"));
 925                       continue;
 926                     }
 927                     memcpy(&((struct sockaddr_in6 *)policy->my_sa_ipaddr->a.ipaddr)->sin6_addr, 
 928                            &((struct sockaddr_in6 *)ike_sa->local)->sin6_addr,
 929                            sizeof(struct in6_addr));
 930                   }
 931                   if (policy->peers_sa_ipaddr) {
 932                     if (policy->peers_sa_ipaddr->type != RCT_ADDR_INET) {
 933                       TRACE((PLOGLOC, "unexpected type\n"));
 934                       continue;
 935                     }
 936                     memcpy(&((struct sockaddr_in6 *)policy->peers_sa_ipaddr->a.ipaddr)->sin6_addr,
 937                            &((struct sockaddr_in6 *)ike_sa->remote)->sin6_addr,
 938                            sizeof(struct in6_addr));
 939                   }
 940                   break;
 941 #endif
 942                 }
 943                 plog(PLOG_INFO, PLOGLOC, 0, "move child_sa(%p)\n", child_sa);
 944         }
 945 
 946         ikev2_migrate_script_hook(ike_sa, param->sa_src, param->sa_dst,
 947                                   param->sa2_src, param->sa2_dst);
 948 
 949     v1:
 950 #ifdef IKEV1
 951         /* migrate the ISAKMP SA (aka phase 1) */
 952 
 953         iph1 = getph1bydstaddrwop(param->sa_dst);
 954         if (iph1 == NULL)
 955                 return 0;
 956         plog(PLOG_INFO, PLOGLOC, 0, "move ikev1_ph1(%p): from %s -> %s\n",
 957              iph1, rcs_sa2str(iph1->local), rcs_sa2str(iph1->remote));
 958           
 959         switch (iph1->remote->sa_family) {
 960         case AF_INET:
 961                 ((struct sockaddr_in *)iph1->local)->sin_addr =
 962                         ((struct sockaddr_in *)param->sa2_src)->sin_addr;
 963                 ((struct sockaddr_in *)iph1->remote)->sin_addr =
 964                         ((struct sockaddr_in *)param->sa2_dst)->sin_addr;
 965 #ifdef INET6
 966         case AF_INET6:
 967                 memcpy(&((struct sockaddr_in6 *)iph1->local)->sin6_addr, 
 968                        &((struct sockaddr_in6 *)param->sa2_src)->sin6_addr,
 969                        sizeof(struct in6_addr));
 970                 memcpy(&((struct sockaddr_in6 *)iph1->remote)->sin6_addr,
 971                        &((struct sockaddr_in6 *)param->sa2_dst)->sin6_addr,
 972                        sizeof(struct in6_addr));
 973                 break;
 974 #endif
 975         default:
 976                 return -1;
 977         }
 978         plog(PLOG_INFO, PLOGLOC, 0, "move ikev1_ph1(%p): to %s -> %s\n",
 979              iph1, rcs_sa2str(iph1->local), rcs_sa2str(iph1->remote));
 980         
 981         /* migrate children aka phases 2 */
 982 
 983         LIST_FOREACH(iph2, &iph1->ph2tree, ph1bind) {
 984                 if (!iph2->selector)
 985                         continue;
 986                 if (param->reqid != iph2->selector->reqid)
 987                         continue;
 988                 switch (iph1->remote->sa_family) {
 989                 case AF_INET:
 990                   if (iph2->src)
 991                     ((struct sockaddr_in *)iph2->src)->sin_addr =
 992                       ((struct sockaddr_in *)iph1->local)->sin_addr;
 993                   if (iph2->dst)
 994                     ((struct sockaddr_in *)iph2->dst)->sin_addr =
 995                       ((struct sockaddr_in *)iph1->remote)->sin_addr;
 996 
 997                   policy = iph2->selector->pl;
 998                   if (policy->my_sa_ipaddr) {
 999                     if (policy->my_sa_ipaddr->type != RCT_ADDR_INET) {
1000                       TRACE((PLOGLOC, "unexpected type\n"));
1001                       continue;
1002                     }
1003                     ((struct sockaddr_in *)policy->my_sa_ipaddr->a.ipaddr)->sin_addr =
1004                       ((struct sockaddr_in *)iph1->local)->sin_addr;
1005                   }
1006                   if (policy->peers_sa_ipaddr) {
1007                     if (policy->peers_sa_ipaddr->type != RCT_ADDR_INET) {
1008                       TRACE((PLOGLOC, "unexpected type\n"));
1009                       continue;
1010                     }
1011                     ((struct sockaddr_in *)policy->peers_sa_ipaddr->a.ipaddr)->sin_addr =
1012                       ((struct sockaddr_in *)iph1->local)->sin_addr;
1013                   }
1014                   break;
1015 #ifdef INET6
1016                 case AF_INET6:
1017                   if (iph2->src)
1018                     memcpy(&((struct sockaddr_in6 *)iph2->src)->sin6_addr,
1019                            &((struct sockaddr_in6 *)iph1->local)->sin6_addr,
1020                            sizeof(struct in6_addr));
1021                   if (iph2->dst)
1022                     memcpy(&((struct sockaddr_in6 *)iph2->dst)->sin6_addr,
1023                            &((struct sockaddr_in6 *)iph1->remote)->sin6_addr,
1024                            sizeof(struct in6_addr));
1025 
1026                   policy = iph2->selector->pl;
1027                   if (policy->my_sa_ipaddr) {
1028                     if (policy->my_sa_ipaddr->type != RCT_ADDR_INET) {
1029                       TRACE((PLOGLOC, "unexpected type\n"));
1030                       continue;
1031                     }
1032                     memcpy(&((struct sockaddr_in6 *)policy->my_sa_ipaddr->a.ipaddr)->sin6_addr, 
1033                            &((struct sockaddr_in6 *)iph1->local)->sin6_addr,
1034                            sizeof(struct in6_addr));
1035                   }
1036                   if (policy->peers_sa_ipaddr) {
1037                     if (policy->peers_sa_ipaddr->type != RCT_ADDR_INET) {
1038                       TRACE((PLOGLOC, "unexpected type\n"));
1039                       continue;
1040                     }
1041                     memcpy(&((struct sockaddr_in6 *)policy->peers_sa_ipaddr->a.ipaddr)->sin6_addr,
1042                            &((struct sockaddr_in6 *)iph1->remote)->sin6_addr,
1043                            sizeof(struct in6_addr));
1044                   }
1045                   break;
1046 #endif
1047                 }
1048                 plog(PLOG_INFO, PLOGLOC, 0, "move iph2(%p)\n", iph2);
1049         }
1050 
1051         ikev1_migrate_script_hook(iph1, param->sa_src, param->sa_dst,
1052                                   param->sa2_src, param->sa2_dst);
1053 
1054 #endif
1055         return 0;
1056 }
1057 #endif
1058 
1059 /* #ifdef DEBUG */
1060 static int sadb_debug_getspi(struct rcpfk_msg *param);
1061 static int sadb_debug_acquire_error(struct rcpfk_msg *param);
1062 static int sadb_debug_update(struct rcpfk_msg *param);
1063 static int sadb_debug_add(struct rcpfk_msg *param);
1064 static int sadb_debug_delete(struct rcpfk_msg *param);
1065 
1066 struct sadb_request_method sadb_debug_method = {
1067         sadb_debug_getspi,
1068         sadb_debug_acquire_error,
1069         sadb_debug_update,
1070         sadb_debug_add,
1071         sadb_debug_delete,
1072 };
1073 
1074 uint32_t debug_spi = 0x10000;
1075 
1076 static int
1077 sadb_debug_getspi(struct rcpfk_msg *param)
1078 {
1079         int err;
1080 
1081         TRACE((PLOGLOC, "sadb_debug_getspi: seq=%d, satype=%d\n",
1082                param->seq, param->satype));
1083 
1084         param->spi = htonl(debug_spi++);
1085         err = sadb_getspi_callback(param);
1086         TRACE((PLOGLOC, "sadb_getspi_callback retval %d\n", err));
1087         return 0;
1088 }
1089 
1090 static int
1091 sadb_debug_acquire_error(struct rcpfk_msg *param)
1092 {
1093         TRACE((PLOGLOC,
1094                "sadb_debug_acquire_error: seq=%d, satype=%d, spi=0x%08x, errno=%d\n",
1095                param->seq, param->satype, ntohl(param->spi), param->eno));
1096         return 0;
1097 }
1098 
1099 static int
1100 sadb_debug_update(struct rcpfk_msg *param)
1101 {
1102         dump_param("sadb_debug_update", param);
1103         return 0;
1104 }
1105 
1106 static int
1107 sadb_debug_add(struct rcpfk_msg *param)
1108 {
1109         dump_param("sadb_debug_add", param);
1110         return 0;
1111 }
1112 
1113 static int
1114 sadb_debug_delete(struct rcpfk_msg *param)
1115 {
1116         dump_param("sadb_debug_delete", param);
1117         return 0;
1118 }
1119 
1120 /*
1121  * dump add/update parameters
1122  */
1123 static void
1124 dump_param(char *msg, struct rcpfk_msg *param)
1125 {
1126         int i;
1127         char buf[BUFSIZ];
1128         char *bufp;
1129         ssize_t buflen;
1130 
1131 #define DUMP(x_)        do {                                            \
1132                             buflen -= strlen(bufp);                     \
1133                             bufp += strlen(bufp);                       \
1134                             if (buflen > 0) {                                \
1135                                 x_;                                     \
1136                             }                                           \
1137                         } while (0)
1138 
1139         buf[0] = '\0';
1140         bufp = &buf[0];
1141         buflen = sizeof(buf) - 1;
1142         DUMP(snprintf(bufp, buflen,
1143                       "%s: seq=%d, ul_proto=%d sa_src=%s/%d, sa_dst=%s/%d, "
1144                       "satype=%d (%s), spi=0x%08x, wsize=%d, "
1145                       "authtype=%d (%s), enctype=%d (%s), saflags=0x%x, "
1146                       "samode=%d (%s), reqid=%d, "
1147                       "lifetime hard time %" PRIu64 ", bytes %" PRIu64 ", "
1148                       "lifetime soft time %" PRIu64 ", bytes %" PRIu64 ", "
1149                       "enckey len=%lu [",
1150                       msg,
1151                       param->seq, param->ul_proto,
1152                       rcs_sa2str(param->sa_src), param->pref_src,
1153                       rcs_sa2str(param->sa_dst), param->pref_dst,
1154                       param->satype, rct2str(param->satype),
1155                       ntohl(param->spi), param->wsize,
1156                       param->authtype, rct2str(param->authtype),
1157                       param->enctype, rct2str(param->enctype),
1158                       param->saflags,
1159                       param->samode, rct2str(param->samode),
1160                       param->reqid,
1161                       param->lft_hard_time, param->lft_hard_bytes,
1162                       param->lft_soft_time, param->lft_soft_bytes,
1163                       (unsigned long)param->enckeylen));
1164         for (i = 0; i < (int)param->enckeylen; ++i) {
1165                 DUMP(snprintf(bufp, buflen,
1166                               "%02x", ((uint8_t *)param->enckey)[i]));
1167         }
1168         DUMP(snprintf(bufp, buflen, "], authkey len=%lu [", 
1169                       (unsigned long)param->authkeylen));
1170         for (i = 0; i < (int)param->authkeylen; ++i) {
1171                 DUMP(snprintf(bufp, buflen,
1172                               "%02x", ((uint8_t *)param->authkey)[i]));
1173         }
1174         DUMP(snprintf(bufp, buflen, "]\n"));
1175 
1176         TRACE((PLOGLOC, "%s", buf));
1177 }
1178 
1179 #ifdef DEBUG
1180 #include <sys/socket.h>
1181 #include <netdb.h>
1182 
1183 void
1184 debug_initiate(char *addr, const char *selector_index)
1185 {
1186         struct isakmp_acquire_request *req;
1187         struct addrinfo *res;
1188         int err;
1189 
1190         req = racoon_calloc(1, sizeof(*req));
1191 
1192         err = getaddrinfo(addr, 0, 0, &res);
1193         if (err) {
1194                 fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(err));
1195                 return;
1196         }
1197         if (!res) {
1198                 fprintf(stderr, "res is null\n");
1199                 return;
1200         }
1201         if (!res->ai_addr) {
1202                 fprintf(stderr, "res->ai_addr is null\n");
1203                 return;
1204         }
1205 
1206         req->callback_method = &sadb_debug_method;
1207         req->request_msg_seq = 1;
1208         req->dst = rcs_sadup(res->ai_addr);
1209         isakmp_initiate_cont(req, selector_index);
1210 
1211         freeaddrinfo(res);
1212 }
1213 #endif
1214 /* #endif */