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