1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  *
  26  * Copyright 2017 Jason King.
  27  * Copyright (c) 2017, Joyent, Inc.
  28  */
  29 
  30 #include <sys/types.h>
  31 #include <net/pfkeyv2.h>
  32 #include <ipsec_util.h>
  33 #include <string.h>
  34 #include <errno.h>
  35 #include <locale.h>
  36 #include <netdb.h>
  37 #include <stdio.h>
  38 #include <note.h>
  39 #include <atomic.h>
  40 #include <pthread.h>
  41 #include <sys/stropts.h>  /* For I_NREAD */
  42 #include <libuutil.h>
  43 #include <bunyan.h>
  44 
  45 #include "defs.h"
  46 #include "ikev2.h"
  47 #include "ikev2_pkt.h"
  48 #include "ikev2_sa.h"
  49 #include "pkcs11.h"
  50 
  51 struct pfreq;
  52 typedef struct pfreq {
  53         uu_list_node_t  pr_node;
  54         pfreq_cb_t      *pr_cb;
  55         void            *pr_data;
  56         uint32_t        pr_msgid;
  57 } pfreq_t;
  58 
  59 static bunyan_logger_t  *pflog;
  60 static uu_list_pool_t   *pfreq_pool;
  61 static umem_cache_t     *pfreq_cache;
  62 static pthread_mutex_t  pfreq_lock = PTHREAD_MUTEX_INITIALIZER;
  63 static uu_list_t        *pfreq_list;
  64 
  65 /* PF_KEY socket. */
  66 int pfkey;
  67 
  68 /* our msgids */
  69 static volatile uint32_t msgid = 0;
  70 
  71 static int pfreq_ctor(void *, void *, int);
  72 static pfreq_t *pfreq_new(pfreq_cb_t *, void *);
  73 static void pfreq_free(pfreq_t *);
  74 
  75 static void handle_reply(sadb_msg_t *);
  76 static void handle_delete(sadb_msg_t *);
  77 static void handle_flush(sadb_msg_t *);
  78 static void handle_expire(sadb_msg_t *);
  79 static void handle_acquire(sadb_msg_t *, boolean_t);
  80 static void handle_register(sadb_msg_t *);
  81 
  82 #if 0
  83 static ikev2_pay_sa_t *convert_acquire(parsedmsg_t *);
  84 static ikev2_pay_sa_t *convert_ext_acquire(parsedmsg_t *, ikev2_spi_proto_t);
  85 static ikev2_xf_auth_t ikev2_pf_to_auth(int);
  86 #endif
  87 
  88 static const char *pfkey_opcodes[] = {
  89         "RESERVED", "GETSPI", "UPDATE", "ADD", "DELETE", "GET",
  90         "ACQUIRE", "REGISTER", "EXPIRE", "FLUSH", "DUMP", "X_PROMISC",
  91         "X_INVERSE_ACQUIRE", "X_UPDATEPAIR", "X_DELPAIR"
  92 };
  93 
  94 static const char *
  95 pfkey_type(unsigned int type)
  96 {
  97         if (type > SADB_MAX)
  98                 return ("ILLEGAL");
  99         else
 100                 return (pfkey_opcodes[type]);
 101 }
 102 
 103 static const char *pfkey_satypes[] = {
 104         "UNSPEC", "<undef>", "AH", "ESP", "<undef>", "RSVP", "OSPFV2",
 105         "RIPV2", "MIP"
 106 };
 107 
 108 static const char *
 109 pfkey_satype(unsigned int type)
 110 {
 111         if (type > SADB_SATYPE_MAX)
 112                 return ("ILLEGAL");
 113         else
 114                 return (pfkey_satypes[type]);
 115 }
 116 
 117 /* Deal with algorithm name lookups */
 118 
 119 static const char *
 120 alg_to_string(int doi_number, const algindex_t *algindex)
 121 {
 122         int i;
 123 
 124         for (i = 0; algindex[i].desc; i++)
 125                 if (doi_number == algindex[i].doi_num)
 126                         return (algindex[i].desc);
 127         return ("unknown");
 128 }
 129 
 130 char *
 131 kef_alg_to_string(int algnum, int protonum, char *algname)
 132 {
 133         struct ipsecalgent *testentry;
 134         int error;
 135 
 136         testentry = getipsecalgbynum(algnum, protonum, &error);
 137         if (testentry == NULL || testentry->a_names[0] == NULL)
 138                 (void) snprintf(algname, 80, "unknown");
 139         else
 140                 (void) snprintf(algname, 80, "%s", testentry->a_names[0]);
 141 
 142         /* safe to use on a NULL pointer */
 143         (void) freeipsecalgent(testentry);
 144         return (algname);
 145 }
 146 
 147 /*
 148  * The passed in parsedmsg_t looks like this (see defs.h):
 149  *
 150  * {
 151  *      *pmsg_next
 152  *      *pmsg_samsg
 153  *      *pmsg_exts[0][1][2][3].....[SADB_EXT_MAX + 2]
 154  *      *pmsg_sss  (struct sockaddr_storage *)
 155  *      *pmsg_dss  (struct sockaddr_storage *)
 156  *      *pmsg_isss (struct sockaddr_storage *)
 157  *      *pmsg_idss (struct sockaddr_storage *)
 158  *      *pmsg_nlss (struct sockaddr_storage *)
 159  *      *pmsg_nrss (struct sockaddr_storage *)
 160  * } parsedmsg_t;
 161  *
 162  * This function parses through the whole samsg looking for valid PF_KEY
 163  * extensions. Each extension type found is saved in the pmsg_exts array.
 164  * As the parsedmsg_t is initialised as zero's when entering the function, it's
 165  * easy to check later to see which extensions exist in the samsg by
 166  * checking for NULL.
 167  *
 168  * Some extensions will have a sockaddr_storage associated with the type
 169  * EG: SADB_EXT_ADDRESS_SRC, in these cases a pointer to the appropriate
 170  * structure in samsg is set in the parsedmsg_t.
 171  *
 172  * After parsing the whole samsg, the optional arguments (which is a list
 173  * of required extensions) are checked for in the parsedmsg_t. If all of the
 174  * required extensions are valid then the function returns B_TRUE.
 175  *
 176  * Even if the required extensions are not in the samsg (and the function
 177  * returns B_FALSE) the pmsg->pmsg_exts array will still contain the headers
 178  * that were in the samsg.
 179  *
 180  * Assume the kernel knows what it's doing with messages that get passed up.
 181  * The variable arguments are a list of ints with SADB_EXT_* values.
 182  */
 183 static boolean_t
 184 extract_exts(sadb_msg_t *samsg, parsedmsg_t *pmsg, int numexts, ...)
 185 {
 186         sadb_ext_t *ext;
 187         sadb_ext_t **exts = pmsg->pmsg_exts;
 188         int current_ext;
 189         va_list ap;
 190         boolean_t rc = B_TRUE;
 191 
 192         (void) memset(pmsg, 0, sizeof (parsedmsg_t));
 193 
 194         ext = (sadb_ext_t *)(samsg + 1);
 195         pmsg->pmsg_samsg = samsg;
 196 
 197         do {
 198                 exts[ext->sadb_ext_type] = ext;
 199                 if (ext->sadb_ext_type == SADB_EXT_ADDRESS_SRC)
 200                         pmsg->pmsg_sss = (struct sockaddr_storage *)
 201                             (((sadb_address_t *)ext) + 1);
 202                 if (ext->sadb_ext_type == SADB_EXT_ADDRESS_DST)
 203                         pmsg->pmsg_dss = (struct sockaddr_storage *)
 204                             (((sadb_address_t *)ext) + 1);
 205                 if (ext->sadb_ext_type == SADB_X_EXT_ADDRESS_INNER_SRC)
 206                         pmsg->pmsg_isss = (struct sockaddr_storage *)
 207                             (((sadb_address_t *)ext) + 1);
 208                 if (ext->sadb_ext_type == SADB_X_EXT_ADDRESS_INNER_DST)
 209                         pmsg->pmsg_idss = (struct sockaddr_storage *)
 210                             (((sadb_address_t *)ext) + 1);
 211                 if (ext->sadb_ext_type == SADB_X_EXT_ADDRESS_NATT_REM)
 212                         pmsg->pmsg_nrss = (struct sockaddr_storage *)
 213                             (((sadb_address_t *)ext) + 1);
 214                 if (ext->sadb_ext_type == SADB_X_EXT_ADDRESS_NATT_LOC)
 215                         pmsg->pmsg_nlss = (struct sockaddr_storage *)
 216                             (((sadb_address_t *)ext) + 1);
 217 
 218                 ext = (sadb_ext_t *)(((uint64_t *)ext) + ext->sadb_ext_len);
 219 
 220         } while (((uint8_t *)ext) - ((uint8_t *)samsg) <
 221             SADB_64TO8(samsg->sadb_msg_len));
 222 
 223         va_start(ap, numexts);
 224         while (numexts-- > 0) {
 225                 current_ext = va_arg(ap, int);
 226                 if (exts[current_ext] == NULL) {
 227                         rc = B_FALSE;
 228                         break;
 229                 }
 230         }
 231         va_end(ap);
 232 
 233         return (rc);
 234 }
 235 
 236 static void
 237 pfkey_inbound(int s, void *arg)
 238 {
 239         _NOTE(ARGUNUSED(arg))
 240 
 241         sadb_msg_t *samsg;
 242         ssize_t rc;
 243         int length;
 244 
 245         if (ioctl(s, I_NREAD, &length) < 0) {
 246                 STDERR(error, log, "ioctl(I_NREAD) failed");
 247 
 248                 /* XXX KEBE ASKS - will we rapidly return at this point? */
 249                 schedule_socket(s, pfkey_inbound);
 250                 return;
 251         }
 252 
 253         if (length == 0) {
 254                 bunyan_info(log, "ioctl: zero length message",
 255                     BUNYAN_T_STRING, "func", __func__,
 256                     BUNYAN_T_STRING, "file", __FILE__,
 257                     BUNYAN_T_INT32, "line", __LINE__,
 258                     BUNYAN_T_END);
 259                 /* XXX KEBE ASKS - will we rapidly return at this point? */
 260                 schedule_socket(s, pfkey_inbound);
 261                 return;
 262         }
 263 
 264         samsg = malloc(length);
 265         if (samsg == NULL) {
 266                 STDERR(error, log, "malloc failure");
 267                 schedule_socket(s, pfkey_inbound);
 268                 return;
 269         }
 270 
 271         rc = read(s, samsg, length);
 272         if (rc <= 0) {
 273                 if (rc == -1) {
 274                         STDERR(error, log, "read failed");
 275                         /* Should I exit()? */
 276                 }
 277                 free(samsg);
 278                 /* XXX KEBE ASKS - will we rapidly return at this point? */
 279                 schedule_socket(s, pfkey_inbound);
 280                 return;
 281         }
 282 
 283         /* At this point, we can safely re-schedule the socket for reading. */
 284         schedule_socket(s, pfkey_inbound);
 285 
 286         bunyan_debug(log, "SADB message received",
 287             BUNYAN_T_STRING, "msg_type", pfkey_type(samsg->sadb_msg_type),
 288             BUNYAN_T_UINT32, "msg_type_val", (uint32_t)samsg->sadb_msg_type,
 289             BUNYAN_T_STRING, "sa_type", pfkey_satype(samsg->sadb_msg_satype),
 290             BUNYAN_T_UINT32, "sa_type_val", (uint32_t)samsg->sadb_msg_satype,
 291             BUNYAN_T_UINT32, "msg_pid", samsg->sadb_msg_pid,
 292             BUNYAN_T_UINT32, "msg_seq", samsg->sadb_msg_seq,
 293             BUNYAN_T_UINT32, "msg_errno_val", (uint32_t)samsg->sadb_msg_errno,
 294             BUNYAN_T_STRING, "msg_errno", strerror(samsg->sadb_msg_errno),
 295             BUNYAN_T_UINT32, "msg_diagnostic_val",
 296             (uint32_t)samsg->sadb_x_msg_diagnostic,
 297             BUNYAN_T_UINT32, "msg_diagnostic",
 298             keysock_diag(samsg->sadb_x_msg_diagnostic),
 299             BUNYAN_T_UINT32, "length", (uint32_t)samsg->sadb_msg_len,
 300             BUNYAN_T_END);
 301 
 302         /*
 303          * XXX KEBE SAYS for now don't print the full inbound message.  An
 304          * "ipseckey monitor" instance is useful here.
 305          */
 306 
 307         /*
 308          * If it might be a reply to us, handle it.
 309          */
 310         if (samsg->sadb_msg_pid == getpid()) {
 311                 handle_reply(samsg);
 312                 return;
 313         }
 314 
 315         /*
 316          * Silently pitch the message if it's an error reply to someone else.
 317          */
 318         if (samsg->sadb_msg_errno != 0) {
 319                 bunyan_debug(log, "reply not for us, dropped", BUNYAN_T_END);
 320                 free(samsg);
 321                 return;
 322         }
 323 
 324         /*
 325          * At this point, we have a kernel-emitted message.  Typically this
 326          * will be an ACQUIRE, EXPIRE, or DELETE/DELPAIR.  Other ones include
 327          * FLUSH (which if we follow in.iked semantics, will nuke all IKE SA
 328          * state) and REGISTER (indicating a change in kernel algorithm
 329          * support).
 330          */
 331 
 332         switch (samsg->sadb_msg_type) {
 333         case SADB_ACQUIRE:
 334                 handle_acquire(samsg, B_TRUE);
 335                 return;
 336         case SADB_EXPIRE:
 337                 handle_expire(samsg);
 338                 return;
 339         case SADB_DELETE:
 340         case SADB_X_DELPAIR:
 341                 handle_delete(samsg);
 342                 return;
 343         case SADB_FLUSH:
 344                 handle_flush(samsg);
 345                 return;
 346         case SADB_REGISTER:
 347                 handle_register(samsg);
 348                 /*
 349                  * Explicitly free it here because handle_register() is also
 350                  * called from pf_key_init(), which has samsg on the stack
 351                  * instead.
 352                  */
 353                 free(samsg);
 354                 return;
 355         }
 356 
 357         bunyan_debug(log, "SADB message type unknown, ignored.",
 358             BUNYAN_T_UINT32, "msg_type_val", (uint32_t)samsg->sadb_msg_type,
 359             BUNYAN_T_END);
 360         free(samsg);
 361 }
 362 
 363 /*
 364  * Send a pfkey message 'msg'.  The reply will invoke the callback
 365  * function 'cb' with data as an argument.
 366  * Returns B_TRUE if the request is successfully sent,
 367  * B_FALSE if there was an error.
 368  */
 369 boolean_t
 370 pfkey_send_msg(sadb_msg_t *msg, pfreq_cb_t *cb, void *data)
 371 {
 372         pfreq_t *req;
 373         uu_list_index_t idx;
 374         ssize_t n;
 375 
 376         req = pfreq_new(cb, data);
 377         if (req == NULL)
 378                 return (B_FALSE);
 379 
 380         msg->sadb_msg_seq = req->pr_msgid;
 381         msg->sadb_msg_pid = getpid();
 382         n = write(pfkey, msg, msg->sadb_msg_len);
 383         if (n != msg->sadb_msg_len) {
 384                 if (n < 0) {
 385                         STDERR(error, log, "pf_key write failed");
 386                 } else {
 387                         bunyan_error(log, "pf_key truncated write",
 388                             BUNYAN_T_UINT32, "n", (uint32_t)n,
 389                             BUNYAN_T_END);
 390                 }
 391                 pfreq_free(req);
 392                 return (B_FALSE);
 393         }
 394 
 395         (void) pthread_mutex_lock(&pfreq_lock);
 396 
 397         (void) uu_list_find(pfreq_list, req, NULL, &idx);
 398         uu_list_insert(pfreq_list, req, idx);
 399         (void) pthread_mutex_unlock(&pfreq_lock);
 400 
 401         return (B_TRUE);
 402 }
 403 
 404 /*
 405  * Inform the kernel of an error.
 406  * src is the pfkey message the error is a response to, reason is
 407  * the reason for the error
 408  */
 409 void
 410 pfkey_send_error(const sadb_msg_t *src, uint8_t reason)
 411 {
 412         sadb_msg_t msg = { 0 };
 413         ssize_t n;
 414 
 415         /* Errors consists of just the sadb header */
 416         msg.sadb_msg_len = SADB_8TO64(sizeof (sadb_msg_t));
 417         msg.sadb_msg_version = PF_KEY_V2;
 418         msg.sadb_msg_type = src->sadb_msg_type;
 419         msg.sadb_msg_errno = reason;
 420         msg.sadb_msg_satype = src->sadb_msg_satype;
 421         msg.sadb_x_msg_diagnostic = SADB_X_DIAGNOSTIC_NONE;
 422         msg.sadb_msg_seq = src->sadb_msg_seq;
 423         msg.sadb_msg_pid = src->sadb_msg_pid;
 424 
 425         n = write(pfkey, &msg, sizeof (sadb_msg_t));
 426         if (n != sizeof (sadb_msg_t))
 427                 STDERR(error, log, "Unable to send PFKEY error notification");
 428 }
 429 
 430 static void
 431 handle_reply(sadb_msg_t *reply)
 432 {
 433         pfreq_t *req;
 434         uu_list_index_t idx;
 435 
 436         PTH(pthread_mutex_lock(&pfreq_lock));
 437         req = uu_list_find(pfreq_list, NULL, reply, &idx);
 438         if (req != NULL)
 439                 uu_list_remove(pfreq_list, req);
 440         PTH(pthread_mutex_unlock(&pfreq_lock));
 441 
 442         if (req == NULL) {
 443                 /* XXX: log more fields? */
 444                 bunyan_info(pflog, "Received a reply to an unknown request; "
 445                     "ignorning.",
 446                     BUNYAN_T_STRING, "msg_type",
 447                     pfkey_satype(reply->sadb_msg_type),
 448                     BUNYAN_T_UINT32, "msg_type_val",
 449                     (uint32_t)reply->sadb_msg_type,
 450                     BUNYAN_T_INT32, "pid", reply->sadb_msg_pid,
 451                     BUNYAN_T_UINT32, "seq", reply->sadb_msg_seq,
 452                     BUNYAN_T_END);
 453                 free(reply);
 454                 return;
 455         }
 456 
 457 #if 0
 458         req->pr_cb(reply, req->pr_data);
 459         pfreq_free(req);
 460 #endif
 461 
 462         switch (reply->sadb_msg_type) {
 463         case SADB_ACQUIRE:
 464         {
 465                 /* Should be a response to our inverse acquire */
 466                 parsedmsg_t pmsg = { 0 };
 467 
 468                 if (!extract_exts(reply, &pmsg, 1, SADB_X_EXT_EPROP)) {
 469                         bunyan_info(pflog, "No extended proposal found in "
 470                             "ACQUIRE reply.", BUNYAN_T_END);
 471                         free(reply);
 472                         return;
 473                 }
 474 
 475                 /*
 476                  * XXX: lookup what we queried based on msgid, extract
 477                  * SA type and pass to convert_ext_acquire
 478                  */
 479 
 480                 /* XXX: continue CHILD SA processing */
 481                 break;
 482         }
 483         default:
 484                 /* XXX: More to come */
 485                 ;
 486         }
 487 
 488         free(reply);
 489 }
 490 
 491 static void
 492 handle_flush(sadb_msg_t *samsg)
 493 {
 494         bunyan_trace(pflog, "Handling SADB flush message", BUNYAN_T_END);
 495 
 496         /* Return if just AH or ESP SAs are being freed. */
 497         if (samsg->sadb_msg_satype != SADB_SATYPE_UNSPEC)
 498                 return;
 499 
 500         /* XXX KEBE SAYS FILL ME IN! */
 501 
 502         ikev2_sa_flush();
 503 
 504         /*
 505          * If we receive an SADB_FLUSH for all SA types, get rid of any IKE
 506          * SAs.
 507          */
 508 
 509         free(samsg);
 510 }
 511 
 512 /*
 513  * Handle the PF_KEY SADB_EXPIRE message for idle timeout.
 514  *
 515  * XXX KEBE SAYS this'll most likely kick off Dead Peer Detection if we can
 516  * find an IKE SA.
 517  */
 518 static void
 519 handle_idle_timeout(sadb_msg_t *samsg)
 520 {
 521         bunyan_trace(pflog, "Handling SADB idle expire message", BUNYAN_T_END);
 522 
 523         /* XXX KEBE SAYS FILL ME IN! */
 524         free(samsg);
 525 }
 526 
 527 static void
 528 handle_expire(sadb_msg_t *samsg)
 529 {
 530         parsedmsg_t pmsg;
 531 
 532         /*
 533          * If SOFT expire, see if the SADB_X_SAFLAGS_KM1 (initiator) is set,
 534          * if so, consider treating this expire as an ACQUIRE message.
 535          *
 536          * If HARD expire, treat this message like a DELETE.
 537          *
 538          * If IDLE expire, see if we need to do a little DPD or not.
 539          */
 540 
 541         if (extract_exts(samsg, &pmsg, 1, SADB_EXT_LIFETIME_HARD)) {
 542                 bunyan_debug(pflog, "Handling SADB hard expire message",
 543                     BUNYAN_T_END);
 544                 handle_delete(samsg);
 545                 return;
 546         }
 547 
 548         if (pmsg.pmsg_exts[SADB_X_EXT_LIFETIME_IDLE] != NULL) {
 549                 handle_idle_timeout(samsg);
 550                 return;
 551         }
 552 
 553         /*
 554          * extract_exts() has already filled in pmsg with data from
 555          * samsg. pmsg.pmsg_exts[foo] will be NULL if this was
 556          * not set in samsg. Bail out if the message appears to be
 557          * poorly formed. If everything looks good, create a new
 558          * "ACQUIRE like" message and pass off to handle_acquire().
 559          */
 560 
 561         if (pmsg.pmsg_exts[SADB_EXT_LIFETIME_SOFT] == NULL) {
 562                 /* XXX: more fields */
 563                 bunyan_info(pflog, "SADB EXPIRE message is missing both "
 564                     "hard and soft lifetimes", BUNYAN_T_END);
 565                 /* XXX: ignore? */
 566         }
 567 
 568         bunyan_debug(pflog, "Handling SADB soft expire message", BUNYAN_T_END);
 569         /* XXX KEBE SAYS FILL ME IN! */
 570 
 571         free(samsg);
 572 }
 573 
 574 static void
 575 handle_register(sadb_msg_t *samsg)
 576 {
 577         _NOTE(ARGUNUSED(samsg))
 578         /* XXX KEBE SAYS FILL ME IN! */
 579 
 580         /*
 581          * XXX KEBE wonders if this is as necessary as 2367 first imagined?
 582          *
 583          * With inverse-ACQUIRE, you know better what algorithms are available
 584          * and acceptable.  This may go away or remain a mere stub.
 585          */
 586 }
 587 
 588 static void
 589 handle_delete(sadb_msg_t *samsg)
 590 {
 591         bunyan_trace(pflog, "Handling SADB delete", BUNYAN_T_END);
 592 
 593         /* XXX KEBE SAYS FILL ME IN! */
 594         free(samsg);
 595 }
 596 
 597 /*
 598  * Handle a PF_KEY ACQUIRE message.  This function, or something that it
 599  * calls (either directly or via callbacks) must free samsg.
 600  */
 601 /* XXX KEBE wonders if create_child_sa will be needed here or not. */
 602 static void
 603 handle_acquire(sadb_msg_t *samsg, boolean_t create_child_sa)
 604 {
 605         /* XXX: for now */
 606         _NOTE(ARGUNUSED(create_child_sa))
 607 
 608         parsedmsg_t pmsg;
 609 
 610         bunyan_debug(pflog, "Handling SADB acquire", BUNYAN_T_END);
 611 
 612         if (!extract_exts(samsg, &pmsg, 1, SADB_EXT_PROPOSAL)) {
 613                 bunyan_info(pflog, "No proposal found in ACQUIRE message",
 614                     BUNYAN_T_END);
 615                 free(samsg);
 616                 return;
 617         }
 618 
 619         /* XXX KEBE SAYS FILL ME IN! */
 620         free(samsg);
 621 }
 622 
 623 static int
 624 pfreq_compare(const void *l_arg, const void *r_arg, void *msg_arg)
 625 {
 626         const pfreq_t *l = l_arg;
 627         const pfreq_t *r = r_arg;
 628         sadb_msg_t *msg = msg_arg;
 629         uint32_t msgid;
 630         
 631         ASSERT((r != NULL && msg == NULL) || (r == NULL && msg != NULL));
 632 
 633         if (r != NULL)
 634                 msgid = r->pr_msgid;
 635         else
 636                 msgid = msg->sadb_msg_seq;
 637 
 638         if (l->pr_msgid < msgid)
 639                 return (-1);
 640         if (l->pr_msgid > msgid)
 641                 return (1);
 642         if (r == NULL)
 643                 return (0);
 644 
 645         if (l->pr_data < r->pr_data)
 646                 return (-1);
 647         if (l->pr_data > r->pr_data)
 648                 return (1);
 649         return (0);
 650 }
 651 
 652 static int
 653 pfreq_ctor(void *buf, void *ignore, int flags)
 654 {
 655         _NOTE(ARGUNUSED(ignore, flags))
 656         (void) memset(buf, 0, sizeof (pfreq_t));
 657         return (0);
 658 }
 659 
 660 static pfreq_t *
 661 pfreq_new(pfreq_cb_t *cb, void *data)
 662 {
 663         pfreq_t *req = umem_cache_alloc(pfreq_cache, UMEM_DEFAULT);
 664 
 665         if (req == NULL)
 666                 return (NULL);
 667 
 668         req->pr_msgid = atomic_inc_32_nv(&msgid);
 669         req->pr_cb = cb;
 670         req->pr_data = data;
 671         return (req);
 672 }
 673 
 674 static void
 675 pfreq_free(pfreq_t *req)
 676 {
 677         (void) pfreq_ctor(req, NULL, 0);
 678         umem_cache_free(pfreq_cache, req);
 679 }
 680 
 681 static void
 682 pfkey_register(uint8_t satype)
 683 {
 684         uint64_t buffer[128] = { 0 };
 685         sadb_msg_t *samsg = (sadb_msg_t *)buffer;
 686         ssize_t n;
 687         uint32_t msgid = atomic_inc_32_nv(&msgid);
 688         pid_t pid = getpid();
 689 
 690         CTASSERT(sizeof (buffer) >= sizeof (*samsg));
 691 
 692         samsg->sadb_msg_version = PF_KEY_V2;
 693         samsg->sadb_msg_type = SADB_REGISTER;
 694         samsg->sadb_msg_errno = 0;
 695         samsg->sadb_msg_satype = satype;
 696         samsg->sadb_msg_reserved = 0;
 697         samsg->sadb_msg_seq = msgid;
 698         samsg->sadb_msg_pid = pid;
 699         samsg->sadb_msg_len = SADB_8TO64(sizeof (*samsg));
 700 
 701         n = write(pfkey, buffer, sizeof (*samsg));
 702         if (n < 0)
 703                 err(EXIT_FAILURE, "pf_key write error");
 704         if (n < sizeof (*samsg))
 705                 errx(EXIT_FAILURE, "Unable to write pf_key register message");
 706 
 707         do {
 708                 (void) memset(buffer, 0, sizeof (buffer));
 709                 n = read(pfkey, buffer, sizeof (buffer));
 710                 if (n < 0)
 711                         err(EXIT_FAILURE, "pf_key read failure");
 712         } while (samsg->sadb_msg_seq != msgid ||
 713             samsg->sadb_msg_pid != pid ||
 714             samsg->sadb_msg_type != SADB_REGISTER);
 715 
 716         if (samsg->sadb_msg_errno != 0) {
 717                 if (samsg->sadb_msg_errno != EPROTONOSUPPORT)
 718                         errx(EXIT_FAILURE, "pf_key register returned %s (%d).",
 719                             strerror(samsg->sadb_msg_errno),
 720                             samsg->sadb_msg_errno);
 721                 bunyan_error(pflog, "Protocol not supported",
 722                     BUNYAN_T_UINT32, "msg_satype",
 723                     (uint32_t)samsg->sadb_msg_satype, BUNYAN_T_END);
 724         }
 725 
 726         bunyan_debug(pflog, "Initial REGISTER with SADB",
 727             BUNYAN_T_STRING, "satype", pfkey_satype(samsg->sadb_msg_satype),
 728             BUNYAN_T_END);
 729 
 730         handle_register(samsg);
 731 }
 732 
 733 void
 734 pfkey_init(void)
 735 {
 736         uint32_t flag = 0;
 737         int rc;
 738 
 739 #ifdef DEBUG
 740         flag |= UU_LIST_POOL_DEBUG;
 741 #endif
 742 
 743         pfreq_pool = uu_list_pool_create("pfreq_list", sizeof (pfreq_t),
 744             offsetof(pfreq_t, pr_node), pfreq_compare, flag);
 745         if (pfreq_pool == NULL)
 746                 errx(EXIT_FAILURE, "Unable to create pfreq list pool: %s",
 747                     uu_strerror(uu_error()));
 748 
 749         pfreq_cache = umem_cache_create("pfreq cache", sizeof (pfreq_t),
 750             sizeof (uint64_t), pfreq_ctor, NULL, NULL, NULL, NULL, 0);
 751         if (pfreq_cache == NULL)
 752                 err(EXIT_FAILURE, "Unable to create pfreq cache");
 753 
 754         pfkey = socket(PF_KEY, SOCK_RAW, PF_KEY_V2);
 755         if (pfkey == -1)
 756                 err(EXIT_FAILURE, "Unable to create pf_key socket");
 757 
 758         rc = bunyan_child(log, &pflog,
 759             BUNYAN_T_INT32, "socketfd", (int32_t)pfkey,
 760             BUNYAN_T_END);
 761         if (rc != 0)
 762                 errx(EXIT_FAILURE, "Unable to create child logger: %s",
 763                     strerror(rc));
 764 
 765         pfkey_register(SADB_SATYPE_ESP);
 766         pfkey_register(SADB_SATYPE_AH);
 767 
 768         schedule_socket(pfkey, pfkey_inbound);
 769 }