Print this page
    
First attempt at further IPsec cluster cleanup
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/inet/ip/sadb.c
          +++ new/usr/src/uts/common/inet/ip/sadb.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  23   23   * Use is subject to license terms.
  24   24   *
  25   25   * Copyright 2015 Garrett D'Amore <garrett@damore.org>
  26   26   */
  27   27  
  28   28  #include <sys/types.h>
  29   29  #include <sys/stream.h>
  30   30  #include <sys/stropts.h>
  31   31  #include <sys/strsubr.h>
  32   32  #include <sys/errno.h>
  33   33  #include <sys/ddi.h>
  34   34  #include <sys/debug.h>
  35   35  #include <sys/cmn_err.h>
  36   36  #include <sys/stream.h>
  37   37  #include <sys/strlog.h>
  38   38  #include <sys/kmem.h>
  39   39  #include <sys/sunddi.h>
  40   40  #include <sys/tihdr.h>
  41   41  #include <sys/atomic.h>
  42   42  #include <sys/socket.h>
  43   43  #include <sys/sysmacros.h>
  44   44  #include <sys/crypto/common.h>
  45   45  #include <sys/crypto/api.h>
  46   46  #include <sys/zone.h>
  47   47  #include <netinet/in.h>
  48   48  #include <net/if.h>
  49   49  #include <net/pfkeyv2.h>
  50   50  #include <net/pfpolicy.h>
  51   51  #include <inet/common.h>
  52   52  #include <netinet/ip6.h>
  53   53  #include <inet/ip.h>
  54   54  #include <inet/ip_ire.h>
  55   55  #include <inet/ip6.h>
  56   56  #include <inet/ipsec_info.h>
  57   57  #include <inet/tcp.h>
  58   58  #include <inet/sadb.h>
  59   59  #include <inet/ipsec_impl.h>
  60   60  #include <inet/ipsecah.h>
  61   61  #include <inet/ipsecesp.h>
  62   62  #include <sys/random.h>
  63   63  #include <sys/dlpi.h>
  64   64  #include <sys/strsun.h>
  65   65  #include <sys/strsubr.h>
  66   66  #include <inet/ip_if.h>
  67   67  #include <inet/ipdrop.h>
  68   68  #include <inet/ipclassifier.h>
  69   69  #include <inet/sctp_ip.h>
  70   70  #include <sys/tsol/tnet.h>
  71   71  
  72   72  /*
  73   73   * This source file contains Security Association Database (SADB) common
  74   74   * routines.  They are linked in with the AH module.  Since AH has no chance
  75   75   * of falling under export control, it was safe to link it in there.
  76   76   */
  77   77  
  78   78  static mblk_t *sadb_extended_acquire(ipsec_selector_t *, ipsec_policy_t *,
  79   79      ipsec_action_t *, boolean_t, uint32_t, uint32_t, sadb_sens_t *,
  80   80      netstack_t *);
  81   81  static ipsa_t *sadb_torch_assoc(isaf_t *, ipsa_t *);
  82   82  static void sadb_destroy_acqlist(iacqf_t **, uint_t, boolean_t,
  83   83                              netstack_t *);
  84   84  static void sadb_destroy(sadb_t *, netstack_t *);
  85   85  static mblk_t *sadb_sa2msg(ipsa_t *, sadb_msg_t *);
  86   86  static ts_label_t *sadb_label_from_sens(sadb_sens_t *, uint64_t *);
  87   87  static sadb_sens_t *sadb_make_sens_ext(ts_label_t *tsl, int *len);
  88   88  
  89   89  static time_t sadb_add_time(time_t, uint64_t);
  90   90  static void lifetime_fuzz(ipsa_t *);
  91   91  static void age_pair_peer_list(templist_t *, sadb_t *, boolean_t);
  92   92  static int get_ipsa_pair(ipsa_query_t *, ipsap_t *, int *);
  93   93  static void init_ipsa_pair(ipsap_t *);
  94   94  static void destroy_ipsa_pair(ipsap_t *);
  95   95  static int update_pairing(ipsap_t *, ipsa_query_t *, keysock_in_t *, int *);
  96   96  static void ipsa_set_replay(ipsa_t *ipsa, uint32_t offset);
  97   97  
  98   98  /*
  99   99   * ipsacq_maxpackets is defined here to make it tunable
 100  100   * from /etc/system.
 101  101   */
 102  102  extern uint64_t ipsacq_maxpackets;
 103  103  
 104  104  #define SET_EXPIRE(sa, delta, exp) {                            \
 105  105          if (((sa)->ipsa_ ## delta) != 0) {                              \
 106  106                  (sa)->ipsa_ ## exp = sadb_add_time((sa)->ipsa_addtime,  \
 107  107                          (sa)->ipsa_ ## delta);                          \
 108  108          }                                                               \
 109  109  }
 110  110  
 111  111  #define UPDATE_EXPIRE(sa, delta, exp) {                                 \
 112  112          if (((sa)->ipsa_ ## delta) != 0) {                              \
 113  113                  time_t tmp = sadb_add_time((sa)->ipsa_usetime,          \
 114  114                          (sa)->ipsa_ ## delta);                          \
 115  115                  if (((sa)->ipsa_ ## exp) == 0)                          \
 116  116                          (sa)->ipsa_ ## exp = tmp;                       \
 117  117                  else                                                    \
 118  118                          (sa)->ipsa_ ## exp =                            \
 119  119                              MIN((sa)->ipsa_ ## exp, tmp);               \
 120  120          }                                                               \
 121  121  }
 122  122  
 123  123  
 124  124  /* wrap the macro so we can pass it as a function pointer */
 125  125  void
 126  126  sadb_sa_refrele(void *target)
 127  127  {
 128  128          IPSA_REFRELE(((ipsa_t *)target));
 129  129  }
 130  130  
 131  131  /*
 132  132   * We presume that sizeof (long) == sizeof (time_t) and that time_t is
 133  133   * a signed type.
 134  134   */
 135  135  #define TIME_MAX LONG_MAX
 136  136  
 137  137  /*
 138  138   * PF_KEY gives us lifetimes in uint64_t seconds.  We presume that
 139  139   * time_t is defined to be a signed type with the same range as
 140  140   * "long".  On ILP32 systems, we thus run the risk of wrapping around
 141  141   * at end of time, as well as "overwrapping" the clock back around
 142  142   * into a seemingly valid but incorrect future date earlier than the
 143  143   * desired expiration.
 144  144   *
 145  145   * In order to avoid odd behavior (either negative lifetimes or loss
 146  146   * of high order bits) when someone asks for bizarrely long SA
 147  147   * lifetimes, we do a saturating add for expire times.
 148  148   *
 149  149   * We presume that ILP32 systems will be past end of support life when
 150  150   * the 32-bit time_t overflows (a dangerous assumption, mind you..).
 151  151   *
 152  152   * On LP64, 2^64 seconds are about 5.8e11 years, at which point we
 153  153   * will hopefully have figured out clever ways to avoid the use of
 154  154   * fixed-sized integers in computation.
 155  155   */
 156  156  static time_t
 157  157  sadb_add_time(time_t base, uint64_t delta)
 158  158  {
 159  159          time_t sum;
 160  160  
 161  161          /*
 162  162           * Clip delta to the maximum possible time_t value to
 163  163           * prevent "overwrapping" back into a shorter-than-desired
 164  164           * future time.
 165  165           */
 166  166          if (delta > TIME_MAX)
 167  167                  delta = TIME_MAX;
 168  168          /*
 169  169           * This sum may still overflow.
 170  170           */
 171  171          sum = base + delta;
 172  172  
 173  173          /*
 174  174           * .. so if the result is less than the base, we overflowed.
 175  175           */
 176  176          if (sum < base)
 177  177                  sum = TIME_MAX;
 178  178  
 179  179          return (sum);
 180  180  }
 181  181  
 182  182  /*
 183  183   * Callers of this function have already created a working security
 184  184   * association, and have found the appropriate table & hash chain.  All this
 185  185   * function does is check duplicates, and insert the SA.  The caller needs to
 186  186   * hold the hash bucket lock and increment the refcnt before insertion.
 187  187   *
 188  188   * Return 0 if success, EEXIST if collision.
 189  189   */
 190  190  #define SA_UNIQUE_MATCH(sa1, sa2) \
 191  191          (((sa1)->ipsa_unique_id & (sa1)->ipsa_unique_mask) == \
 192  192          ((sa2)->ipsa_unique_id & (sa2)->ipsa_unique_mask))
 193  193  
 194  194  int
 195  195  sadb_insertassoc(ipsa_t *ipsa, isaf_t *bucket)
 196  196  {
 197  197          ipsa_t **ptpn = NULL;
 198  198          ipsa_t *walker;
 199  199          boolean_t unspecsrc;
 200  200  
 201  201          ASSERT(MUTEX_HELD(&bucket->isaf_lock));
 202  202  
 203  203          unspecsrc = IPSA_IS_ADDR_UNSPEC(ipsa->ipsa_srcaddr, ipsa->ipsa_addrfam);
 204  204  
 205  205          walker = bucket->isaf_ipsa;
 206  206          ASSERT(walker == NULL || ipsa->ipsa_addrfam == walker->ipsa_addrfam);
 207  207  
 208  208          /*
 209  209           * Find insertion point (pointed to with **ptpn).  Insert at the head
 210  210           * of the list unless there's an unspecified source address, then
 211  211           * insert it after the last SA with a specified source address.
 212  212           *
 213  213           * BTW, you'll have to walk the whole chain, matching on {DST, SPI}
 214  214           * checking for collisions.
 215  215           */
 216  216  
 217  217          while (walker != NULL) {
 218  218                  if (IPSA_ARE_ADDR_EQUAL(walker->ipsa_dstaddr,
 219  219                      ipsa->ipsa_dstaddr, ipsa->ipsa_addrfam)) {
 220  220                          if (walker->ipsa_spi == ipsa->ipsa_spi)
 221  221                                  return (EEXIST);
 222  222  
 223  223                          mutex_enter(&walker->ipsa_lock);
 224  224                          if (ipsa->ipsa_state == IPSA_STATE_MATURE &&
 225  225                              (walker->ipsa_flags & IPSA_F_USED) &&
 226  226                              SA_UNIQUE_MATCH(walker, ipsa)) {
 227  227                                  walker->ipsa_flags |= IPSA_F_CINVALID;
 228  228                          }
 229  229                          mutex_exit(&walker->ipsa_lock);
 230  230                  }
 231  231  
 232  232                  if (ptpn == NULL && unspecsrc) {
 233  233                          if (IPSA_IS_ADDR_UNSPEC(walker->ipsa_srcaddr,
 234  234                              walker->ipsa_addrfam))
 235  235                                  ptpn = walker->ipsa_ptpn;
 236  236                          else if (walker->ipsa_next == NULL)
 237  237                                  ptpn = &walker->ipsa_next;
 238  238                  }
 239  239  
 240  240                  walker = walker->ipsa_next;
 241  241          }
 242  242  
 243  243          if (ptpn == NULL)
 244  244                  ptpn = &bucket->isaf_ipsa;
 245  245          ipsa->ipsa_next = *ptpn;
 246  246          ipsa->ipsa_ptpn = ptpn;
 247  247          if (ipsa->ipsa_next != NULL)
 248  248                  ipsa->ipsa_next->ipsa_ptpn = &ipsa->ipsa_next;
 249  249          *ptpn = ipsa;
 250  250          ipsa->ipsa_linklock = &bucket->isaf_lock;
 251  251  
 252  252          return (0);
 253  253  }
 254  254  #undef SA_UNIQUE_MATCH
 255  255  
 256  256  /*
 257  257   * Free a security association.  Its reference count is 0, which means
 258  258   * I must free it.  The SA must be unlocked and must not be linked into
 259  259   * any fanout list.
 260  260   */
 261  261  static void
 262  262  sadb_freeassoc(ipsa_t *ipsa)
 263  263  {
 264  264          ipsec_stack_t   *ipss = ipsa->ipsa_netstack->netstack_ipsec;
 265  265          mblk_t          *asyncmp, *mp;
 266  266  
 267  267          ASSERT(ipss != NULL);
 268  268          ASSERT(MUTEX_NOT_HELD(&ipsa->ipsa_lock));
 269  269          ASSERT(ipsa->ipsa_refcnt == 0);
 270  270          ASSERT(ipsa->ipsa_next == NULL);
 271  271          ASSERT(ipsa->ipsa_ptpn == NULL);
 272  272  
 273  273  
 274  274          asyncmp = sadb_clear_lpkt(ipsa);
 275  275          if (asyncmp != NULL) {
 276  276                  mp = ip_recv_attr_free_mblk(asyncmp);
 277  277                  ip_drop_packet(mp, B_TRUE, NULL,
 278  278                      DROPPER(ipss, ipds_sadb_inlarval_timeout),
 279  279                      &ipss->ipsec_sadb_dropper);
 280  280          }
 281  281          mutex_enter(&ipsa->ipsa_lock);
 282  282  
 283  283          if (ipsa->ipsa_tsl != NULL) {
 284  284                  label_rele(ipsa->ipsa_tsl);
 285  285                  ipsa->ipsa_tsl = NULL;
 286  286          }
 287  287  
 288  288          if (ipsa->ipsa_otsl != NULL) {
 289  289                  label_rele(ipsa->ipsa_otsl);
 290  290                  ipsa->ipsa_otsl = NULL;
 291  291          }
 292  292  
 293  293          ipsec_destroy_ctx_tmpl(ipsa, IPSEC_ALG_AUTH);
 294  294          ipsec_destroy_ctx_tmpl(ipsa, IPSEC_ALG_ENCR);
 295  295          mutex_exit(&ipsa->ipsa_lock);
 296  296  
 297  297          /* bzero() these fields for paranoia's sake. */
 298  298          if (ipsa->ipsa_authkey != NULL) {
 299  299                  bzero(ipsa->ipsa_authkey, ipsa->ipsa_authkeylen);
 300  300                  kmem_free(ipsa->ipsa_authkey, ipsa->ipsa_authkeylen);
 301  301          }
 302  302          if (ipsa->ipsa_encrkey != NULL) {
 303  303                  bzero(ipsa->ipsa_encrkey, ipsa->ipsa_encrkeylen);
 304  304                  kmem_free(ipsa->ipsa_encrkey, ipsa->ipsa_encrkeylen);
 305  305          }
 306  306          if (ipsa->ipsa_nonce_buf != NULL) {
 307  307                  bzero(ipsa->ipsa_nonce_buf, sizeof (ipsec_nonce_t));
 308  308                  kmem_free(ipsa->ipsa_nonce_buf, sizeof (ipsec_nonce_t));
 309  309          }
 310  310          if (ipsa->ipsa_src_cid != NULL) {
 311  311                  IPSID_REFRELE(ipsa->ipsa_src_cid);
 312  312          }
 313  313          if (ipsa->ipsa_dst_cid != NULL) {
 314  314                  IPSID_REFRELE(ipsa->ipsa_dst_cid);
 315  315          }
 316  316          if (ipsa->ipsa_emech.cm_param != NULL)
 317  317                  kmem_free(ipsa->ipsa_emech.cm_param,
 318  318                      ipsa->ipsa_emech.cm_param_len);
 319  319  
 320  320          mutex_destroy(&ipsa->ipsa_lock);
 321  321          kmem_free(ipsa, sizeof (*ipsa));
 322  322  }
 323  323  
 324  324  /*
 325  325   * Unlink a security association from a hash bucket.  Assume the hash bucket
 326  326   * lock is held, but the association's lock is not.
 327  327   *
 328  328   * Note that we do not bump the bucket's generation number here because
 329  329   * we might not be making a visible change to the set of visible SA's.
 330  330   * All callers MUST bump the bucket's generation number before they unlock
 331  331   * the bucket if they use sadb_unlinkassoc to permanetly remove an SA which
 332  332   * was present in the bucket at the time it was locked.
 333  333   */
 334  334  void
 335  335  sadb_unlinkassoc(ipsa_t *ipsa)
 336  336  {
 337  337          ASSERT(ipsa->ipsa_linklock != NULL);
 338  338          ASSERT(MUTEX_HELD(ipsa->ipsa_linklock));
 339  339  
 340  340          /* These fields are protected by the link lock. */
 341  341          *(ipsa->ipsa_ptpn) = ipsa->ipsa_next;
 342  342          if (ipsa->ipsa_next != NULL) {
 343  343                  ipsa->ipsa_next->ipsa_ptpn = ipsa->ipsa_ptpn;
 344  344                  ipsa->ipsa_next = NULL;
 345  345          }
 346  346  
 347  347          ipsa->ipsa_ptpn = NULL;
 348  348  
 349  349          /* This may destroy the SA. */
 350  350          IPSA_REFRELE(ipsa);
 351  351  }
 352  352  
 353  353  /*
 354  354   * Create a larval security association with the specified SPI.  All other
 355  355   * fields are zeroed.
 356  356   */
 357  357  static ipsa_t *
 358  358  sadb_makelarvalassoc(uint32_t spi, uint32_t *src, uint32_t *dst, int addrfam,
 359  359      netstack_t *ns)
 360  360  {
 361  361          ipsa_t *newbie;
 362  362  
 363  363          /*
 364  364           * Allocate...
 365  365           */
 366  366  
 367  367          newbie = (ipsa_t *)kmem_zalloc(sizeof (ipsa_t), KM_NOSLEEP);
 368  368          if (newbie == NULL) {
 369  369                  /* Can't make new larval SA. */
 370  370                  return (NULL);
 371  371          }
 372  372  
 373  373          /* Assigned requested SPI, assume caller does SPI allocation magic. */
 374  374          newbie->ipsa_spi = spi;
 375  375          newbie->ipsa_netstack = ns;     /* No netstack_hold */
 376  376  
 377  377          /*
 378  378           * Copy addresses...
 379  379           */
 380  380  
 381  381          IPSA_COPY_ADDR(newbie->ipsa_srcaddr, src, addrfam);
 382  382          IPSA_COPY_ADDR(newbie->ipsa_dstaddr, dst, addrfam);
 383  383  
 384  384          newbie->ipsa_addrfam = addrfam;
 385  385  
 386  386          /*
 387  387           * Set common initialization values, including refcnt.
 388  388           */
 389  389          mutex_init(&newbie->ipsa_lock, NULL, MUTEX_DEFAULT, NULL);
 390  390          newbie->ipsa_state = IPSA_STATE_LARVAL;
 391  391          newbie->ipsa_refcnt = 1;
 392  392          newbie->ipsa_freefunc = sadb_freeassoc;
 393  393  
 394  394          /*
 395  395           * There aren't a lot of other common initialization values, as
 396  396           * they are copied in from the PF_KEY message.
 397  397           */
 398  398  
 399  399          return (newbie);
 400  400  }
 401  401  
 402  402  /*
 403  403   * Call me to initialize a security association fanout.
 404  404   */
 405  405  static int
 406  406  sadb_init_fanout(isaf_t **tablep, uint_t size, int kmflag)
 407  407  {
 408  408          isaf_t *table;
 409  409          int i;
 410  410  
 411  411          table = (isaf_t *)kmem_alloc(size * sizeof (*table), kmflag);
 412  412          *tablep = table;
 413  413  
 414  414          if (table == NULL)
 415  415                  return (ENOMEM);
 416  416  
 417  417          for (i = 0; i < size; i++) {
 418  418                  mutex_init(&(table[i].isaf_lock), NULL, MUTEX_DEFAULT, NULL);
 419  419                  table[i].isaf_ipsa = NULL;
 420  420                  table[i].isaf_gen = 0;
 421  421          }
 422  422  
 423  423          return (0);
 424  424  }
 425  425  
 426  426  /*
 427  427   * Call me to initialize an acquire fanout
 428  428   */
 429  429  static int
 430  430  sadb_init_acfanout(iacqf_t **tablep, uint_t size, int kmflag)
 431  431  {
 432  432          iacqf_t *table;
 433  433          int i;
 434  434  
 435  435          table = (iacqf_t *)kmem_alloc(size * sizeof (*table), kmflag);
 436  436          *tablep = table;
 437  437  
 438  438          if (table == NULL)
 439  439                  return (ENOMEM);
 440  440  
 441  441          for (i = 0; i < size; i++) {
 442  442                  mutex_init(&(table[i].iacqf_lock), NULL, MUTEX_DEFAULT, NULL);
 443  443                  table[i].iacqf_ipsacq = NULL;
 444  444          }
 445  445  
 446  446          return (0);
 447  447  }
 448  448  
 449  449  /*
 450  450   * Attempt to initialize an SADB instance.  On failure, return ENOMEM;
 451  451   * caller must clean up partial allocations.
 452  452   */
 453  453  static int
 454  454  sadb_init_trial(sadb_t *sp, uint_t size, int kmflag)
 455  455  {
 456  456          ASSERT(sp->sdb_of == NULL);
 457  457          ASSERT(sp->sdb_if == NULL);
 458  458          ASSERT(sp->sdb_acq == NULL);
 459  459  
 460  460          sp->sdb_hashsize = size;
 461  461          if (sadb_init_fanout(&sp->sdb_of, size, kmflag) != 0)
 462  462                  return (ENOMEM);
 463  463          if (sadb_init_fanout(&sp->sdb_if, size, kmflag) != 0)
 464  464                  return (ENOMEM);
 465  465          if (sadb_init_acfanout(&sp->sdb_acq, size, kmflag) != 0)
 466  466                  return (ENOMEM);
 467  467  
 468  468          return (0);
 469  469  }
 470  470  
 471  471  /*
 472  472   * Call me to initialize an SADB instance; fall back to default size on failure.
 473  473   */
 474  474  static void
 475  475  sadb_init(const char *name, sadb_t *sp, uint_t size, uint_t ver,
 476  476      netstack_t *ns)
 477  477  {
 478  478          ASSERT(sp->sdb_of == NULL);
 479  479          ASSERT(sp->sdb_if == NULL);
 480  480          ASSERT(sp->sdb_acq == NULL);
 481  481  
 482  482          if (size < IPSEC_DEFAULT_HASH_SIZE)
 483  483                  size = IPSEC_DEFAULT_HASH_SIZE;
 484  484  
 485  485          if (sadb_init_trial(sp, size, KM_NOSLEEP) != 0) {
 486  486  
 487  487                  cmn_err(CE_WARN,
 488  488                      "Unable to allocate %u entry IPv%u %s SADB hash table",
 489  489                      size, ver, name);
 490  490  
 491  491                  sadb_destroy(sp, ns);
 492  492                  size = IPSEC_DEFAULT_HASH_SIZE;
 493  493                  cmn_err(CE_WARN, "Falling back to %d entries", size);
 494  494                  (void) sadb_init_trial(sp, size, KM_SLEEP);
 495  495          }
 496  496  }
 497  497  
 498  498  
 499  499  /*
 500  500   * Initialize an SADB-pair.
 501  501   */
 502  502  void
 503  503  sadbp_init(const char *name, sadbp_t *sp, int type, int size, netstack_t *ns)
 504  504  {
 505  505          sadb_init(name, &sp->s_v4, size, 4, ns);
 506  506          sadb_init(name, &sp->s_v6, size, 6, ns);
 507  507  
 508  508          sp->s_satype = type;
 509  509  
 510  510          ASSERT((type == SADB_SATYPE_AH) || (type == SADB_SATYPE_ESP));
 511  511          if (type == SADB_SATYPE_AH) {
 512  512                  ipsec_stack_t   *ipss = ns->netstack_ipsec;
 513  513  
 514  514                  ip_drop_register(&ipss->ipsec_sadb_dropper, "IPsec SADB");
 515  515                  sp->s_addflags = AH_ADD_SETTABLE_FLAGS;
 516  516                  sp->s_updateflags = AH_UPDATE_SETTABLE_FLAGS;
 517  517          } else {
 518  518                  sp->s_addflags = ESP_ADD_SETTABLE_FLAGS;
 519  519                  sp->s_updateflags = ESP_UPDATE_SETTABLE_FLAGS;
 520  520          }
 521  521  }
 522  522  
 523  523  /*
 524  524   * Deliver a single SADB_DUMP message representing a single SA.  This is
 525  525   * called many times by sadb_dump().
 526  526   *
 527  527   * If the return value of this is ENOBUFS (not the same as ENOMEM), then
 528  528   * the caller should take that as a hint that dupb() on the "original answer"
 529  529   * failed, and that perhaps the caller should try again with a copyb()ed
 530  530   * "original answer".
 531  531   */
 532  532  static int
 533  533  sadb_dump_deliver(queue_t *pfkey_q, mblk_t *original_answer, ipsa_t *ipsa,
 534  534      sadb_msg_t *samsg)
 535  535  {
 536  536          mblk_t *answer;
 537  537  
 538  538          answer = dupb(original_answer);
 539  539          if (answer == NULL)
 540  540                  return (ENOBUFS);
 541  541          answer->b_cont = sadb_sa2msg(ipsa, samsg);
 542  542          if (answer->b_cont == NULL) {
 543  543                  freeb(answer);
 544  544                  return (ENOMEM);
 545  545          }
 546  546  
 547  547          /* Just do a putnext, and let keysock deal with flow control. */
 548  548          putnext(pfkey_q, answer);
 549  549          return (0);
 550  550  }
 551  551  
 552  552  /*
 553  553   * Common function to allocate and prepare a keysock_out_t M_CTL message.
 554  554   */
 555  555  mblk_t *
 556  556  sadb_keysock_out(minor_t serial)
 557  557  {
 558  558          mblk_t *mp;
 559  559          keysock_out_t *kso;
 560  560  
 561  561          mp = allocb(sizeof (ipsec_info_t), BPRI_HI);
 562  562          if (mp != NULL) {
 563  563                  mp->b_datap->db_type = M_CTL;
 564  564                  mp->b_wptr += sizeof (ipsec_info_t);
 565  565                  kso = (keysock_out_t *)mp->b_rptr;
 566  566                  kso->ks_out_type = KEYSOCK_OUT;
 567  567                  kso->ks_out_len = sizeof (*kso);
 568  568                  kso->ks_out_serial = serial;
 569  569          }
  
    | 
      ↓ open down ↓ | 
    569 lines elided | 
    
      ↑ open up ↑ | 
  
 570  570  
 571  571          return (mp);
 572  572  }
 573  573  
 574  574  /*
 575  575   * Perform an SADB_DUMP, spewing out every SA in an array of SA fanouts
 576  576   * to keysock.
 577  577   */
 578  578  static int
 579  579  sadb_dump_fanout(queue_t *pfkey_q, mblk_t *mp, minor_t serial, isaf_t *fanout,
 580      -    int num_entries, boolean_t do_peers, time_t active_time)
      580 +    int num_entries, boolean_t do_peers)
 581  581  {
 582  582          int i, error = 0;
 583  583          mblk_t *original_answer;
 584  584          ipsa_t *walker;
 585  585          sadb_msg_t *samsg;
 586      -        time_t  current;
 587  586  
 588  587          /*
 589  588           * For each IPSA hash bucket do:
 590  589           *      - Hold the mutex
 591  590           *      - Walk each entry, doing an sadb_dump_deliver() on it.
 592  591           */
 593  592          ASSERT(mp->b_cont != NULL);
 594  593          samsg = (sadb_msg_t *)mp->b_cont->b_rptr;
 595  594  
 596  595          original_answer = sadb_keysock_out(serial);
 597  596          if (original_answer == NULL)
 598  597                  return (ENOMEM);
 599  598  
 600      -        current = gethrestime_sec();
 601  599          for (i = 0; i < num_entries; i++) {
 602  600                  mutex_enter(&fanout[i].isaf_lock);
 603  601                  for (walker = fanout[i].isaf_ipsa; walker != NULL;
 604  602                      walker = walker->ipsa_next) {
 605  603                          if (!do_peers && walker->ipsa_haspeer)
 606  604                                  continue;
 607      -                        if ((active_time != 0) &&
 608      -                            ((current - walker->ipsa_lastuse) > active_time))
 609      -                                continue;
 610  605                          error = sadb_dump_deliver(pfkey_q, original_answer,
 611  606                              walker, samsg);
 612  607                          if (error == ENOBUFS) {
 613  608                                  mblk_t *new_original_answer;
 614  609  
 615  610                                  /* Ran out of dupb's.  Try a copyb. */
 616  611                                  new_original_answer = copyb(original_answer);
 617  612                                  if (new_original_answer == NULL) {
 618  613                                          error = ENOMEM;
 619  614                                  } else {
 620  615                                          freeb(original_answer);
 621  616                                          original_answer = new_original_answer;
 622  617                                          error = sadb_dump_deliver(pfkey_q,
 623  618                                              original_answer, walker, samsg);
 624  619                                  }
 625  620                          }
 626  621                          if (error != 0)
 627  622                                  break;  /* out of for loop. */
 628  623                  }
 629  624                  mutex_exit(&fanout[i].isaf_lock);
 630  625                  if (error != 0)
 631  626                          break;  /* out of for loop. */
 632  627          }
 633  628  
 634  629          freeb(original_answer);
 635  630          return (error);
  
    | 
      ↓ open down ↓ | 
    16 lines elided | 
    
      ↑ open up ↑ | 
  
 636  631  }
 637  632  
 638  633  /*
 639  634   * Dump an entire SADB; outbound first, then inbound.
 640  635   */
 641  636  
 642  637  int
 643  638  sadb_dump(queue_t *pfkey_q, mblk_t *mp, keysock_in_t *ksi, sadb_t *sp)
 644  639  {
 645  640          int error;
 646      -        time_t  active_time = 0;
 647      -        sadb_x_edump_t  *edump =
 648      -            (sadb_x_edump_t *)ksi->ks_in_extv[SADB_X_EXT_EDUMP];
 649  641  
 650      -        if (edump != NULL) {
 651      -                active_time = edump->sadb_x_edump_timeout;
 652      -        }
 653      -
 654  642          /* Dump outbound */
 655  643          error = sadb_dump_fanout(pfkey_q, mp, ksi->ks_in_serial, sp->sdb_of,
 656      -            sp->sdb_hashsize, B_TRUE, active_time);
      644 +            sp->sdb_hashsize, B_TRUE);
 657  645          if (error)
 658  646                  return (error);
 659  647  
 660  648          /* Dump inbound */
 661      -        return sadb_dump_fanout(pfkey_q, mp, ksi->ks_in_serial, sp->sdb_if,
 662      -            sp->sdb_hashsize, B_FALSE, active_time);
      649 +        return (sadb_dump_fanout(pfkey_q, mp, ksi->ks_in_serial, sp->sdb_if,
      650 +            sp->sdb_hashsize, B_FALSE));
 663  651  }
 664  652  
 665  653  /*
 666  654   * Generic sadb table walker.
 667  655   *
 668  656   * Call "walkfn" for each SA in each bucket in "table"; pass the
 669  657   * bucket, the entry and "cookie" to the callback function.
 670  658   * Take care to ensure that walkfn can delete the SA without screwing
 671  659   * up our traverse.
 672  660   *
 673  661   * The bucket is locked for the duration of the callback, both so that the
 674  662   * callback can just call sadb_unlinkassoc() when it wants to delete something,
 675  663   * and so that no new entries are added while we're walking the list.
 676  664   */
 677  665  static void
 678  666  sadb_walker(isaf_t *table, uint_t numentries,
 679  667      void (*walkfn)(isaf_t *head, ipsa_t *entry, void *cookie),
 680  668      void *cookie)
 681  669  {
 682  670          int i;
 683  671          for (i = 0; i < numentries; i++) {
 684  672                  ipsa_t *entry, *next;
 685  673  
 686  674                  mutex_enter(&table[i].isaf_lock);
 687  675  
 688  676                  for (entry = table[i].isaf_ipsa; entry != NULL;
 689  677                      entry = next) {
 690  678                          next = entry->ipsa_next;
  
    | 
      ↓ open down ↓ | 
    18 lines elided | 
    
      ↑ open up ↑ | 
  
 691  679                          (*walkfn)(&table[i], entry, cookie);
 692  680                  }
 693  681                  mutex_exit(&table[i].isaf_lock);
 694  682          }
 695  683  }
 696  684  
 697  685  /*
 698  686   * Call me to free up a security association fanout.  Use the forever
 699  687   * variable to indicate freeing up the SAs (forever == B_FALSE, e.g.
 700  688   * an SADB_FLUSH message), or destroying everything (forever == B_TRUE,
 701      - * when a module is unloaded).
      689 + * when a netstack is destroyed or a module is unloaded).
 702  690   */
 703  691  static void
 704      -sadb_destroyer(isaf_t **tablep, uint_t numentries, boolean_t forever,
 705      -    boolean_t inbound)
      692 +sadb_destroyer(isaf_t **tablep, uint_t numentries, boolean_t forever)
 706  693  {
 707  694          int i;
 708  695          isaf_t *table = *tablep;
 709  696          ipsa_t *sa;
 710  697  
 711  698          if (table == NULL)
 712  699                  return;
 713  700  
 714  701          for (i = 0; i < numentries; i++) {
 715  702                  mutex_enter(&table[i].isaf_lock);
 716  703                  while ((sa = table[i].isaf_ipsa) != NULL) {
 717  704                          sadb_unlinkassoc(sa);
 718  705                  }
 719  706                  table[i].isaf_gen++;
 720  707                  mutex_exit(&table[i].isaf_lock);
 721  708                  if (forever)
 722  709                          mutex_destroy(&(table[i].isaf_lock));
 723  710          }
 724  711  
 725  712          if (forever) {
 726  713                  *tablep = NULL;
 727  714                  kmem_free(table, numentries * sizeof (*table));
 728  715          }
 729  716  }
 730  717  
 731  718  /*
 732  719   * Entry points to sadb_destroyer().
  
    | 
      ↓ open down ↓ | 
    17 lines elided | 
    
      ↑ open up ↑ | 
  
 733  720   */
 734  721  static void
 735  722  sadb_flush(sadb_t *sp, netstack_t *ns)
 736  723  {
 737  724          /*
 738  725           * Flush out each bucket, one at a time.  Were it not for keysock's
 739  726           * enforcement, there would be a subtlety where I could add on the
 740  727           * heels of a flush.  With keysock's enforcement, however, this
 741  728           * makes ESP's job easy.
 742  729           */
 743      -        sadb_destroyer(&sp->sdb_of, sp->sdb_hashsize, B_FALSE, B_FALSE);
 744      -        sadb_destroyer(&sp->sdb_if, sp->sdb_hashsize, B_FALSE, B_TRUE);
      730 +        sadb_destroyer(&sp->sdb_of, sp->sdb_hashsize, B_FALSE);
      731 +        sadb_destroyer(&sp->sdb_if, sp->sdb_hashsize, B_FALSE);
 745  732  
 746  733          /* For each acquire, destroy it; leave the bucket mutex alone. */
 747  734          sadb_destroy_acqlist(&sp->sdb_acq, sp->sdb_hashsize, B_FALSE, ns);
 748  735  }
 749  736  
 750  737  static void
 751  738  sadb_destroy(sadb_t *sp, netstack_t *ns)
 752  739  {
 753      -        sadb_destroyer(&sp->sdb_of, sp->sdb_hashsize, B_TRUE, B_FALSE);
 754      -        sadb_destroyer(&sp->sdb_if, sp->sdb_hashsize, B_TRUE, B_TRUE);
      740 +        sadb_destroyer(&sp->sdb_of, sp->sdb_hashsize, B_TRUE);
      741 +        sadb_destroyer(&sp->sdb_if, sp->sdb_hashsize, B_TRUE);
 755  742  
 756  743          /* For each acquire, destroy it, including the bucket mutex. */
 757  744          sadb_destroy_acqlist(&sp->sdb_acq, sp->sdb_hashsize, B_TRUE, ns);
 758  745  
 759  746          ASSERT(sp->sdb_of == NULL);
 760  747          ASSERT(sp->sdb_if == NULL);
 761  748          ASSERT(sp->sdb_acq == NULL);
 762  749  }
 763  750  
 764  751  void
 765  752  sadbp_flush(sadbp_t *spp, netstack_t *ns)
 766  753  {
 767  754          sadb_flush(&spp->s_v4, ns);
 768  755          sadb_flush(&spp->s_v6, ns);
 769  756  }
 770  757  
 771  758  void
 772  759  sadbp_destroy(sadbp_t *spp, netstack_t *ns)
 773  760  {
 774  761          sadb_destroy(&spp->s_v4, ns);
 775  762          sadb_destroy(&spp->s_v6, ns);
 776  763  
 777  764          if (spp->s_satype == SADB_SATYPE_AH) {
 778  765                  ipsec_stack_t   *ipss = ns->netstack_ipsec;
 779  766  
 780  767                  ip_drop_unregister(&ipss->ipsec_sadb_dropper);
 781  768          }
 782  769  }
 783  770  
 784  771  
 785  772  /*
 786  773   * Check hard vs. soft lifetimes.  If there's a reality mismatch (e.g.
 787  774   * soft lifetimes > hard lifetimes) return an appropriate diagnostic for
 788  775   * EINVAL.
 789  776   */
 790  777  int
 791  778  sadb_hardsoftchk(sadb_lifetime_t *hard, sadb_lifetime_t *soft,
 792  779      sadb_lifetime_t *idle)
 793  780  {
 794  781          if (hard == NULL || soft == NULL)
 795  782                  return (0);
 796  783  
 797  784          if (hard->sadb_lifetime_allocations != 0 &&
 798  785              soft->sadb_lifetime_allocations != 0 &&
 799  786              hard->sadb_lifetime_allocations < soft->sadb_lifetime_allocations)
 800  787                  return (SADB_X_DIAGNOSTIC_ALLOC_HSERR);
 801  788  
 802  789          if (hard->sadb_lifetime_bytes != 0 &&
 803  790              soft->sadb_lifetime_bytes != 0 &&
 804  791              hard->sadb_lifetime_bytes < soft->sadb_lifetime_bytes)
 805  792                  return (SADB_X_DIAGNOSTIC_BYTES_HSERR);
 806  793  
 807  794          if (hard->sadb_lifetime_addtime != 0 &&
 808  795              soft->sadb_lifetime_addtime != 0 &&
 809  796              hard->sadb_lifetime_addtime < soft->sadb_lifetime_addtime)
 810  797                  return (SADB_X_DIAGNOSTIC_ADDTIME_HSERR);
 811  798  
 812  799          if (hard->sadb_lifetime_usetime != 0 &&
 813  800              soft->sadb_lifetime_usetime != 0 &&
 814  801              hard->sadb_lifetime_usetime < soft->sadb_lifetime_usetime)
 815  802                  return (SADB_X_DIAGNOSTIC_USETIME_HSERR);
 816  803  
 817  804          if (idle != NULL) {
 818  805                  if (hard->sadb_lifetime_addtime != 0 &&
 819  806                      idle->sadb_lifetime_addtime != 0 &&
 820  807                      hard->sadb_lifetime_addtime < idle->sadb_lifetime_addtime)
 821  808                          return (SADB_X_DIAGNOSTIC_ADDTIME_HSERR);
 822  809  
 823  810                  if (soft->sadb_lifetime_addtime != 0 &&
 824  811                      idle->sadb_lifetime_addtime != 0 &&
 825  812                      soft->sadb_lifetime_addtime < idle->sadb_lifetime_addtime)
 826  813                          return (SADB_X_DIAGNOSTIC_ADDTIME_HSERR);
 827  814  
 828  815                  if (hard->sadb_lifetime_usetime != 0 &&
 829  816                      idle->sadb_lifetime_usetime != 0 &&
 830  817                      hard->sadb_lifetime_usetime < idle->sadb_lifetime_usetime)
 831  818                          return (SADB_X_DIAGNOSTIC_USETIME_HSERR);
 832  819  
 833  820                  if (soft->sadb_lifetime_usetime != 0 &&
 834  821                      idle->sadb_lifetime_usetime != 0 &&
 835  822                      soft->sadb_lifetime_usetime < idle->sadb_lifetime_usetime)
 836  823                          return (SADB_X_DIAGNOSTIC_USETIME_HSERR);
 837  824          }
 838  825  
 839  826          return (0);
 840  827  }
 841  828  
 842  829  /*
 843  830   * Sanity check sensitivity labels.
 844  831   *
 845  832   * For now, just reject labels on unlabeled systems.
 846  833   */
 847  834  int
 848  835  sadb_labelchk(keysock_in_t *ksi)
 849  836  {
 850  837          if (!is_system_labeled()) {
 851  838                  if (ksi->ks_in_extv[SADB_EXT_SENSITIVITY] != NULL)
 852  839                          return (SADB_X_DIAGNOSTIC_BAD_LABEL);
 853  840  
 854  841                  if (ksi->ks_in_extv[SADB_X_EXT_OUTER_SENS] != NULL)
 855  842                          return (SADB_X_DIAGNOSTIC_BAD_LABEL);
 856  843          }
 857  844  
 858  845          return (0);
 859  846  }
 860  847  
 861  848  /*
 862  849   * Clone a security association for the purposes of inserting a single SA
 863  850   * into inbound and outbound tables respectively. This function should only
 864  851   * be called from sadb_common_add().
 865  852   */
 866  853  static ipsa_t *
 867  854  sadb_cloneassoc(ipsa_t *ipsa)
 868  855  {
 869  856          ipsa_t *newbie;
 870  857          boolean_t error = B_FALSE;
 871  858  
 872  859          ASSERT(MUTEX_NOT_HELD(&(ipsa->ipsa_lock)));
 873  860  
 874  861          newbie = kmem_alloc(sizeof (ipsa_t), KM_NOSLEEP);
 875  862          if (newbie == NULL)
 876  863                  return (NULL);
 877  864  
 878  865          /* Copy over what we can. */
 879  866          *newbie = *ipsa;
 880  867  
 881  868          /* bzero and initialize locks, in case *_init() allocates... */
 882  869          mutex_init(&newbie->ipsa_lock, NULL, MUTEX_DEFAULT, NULL);
 883  870  
 884  871          if (newbie->ipsa_tsl != NULL)
 885  872                  label_hold(newbie->ipsa_tsl);
 886  873  
 887  874          if (newbie->ipsa_otsl != NULL)
 888  875                  label_hold(newbie->ipsa_otsl);
 889  876  
 890  877          /*
 891  878           * While somewhat dain-bramaged, the most graceful way to
 892  879           * recover from errors is to keep plowing through the
 893  880           * allocations, and getting what I can.  It's easier to call
 894  881           * sadb_freeassoc() on the stillborn clone when all the
 895  882           * pointers aren't pointing to the parent's data.
 896  883           */
 897  884  
 898  885          if (ipsa->ipsa_authkey != NULL) {
 899  886                  newbie->ipsa_authkey = kmem_alloc(newbie->ipsa_authkeylen,
 900  887                      KM_NOSLEEP);
 901  888                  if (newbie->ipsa_authkey == NULL) {
 902  889                          error = B_TRUE;
 903  890                  } else {
 904  891                          bcopy(ipsa->ipsa_authkey, newbie->ipsa_authkey,
 905  892                              newbie->ipsa_authkeylen);
 906  893  
 907  894                          newbie->ipsa_kcfauthkey.ck_data =
 908  895                              newbie->ipsa_authkey;
 909  896                  }
 910  897  
 911  898                  if (newbie->ipsa_amech.cm_param != NULL) {
 912  899                          newbie->ipsa_amech.cm_param =
 913  900                              (char *)&newbie->ipsa_mac_len;
 914  901                  }
 915  902          }
 916  903  
 917  904          if (ipsa->ipsa_encrkey != NULL) {
 918  905                  newbie->ipsa_encrkey = kmem_alloc(newbie->ipsa_encrkeylen,
 919  906                      KM_NOSLEEP);
 920  907                  if (newbie->ipsa_encrkey == NULL) {
 921  908                          error = B_TRUE;
 922  909                  } else {
 923  910                          bcopy(ipsa->ipsa_encrkey, newbie->ipsa_encrkey,
 924  911                              newbie->ipsa_encrkeylen);
 925  912  
 926  913                          newbie->ipsa_kcfencrkey.ck_data =
 927  914                              newbie->ipsa_encrkey;
 928  915                  }
 929  916          }
 930  917  
 931  918          newbie->ipsa_authtmpl = NULL;
 932  919          newbie->ipsa_encrtmpl = NULL;
 933  920          newbie->ipsa_haspeer = B_TRUE;
 934  921  
 935  922          if (ipsa->ipsa_src_cid != NULL) {
 936  923                  newbie->ipsa_src_cid = ipsa->ipsa_src_cid;
 937  924                  IPSID_REFHOLD(ipsa->ipsa_src_cid);
 938  925          }
 939  926  
 940  927          if (ipsa->ipsa_dst_cid != NULL) {
 941  928                  newbie->ipsa_dst_cid = ipsa->ipsa_dst_cid;
 942  929                  IPSID_REFHOLD(ipsa->ipsa_dst_cid);
 943  930          }
 944  931  
 945  932          if (error) {
 946  933                  sadb_freeassoc(newbie);
 947  934                  return (NULL);
 948  935          }
 949  936  
 950  937          return (newbie);
 951  938  }
 952  939  
 953  940  /*
 954  941   * Initialize a SADB address extension at the address specified by addrext.
 955  942   * Return a pointer to the end of the new address extension.
 956  943   */
 957  944  static uint8_t *
 958  945  sadb_make_addr_ext(uint8_t *start, uint8_t *end, uint16_t exttype,
 959  946      sa_family_t af, uint32_t *addr, uint16_t port, uint8_t proto, int prefix)
 960  947  {
 961  948          struct sockaddr_in *sin;
 962  949          struct sockaddr_in6 *sin6;
 963  950          uint8_t *cur = start;
 964  951          int addrext_len;
 965  952          int sin_len;
 966  953          sadb_address_t *addrext = (sadb_address_t *)cur;
 967  954  
 968  955          if (cur == NULL)
 969  956                  return (NULL);
 970  957  
 971  958          cur += sizeof (*addrext);
 972  959          if (cur > end)
 973  960                  return (NULL);
 974  961  
 975  962          addrext->sadb_address_proto = proto;
 976  963          addrext->sadb_address_prefixlen = prefix;
 977  964          addrext->sadb_address_reserved = 0;
 978  965          addrext->sadb_address_exttype = exttype;
 979  966  
 980  967          switch (af) {
 981  968          case AF_INET:
 982  969                  sin = (struct sockaddr_in *)cur;
 983  970                  sin_len = sizeof (*sin);
 984  971                  cur += sin_len;
 985  972                  if (cur > end)
 986  973                          return (NULL);
 987  974  
 988  975                  sin->sin_family = af;
 989  976                  bzero(sin->sin_zero, sizeof (sin->sin_zero));
 990  977                  sin->sin_port = port;
 991  978                  IPSA_COPY_ADDR(&sin->sin_addr, addr, af);
 992  979                  break;
 993  980          case AF_INET6:
 994  981                  sin6 = (struct sockaddr_in6 *)cur;
 995  982                  sin_len = sizeof (*sin6);
 996  983                  cur += sin_len;
 997  984                  if (cur > end)
 998  985                          return (NULL);
 999  986  
1000  987                  bzero(sin6, sizeof (*sin6));
1001  988                  sin6->sin6_family = af;
1002  989                  sin6->sin6_port = port;
1003  990                  IPSA_COPY_ADDR(&sin6->sin6_addr, addr, af);
1004  991                  break;
1005  992          }
1006  993  
1007  994          addrext_len = roundup(cur - start, sizeof (uint64_t));
1008  995          addrext->sadb_address_len = SADB_8TO64(addrext_len);
1009  996  
1010  997          cur = start + addrext_len;
1011  998          if (cur > end)
1012  999                  cur = NULL;
1013 1000  
1014 1001          return (cur);
1015 1002  }
1016 1003  
1017 1004  /*
1018 1005   * Construct a key management cookie extension.
1019 1006   */
1020 1007  
1021 1008  static uint8_t *
1022 1009  sadb_make_kmc_ext(uint8_t *cur, uint8_t *end, uint32_t kmp, uint32_t kmc)
1023 1010  {
1024 1011          sadb_x_kmc_t *kmcext = (sadb_x_kmc_t *)cur;
1025 1012  
1026 1013          if (cur == NULL)
1027 1014                  return (NULL);
1028 1015  
1029 1016          cur += sizeof (*kmcext);
1030 1017  
1031 1018          if (cur > end)
1032 1019                  return (NULL);
1033 1020  
1034 1021          kmcext->sadb_x_kmc_len = SADB_8TO64(sizeof (*kmcext));
1035 1022          kmcext->sadb_x_kmc_exttype = SADB_X_EXT_KM_COOKIE;
1036 1023          kmcext->sadb_x_kmc_proto = kmp;
1037 1024          kmcext->sadb_x_kmc_cookie = kmc;
1038 1025          kmcext->sadb_x_kmc_reserved = 0;
1039 1026  
1040 1027          return (cur);
1041 1028  }
1042 1029  
1043 1030  /*
1044 1031   * Given an original message header with sufficient space following it, and an
1045 1032   * SA, construct a full PF_KEY message with all of the relevant extensions.
1046 1033   * This is mostly used for SADB_GET, and SADB_DUMP.
1047 1034   */
1048 1035  static mblk_t *
1049 1036  sadb_sa2msg(ipsa_t *ipsa, sadb_msg_t *samsg)
1050 1037  {
1051 1038          int alloclen, addrsize, paddrsize, authsize, encrsize;
1052 1039          int srcidsize, dstidsize, senslen, osenslen;
1053 1040          sa_family_t fam, pfam;  /* Address family for SADB_EXT_ADDRESS */
1054 1041                                  /* src/dst and proxy sockaddrs. */
1055 1042          /*
1056 1043           * The following are pointers into the PF_KEY message this PF_KEY
1057 1044           * message creates.
1058 1045           */
1059 1046          sadb_msg_t *newsamsg;
1060 1047          sadb_sa_t *assoc;
1061 1048          sadb_lifetime_t *lt;
1062 1049          sadb_key_t *key;
1063 1050          sadb_ident_t *ident;
1064 1051          sadb_sens_t *sens;
1065 1052          sadb_ext_t *walker;     /* For when we need a generic ext. pointer. */
1066 1053          sadb_x_replay_ctr_t *repl_ctr;
1067 1054          sadb_x_pair_t *pair_ext;
1068 1055  
1069 1056          mblk_t *mp;
1070 1057          uint8_t *cur, *end;
1071 1058          /* These indicate the presence of the above extension fields. */
1072 1059          boolean_t soft = B_FALSE, hard = B_FALSE;
1073 1060          boolean_t isrc = B_FALSE, idst = B_FALSE;
1074 1061          boolean_t auth = B_FALSE, encr = B_FALSE;
1075 1062          boolean_t sensinteg = B_FALSE, osensinteg = B_FALSE;
1076 1063          boolean_t srcid = B_FALSE, dstid = B_FALSE;
1077 1064          boolean_t idle;
1078 1065          boolean_t paired;
1079 1066          uint32_t otherspi;
1080 1067  
1081 1068          /* First off, figure out the allocation length for this message. */
1082 1069          /*
1083 1070           * Constant stuff.  This includes base, SA, address (src, dst),
1084 1071           * and lifetime (current).
1085 1072           */
1086 1073          alloclen = sizeof (sadb_msg_t) + sizeof (sadb_sa_t) +
1087 1074              sizeof (sadb_lifetime_t);
1088 1075  
1089 1076          fam = ipsa->ipsa_addrfam;
1090 1077          switch (fam) {
1091 1078          case AF_INET:
1092 1079                  addrsize = roundup(sizeof (struct sockaddr_in) +
1093 1080                      sizeof (sadb_address_t), sizeof (uint64_t));
1094 1081                  break;
1095 1082          case AF_INET6:
1096 1083                  addrsize = roundup(sizeof (struct sockaddr_in6) +
1097 1084                      sizeof (sadb_address_t), sizeof (uint64_t));
1098 1085                  break;
1099 1086          default:
1100 1087                  return (NULL);
1101 1088          }
1102 1089          /*
1103 1090           * Allocate TWO address extensions, for source and destination.
1104 1091           * (Thus, the * 2.)
1105 1092           */
1106 1093          alloclen += addrsize * 2;
1107 1094          if (ipsa->ipsa_flags & IPSA_F_NATT_REM)
1108 1095                  alloclen += addrsize;
1109 1096          if (ipsa->ipsa_flags & IPSA_F_NATT_LOC)
1110 1097                  alloclen += addrsize;
1111 1098  
1112 1099          if (ipsa->ipsa_flags & IPSA_F_PAIRED) {
1113 1100                  paired = B_TRUE;
1114 1101                  alloclen += sizeof (sadb_x_pair_t);
1115 1102                  otherspi = ipsa->ipsa_otherspi;
1116 1103          } else {
1117 1104                  paired = B_FALSE;
1118 1105          }
1119 1106  
1120 1107          /* How 'bout other lifetimes? */
1121 1108          if (ipsa->ipsa_softaddlt != 0 || ipsa->ipsa_softuselt != 0 ||
1122 1109              ipsa->ipsa_softbyteslt != 0 || ipsa->ipsa_softalloc != 0) {
1123 1110                  alloclen += sizeof (sadb_lifetime_t);
1124 1111                  soft = B_TRUE;
1125 1112          }
1126 1113  
1127 1114          if (ipsa->ipsa_hardaddlt != 0 || ipsa->ipsa_harduselt != 0 ||
1128 1115              ipsa->ipsa_hardbyteslt != 0 || ipsa->ipsa_hardalloc != 0) {
1129 1116                  alloclen += sizeof (sadb_lifetime_t);
1130 1117                  hard = B_TRUE;
1131 1118          }
1132 1119  
1133 1120          if (ipsa->ipsa_idleaddlt != 0 || ipsa->ipsa_idleuselt != 0) {
1134 1121                  alloclen += sizeof (sadb_lifetime_t);
1135 1122                  idle = B_TRUE;
1136 1123          } else {
1137 1124                  idle = B_FALSE;
1138 1125          }
1139 1126  
1140 1127          /* Inner addresses. */
1141 1128          if (ipsa->ipsa_innerfam != 0) {
1142 1129                  pfam = ipsa->ipsa_innerfam;
1143 1130                  switch (pfam) {
1144 1131                  case AF_INET6:
1145 1132                          paddrsize = roundup(sizeof (struct sockaddr_in6) +
1146 1133                              sizeof (sadb_address_t), sizeof (uint64_t));
1147 1134                          break;
1148 1135                  case AF_INET:
1149 1136                          paddrsize = roundup(sizeof (struct sockaddr_in) +
1150 1137                              sizeof (sadb_address_t), sizeof (uint64_t));
1151 1138                          break;
1152 1139                  default:
1153 1140                          cmn_err(CE_PANIC,
1154 1141                              "IPsec SADB: Proxy length failure.\n");
1155 1142                          break;
1156 1143                  }
1157 1144                  isrc = B_TRUE;
1158 1145                  idst = B_TRUE;
1159 1146                  alloclen += 2 * paddrsize;
1160 1147          }
1161 1148  
1162 1149          /* For the following fields, assume that length != 0 ==> stuff */
1163 1150          if (ipsa->ipsa_authkeylen != 0) {
1164 1151                  authsize = roundup(sizeof (sadb_key_t) + ipsa->ipsa_authkeylen,
1165 1152                      sizeof (uint64_t));
1166 1153                  alloclen += authsize;
1167 1154                  auth = B_TRUE;
1168 1155          }
1169 1156  
1170 1157          if (ipsa->ipsa_encrkeylen != 0) {
1171 1158                  encrsize = roundup(sizeof (sadb_key_t) + ipsa->ipsa_encrkeylen +
1172 1159                      ipsa->ipsa_nonce_len, sizeof (uint64_t));
1173 1160                  alloclen += encrsize;
1174 1161                  encr = B_TRUE;
1175 1162          } else {
1176 1163                  encr = B_FALSE;
1177 1164          }
1178 1165  
1179 1166          if (ipsa->ipsa_tsl != NULL) {
1180 1167                  senslen = sadb_sens_len_from_label(ipsa->ipsa_tsl);
1181 1168                  alloclen += senslen;
1182 1169                  sensinteg = B_TRUE;
1183 1170          }
1184 1171  
1185 1172          if (ipsa->ipsa_otsl != NULL) {
1186 1173                  osenslen = sadb_sens_len_from_label(ipsa->ipsa_otsl);
1187 1174                  alloclen += osenslen;
1188 1175                  osensinteg = B_TRUE;
1189 1176          }
1190 1177  
1191 1178          /*
1192 1179           * Must use strlen() here for lengths.  Identities use NULL
1193 1180           * pointers to indicate their nonexistence.
1194 1181           */
1195 1182          if (ipsa->ipsa_src_cid != NULL) {
1196 1183                  srcidsize = roundup(sizeof (sadb_ident_t) +
1197 1184                      strlen(ipsa->ipsa_src_cid->ipsid_cid) + 1,
1198 1185                      sizeof (uint64_t));
1199 1186                  alloclen += srcidsize;
1200 1187                  srcid = B_TRUE;
1201 1188          }
1202 1189  
1203 1190          if (ipsa->ipsa_dst_cid != NULL) {
1204 1191                  dstidsize = roundup(sizeof (sadb_ident_t) +
1205 1192                      strlen(ipsa->ipsa_dst_cid->ipsid_cid) + 1,
1206 1193                      sizeof (uint64_t));
1207 1194                  alloclen += dstidsize;
1208 1195                  dstid = B_TRUE;
1209 1196          }
1210 1197  
1211 1198          if ((ipsa->ipsa_kmp != 0) || (ipsa->ipsa_kmc != 0))
1212 1199                  alloclen += sizeof (sadb_x_kmc_t);
1213 1200  
1214 1201          if (ipsa->ipsa_replay != 0) {
1215 1202                  alloclen += sizeof (sadb_x_replay_ctr_t);
1216 1203          }
1217 1204  
1218 1205          /* Make sure the allocation length is a multiple of 8 bytes. */
1219 1206          ASSERT((alloclen & 0x7) == 0);
1220 1207  
1221 1208          /* XXX Possibly make it esballoc, with a bzero-ing free_ftn. */
1222 1209          mp = allocb(alloclen, BPRI_HI);
1223 1210          if (mp == NULL)
1224 1211                  return (NULL);
1225 1212          bzero(mp->b_rptr, alloclen);
1226 1213  
1227 1214          mp->b_wptr += alloclen;
1228 1215          end = mp->b_wptr;
1229 1216          newsamsg = (sadb_msg_t *)mp->b_rptr;
1230 1217          *newsamsg = *samsg;
1231 1218          newsamsg->sadb_msg_len = (uint16_t)SADB_8TO64(alloclen);
1232 1219  
1233 1220          mutex_enter(&ipsa->ipsa_lock);  /* Since I'm grabbing SA fields... */
1234 1221  
1235 1222          newsamsg->sadb_msg_satype = ipsa->ipsa_type;
1236 1223  
1237 1224          assoc = (sadb_sa_t *)(newsamsg + 1);
1238 1225          assoc->sadb_sa_len = SADB_8TO64(sizeof (*assoc));
1239 1226          assoc->sadb_sa_exttype = SADB_EXT_SA;
1240 1227          assoc->sadb_sa_spi = ipsa->ipsa_spi;
1241 1228          assoc->sadb_sa_replay = ipsa->ipsa_replay_wsize;
1242 1229          assoc->sadb_sa_state = ipsa->ipsa_state;
1243 1230          assoc->sadb_sa_auth = ipsa->ipsa_auth_alg;
1244 1231          assoc->sadb_sa_encrypt = ipsa->ipsa_encr_alg;
1245 1232          assoc->sadb_sa_flags = ipsa->ipsa_flags;
1246 1233  
1247 1234          lt = (sadb_lifetime_t *)(assoc + 1);
1248 1235          lt->sadb_lifetime_len = SADB_8TO64(sizeof (*lt));
1249 1236          lt->sadb_lifetime_exttype = SADB_EXT_LIFETIME_CURRENT;
1250 1237          /* We do not support the concept. */
1251 1238          lt->sadb_lifetime_allocations = 0;
1252 1239          lt->sadb_lifetime_bytes = ipsa->ipsa_bytes;
1253 1240          lt->sadb_lifetime_addtime = ipsa->ipsa_addtime;
1254 1241          lt->sadb_lifetime_usetime = ipsa->ipsa_usetime;
1255 1242  
1256 1243          if (hard) {
1257 1244                  lt++;
1258 1245                  lt->sadb_lifetime_len = SADB_8TO64(sizeof (*lt));
1259 1246                  lt->sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
1260 1247                  lt->sadb_lifetime_allocations = ipsa->ipsa_hardalloc;
1261 1248                  lt->sadb_lifetime_bytes = ipsa->ipsa_hardbyteslt;
1262 1249                  lt->sadb_lifetime_addtime = ipsa->ipsa_hardaddlt;
1263 1250                  lt->sadb_lifetime_usetime = ipsa->ipsa_harduselt;
1264 1251          }
1265 1252  
1266 1253          if (soft) {
1267 1254                  lt++;
1268 1255                  lt->sadb_lifetime_len = SADB_8TO64(sizeof (*lt));
1269 1256                  lt->sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;
1270 1257                  lt->sadb_lifetime_allocations = ipsa->ipsa_softalloc;
1271 1258                  lt->sadb_lifetime_bytes = ipsa->ipsa_softbyteslt;
1272 1259                  lt->sadb_lifetime_addtime = ipsa->ipsa_softaddlt;
1273 1260                  lt->sadb_lifetime_usetime = ipsa->ipsa_softuselt;
1274 1261          }
1275 1262  
1276 1263          if (idle) {
1277 1264                  lt++;
1278 1265                  lt->sadb_lifetime_len = SADB_8TO64(sizeof (*lt));
1279 1266                  lt->sadb_lifetime_exttype = SADB_X_EXT_LIFETIME_IDLE;
1280 1267                  lt->sadb_lifetime_addtime = ipsa->ipsa_idleaddlt;
1281 1268                  lt->sadb_lifetime_usetime = ipsa->ipsa_idleuselt;
1282 1269          }
1283 1270  
1284 1271          cur = (uint8_t *)(lt + 1);
1285 1272  
1286 1273          /* NOTE:  Don't fill in ports here if we are a tunnel-mode SA. */
1287 1274          cur = sadb_make_addr_ext(cur, end, SADB_EXT_ADDRESS_SRC, fam,
1288 1275              ipsa->ipsa_srcaddr, (!isrc && !idst) ? SA_SRCPORT(ipsa) : 0,
1289 1276              SA_PROTO(ipsa), 0);
1290 1277          if (cur == NULL) {
1291 1278                  freemsg(mp);
1292 1279                  mp = NULL;
1293 1280                  goto bail;
1294 1281          }
1295 1282  
1296 1283          cur = sadb_make_addr_ext(cur, end, SADB_EXT_ADDRESS_DST, fam,
1297 1284              ipsa->ipsa_dstaddr, (!isrc && !idst) ? SA_DSTPORT(ipsa) : 0,
1298 1285              SA_PROTO(ipsa), 0);
1299 1286          if (cur == NULL) {
1300 1287                  freemsg(mp);
1301 1288                  mp = NULL;
1302 1289                  goto bail;
1303 1290          }
1304 1291  
1305 1292          if (ipsa->ipsa_flags & IPSA_F_NATT_LOC) {
1306 1293                  cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_NATT_LOC,
1307 1294                      fam, &ipsa->ipsa_natt_addr_loc, ipsa->ipsa_local_nat_port,
1308 1295                      IPPROTO_UDP, 0);
1309 1296                  if (cur == NULL) {
1310 1297                          freemsg(mp);
1311 1298                          mp = NULL;
1312 1299                          goto bail;
1313 1300                  }
1314 1301          }
1315 1302  
1316 1303          if (ipsa->ipsa_flags & IPSA_F_NATT_REM) {
1317 1304                  cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_NATT_REM,
1318 1305                      fam, &ipsa->ipsa_natt_addr_rem, ipsa->ipsa_remote_nat_port,
1319 1306                      IPPROTO_UDP, 0);
1320 1307                  if (cur == NULL) {
1321 1308                          freemsg(mp);
1322 1309                          mp = NULL;
1323 1310                          goto bail;
1324 1311                  }
1325 1312          }
1326 1313  
1327 1314          /* If we are a tunnel-mode SA, fill in the inner-selectors. */
1328 1315          if (isrc) {
1329 1316                  cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_INNER_SRC,
1330 1317                      pfam, ipsa->ipsa_innersrc, SA_SRCPORT(ipsa),
1331 1318                      SA_IPROTO(ipsa), ipsa->ipsa_innersrcpfx);
1332 1319                  if (cur == NULL) {
1333 1320                          freemsg(mp);
1334 1321                          mp = NULL;
1335 1322                          goto bail;
1336 1323                  }
1337 1324          }
1338 1325  
1339 1326          if (idst) {
1340 1327                  cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_INNER_DST,
1341 1328                      pfam, ipsa->ipsa_innerdst, SA_DSTPORT(ipsa),
1342 1329                      SA_IPROTO(ipsa), ipsa->ipsa_innerdstpfx);
1343 1330                  if (cur == NULL) {
1344 1331                          freemsg(mp);
1345 1332                          mp = NULL;
1346 1333                          goto bail;
1347 1334                  }
1348 1335          }
1349 1336  
1350 1337          if ((ipsa->ipsa_kmp != 0) || (ipsa->ipsa_kmc != 0)) {
1351 1338                  cur = sadb_make_kmc_ext(cur, end,
1352 1339                      ipsa->ipsa_kmp, ipsa->ipsa_kmc);
1353 1340                  if (cur == NULL) {
1354 1341                          freemsg(mp);
1355 1342                          mp = NULL;
1356 1343                          goto bail;
1357 1344                  }
1358 1345          }
1359 1346  
1360 1347          walker = (sadb_ext_t *)cur;
1361 1348          if (auth) {
1362 1349                  key = (sadb_key_t *)walker;
1363 1350                  key->sadb_key_len = SADB_8TO64(authsize);
1364 1351                  key->sadb_key_exttype = SADB_EXT_KEY_AUTH;
1365 1352                  key->sadb_key_bits = ipsa->ipsa_authkeybits;
1366 1353                  key->sadb_key_reserved = 0;
1367 1354                  bcopy(ipsa->ipsa_authkey, key + 1, ipsa->ipsa_authkeylen);
1368 1355                  walker = (sadb_ext_t *)((uint64_t *)walker +
1369 1356                      walker->sadb_ext_len);
1370 1357          }
1371 1358  
1372 1359          if (encr) {
1373 1360                  uint8_t *buf_ptr;
1374 1361                  key = (sadb_key_t *)walker;
1375 1362                  key->sadb_key_len = SADB_8TO64(encrsize);
1376 1363                  key->sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
1377 1364                  key->sadb_key_bits = ipsa->ipsa_encrkeybits;
1378 1365                  key->sadb_key_reserved = ipsa->ipsa_saltbits;
1379 1366                  buf_ptr = (uint8_t *)(key + 1);
1380 1367                  bcopy(ipsa->ipsa_encrkey, buf_ptr, ipsa->ipsa_encrkeylen);
1381 1368                  if (ipsa->ipsa_salt != NULL) {
1382 1369                          buf_ptr += ipsa->ipsa_encrkeylen;
1383 1370                          bcopy(ipsa->ipsa_salt, buf_ptr, ipsa->ipsa_saltlen);
1384 1371                  }
1385 1372                  walker = (sadb_ext_t *)((uint64_t *)walker +
1386 1373                      walker->sadb_ext_len);
1387 1374          }
1388 1375  
1389 1376          if (srcid) {
1390 1377                  ident = (sadb_ident_t *)walker;
1391 1378                  ident->sadb_ident_len = SADB_8TO64(srcidsize);
1392 1379                  ident->sadb_ident_exttype = SADB_EXT_IDENTITY_SRC;
1393 1380                  ident->sadb_ident_type = ipsa->ipsa_src_cid->ipsid_type;
1394 1381                  ident->sadb_ident_id = 0;
1395 1382                  ident->sadb_ident_reserved = 0;
1396 1383                  (void) strcpy((char *)(ident + 1),
1397 1384                      ipsa->ipsa_src_cid->ipsid_cid);
1398 1385                  walker = (sadb_ext_t *)((uint64_t *)walker +
1399 1386                      walker->sadb_ext_len);
1400 1387          }
1401 1388  
1402 1389          if (dstid) {
1403 1390                  ident = (sadb_ident_t *)walker;
1404 1391                  ident->sadb_ident_len = SADB_8TO64(dstidsize);
1405 1392                  ident->sadb_ident_exttype = SADB_EXT_IDENTITY_DST;
1406 1393                  ident->sadb_ident_type = ipsa->ipsa_dst_cid->ipsid_type;
1407 1394                  ident->sadb_ident_id = 0;
1408 1395                  ident->sadb_ident_reserved = 0;
1409 1396                  (void) strcpy((char *)(ident + 1),
1410 1397                      ipsa->ipsa_dst_cid->ipsid_cid);
1411 1398                  walker = (sadb_ext_t *)((uint64_t *)walker +
1412 1399                      walker->sadb_ext_len);
1413 1400          }
1414 1401  
1415 1402          if (sensinteg) {
1416 1403                  sens = (sadb_sens_t *)walker;
1417 1404                  sadb_sens_from_label(sens, SADB_EXT_SENSITIVITY,
1418 1405                      ipsa->ipsa_tsl, senslen);
1419 1406  
1420 1407                  walker = (sadb_ext_t *)((uint64_t *)walker +
1421 1408                      walker->sadb_ext_len);
1422 1409          }
1423 1410  
1424 1411          if (osensinteg) {
1425 1412                  sens = (sadb_sens_t *)walker;
1426 1413  
1427 1414                  sadb_sens_from_label(sens, SADB_X_EXT_OUTER_SENS,
1428 1415                      ipsa->ipsa_otsl, osenslen);
1429 1416                  if (ipsa->ipsa_mac_exempt)
1430 1417                          sens->sadb_x_sens_flags = SADB_X_SENS_IMPLICIT;
1431 1418  
1432 1419                  walker = (sadb_ext_t *)((uint64_t *)walker +
1433 1420                      walker->sadb_ext_len);
1434 1421          }
1435 1422  
1436 1423          if (paired) {
1437 1424                  pair_ext = (sadb_x_pair_t *)walker;
1438 1425  
1439 1426                  pair_ext->sadb_x_pair_len = SADB_8TO64(sizeof (sadb_x_pair_t));
1440 1427                  pair_ext->sadb_x_pair_exttype = SADB_X_EXT_PAIR;
1441 1428                  pair_ext->sadb_x_pair_spi = otherspi;
1442 1429  
1443 1430                  walker = (sadb_ext_t *)((uint64_t *)walker +
1444 1431                      walker->sadb_ext_len);
1445 1432          }
1446 1433  
1447 1434          if (ipsa->ipsa_replay != 0) {
1448 1435                  repl_ctr = (sadb_x_replay_ctr_t *)walker;
1449 1436                  repl_ctr->sadb_x_rc_len = SADB_8TO64(sizeof (*repl_ctr));
1450 1437                  repl_ctr->sadb_x_rc_exttype = SADB_X_EXT_REPLAY_VALUE;
1451 1438                  repl_ctr->sadb_x_rc_replay32 = ipsa->ipsa_replay;
1452 1439                  repl_ctr->sadb_x_rc_replay64 = 0;
1453 1440                  walker = (sadb_ext_t *)(repl_ctr + 1);
1454 1441          }
1455 1442  
1456 1443  bail:
1457 1444          /* Pardon any delays... */
1458 1445          mutex_exit(&ipsa->ipsa_lock);
1459 1446  
1460 1447          return (mp);
1461 1448  }
1462 1449  
1463 1450  /*
1464 1451   * Strip out key headers or unmarked headers (SADB_EXT_KEY_*, SADB_EXT_UNKNOWN)
1465 1452   * and adjust base message accordingly.
1466 1453   *
1467 1454   * Assume message is pulled up in one piece of contiguous memory.
1468 1455   *
1469 1456   * Say if we start off with:
1470 1457   *
1471 1458   * +------+----+-------------+-----------+---------------+---------------+
1472 1459   * | base | SA | source addr | dest addr | rsrvd. or key | soft lifetime |
1473 1460   * +------+----+-------------+-----------+---------------+---------------+
1474 1461   *
1475 1462   * we will end up with
1476 1463   *
1477 1464   * +------+----+-------------+-----------+---------------+
1478 1465   * | base | SA | source addr | dest addr | soft lifetime |
1479 1466   * +------+----+-------------+-----------+---------------+
1480 1467   */
1481 1468  static void
1482 1469  sadb_strip(sadb_msg_t *samsg)
1483 1470  {
1484 1471          sadb_ext_t *ext;
1485 1472          uint8_t *target = NULL;
  
    | 
      ↓ open down ↓ | 
    721 lines elided | 
    
      ↑ open up ↑ | 
  
1486 1473          uint8_t *msgend;
1487 1474          int sofar = SADB_8TO64(sizeof (*samsg));
1488 1475          int copylen;
1489 1476  
1490 1477          ext = (sadb_ext_t *)(samsg + 1);
1491 1478          msgend = (uint8_t *)samsg;
1492 1479          msgend += SADB_64TO8(samsg->sadb_msg_len);
1493 1480          while ((uint8_t *)ext < msgend) {
1494 1481                  if (ext->sadb_ext_type == SADB_EXT_RESERVED ||
1495 1482                      ext->sadb_ext_type == SADB_EXT_KEY_AUTH ||
1496      -                    ext->sadb_ext_type == SADB_X_EXT_EDUMP ||
1497 1483                      ext->sadb_ext_type == SADB_EXT_KEY_ENCRYPT) {
1498 1484                          /*
1499 1485                           * Aha!  I found a header to be erased.
1500 1486                           */
1501 1487  
1502 1488                          if (target != NULL) {
1503 1489                                  /*
1504 1490                                   * If I had a previous header to be erased,
1505 1491                                   * copy over it.  I can get away with just
1506 1492                                   * copying backwards because the target will
1507 1493                                   * always be 8 bytes behind the source.
1508 1494                                   */
1509 1495                                  copylen = ((uint8_t *)ext) - (target +
1510 1496                                      SADB_64TO8(
1511 1497                                      ((sadb_ext_t *)target)->sadb_ext_len));
1512 1498                                  ovbcopy(((uint8_t *)ext - copylen), target,
1513 1499                                      copylen);
1514 1500                                  target += copylen;
1515 1501                                  ((sadb_ext_t *)target)->sadb_ext_len =
1516 1502                                      SADB_8TO64(((uint8_t *)ext) - target +
1517 1503                                      SADB_64TO8(ext->sadb_ext_len));
1518 1504                          } else {
1519 1505                                  target = (uint8_t *)ext;
1520 1506                          }
1521 1507                  } else {
1522 1508                          sofar += ext->sadb_ext_len;
1523 1509                  }
1524 1510  
1525 1511                  ext = (sadb_ext_t *)(((uint64_t *)ext) + ext->sadb_ext_len);
1526 1512          }
1527 1513  
1528 1514          ASSERT((uint8_t *)ext == msgend);
1529 1515  
1530 1516          if (target != NULL) {
1531 1517                  copylen = ((uint8_t *)ext) - (target +
1532 1518                      SADB_64TO8(((sadb_ext_t *)target)->sadb_ext_len));
1533 1519                  if (copylen != 0)
1534 1520                          ovbcopy(((uint8_t *)ext - copylen), target, copylen);
1535 1521          }
1536 1522  
1537 1523          /* Adjust samsg. */
1538 1524          samsg->sadb_msg_len = (uint16_t)sofar;
1539 1525  
1540 1526          /* Assume all of the rest is cleared by caller in sadb_pfkey_echo(). */
1541 1527  }
1542 1528  
1543 1529  /*
1544 1530   * AH needs to send an error to PF_KEY.  Assume mp points to an M_CTL
1545 1531   * followed by an M_DATA with a PF_KEY message in it.  The serial of
1546 1532   * the sending keysock instance is included.
1547 1533   */
1548 1534  void
1549 1535  sadb_pfkey_error(queue_t *pfkey_q, mblk_t *mp, int error, int diagnostic,
1550 1536      uint_t serial)
1551 1537  {
1552 1538          mblk_t *msg = mp->b_cont;
1553 1539          sadb_msg_t *samsg;
1554 1540          keysock_out_t *kso;
1555 1541  
1556 1542          /*
1557 1543           * Enough functions call this to merit a NULL queue check.
1558 1544           */
1559 1545          if (pfkey_q == NULL) {
1560 1546                  freemsg(mp);
1561 1547                  return;
1562 1548          }
1563 1549  
1564 1550          ASSERT(msg != NULL);
1565 1551          ASSERT((mp->b_wptr - mp->b_rptr) == sizeof (ipsec_info_t));
1566 1552          ASSERT((msg->b_wptr - msg->b_rptr) >= sizeof (sadb_msg_t));
1567 1553          samsg = (sadb_msg_t *)msg->b_rptr;
1568 1554          kso = (keysock_out_t *)mp->b_rptr;
1569 1555  
1570 1556          kso->ks_out_type = KEYSOCK_OUT;
1571 1557          kso->ks_out_len = sizeof (*kso);
1572 1558          kso->ks_out_serial = serial;
1573 1559  
1574 1560          /*
1575 1561           * Only send the base message up in the event of an error.
1576 1562           * Don't worry about bzero()-ing, because it was probably bogus
1577 1563           * anyway.
1578 1564           */
1579 1565          msg->b_wptr = msg->b_rptr + sizeof (*samsg);
1580 1566          samsg = (sadb_msg_t *)msg->b_rptr;
1581 1567          samsg->sadb_msg_len = SADB_8TO64(sizeof (*samsg));
1582 1568          samsg->sadb_msg_errno = (uint8_t)error;
1583 1569          if (diagnostic != SADB_X_DIAGNOSTIC_PRESET)
1584 1570                  samsg->sadb_x_msg_diagnostic = (uint16_t)diagnostic;
1585 1571  
1586 1572          putnext(pfkey_q, mp);
1587 1573  }
1588 1574  
1589 1575  /*
1590 1576   * Send a successful return packet back to keysock via the queue in pfkey_q.
1591 1577   *
1592 1578   * Often, an SA is associated with the reply message, it's passed in if needed,
1593 1579   * and NULL if not.  BTW, that ipsa will have its refcnt appropriately held,
1594 1580   * and the caller will release said refcnt.
1595 1581   */
1596 1582  void
1597 1583  sadb_pfkey_echo(queue_t *pfkey_q, mblk_t *mp, sadb_msg_t *samsg,
1598 1584      keysock_in_t *ksi, ipsa_t *ipsa)
1599 1585  {
1600 1586          keysock_out_t *kso;
1601 1587          mblk_t *mp1;
1602 1588          sadb_msg_t *newsamsg;
  
    | 
      ↓ open down ↓ | 
    96 lines elided | 
    
      ↑ open up ↑ | 
  
1603 1589          uint8_t *oldend;
1604 1590  
1605 1591          ASSERT((mp->b_cont != NULL) &&
1606 1592              ((void *)samsg == (void *)mp->b_cont->b_rptr) &&
1607 1593              ((void *)mp->b_rptr == (void *)ksi));
1608 1594  
1609 1595          switch (samsg->sadb_msg_type) {
1610 1596          case SADB_ADD:
1611 1597          case SADB_UPDATE:
1612 1598          case SADB_X_UPDATEPAIR:
1613      -        case SADB_X_DELPAIR_STATE:
1614 1599          case SADB_FLUSH:
1615 1600          case SADB_DUMP:
1616 1601                  /*
1617 1602                   * I have all of the message already.  I just need to strip
1618 1603                   * out the keying material and echo the message back.
1619 1604                   *
1620 1605                   * NOTE: for SADB_DUMP, the function sadb_dump() did the
1621 1606                   * work.  When DUMP reaches here, it should only be a base
1622 1607                   * message.
1623 1608                   */
1624 1609          justecho:
     1610 +                ASSERT(samsg->sadb_msg_type != SADB_DUMP ||
     1611 +                    samsg->sadb_msg_len == SADB_8TO64(sizeof (sadb_msg_t)));
1625 1612                  if (ksi->ks_in_extv[SADB_EXT_KEY_AUTH] != NULL ||
1626      -                    ksi->ks_in_extv[SADB_EXT_KEY_ENCRYPT] != NULL ||
1627      -                    ksi->ks_in_extv[SADB_X_EXT_EDUMP] != NULL) {
     1613 +                    ksi->ks_in_extv[SADB_EXT_KEY_ENCRYPT] != NULL) {
1628 1614                          sadb_strip(samsg);
1629 1615                          /* Assume PF_KEY message is contiguous. */
1630 1616                          ASSERT(mp->b_cont->b_cont == NULL);
1631 1617                          oldend = mp->b_cont->b_wptr;
1632 1618                          mp->b_cont->b_wptr = mp->b_cont->b_rptr +
1633 1619                              SADB_64TO8(samsg->sadb_msg_len);
1634 1620                          bzero(mp->b_cont->b_wptr, oldend - mp->b_cont->b_wptr);
1635 1621                  }
1636 1622                  break;
1637 1623          case SADB_GET:
1638 1624                  /*
1639 1625                   * Do a lot of work here, because of the ipsa I just found.
1640 1626                   * First construct the new PF_KEY message, then abandon
1641 1627                   * the old one.
1642 1628                   */
1643 1629                  mp1 = sadb_sa2msg(ipsa, samsg);
1644 1630                  if (mp1 == NULL) {
1645 1631                          sadb_pfkey_error(pfkey_q, mp, ENOMEM,
1646 1632                              SADB_X_DIAGNOSTIC_NONE, ksi->ks_in_serial);
1647 1633                          return;
1648 1634                  }
1649 1635                  freemsg(mp->b_cont);
1650 1636                  mp->b_cont = mp1;
1651 1637                  break;
1652 1638          case SADB_DELETE:
1653 1639          case SADB_X_DELPAIR:
1654 1640                  if (ipsa == NULL)
1655 1641                          goto justecho;
1656 1642                  /*
1657 1643                   * Because listening KMds may require more info, treat
1658 1644                   * DELETE like a special case of GET.
1659 1645                   */
1660 1646                  mp1 = sadb_sa2msg(ipsa, samsg);
1661 1647                  if (mp1 == NULL) {
1662 1648                          sadb_pfkey_error(pfkey_q, mp, ENOMEM,
1663 1649                              SADB_X_DIAGNOSTIC_NONE, ksi->ks_in_serial);
1664 1650                          return;
1665 1651                  }
1666 1652                  newsamsg = (sadb_msg_t *)mp1->b_rptr;
1667 1653                  sadb_strip(newsamsg);
1668 1654                  oldend = mp1->b_wptr;
1669 1655                  mp1->b_wptr = mp1->b_rptr + SADB_64TO8(newsamsg->sadb_msg_len);
1670 1656                  bzero(mp1->b_wptr, oldend - mp1->b_wptr);
1671 1657                  freemsg(mp->b_cont);
1672 1658                  mp->b_cont = mp1;
1673 1659                  break;
1674 1660          default:
1675 1661                  if (mp != NULL)
1676 1662                          freemsg(mp);
1677 1663                  return;
1678 1664          }
1679 1665  
1680 1666          /* ksi is now null and void. */
1681 1667          kso = (keysock_out_t *)ksi;
1682 1668          kso->ks_out_type = KEYSOCK_OUT;
1683 1669          kso->ks_out_len = sizeof (*kso);
1684 1670          kso->ks_out_serial = ksi->ks_in_serial;
1685 1671          /* We're ready to send... */
1686 1672          putnext(pfkey_q, mp);
1687 1673  }
1688 1674  
1689 1675  /*
1690 1676   * Set up a global pfkey_q instance for AH, ESP, or some other consumer.
1691 1677   */
1692 1678  void
1693 1679  sadb_keysock_hello(queue_t **pfkey_qp, queue_t *q, mblk_t *mp,
1694 1680      void (*ager)(void *), void *agerarg, timeout_id_t *top, int satype)
1695 1681  {
1696 1682          keysock_hello_ack_t *kha;
1697 1683          queue_t *oldq;
1698 1684  
1699 1685          ASSERT(OTHERQ(q) != NULL);
1700 1686  
1701 1687          /*
1702 1688           * First, check atomically that I'm the first and only keysock
1703 1689           * instance.
1704 1690           *
1705 1691           * Use OTHERQ(q), because qreply(q, mp) == putnext(OTHERQ(q), mp),
1706 1692           * and I want this module to say putnext(*_pfkey_q, mp) for PF_KEY
1707 1693           * messages.
1708 1694           */
1709 1695  
1710 1696          oldq = atomic_cas_ptr((void **)pfkey_qp, NULL, OTHERQ(q));
1711 1697          if (oldq != NULL) {
1712 1698                  ASSERT(oldq != q);
1713 1699                  cmn_err(CE_WARN, "Danger!  Multiple keysocks on top of %s.\n",
1714 1700                      (satype == SADB_SATYPE_ESP)? "ESP" : "AH or other");
1715 1701                  freemsg(mp);
1716 1702                  return;
1717 1703          }
1718 1704  
1719 1705          kha = (keysock_hello_ack_t *)mp->b_rptr;
1720 1706          kha->ks_hello_len = sizeof (keysock_hello_ack_t);
1721 1707          kha->ks_hello_type = KEYSOCK_HELLO_ACK;
1722 1708          kha->ks_hello_satype = (uint8_t)satype;
1723 1709  
1724 1710          /*
1725 1711           * If we made it past the atomic_cas_ptr, then we have "exclusive"
1726 1712           * access to the timeout handle.  Fire it off after the default ager
1727 1713           * interval.
1728 1714           */
1729 1715          *top = qtimeout(*pfkey_qp, ager, agerarg,
1730 1716              drv_usectohz(SADB_AGE_INTERVAL_DEFAULT * 1000));
1731 1717  
1732 1718          putnext(*pfkey_qp, mp);
1733 1719  }
1734 1720  
1735 1721  /*
1736 1722   * Normalize IPv4-mapped IPv6 addresses (and prefixes) as appropriate.
1737 1723   *
1738 1724   * Check addresses themselves for wildcard or multicast.
1739 1725   * Check ire table for local/non-local/broadcast.
1740 1726   */
1741 1727  int
1742 1728  sadb_addrcheck(queue_t *pfkey_q, mblk_t *mp, sadb_ext_t *ext, uint_t serial,
1743 1729      netstack_t *ns)
1744 1730  {
1745 1731          sadb_address_t *addr = (sadb_address_t *)ext;
1746 1732          struct sockaddr_in *sin;
1747 1733          struct sockaddr_in6 *sin6;
1748 1734          int diagnostic, type;
1749 1735          boolean_t normalized = B_FALSE;
1750 1736  
1751 1737          ASSERT(ext != NULL);
1752 1738          ASSERT((ext->sadb_ext_type == SADB_EXT_ADDRESS_SRC) ||
1753 1739              (ext->sadb_ext_type == SADB_EXT_ADDRESS_DST) ||
1754 1740              (ext->sadb_ext_type == SADB_X_EXT_ADDRESS_INNER_SRC) ||
1755 1741              (ext->sadb_ext_type == SADB_X_EXT_ADDRESS_INNER_DST) ||
1756 1742              (ext->sadb_ext_type == SADB_X_EXT_ADDRESS_NATT_LOC) ||
1757 1743              (ext->sadb_ext_type == SADB_X_EXT_ADDRESS_NATT_REM));
1758 1744  
1759 1745          /* Assign both sockaddrs, the compiler will do the right thing. */
1760 1746          sin = (struct sockaddr_in *)(addr + 1);
1761 1747          sin6 = (struct sockaddr_in6 *)(addr + 1);
1762 1748  
1763 1749          if (sin6->sin6_family == AF_INET6) {
1764 1750                  if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
1765 1751                          /*
1766 1752                           * Convert to an AF_INET sockaddr.  This means the
1767 1753                           * return messages will have the extra space, but have
1768 1754                           * AF_INET sockaddrs instead of AF_INET6.
1769 1755                           *
1770 1756                           * Yes, RFC 2367 isn't clear on what to do here w.r.t.
1771 1757                           * mapped addresses, but since AF_INET6 ::ffff:<v4> is
1772 1758                           * equal to AF_INET <v4>, it shouldnt be a huge
1773 1759                           * problem.
1774 1760                           */
1775 1761                          sin->sin_family = AF_INET;
1776 1762                          IN6_V4MAPPED_TO_INADDR(&sin6->sin6_addr,
1777 1763                              &sin->sin_addr);
1778 1764                          bzero(&sin->sin_zero, sizeof (sin->sin_zero));
1779 1765                          normalized = B_TRUE;
1780 1766                  }
1781 1767          } else if (sin->sin_family != AF_INET) {
1782 1768                  switch (ext->sadb_ext_type) {
1783 1769                  case SADB_EXT_ADDRESS_SRC:
1784 1770                          diagnostic = SADB_X_DIAGNOSTIC_BAD_SRC_AF;
1785 1771                          break;
1786 1772                  case SADB_EXT_ADDRESS_DST:
1787 1773                          diagnostic = SADB_X_DIAGNOSTIC_BAD_DST_AF;
1788 1774                          break;
1789 1775                  case SADB_X_EXT_ADDRESS_INNER_SRC:
1790 1776                          diagnostic = SADB_X_DIAGNOSTIC_BAD_PROXY_AF;
1791 1777                          break;
1792 1778                  case SADB_X_EXT_ADDRESS_INNER_DST:
1793 1779                          diagnostic = SADB_X_DIAGNOSTIC_BAD_INNER_DST_AF;
1794 1780                          break;
1795 1781                  case SADB_X_EXT_ADDRESS_NATT_LOC:
1796 1782                          diagnostic = SADB_X_DIAGNOSTIC_BAD_NATT_LOC_AF;
1797 1783                          break;
1798 1784                  case SADB_X_EXT_ADDRESS_NATT_REM:
1799 1785                          diagnostic = SADB_X_DIAGNOSTIC_BAD_NATT_REM_AF;
1800 1786                          break;
1801 1787                          /* There is no default, see above ASSERT. */
1802 1788                  }
1803 1789  bail:
1804 1790                  if (pfkey_q != NULL) {
1805 1791                          sadb_pfkey_error(pfkey_q, mp, EINVAL, diagnostic,
1806 1792                              serial);
1807 1793                  } else {
1808 1794                          /*
1809 1795                           * Scribble in sadb_msg that we got passed in.
1810 1796                           * Overload "mp" to be an sadb_msg pointer.
1811 1797                           */
1812 1798                          sadb_msg_t *samsg = (sadb_msg_t *)mp;
1813 1799  
1814 1800                          samsg->sadb_msg_errno = EINVAL;
1815 1801                          samsg->sadb_x_msg_diagnostic = diagnostic;
1816 1802                  }
1817 1803                  return (KS_IN_ADDR_UNKNOWN);
1818 1804          }
1819 1805  
1820 1806          if (ext->sadb_ext_type == SADB_X_EXT_ADDRESS_INNER_SRC ||
1821 1807              ext->sadb_ext_type == SADB_X_EXT_ADDRESS_INNER_DST) {
1822 1808                  /*
1823 1809                   * We need only check for prefix issues.
1824 1810                   */
1825 1811  
1826 1812                  /* Set diagnostic now, in case we need it later. */
1827 1813                  diagnostic =
1828 1814                      (ext->sadb_ext_type == SADB_X_EXT_ADDRESS_INNER_SRC) ?
1829 1815                      SADB_X_DIAGNOSTIC_PREFIX_INNER_SRC :
1830 1816                      SADB_X_DIAGNOSTIC_PREFIX_INNER_DST;
1831 1817  
1832 1818                  if (normalized)
1833 1819                          addr->sadb_address_prefixlen -= 96;
1834 1820  
1835 1821                  /*
1836 1822                   * Verify and mask out inner-addresses based on prefix length.
1837 1823                   */
1838 1824                  if (sin->sin_family == AF_INET) {
1839 1825                          if (addr->sadb_address_prefixlen > 32)
1840 1826                                  goto bail;
1841 1827                          sin->sin_addr.s_addr &=
1842 1828                              ip_plen_to_mask(addr->sadb_address_prefixlen);
1843 1829                  } else {
1844 1830                          in6_addr_t mask;
1845 1831  
1846 1832                          ASSERT(sin->sin_family == AF_INET6);
1847 1833                          /*
1848 1834                           * ip_plen_to_mask_v6() returns NULL if the value in
1849 1835                           * question is out of range.
1850 1836                           */
1851 1837                          if (ip_plen_to_mask_v6(addr->sadb_address_prefixlen,
1852 1838                              &mask) == NULL)
1853 1839                                  goto bail;
1854 1840                          sin6->sin6_addr.s6_addr32[0] &= mask.s6_addr32[0];
1855 1841                          sin6->sin6_addr.s6_addr32[1] &= mask.s6_addr32[1];
1856 1842                          sin6->sin6_addr.s6_addr32[2] &= mask.s6_addr32[2];
1857 1843                          sin6->sin6_addr.s6_addr32[3] &= mask.s6_addr32[3];
1858 1844                  }
1859 1845  
1860 1846                  /* We don't care in these cases. */
1861 1847                  return (KS_IN_ADDR_DONTCARE);
1862 1848          }
1863 1849  
1864 1850          if (sin->sin_family == AF_INET6) {
1865 1851                  /* Check the easy ones now. */
1866 1852                  if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
1867 1853                          return (KS_IN_ADDR_MBCAST);
1868 1854                  if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
1869 1855                          return (KS_IN_ADDR_UNSPEC);
1870 1856                  /*
1871 1857                   * At this point, we're a unicast IPv6 address.
1872 1858                   *
1873 1859                   * XXX Zones alert -> me/notme decision needs to be tempered
1874 1860                   * by what zone we're in when we go to zone-aware IPsec.
1875 1861                   */
1876 1862                  if (ip_type_v6(&sin6->sin6_addr, ns->netstack_ip) ==
1877 1863                      IRE_LOCAL) {
1878 1864                          /* Hey hey, it's local. */
1879 1865                          return (KS_IN_ADDR_ME);
1880 1866                  }
1881 1867          } else {
1882 1868                  ASSERT(sin->sin_family == AF_INET);
1883 1869                  if (sin->sin_addr.s_addr == INADDR_ANY)
1884 1870                          return (KS_IN_ADDR_UNSPEC);
1885 1871                  if (CLASSD(sin->sin_addr.s_addr))
1886 1872                          return (KS_IN_ADDR_MBCAST);
1887 1873                  /*
1888 1874                   * At this point we're a unicast or broadcast IPv4 address.
1889 1875                   *
1890 1876                   * Check if the address is IRE_BROADCAST or IRE_LOCAL.
1891 1877                   *
1892 1878                   * XXX Zones alert -> me/notme decision needs to be tempered
1893 1879                   * by what zone we're in when we go to zone-aware IPsec.
1894 1880                   */
1895 1881                  type = ip_type_v4(sin->sin_addr.s_addr, ns->netstack_ip);
1896 1882                  switch (type) {
1897 1883                  case IRE_LOCAL:
1898 1884                          return (KS_IN_ADDR_ME);
1899 1885                  case IRE_BROADCAST:
1900 1886                          return (KS_IN_ADDR_MBCAST);
1901 1887                  }
1902 1888          }
1903 1889  
1904 1890          return (KS_IN_ADDR_NOTME);
1905 1891  }
1906 1892  
1907 1893  /*
1908 1894   * Address normalizations and reality checks for inbound PF_KEY messages.
1909 1895   *
1910 1896   * For the case of src == unspecified AF_INET6, and dst == AF_INET, convert
1911 1897   * the source to AF_INET.  Do the same for the inner sources.
1912 1898   */
1913 1899  boolean_t
1914 1900  sadb_addrfix(keysock_in_t *ksi, queue_t *pfkey_q, mblk_t *mp, netstack_t *ns)
1915 1901  {
1916 1902          struct sockaddr_in *src, *isrc;
1917 1903          struct sockaddr_in6 *dst, *idst;
1918 1904          sadb_address_t *srcext, *dstext;
1919 1905          uint16_t sport;
1920 1906          sadb_ext_t **extv = ksi->ks_in_extv;
1921 1907          int rc;
1922 1908  
1923 1909          if (extv[SADB_EXT_ADDRESS_SRC] != NULL) {
1924 1910                  rc = sadb_addrcheck(pfkey_q, mp, extv[SADB_EXT_ADDRESS_SRC],
1925 1911                      ksi->ks_in_serial, ns);
1926 1912                  if (rc == KS_IN_ADDR_UNKNOWN)
1927 1913                          return (B_FALSE);
1928 1914                  if (rc == KS_IN_ADDR_MBCAST) {
1929 1915                          sadb_pfkey_error(pfkey_q, mp, EINVAL,
1930 1916                              SADB_X_DIAGNOSTIC_BAD_SRC, ksi->ks_in_serial);
1931 1917                          return (B_FALSE);
1932 1918                  }
1933 1919                  ksi->ks_in_srctype = rc;
1934 1920          }
1935 1921  
1936 1922          if (extv[SADB_EXT_ADDRESS_DST] != NULL) {
1937 1923                  rc = sadb_addrcheck(pfkey_q, mp, extv[SADB_EXT_ADDRESS_DST],
1938 1924                      ksi->ks_in_serial, ns);
1939 1925                  if (rc == KS_IN_ADDR_UNKNOWN)
1940 1926                          return (B_FALSE);
1941 1927                  if (rc == KS_IN_ADDR_UNSPEC) {
1942 1928                          sadb_pfkey_error(pfkey_q, mp, EINVAL,
1943 1929                              SADB_X_DIAGNOSTIC_BAD_DST, ksi->ks_in_serial);
1944 1930                          return (B_FALSE);
1945 1931                  }
1946 1932                  ksi->ks_in_dsttype = rc;
1947 1933          }
1948 1934  
1949 1935          /*
1950 1936           * NAT-Traversal addrs are simple enough to not require all of
1951 1937           * the checks in sadb_addrcheck().  Just normalize or reject if not
1952 1938           * AF_INET.
1953 1939           */
1954 1940          if (extv[SADB_X_EXT_ADDRESS_NATT_LOC] != NULL) {
1955 1941                  rc = sadb_addrcheck(pfkey_q, mp,
1956 1942                      extv[SADB_X_EXT_ADDRESS_NATT_LOC], ksi->ks_in_serial, ns);
1957 1943  
1958 1944                  /*
1959 1945                   * Local NAT-T addresses never use an IRE_LOCAL, so it should
1960 1946                   * always be NOTME, or UNSPEC (to handle both tunnel mode
1961 1947                   * AND local-port flexibility).
1962 1948                   */
1963 1949                  if (rc != KS_IN_ADDR_NOTME && rc != KS_IN_ADDR_UNSPEC) {
1964 1950                          sadb_pfkey_error(pfkey_q, mp, EINVAL,
1965 1951                              SADB_X_DIAGNOSTIC_MALFORMED_NATT_LOC,
1966 1952                              ksi->ks_in_serial);
1967 1953                          return (B_FALSE);
1968 1954                  }
1969 1955                  src = (struct sockaddr_in *)
1970 1956                      (((sadb_address_t *)extv[SADB_X_EXT_ADDRESS_NATT_LOC]) + 1);
1971 1957                  if (src->sin_family != AF_INET) {
1972 1958                          sadb_pfkey_error(pfkey_q, mp, EINVAL,
1973 1959                              SADB_X_DIAGNOSTIC_BAD_NATT_LOC_AF,
1974 1960                              ksi->ks_in_serial);
1975 1961                          return (B_FALSE);
1976 1962                  }
1977 1963          }
1978 1964  
1979 1965          if (extv[SADB_X_EXT_ADDRESS_NATT_REM] != NULL) {
1980 1966                  rc = sadb_addrcheck(pfkey_q, mp,
1981 1967                      extv[SADB_X_EXT_ADDRESS_NATT_REM], ksi->ks_in_serial, ns);
1982 1968  
1983 1969                  /*
1984 1970                   * Remote NAT-T addresses never use an IRE_LOCAL, so it should
1985 1971                   * always be NOTME, or UNSPEC if it's a tunnel-mode SA.
1986 1972                   */
1987 1973                  if (rc != KS_IN_ADDR_NOTME &&
1988 1974                      !(extv[SADB_X_EXT_ADDRESS_INNER_SRC] != NULL &&
1989 1975                      rc == KS_IN_ADDR_UNSPEC)) {
1990 1976                          sadb_pfkey_error(pfkey_q, mp, EINVAL,
1991 1977                              SADB_X_DIAGNOSTIC_MALFORMED_NATT_REM,
1992 1978                              ksi->ks_in_serial);
1993 1979                          return (B_FALSE);
1994 1980                  }
1995 1981                  src = (struct sockaddr_in *)
1996 1982                      (((sadb_address_t *)extv[SADB_X_EXT_ADDRESS_NATT_REM]) + 1);
1997 1983                  if (src->sin_family != AF_INET) {
1998 1984                          sadb_pfkey_error(pfkey_q, mp, EINVAL,
1999 1985                              SADB_X_DIAGNOSTIC_BAD_NATT_REM_AF,
2000 1986                              ksi->ks_in_serial);
2001 1987                          return (B_FALSE);
2002 1988                  }
2003 1989          }
2004 1990  
2005 1991          if (extv[SADB_X_EXT_ADDRESS_INNER_SRC] != NULL) {
2006 1992                  if (extv[SADB_X_EXT_ADDRESS_INNER_DST] == NULL) {
2007 1993                          sadb_pfkey_error(pfkey_q, mp, EINVAL,
2008 1994                              SADB_X_DIAGNOSTIC_MISSING_INNER_DST,
2009 1995                              ksi->ks_in_serial);
2010 1996                          return (B_FALSE);
2011 1997                  }
2012 1998  
2013 1999                  if (sadb_addrcheck(pfkey_q, mp,
2014 2000                      extv[SADB_X_EXT_ADDRESS_INNER_DST], ksi->ks_in_serial, ns)
2015 2001                      == KS_IN_ADDR_UNKNOWN ||
2016 2002                      sadb_addrcheck(pfkey_q, mp,
2017 2003                      extv[SADB_X_EXT_ADDRESS_INNER_SRC], ksi->ks_in_serial, ns)
2018 2004                      == KS_IN_ADDR_UNKNOWN)
2019 2005                          return (B_FALSE);
2020 2006  
2021 2007                  isrc = (struct sockaddr_in *)
2022 2008                      (((sadb_address_t *)extv[SADB_X_EXT_ADDRESS_INNER_SRC]) +
2023 2009                      1);
2024 2010                  idst = (struct sockaddr_in6 *)
2025 2011                      (((sadb_address_t *)extv[SADB_X_EXT_ADDRESS_INNER_DST]) +
2026 2012                      1);
2027 2013                  if (isrc->sin_family != idst->sin6_family) {
2028 2014                          sadb_pfkey_error(pfkey_q, mp, EINVAL,
2029 2015                              SADB_X_DIAGNOSTIC_INNER_AF_MISMATCH,
2030 2016                              ksi->ks_in_serial);
2031 2017                          return (B_FALSE);
2032 2018                  }
2033 2019          } else if (extv[SADB_X_EXT_ADDRESS_INNER_DST] != NULL) {
2034 2020                          sadb_pfkey_error(pfkey_q, mp, EINVAL,
2035 2021                              SADB_X_DIAGNOSTIC_MISSING_INNER_SRC,
2036 2022                              ksi->ks_in_serial);
2037 2023                          return (B_FALSE);
2038 2024          } else {
2039 2025                  isrc = NULL;    /* For inner/outer port check below. */
2040 2026          }
2041 2027  
2042 2028          dstext = (sadb_address_t *)extv[SADB_EXT_ADDRESS_DST];
2043 2029          srcext = (sadb_address_t *)extv[SADB_EXT_ADDRESS_SRC];
2044 2030  
2045 2031          if (dstext == NULL || srcext == NULL)
2046 2032                  return (B_TRUE);
2047 2033  
2048 2034          dst = (struct sockaddr_in6 *)(dstext + 1);
2049 2035          src = (struct sockaddr_in *)(srcext + 1);
2050 2036  
2051 2037          if (isrc != NULL &&
2052 2038              (isrc->sin_port != 0 || idst->sin6_port != 0) &&
2053 2039              (src->sin_port != 0 || dst->sin6_port != 0)) {
2054 2040                  /* Can't set inner and outer ports in one SA. */
2055 2041                  sadb_pfkey_error(pfkey_q, mp, EINVAL,
2056 2042                      SADB_X_DIAGNOSTIC_DUAL_PORT_SETS,
2057 2043                      ksi->ks_in_serial);
2058 2044                  return (B_FALSE);
2059 2045          }
2060 2046  
2061 2047          if (dst->sin6_family == src->sin_family)
2062 2048                  return (B_TRUE);
2063 2049  
2064 2050          if (srcext->sadb_address_proto != dstext->sadb_address_proto) {
2065 2051                  if (srcext->sadb_address_proto == 0) {
2066 2052                          srcext->sadb_address_proto = dstext->sadb_address_proto;
2067 2053                  } else if (dstext->sadb_address_proto == 0) {
2068 2054                          dstext->sadb_address_proto = srcext->sadb_address_proto;
2069 2055                  } else {
2070 2056                          /* Inequal protocols, neither were 0.  Report error. */
2071 2057                          sadb_pfkey_error(pfkey_q, mp, EINVAL,
2072 2058                              SADB_X_DIAGNOSTIC_PROTO_MISMATCH,
2073 2059                              ksi->ks_in_serial);
2074 2060                          return (B_FALSE);
2075 2061                  }
2076 2062          }
2077 2063  
2078 2064          /*
2079 2065           * With the exception of an unspec IPv6 source and an IPv4
2080 2066           * destination, address families MUST me matched.
2081 2067           */
2082 2068          if (src->sin_family == AF_INET ||
2083 2069              ksi->ks_in_srctype != KS_IN_ADDR_UNSPEC) {
2084 2070                  sadb_pfkey_error(pfkey_q, mp, EINVAL,
2085 2071                      SADB_X_DIAGNOSTIC_AF_MISMATCH, ksi->ks_in_serial);
2086 2072                  return (B_FALSE);
2087 2073          }
2088 2074  
2089 2075          /*
2090 2076           * Convert "src" to AF_INET INADDR_ANY.  We rely on sin_port being
2091 2077           * in the same place for sockaddr_in and sockaddr_in6.
2092 2078           */
2093 2079          sport = src->sin_port;
2094 2080          bzero(src, sizeof (*src));
2095 2081          src->sin_family = AF_INET;
2096 2082          src->sin_port = sport;
2097 2083  
2098 2084          return (B_TRUE);
2099 2085  }
2100 2086  
2101 2087  /*
2102 2088   * Set the results in "addrtype", given an IRE as requested by
2103 2089   * sadb_addrcheck().
2104 2090   */
2105 2091  int
2106 2092  sadb_addrset(ire_t *ire)
2107 2093  {
2108 2094          if ((ire->ire_type & IRE_BROADCAST) ||
2109 2095              (ire->ire_ipversion == IPV4_VERSION && CLASSD(ire->ire_addr)) ||
2110 2096              (ire->ire_ipversion == IPV6_VERSION &&
2111 2097              IN6_IS_ADDR_MULTICAST(&(ire->ire_addr_v6))))
2112 2098                  return (KS_IN_ADDR_MBCAST);
2113 2099          if (ire->ire_type & (IRE_LOCAL | IRE_LOOPBACK))
2114 2100                  return (KS_IN_ADDR_ME);
2115 2101          return (KS_IN_ADDR_NOTME);
2116 2102  }
2117 2103  
2118 2104  /*
2119 2105   * Match primitives..
2120 2106   * !!! TODO: short term: inner selectors
2121 2107   *              ipv6 scope id (ifindex)
2122 2108   * longer term:  zone id.  sensitivity label. uid.
2123 2109   */
2124 2110  boolean_t
2125 2111  sadb_match_spi(ipsa_query_t *sq, ipsa_t *sa)
2126 2112  {
2127 2113          return (sq->spi == sa->ipsa_spi);
2128 2114  }
2129 2115  
2130 2116  boolean_t
2131 2117  sadb_match_dst_v6(ipsa_query_t *sq, ipsa_t *sa)
2132 2118  {
2133 2119          return (IPSA_ARE_ADDR_EQUAL(sa->ipsa_dstaddr, sq->dstaddr, AF_INET6));
2134 2120  }
2135 2121  
2136 2122  boolean_t
2137 2123  sadb_match_src_v6(ipsa_query_t *sq, ipsa_t *sa)
2138 2124  {
2139 2125          return (IPSA_ARE_ADDR_EQUAL(sa->ipsa_srcaddr, sq->srcaddr, AF_INET6));
2140 2126  }
2141 2127  
2142 2128  boolean_t
2143 2129  sadb_match_dst_v4(ipsa_query_t *sq, ipsa_t *sa)
2144 2130  {
2145 2131          return (sq->dstaddr[0] == sa->ipsa_dstaddr[0]);
2146 2132  }
2147 2133  
2148 2134  boolean_t
2149 2135  sadb_match_src_v4(ipsa_query_t *sq, ipsa_t *sa)
2150 2136  {
2151 2137          return (sq->srcaddr[0] == sa->ipsa_srcaddr[0]);
2152 2138  }
2153 2139  
2154 2140  boolean_t
2155 2141  sadb_match_dstid(ipsa_query_t *sq, ipsa_t *sa)
2156 2142  {
2157 2143          return ((sa->ipsa_dst_cid != NULL) &&
2158 2144              (sq->didtype == sa->ipsa_dst_cid->ipsid_type) &&
2159 2145              (strcmp(sq->didstr, sa->ipsa_dst_cid->ipsid_cid) == 0));
2160 2146  
2161 2147  }
2162 2148  boolean_t
2163 2149  sadb_match_srcid(ipsa_query_t *sq, ipsa_t *sa)
2164 2150  {
2165 2151          return ((sa->ipsa_src_cid != NULL) &&
2166 2152              (sq->sidtype == sa->ipsa_src_cid->ipsid_type) &&
2167 2153              (strcmp(sq->sidstr, sa->ipsa_src_cid->ipsid_cid) == 0));
2168 2154  }
2169 2155  
2170 2156  boolean_t
2171 2157  sadb_match_kmc(ipsa_query_t *sq, ipsa_t *sa)
2172 2158  {
2173 2159  #define M(a, b) (((a) == 0) || ((b) == 0) || ((a) == (b)))
2174 2160  
2175 2161          return (M(sq->kmc, sa->ipsa_kmc) && M(sq->kmp, sa->ipsa_kmp));
2176 2162  
2177 2163  #undef M
2178 2164  }
2179 2165  
2180 2166  /*
2181 2167   * Common function which extracts several PF_KEY extensions for ease of
2182 2168   * SADB matching.
2183 2169   *
2184 2170   * XXX TODO: weed out ipsa_query_t fields not used during matching
2185 2171   * or afterwards?
2186 2172   */
2187 2173  int
2188 2174  sadb_form_query(keysock_in_t *ksi, uint32_t req, uint32_t match,
2189 2175      ipsa_query_t *sq, int *diagnostic)
2190 2176  {
2191 2177          int i;
2192 2178          ipsa_match_fn_t *mfpp = &(sq->matchers[0]);
2193 2179  
2194 2180          for (i = 0; i < IPSA_NMATCH; i++)
2195 2181                  sq->matchers[i] = NULL;
2196 2182  
2197 2183          ASSERT((req & ~match) == 0);
2198 2184  
2199 2185          sq->req = req;
2200 2186          sq->dstext = (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_DST];
2201 2187          sq->srcext = (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_SRC];
2202 2188          sq->assoc = (sadb_sa_t *)ksi->ks_in_extv[SADB_EXT_SA];
2203 2189  
2204 2190          if ((req & IPSA_Q_DST) && (sq->dstext == NULL)) {
2205 2191                  *diagnostic = SADB_X_DIAGNOSTIC_MISSING_DST;
2206 2192                  return (EINVAL);
2207 2193          }
2208 2194          if ((req & IPSA_Q_SRC) && (sq->srcext == NULL)) {
2209 2195                  *diagnostic = SADB_X_DIAGNOSTIC_MISSING_SRC;
2210 2196                  return (EINVAL);
2211 2197          }
2212 2198          if ((req & IPSA_Q_SA) && (sq->assoc == NULL)) {
2213 2199                  *diagnostic = SADB_X_DIAGNOSTIC_MISSING_SA;
2214 2200                  return (EINVAL);
2215 2201          }
2216 2202  
2217 2203          if (match & IPSA_Q_SA) {
2218 2204                  *mfpp++ = sadb_match_spi;
2219 2205                  sq->spi = sq->assoc->sadb_sa_spi;
2220 2206          }
2221 2207  
2222 2208          if (sq->dstext != NULL)
2223 2209                  sq->dst = (struct sockaddr_in *)(sq->dstext + 1);
2224 2210          else {
2225 2211                  sq->dst = NULL;
2226 2212                  sq->dst6 = NULL;
2227 2213                  sq->dstaddr = NULL;
2228 2214          }
2229 2215  
2230 2216          if (sq->srcext != NULL)
2231 2217                  sq->src = (struct sockaddr_in *)(sq->srcext + 1);
2232 2218          else {
2233 2219                  sq->src = NULL;
2234 2220                  sq->src6 = NULL;
2235 2221                  sq->srcaddr = NULL;
2236 2222          }
2237 2223  
2238 2224          if (sq->dst != NULL)
2239 2225                  sq->af = sq->dst->sin_family;
2240 2226          else if (sq->src != NULL)
2241 2227                  sq->af = sq->src->sin_family;
2242 2228          else
2243 2229                  sq->af = AF_INET;
2244 2230  
2245 2231          if (sq->af == AF_INET6) {
2246 2232                  if ((match & IPSA_Q_DST) && (sq->dstext != NULL)) {
2247 2233                          *mfpp++ = sadb_match_dst_v6;
2248 2234                          sq->dst6 = (struct sockaddr_in6 *)sq->dst;
2249 2235                          sq->dstaddr = (uint32_t *)&(sq->dst6->sin6_addr);
2250 2236                  } else {
2251 2237                          match &= ~IPSA_Q_DST;
2252 2238                          sq->dstaddr = ALL_ZEROES_PTR;
2253 2239                  }
2254 2240  
2255 2241                  if ((match & IPSA_Q_SRC) && (sq->srcext != NULL)) {
2256 2242                          sq->src6 = (struct sockaddr_in6 *)(sq->srcext + 1);
2257 2243                          sq->srcaddr = (uint32_t *)&sq->src6->sin6_addr;
2258 2244                          if (sq->src6->sin6_family != AF_INET6) {
2259 2245                                  *diagnostic = SADB_X_DIAGNOSTIC_AF_MISMATCH;
2260 2246                                  return (EINVAL);
2261 2247                          }
2262 2248                          *mfpp++ = sadb_match_src_v6;
2263 2249                  } else {
2264 2250                          match &= ~IPSA_Q_SRC;
2265 2251                          sq->srcaddr = ALL_ZEROES_PTR;
2266 2252                  }
2267 2253          } else {
2268 2254                  sq->src6 = sq->dst6 = NULL;
2269 2255                  if ((match & IPSA_Q_DST) && (sq->dstext != NULL)) {
2270 2256                          *mfpp++ = sadb_match_dst_v4;
2271 2257                          sq->dstaddr = (uint32_t *)&sq->dst->sin_addr;
2272 2258                  } else {
2273 2259                          match &= ~IPSA_Q_DST;
2274 2260                          sq->dstaddr = ALL_ZEROES_PTR;
2275 2261                  }
2276 2262                  if ((match & IPSA_Q_SRC) && (sq->srcext != NULL)) {
2277 2263                          sq->srcaddr = (uint32_t *)&sq->src->sin_addr;
2278 2264                          if (sq->src->sin_family != AF_INET) {
2279 2265                                  *diagnostic = SADB_X_DIAGNOSTIC_AF_MISMATCH;
2280 2266                                  return (EINVAL);
2281 2267                          }
2282 2268                          *mfpp++ = sadb_match_src_v4;
2283 2269                  } else {
2284 2270                          match &= ~IPSA_Q_SRC;
2285 2271                          sq->srcaddr = ALL_ZEROES_PTR;
2286 2272                  }
2287 2273          }
2288 2274  
2289 2275          sq->dstid = (sadb_ident_t *)ksi->ks_in_extv[SADB_EXT_IDENTITY_DST];
2290 2276          if ((match & IPSA_Q_DSTID) && (sq->dstid != NULL)) {
2291 2277                  sq->didstr = (char *)(sq->dstid + 1);
2292 2278                  sq->didtype = sq->dstid->sadb_ident_type;
2293 2279                  *mfpp++ = sadb_match_dstid;
2294 2280          }
2295 2281  
2296 2282          sq->srcid = (sadb_ident_t *)ksi->ks_in_extv[SADB_EXT_IDENTITY_SRC];
2297 2283  
2298 2284          if ((match & IPSA_Q_SRCID) && (sq->srcid != NULL)) {
2299 2285                  sq->sidstr = (char *)(sq->srcid + 1);
2300 2286                  sq->sidtype = sq->srcid->sadb_ident_type;
2301 2287                  *mfpp++ = sadb_match_srcid;
2302 2288          }
2303 2289  
2304 2290          sq->kmcext = (sadb_x_kmc_t *)ksi->ks_in_extv[SADB_X_EXT_KM_COOKIE];
2305 2291          sq->kmc = 0;
2306 2292          sq->kmp = 0;
2307 2293  
2308 2294          if ((match & IPSA_Q_KMC) && (sq->kmcext)) {
2309 2295                  sq->kmc = sq->kmcext->sadb_x_kmc_cookie;
2310 2296                  sq->kmp = sq->kmcext->sadb_x_kmc_proto;
2311 2297                  *mfpp++ = sadb_match_kmc;
2312 2298          }
2313 2299  
2314 2300          if (match & (IPSA_Q_INBOUND|IPSA_Q_OUTBOUND)) {
2315 2301                  if (sq->af == AF_INET6)
2316 2302                          sq->sp = &sq->spp->s_v6;
2317 2303                  else
2318 2304                          sq->sp = &sq->spp->s_v4;
2319 2305          } else {
2320 2306                  sq->sp = NULL;
2321 2307          }
2322 2308  
2323 2309          if (match & IPSA_Q_INBOUND) {
2324 2310                  sq->inhash = INBOUND_HASH(sq->sp, sq->assoc->sadb_sa_spi);
2325 2311                  sq->inbound = &sq->sp->sdb_if[sq->inhash];
2326 2312          } else {
2327 2313                  sq->inhash = 0;
2328 2314                  sq->inbound = NULL;
2329 2315          }
2330 2316  
2331 2317          if (match & IPSA_Q_OUTBOUND) {
2332 2318                  if (sq->af == AF_INET6) {
2333 2319                          sq->outhash = OUTBOUND_HASH_V6(sq->sp, *(sq->dstaddr));
2334 2320                  } else {
2335 2321                          sq->outhash = OUTBOUND_HASH_V4(sq->sp, *(sq->dstaddr));
2336 2322                  }
2337 2323                  sq->outbound = &sq->sp->sdb_of[sq->outhash];
2338 2324          } else {
2339 2325                  sq->outhash = 0;
2340 2326                  sq->outbound = NULL;
2341 2327          }
2342 2328          sq->match = match;
2343 2329          return (0);
2344 2330  }
2345 2331  
2346 2332  /*
2347 2333   * Match an initialized query structure with a security association;
2348 2334   * return B_TRUE on a match, B_FALSE on a miss.
2349 2335   * Applies match functions set up by sadb_form_query() until one returns false.
2350 2336   */
2351 2337  boolean_t
2352 2338  sadb_match_query(ipsa_query_t *sq, ipsa_t *sa)
2353 2339  {
2354 2340          ipsa_match_fn_t *mfpp = &(sq->matchers[0]);
2355 2341          ipsa_match_fn_t mfp;
2356 2342  
2357 2343          for (mfp = *mfpp++; mfp != NULL; mfp = *mfpp++) {
2358 2344                  if (!mfp(sq, sa))
2359 2345                          return (B_FALSE);
  
    | 
      ↓ open down ↓ | 
    722 lines elided | 
    
      ↑ open up ↑ | 
  
2360 2346          }
2361 2347          return (B_TRUE);
2362 2348  }
2363 2349  
2364 2350  /*
2365 2351   * Walker callback function to delete sa's based on src/dst address.
2366 2352   * Assumes that we're called with *head locked, no other locks held;
2367 2353   * Conveniently, and not coincidentally, this is both what sadb_walker
2368 2354   * gives us and also what sadb_unlinkassoc expects.
2369 2355   */
2370      -struct sadb_purge_state
2371      -{
2372      -        ipsa_query_t sq;
2373      -        boolean_t inbnd;
2374      -        uint8_t sadb_sa_state;
2375      -};
2376      -
2377 2356  static void
2378 2357  sadb_purge_cb(isaf_t *head, ipsa_t *entry, void *cookie)
2379 2358  {
2380      -        struct sadb_purge_state *ps = (struct sadb_purge_state *)cookie;
     2359 +        ipsa_query_t *query = (ipsa_query_t *)cookie;
2381 2360  
2382 2361          ASSERT(MUTEX_HELD(&head->isaf_lock));
2383 2362  
2384 2363          mutex_enter(&entry->ipsa_lock);
2385 2364  
2386 2365          if (entry->ipsa_state == IPSA_STATE_LARVAL ||
2387      -            !sadb_match_query(&ps->sq, entry)) {
     2366 +            !sadb_match_query(query, entry)) {
2388 2367                  mutex_exit(&entry->ipsa_lock);
2389 2368                  return;
2390 2369          }
2391 2370  
2392 2371          entry->ipsa_state = IPSA_STATE_DEAD;
2393 2372          (void) sadb_torch_assoc(head, entry);
2394 2373  }
2395 2374  
2396 2375  /*
2397 2376   * Common code to purge an SA with a matching src or dst address.
2398 2377   * Don't kill larval SA's in such a purge.
2399 2378   */
2400 2379  int
2401 2380  sadb_purge_sa(mblk_t *mp, keysock_in_t *ksi, sadb_t *sp,
2402 2381          int *diagnostic, queue_t *pfkey_q)
2403 2382  {
2404      -        struct sadb_purge_state ps;
     2383 +        ipsa_query_t query;
2405 2384          int error = sadb_form_query(ksi, 0,
2406 2385              IPSA_Q_SRC|IPSA_Q_DST|IPSA_Q_SRCID|IPSA_Q_DSTID|IPSA_Q_KMC,
2407      -            &ps.sq, diagnostic);
     2386 +            &query, diagnostic);
2408 2387  
2409 2388          if (error != 0)
2410 2389                  return (error);
2411 2390  
2412 2391          /*
2413 2392           * This is simple, crude, and effective.
2414 2393           * Unimplemented optimizations (TBD):
2415 2394           * - we can limit how many places we search based on where we
2416 2395           * think the SA is filed.
2417 2396           * - if we get a dst address, we can hash based on dst addr to find
2418 2397           * the correct bucket in the outbound table.
2419 2398           */
2420      -        ps.inbnd = B_TRUE;
2421      -        sadb_walker(sp->sdb_if, sp->sdb_hashsize, sadb_purge_cb, &ps);
2422      -        ps.inbnd = B_FALSE;
2423      -        sadb_walker(sp->sdb_of, sp->sdb_hashsize, sadb_purge_cb, &ps);
     2399 +        sadb_walker(sp->sdb_if, sp->sdb_hashsize, sadb_purge_cb, &query);
     2400 +        sadb_walker(sp->sdb_of, sp->sdb_hashsize, sadb_purge_cb, &query);
2424 2401  
2425 2402          ASSERT(mp->b_cont != NULL);
2426 2403          sadb_pfkey_echo(pfkey_q, mp, (sadb_msg_t *)mp->b_cont->b_rptr, ksi,
2427 2404              NULL);
2428 2405          return (0);
2429 2406  }
2430 2407  
2431      -static void
2432      -sadb_delpair_state_one(isaf_t *head, ipsa_t *entry, void *cookie)
2433      -{
2434      -        struct sadb_purge_state *ps = (struct sadb_purge_state *)cookie;
2435      -        isaf_t  *inbound_bucket;
2436      -        ipsa_t *peer_assoc;
2437      -        ipsa_query_t *sq = &ps->sq;
2438      -
2439      -        ASSERT(MUTEX_HELD(&head->isaf_lock));
2440      -
2441      -        mutex_enter(&entry->ipsa_lock);
2442      -
2443      -        if ((entry->ipsa_state != ps->sadb_sa_state) ||
2444      -            ((sq->srcaddr != NULL) &&
2445      -            !IPSA_ARE_ADDR_EQUAL(entry->ipsa_srcaddr, sq->srcaddr, sq->af))) {
2446      -                mutex_exit(&entry->ipsa_lock);
2447      -                return;
2448      -        }
2449      -
2450      -        /*
2451      -         * The isaf_t *, which is passed in , is always an outbound bucket,
2452      -         * and we are preserving the outbound-then-inbound hash-bucket lock
2453      -         * ordering. The sadb_walker() which triggers this function is called
2454      -         * only on the outbound fanout, and the corresponding inbound bucket
2455      -         * lock is safe to acquire here.
2456      -         */
2457      -
2458      -        if (entry->ipsa_haspeer) {
2459      -                inbound_bucket = INBOUND_BUCKET(sq->sp, entry->ipsa_spi);
2460      -                mutex_enter(&inbound_bucket->isaf_lock);
2461      -                peer_assoc = ipsec_getassocbyspi(inbound_bucket,
2462      -                    entry->ipsa_spi, entry->ipsa_srcaddr,
2463      -                    entry->ipsa_dstaddr, entry->ipsa_addrfam);
2464      -        } else {
2465      -                inbound_bucket = INBOUND_BUCKET(sq->sp, entry->ipsa_otherspi);
2466      -                mutex_enter(&inbound_bucket->isaf_lock);
2467      -                peer_assoc = ipsec_getassocbyspi(inbound_bucket,
2468      -                    entry->ipsa_otherspi, entry->ipsa_dstaddr,
2469      -                    entry->ipsa_srcaddr, entry->ipsa_addrfam);
2470      -        }
2471      -
2472      -        entry->ipsa_state = IPSA_STATE_DEAD;
2473      -        (void) sadb_torch_assoc(head, entry);
2474      -        if (peer_assoc != NULL) {
2475      -                mutex_enter(&peer_assoc->ipsa_lock);
2476      -                peer_assoc->ipsa_state = IPSA_STATE_DEAD;
2477      -                (void) sadb_torch_assoc(inbound_bucket, peer_assoc);
2478      -        }
2479      -        mutex_exit(&inbound_bucket->isaf_lock);
2480      -}
2481      -
2482      -static int
2483      -sadb_delpair_state(mblk_t *mp, keysock_in_t *ksi, sadbp_t *spp,
2484      -    int *diagnostic, queue_t *pfkey_q)
2485      -{
2486      -        sadb_sa_t *assoc = (sadb_sa_t *)ksi->ks_in_extv[SADB_EXT_SA];
2487      -        struct sadb_purge_state ps;
2488      -        int error;
2489      -
2490      -        ps.sq.spp = spp;                /* XXX param */
2491      -
2492      -        error = sadb_form_query(ksi, IPSA_Q_DST|IPSA_Q_SRC,
2493      -            IPSA_Q_SRC|IPSA_Q_DST|IPSA_Q_SRCID|IPSA_Q_DSTID|IPSA_Q_KMC,
2494      -            &ps.sq, diagnostic);
2495      -        if (error != 0)
2496      -                return (error);
2497      -
2498      -        ps.inbnd = B_FALSE;
2499      -        ps.sadb_sa_state = assoc->sadb_sa_state;
2500      -        sadb_walker(ps.sq.sp->sdb_of, ps.sq.sp->sdb_hashsize,
2501      -            sadb_delpair_state_one, &ps);
2502      -
2503      -        ASSERT(mp->b_cont != NULL);
2504      -        sadb_pfkey_echo(pfkey_q, mp, (sadb_msg_t *)mp->b_cont->b_rptr,
2505      -            ksi, NULL);
2506      -        return (0);
2507      -}
2508      -
2509 2408  /*
2510 2409   * Common code to delete/get an SA.
2511 2410   */
2512 2411  int
2513 2412  sadb_delget_sa(mblk_t *mp, keysock_in_t *ksi, sadbp_t *spp,
2514 2413      int *diagnostic, queue_t *pfkey_q, uint8_t sadb_msg_type)
2515 2414  {
2516 2415          ipsa_query_t sq;
2517 2416          ipsa_t *echo_target = NULL;
2518 2417          ipsap_t ipsapp;
2519 2418          uint_t  error = 0;
2520 2419  
2521      -        if (sadb_msg_type == SADB_X_DELPAIR_STATE)
2522      -                return (sadb_delpair_state(mp, ksi, spp, diagnostic, pfkey_q));
2523      -
2524 2420          sq.spp = spp;           /* XXX param */
2525 2421          error = sadb_form_query(ksi, IPSA_Q_DST|IPSA_Q_SA,
2526 2422              IPSA_Q_SRC|IPSA_Q_DST|IPSA_Q_SA|IPSA_Q_INBOUND|IPSA_Q_OUTBOUND,
2527 2423              &sq, diagnostic);
2528 2424          if (error != 0)
2529 2425                  return (error);
2530 2426  
2531 2427          error = get_ipsa_pair(&sq, &ipsapp, diagnostic);
2532 2428          if (error != 0) {
2533 2429                  return (error);
2534 2430          }
2535 2431  
2536 2432          echo_target = ipsapp.ipsap_sa_ptr;
2537 2433          if (echo_target == NULL)
2538 2434                  echo_target = ipsapp.ipsap_psa_ptr;
2539 2435  
2540 2436          if (sadb_msg_type == SADB_DELETE || sadb_msg_type == SADB_X_DELPAIR) {
2541 2437                  /*
2542 2438                   * Bucket locks will be required if SA is actually unlinked.
2543 2439                   * get_ipsa_pair() returns valid hash bucket pointers even
2544 2440                   * if it can't find a pair SA pointer. To prevent a potential
2545 2441                   * deadlock, always lock the outbound bucket before the inbound.
2546 2442                   */
2547 2443                  if (ipsapp.in_inbound_table) {
2548 2444                          mutex_enter(&ipsapp.ipsap_pbucket->isaf_lock);
2549 2445                          mutex_enter(&ipsapp.ipsap_bucket->isaf_lock);
2550 2446                  } else {
2551 2447                          mutex_enter(&ipsapp.ipsap_bucket->isaf_lock);
2552 2448                          mutex_enter(&ipsapp.ipsap_pbucket->isaf_lock);
2553 2449                  }
2554 2450  
2555 2451                  if (ipsapp.ipsap_sa_ptr != NULL) {
2556 2452                          mutex_enter(&ipsapp.ipsap_sa_ptr->ipsa_lock);
2557 2453                          ipsapp.ipsap_sa_ptr->ipsa_state = IPSA_STATE_DEAD;
2558 2454                          (void) sadb_torch_assoc(ipsapp.ipsap_bucket,
2559 2455                              ipsapp.ipsap_sa_ptr);
2560 2456                          /*
2561 2457                           * sadb_torch_assoc() releases the ipsa_lock
2562 2458                           * and calls sadb_unlinkassoc() which does a
2563 2459                           * IPSA_REFRELE.
2564 2460                           */
2565 2461                  }
2566 2462                  if (ipsapp.ipsap_psa_ptr != NULL) {
2567 2463                          mutex_enter(&ipsapp.ipsap_psa_ptr->ipsa_lock);
2568 2464                          if (sadb_msg_type == SADB_X_DELPAIR ||
2569 2465                              ipsapp.ipsap_psa_ptr->ipsa_haspeer) {
2570 2466                                  ipsapp.ipsap_psa_ptr->ipsa_state =
2571 2467                                      IPSA_STATE_DEAD;
2572 2468                                  (void) sadb_torch_assoc(ipsapp.ipsap_pbucket,
2573 2469                                      ipsapp.ipsap_psa_ptr);
2574 2470                          } else {
2575 2471                                  /*
2576 2472                                   * Only half of the "pair" has been deleted.
2577 2473                                   * Update the remaining SA and remove references
2578 2474                                   * to its pair SA, which is now gone.
2579 2475                                   */
2580 2476                                  ipsapp.ipsap_psa_ptr->ipsa_otherspi = 0;
2581 2477                                  ipsapp.ipsap_psa_ptr->ipsa_flags &=
2582 2478                                      ~IPSA_F_PAIRED;
2583 2479                                  mutex_exit(&ipsapp.ipsap_psa_ptr->ipsa_lock);
2584 2480                          }
2585 2481                  } else if (sadb_msg_type == SADB_X_DELPAIR) {
2586 2482                          *diagnostic = SADB_X_DIAGNOSTIC_PAIR_SA_NOTFOUND;
2587 2483                          error = ESRCH;
2588 2484                  }
2589 2485                  mutex_exit(&ipsapp.ipsap_bucket->isaf_lock);
2590 2486                  mutex_exit(&ipsapp.ipsap_pbucket->isaf_lock);
2591 2487          }
2592 2488  
2593 2489          ASSERT(mp->b_cont != NULL);
2594 2490  
2595 2491          if (error == 0)
2596 2492                  sadb_pfkey_echo(pfkey_q, mp, (sadb_msg_t *)
2597 2493                      mp->b_cont->b_rptr, ksi, echo_target);
2598 2494  
2599 2495          destroy_ipsa_pair(&ipsapp);
2600 2496  
2601 2497          return (error);
2602 2498  }
2603 2499  
2604 2500  /*
2605 2501   * This function takes a sadb_sa_t and finds the ipsa_t structure
2606 2502   * and the isaf_t (hash bucket) that its stored under. If the security
2607 2503   * association has a peer, the ipsa_t structure and bucket for that security
2608 2504   * association are also searched for. The "pair" of ipsa_t's and isaf_t's
2609 2505   * are returned as a ipsap_t.
2610 2506   *
2611 2507   * The hash buckets are returned for convenience, if the calling function
2612 2508   * needs to use the hash bucket locks, say to remove the SA's, it should
2613 2509   * take care to observe the convention of locking outbound bucket then
2614 2510   * inbound bucket. The flag in_inbound_table provides direction.
2615 2511   *
2616 2512   * Note that a "pair" is defined as one (but not both) of the following:
2617 2513   *
2618 2514   * A security association which has a soft reference to another security
2619 2515   * association via its SPI.
2620 2516   *
2621 2517   * A security association that is not obviously "inbound" or "outbound" so
2622 2518   * it appears in both hash tables, the "peer" being the same security
2623 2519   * association in the other hash table.
2624 2520   *
2625 2521   * This function will return NULL if the ipsa_t can't be found in the
2626 2522   * inbound or outbound  hash tables (not found). If only one ipsa_t is
2627 2523   * found, the pair ipsa_t will be NULL. Both isaf_t values are valid
2628 2524   * provided at least one ipsa_t is found.
2629 2525   */
2630 2526  static int
2631 2527  get_ipsa_pair(ipsa_query_t *sq, ipsap_t *ipsapp, int *diagnostic)
2632 2528  {
2633 2529          uint32_t pair_srcaddr[IPSA_MAX_ADDRLEN];
2634 2530          uint32_t pair_dstaddr[IPSA_MAX_ADDRLEN];
2635 2531          uint32_t pair_spi;
2636 2532  
2637 2533          init_ipsa_pair(ipsapp);
2638 2534  
2639 2535          ipsapp->in_inbound_table = B_FALSE;
2640 2536  
2641 2537          /* Lock down both buckets. */
2642 2538          mutex_enter(&sq->outbound->isaf_lock);
2643 2539          mutex_enter(&sq->inbound->isaf_lock);
2644 2540  
2645 2541          if (sq->assoc->sadb_sa_flags & IPSA_F_INBOUND) {
2646 2542                  ipsapp->ipsap_sa_ptr = ipsec_getassocbyspi(sq->inbound,
2647 2543                      sq->assoc->sadb_sa_spi, sq->srcaddr, sq->dstaddr, sq->af);
2648 2544                  if (ipsapp->ipsap_sa_ptr != NULL) {
2649 2545                          ipsapp->ipsap_bucket = sq->inbound;
2650 2546                          ipsapp->ipsap_pbucket = sq->outbound;
2651 2547                          ipsapp->in_inbound_table = B_TRUE;
2652 2548                  } else {
2653 2549                          ipsapp->ipsap_sa_ptr = ipsec_getassocbyspi(sq->outbound,
2654 2550                              sq->assoc->sadb_sa_spi, sq->srcaddr, sq->dstaddr,
2655 2551                              sq->af);
2656 2552                          ipsapp->ipsap_bucket = sq->outbound;
2657 2553                          ipsapp->ipsap_pbucket = sq->inbound;
2658 2554                  }
2659 2555          } else {
2660 2556                  /* IPSA_F_OUTBOUND is set *or* no directions flags set. */
2661 2557                  ipsapp->ipsap_sa_ptr =
2662 2558                      ipsec_getassocbyspi(sq->outbound,
2663 2559                      sq->assoc->sadb_sa_spi, sq->srcaddr, sq->dstaddr, sq->af);
2664 2560                  if (ipsapp->ipsap_sa_ptr != NULL) {
2665 2561                          ipsapp->ipsap_bucket = sq->outbound;
2666 2562                          ipsapp->ipsap_pbucket = sq->inbound;
2667 2563                  } else {
2668 2564                          ipsapp->ipsap_sa_ptr = ipsec_getassocbyspi(sq->inbound,
2669 2565                              sq->assoc->sadb_sa_spi, sq->srcaddr, sq->dstaddr,
2670 2566                              sq->af);
2671 2567                          ipsapp->ipsap_bucket = sq->inbound;
2672 2568                          ipsapp->ipsap_pbucket = sq->outbound;
2673 2569                          if (ipsapp->ipsap_sa_ptr != NULL)
2674 2570                                  ipsapp->in_inbound_table = B_TRUE;
2675 2571                  }
2676 2572          }
2677 2573  
2678 2574          if (ipsapp->ipsap_sa_ptr == NULL) {
2679 2575                  mutex_exit(&sq->outbound->isaf_lock);
2680 2576                  mutex_exit(&sq->inbound->isaf_lock);
2681 2577                  *diagnostic = SADB_X_DIAGNOSTIC_SA_NOTFOUND;
2682 2578                  return (ESRCH);
2683 2579          }
2684 2580  
2685 2581          if ((ipsapp->ipsap_sa_ptr->ipsa_state == IPSA_STATE_LARVAL) &&
2686 2582              ipsapp->in_inbound_table) {
2687 2583                  mutex_exit(&sq->outbound->isaf_lock);
2688 2584                  mutex_exit(&sq->inbound->isaf_lock);
2689 2585                  return (0);
2690 2586          }
2691 2587  
2692 2588          mutex_enter(&ipsapp->ipsap_sa_ptr->ipsa_lock);
2693 2589          if (ipsapp->ipsap_sa_ptr->ipsa_haspeer) {
2694 2590                  /*
2695 2591                   * haspeer implies no sa_pairing, look for same spi
2696 2592                   * in other hashtable.
2697 2593                   */
2698 2594                  ipsapp->ipsap_psa_ptr =
2699 2595                      ipsec_getassocbyspi(ipsapp->ipsap_pbucket,
2700 2596                      sq->assoc->sadb_sa_spi, sq->srcaddr, sq->dstaddr, sq->af);
2701 2597                  mutex_exit(&ipsapp->ipsap_sa_ptr->ipsa_lock);
2702 2598                  mutex_exit(&sq->outbound->isaf_lock);
2703 2599                  mutex_exit(&sq->inbound->isaf_lock);
2704 2600                  return (0);
2705 2601          }
2706 2602          pair_spi = ipsapp->ipsap_sa_ptr->ipsa_otherspi;
2707 2603          IPSA_COPY_ADDR(&pair_srcaddr,
2708 2604              ipsapp->ipsap_sa_ptr->ipsa_srcaddr, sq->af);
2709 2605          IPSA_COPY_ADDR(&pair_dstaddr,
2710 2606              ipsapp->ipsap_sa_ptr->ipsa_dstaddr, sq->af);
2711 2607          mutex_exit(&ipsapp->ipsap_sa_ptr->ipsa_lock);
2712 2608          mutex_exit(&sq->inbound->isaf_lock);
2713 2609          mutex_exit(&sq->outbound->isaf_lock);
2714 2610  
2715 2611          if (pair_spi == 0) {
2716 2612                  ASSERT(ipsapp->ipsap_bucket != NULL);
2717 2613                  ASSERT(ipsapp->ipsap_pbucket != NULL);
2718 2614                  return (0);
2719 2615          }
2720 2616  
2721 2617          /* found sa in outbound sadb, peer should be inbound */
2722 2618  
2723 2619          if (ipsapp->in_inbound_table) {
2724 2620                  /* Found SA in inbound table, pair will be in outbound. */
2725 2621                  if (sq->af == AF_INET6) {
2726 2622                          ipsapp->ipsap_pbucket = OUTBOUND_BUCKET_V6(sq->sp,
2727 2623                              *(uint32_t *)pair_srcaddr);
2728 2624                  } else {
2729 2625                          ipsapp->ipsap_pbucket = OUTBOUND_BUCKET_V4(sq->sp,
2730 2626                              *(uint32_t *)pair_srcaddr);
2731 2627                  }
2732 2628          } else {
2733 2629                  ipsapp->ipsap_pbucket = INBOUND_BUCKET(sq->sp, pair_spi);
2734 2630          }
2735 2631          mutex_enter(&ipsapp->ipsap_pbucket->isaf_lock);
2736 2632          ipsapp->ipsap_psa_ptr = ipsec_getassocbyspi(ipsapp->ipsap_pbucket,
2737 2633              pair_spi, pair_dstaddr, pair_srcaddr, sq->af);
2738 2634          mutex_exit(&ipsapp->ipsap_pbucket->isaf_lock);
2739 2635          ASSERT(ipsapp->ipsap_bucket != NULL);
2740 2636          ASSERT(ipsapp->ipsap_pbucket != NULL);
2741 2637          return (0);
2742 2638  }
2743 2639  
2744 2640  /*
2745 2641   * Perform NAT-traversal cached checksum offset calculations here.
2746 2642   */
2747 2643  static void
2748 2644  sadb_nat_calculations(ipsa_t *newbie, sadb_address_t *natt_loc_ext,
2749 2645      sadb_address_t *natt_rem_ext, uint32_t *src_addr_ptr,
2750 2646      uint32_t *dst_addr_ptr)
2751 2647  {
2752 2648          struct sockaddr_in *natt_loc, *natt_rem;
2753 2649          uint32_t *natt_loc_ptr = NULL, *natt_rem_ptr = NULL;
2754 2650          uint32_t running_sum = 0;
2755 2651  
2756 2652  #define DOWN_SUM(x) (x) = ((x) & 0xFFFF) +       ((x) >> 16)
2757 2653  
2758 2654          if (natt_rem_ext != NULL) {
2759 2655                  uint32_t l_src;
2760 2656                  uint32_t l_rem;
2761 2657  
2762 2658                  natt_rem = (struct sockaddr_in *)(natt_rem_ext + 1);
2763 2659  
2764 2660                  /* Ensured by sadb_addrfix(). */
2765 2661                  ASSERT(natt_rem->sin_family == AF_INET);
2766 2662  
2767 2663                  natt_rem_ptr = (uint32_t *)(&natt_rem->sin_addr);
2768 2664                  newbie->ipsa_remote_nat_port = natt_rem->sin_port;
2769 2665                  l_src = *src_addr_ptr;
2770 2666                  l_rem = *natt_rem_ptr;
2771 2667  
2772 2668                  /* Instead of IPSA_COPY_ADDR(), just copy first 32 bits. */
2773 2669                  newbie->ipsa_natt_addr_rem = *natt_rem_ptr;
2774 2670  
2775 2671                  l_src = ntohl(l_src);
2776 2672                  DOWN_SUM(l_src);
2777 2673                  DOWN_SUM(l_src);
2778 2674                  l_rem = ntohl(l_rem);
2779 2675                  DOWN_SUM(l_rem);
2780 2676                  DOWN_SUM(l_rem);
2781 2677  
2782 2678                  /*
2783 2679                   * We're 1's complement for checksums, so check for wraparound
2784 2680                   * here.
2785 2681                   */
2786 2682                  if (l_rem > l_src)
2787 2683                          l_src--;
2788 2684  
2789 2685                  running_sum += l_src - l_rem;
2790 2686  
2791 2687                  DOWN_SUM(running_sum);
2792 2688                  DOWN_SUM(running_sum);
2793 2689          }
2794 2690  
2795 2691          if (natt_loc_ext != NULL) {
2796 2692                  natt_loc = (struct sockaddr_in *)(natt_loc_ext + 1);
2797 2693  
2798 2694                  /* Ensured by sadb_addrfix(). */
2799 2695                  ASSERT(natt_loc->sin_family == AF_INET);
2800 2696  
2801 2697                  natt_loc_ptr = (uint32_t *)(&natt_loc->sin_addr);
2802 2698                  newbie->ipsa_local_nat_port = natt_loc->sin_port;
2803 2699  
2804 2700                  /* Instead of IPSA_COPY_ADDR(), just copy first 32 bits. */
2805 2701                  newbie->ipsa_natt_addr_loc = *natt_loc_ptr;
2806 2702  
2807 2703                  /*
2808 2704                   * NAT-T port agility means we may have natt_loc_ext, but
2809 2705                   * only for a local-port change.
2810 2706                   */
2811 2707                  if (natt_loc->sin_addr.s_addr != INADDR_ANY) {
2812 2708                          uint32_t l_dst = ntohl(*dst_addr_ptr);
2813 2709                          uint32_t l_loc = ntohl(*natt_loc_ptr);
2814 2710  
2815 2711                          DOWN_SUM(l_loc);
2816 2712                          DOWN_SUM(l_loc);
2817 2713                          DOWN_SUM(l_dst);
2818 2714                          DOWN_SUM(l_dst);
2819 2715  
2820 2716                          /*
2821 2717                           * We're 1's complement for checksums, so check for
2822 2718                           * wraparound here.
2823 2719                           */
2824 2720                          if (l_loc > l_dst)
2825 2721                                  l_dst--;
2826 2722  
2827 2723                          running_sum += l_dst - l_loc;
2828 2724                          DOWN_SUM(running_sum);
2829 2725                          DOWN_SUM(running_sum);
2830 2726                  }
2831 2727          }
2832 2728  
2833 2729          newbie->ipsa_inbound_cksum = running_sum;
2834 2730  #undef DOWN_SUM
2835 2731  }
2836 2732  
2837 2733  /*
2838 2734   * This function is called from consumers that need to insert a fully-grown
2839 2735   * security association into its tables.  This function takes into account that
2840 2736   * SAs can be "inbound", "outbound", or "both".  The "primary" and "secondary"
2841 2737   * hash bucket parameters are set in order of what the SA will be most of the
2842 2738   * time.  (For example, an SA with an unspecified source, and a multicast
2843 2739   * destination will primarily be an outbound SA.  OTOH, if that destination
2844 2740   * is unicast for this node, then the SA will primarily be inbound.)
2845 2741   *
2846 2742   * It takes a lot of parameters because even if clone is B_FALSE, this needs
2847 2743   * to check both buckets for purposes of collision.
2848 2744   *
2849 2745   * Return 0 upon success.  Return various errnos (ENOMEM, EEXIST) for
2850 2746   * various error conditions.  We may need to set samsg->sadb_x_msg_diagnostic
2851 2747   * with additional diagnostic information because there is at least one EINVAL
2852 2748   * case here.
2853 2749   */
2854 2750  int
2855 2751  sadb_common_add(queue_t *pfkey_q, mblk_t *mp, sadb_msg_t *samsg,
2856 2752      keysock_in_t *ksi, isaf_t *primary, isaf_t *secondary,
2857 2753      ipsa_t *newbie, boolean_t clone, boolean_t is_inbound, int *diagnostic,
2858 2754      netstack_t *ns, sadbp_t *spp)
2859 2755  {
2860 2756          ipsa_t *newbie_clone = NULL, *scratch;
2861 2757          ipsap_t ipsapp;
2862 2758          sadb_sa_t *assoc = (sadb_sa_t *)ksi->ks_in_extv[SADB_EXT_SA];
2863 2759          sadb_address_t *srcext =
2864 2760              (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_SRC];
2865 2761          sadb_address_t *dstext =
2866 2762              (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_DST];
2867 2763          sadb_address_t *isrcext =
2868 2764              (sadb_address_t *)ksi->ks_in_extv[SADB_X_EXT_ADDRESS_INNER_SRC];
2869 2765          sadb_address_t *idstext =
2870 2766              (sadb_address_t *)ksi->ks_in_extv[SADB_X_EXT_ADDRESS_INNER_DST];
2871 2767          sadb_x_kmc_t *kmcext =
2872 2768              (sadb_x_kmc_t *)ksi->ks_in_extv[SADB_X_EXT_KM_COOKIE];
2873 2769          sadb_key_t *akey = (sadb_key_t *)ksi->ks_in_extv[SADB_EXT_KEY_AUTH];
2874 2770          sadb_key_t *ekey = (sadb_key_t *)ksi->ks_in_extv[SADB_EXT_KEY_ENCRYPT];
2875 2771          sadb_sens_t *sens =
2876 2772              (sadb_sens_t *)ksi->ks_in_extv[SADB_EXT_SENSITIVITY];
2877 2773          sadb_sens_t *osens =
2878 2774              (sadb_sens_t *)ksi->ks_in_extv[SADB_X_EXT_OUTER_SENS];
2879 2775          sadb_x_pair_t *pair_ext =
2880 2776              (sadb_x_pair_t *)ksi->ks_in_extv[SADB_X_EXT_PAIR];
2881 2777          sadb_x_replay_ctr_t *replayext =
2882 2778              (sadb_x_replay_ctr_t *)ksi->ks_in_extv[SADB_X_EXT_REPLAY_VALUE];
2883 2779          int salt_offset;
2884 2780          uint8_t *buf_ptr;
2885 2781          struct sockaddr_in *src, *dst, *isrc, *idst;
2886 2782          struct sockaddr_in6 *src6, *dst6, *isrc6, *idst6;
2887 2783          sadb_lifetime_t *soft =
2888 2784              (sadb_lifetime_t *)ksi->ks_in_extv[SADB_EXT_LIFETIME_SOFT];
2889 2785          sadb_lifetime_t *hard =
2890 2786              (sadb_lifetime_t *)ksi->ks_in_extv[SADB_EXT_LIFETIME_HARD];
2891 2787          sadb_lifetime_t *idle =
2892 2788              (sadb_lifetime_t *)ksi->ks_in_extv[SADB_X_EXT_LIFETIME_IDLE];
2893 2789          sa_family_t af;
2894 2790          int error = 0;
2895 2791          boolean_t isupdate = (newbie != NULL);
2896 2792          uint32_t *src_addr_ptr, *dst_addr_ptr, *isrc_addr_ptr, *idst_addr_ptr;
2897 2793          ipsec_stack_t   *ipss = ns->netstack_ipsec;
2898 2794          ip_stack_t      *ipst = ns->netstack_ip;
2899 2795          ipsec_alginfo_t *alg;
2900 2796          boolean_t       async = B_FALSE;
2901 2797  
2902 2798          init_ipsa_pair(&ipsapp);
2903 2799  
2904 2800          if (srcext == NULL) {
2905 2801                  *diagnostic = SADB_X_DIAGNOSTIC_MISSING_SRC;
2906 2802                  return (EINVAL);
2907 2803          }
2908 2804          if (dstext == NULL) {
2909 2805                  *diagnostic = SADB_X_DIAGNOSTIC_MISSING_DST;
2910 2806                  return (EINVAL);
2911 2807          }
2912 2808          if (assoc == NULL) {
2913 2809                  *diagnostic = SADB_X_DIAGNOSTIC_MISSING_SA;
2914 2810                  return (EINVAL);
2915 2811          }
2916 2812  
2917 2813          src = (struct sockaddr_in *)(srcext + 1);
2918 2814          src6 = (struct sockaddr_in6 *)(srcext + 1);
2919 2815          dst = (struct sockaddr_in *)(dstext + 1);
2920 2816          dst6 = (struct sockaddr_in6 *)(dstext + 1);
2921 2817          if (isrcext != NULL) {
2922 2818                  isrc = (struct sockaddr_in *)(isrcext + 1);
2923 2819                  isrc6 = (struct sockaddr_in6 *)(isrcext + 1);
2924 2820                  ASSERT(idstext != NULL);
2925 2821                  idst = (struct sockaddr_in *)(idstext + 1);
2926 2822                  idst6 = (struct sockaddr_in6 *)(idstext + 1);
2927 2823          } else {
2928 2824                  isrc = NULL;
2929 2825                  isrc6 = NULL;
2930 2826          }
2931 2827  
2932 2828          af = src->sin_family;
2933 2829  
2934 2830          if (af == AF_INET) {
2935 2831                  src_addr_ptr = (uint32_t *)&src->sin_addr;
2936 2832                  dst_addr_ptr = (uint32_t *)&dst->sin_addr;
2937 2833          } else {
2938 2834                  ASSERT(af == AF_INET6);
2939 2835                  src_addr_ptr = (uint32_t *)&src6->sin6_addr;
2940 2836                  dst_addr_ptr = (uint32_t *)&dst6->sin6_addr;
2941 2837          }
2942 2838  
2943 2839          /*
2944 2840           * Check to see if the new SA will be cloned AND paired. The
2945 2841           * reason a SA will be cloned is the source or destination addresses
2946 2842           * are not specific enough to determine if the SA goes in the outbound
2947 2843           * or the inbound hash table, so its cloned and put in both. If
2948 2844           * the SA is paired, it's soft linked to another SA for the other
2949 2845           * direction. Keeping track and looking up SA's that are direction
2950 2846           * unspecific and linked is too hard.
2951 2847           */
2952 2848          if (clone && (pair_ext != NULL)) {
2953 2849                  *diagnostic = SADB_X_DIAGNOSTIC_PAIR_INAPPROPRIATE;
2954 2850                  return (EINVAL);
2955 2851          }
2956 2852  
2957 2853          if (!isupdate) {
2958 2854                  newbie = sadb_makelarvalassoc(assoc->sadb_sa_spi,
2959 2855                      src_addr_ptr, dst_addr_ptr, af, ns);
2960 2856                  if (newbie == NULL)
2961 2857                          return (ENOMEM);
2962 2858          }
2963 2859  
2964 2860          mutex_enter(&newbie->ipsa_lock);
2965 2861  
2966 2862          if (isrc != NULL) {
2967 2863                  if (isrc->sin_family == AF_INET) {
2968 2864                          if (srcext->sadb_address_proto != IPPROTO_ENCAP) {
2969 2865                                  if (srcext->sadb_address_proto != 0) {
2970 2866                                          /*
2971 2867                                           * Mismatched outer-packet protocol
2972 2868                                           * and inner-packet address family.
2973 2869                                           */
2974 2870                                          mutex_exit(&newbie->ipsa_lock);
2975 2871                                          error = EPROTOTYPE;
2976 2872                                          *diagnostic =
2977 2873                                              SADB_X_DIAGNOSTIC_INNER_AF_MISMATCH;
2978 2874                                          goto error;
2979 2875                                  } else {
2980 2876                                          /* Fill in with explicit protocol. */
2981 2877                                          srcext->sadb_address_proto =
2982 2878                                              IPPROTO_ENCAP;
2983 2879                                          dstext->sadb_address_proto =
2984 2880                                              IPPROTO_ENCAP;
2985 2881                                  }
2986 2882                          }
2987 2883                          isrc_addr_ptr = (uint32_t *)&isrc->sin_addr;
2988 2884                          idst_addr_ptr = (uint32_t *)&idst->sin_addr;
2989 2885                  } else {
2990 2886                          ASSERT(isrc->sin_family == AF_INET6);
2991 2887                          if (srcext->sadb_address_proto != IPPROTO_IPV6) {
2992 2888                                  if (srcext->sadb_address_proto != 0) {
2993 2889                                          /*
2994 2890                                           * Mismatched outer-packet protocol
2995 2891                                           * and inner-packet address family.
2996 2892                                           */
2997 2893                                          mutex_exit(&newbie->ipsa_lock);
2998 2894                                          error = EPROTOTYPE;
2999 2895                                          *diagnostic =
3000 2896                                              SADB_X_DIAGNOSTIC_INNER_AF_MISMATCH;
3001 2897                                          goto error;
3002 2898                                  } else {
3003 2899                                          /* Fill in with explicit protocol. */
3004 2900                                          srcext->sadb_address_proto =
3005 2901                                              IPPROTO_IPV6;
3006 2902                                          dstext->sadb_address_proto =
3007 2903                                              IPPROTO_IPV6;
3008 2904                                  }
3009 2905                          }
3010 2906                          isrc_addr_ptr = (uint32_t *)&isrc6->sin6_addr;
3011 2907                          idst_addr_ptr = (uint32_t *)&idst6->sin6_addr;
3012 2908                  }
3013 2909                  newbie->ipsa_innerfam = isrc->sin_family;
3014 2910  
3015 2911                  IPSA_COPY_ADDR(newbie->ipsa_innersrc, isrc_addr_ptr,
3016 2912                      newbie->ipsa_innerfam);
3017 2913                  IPSA_COPY_ADDR(newbie->ipsa_innerdst, idst_addr_ptr,
3018 2914                      newbie->ipsa_innerfam);
3019 2915                  newbie->ipsa_innersrcpfx = isrcext->sadb_address_prefixlen;
3020 2916                  newbie->ipsa_innerdstpfx = idstext->sadb_address_prefixlen;
3021 2917  
3022 2918                  /* Unique value uses inner-ports for Tunnel Mode... */
3023 2919                  newbie->ipsa_unique_id = SA_UNIQUE_ID(isrc->sin_port,
3024 2920                      idst->sin_port, dstext->sadb_address_proto,
3025 2921                      idstext->sadb_address_proto);
3026 2922                  newbie->ipsa_unique_mask = SA_UNIQUE_MASK(isrc->sin_port,
3027 2923                      idst->sin_port, dstext->sadb_address_proto,
3028 2924                      idstext->sadb_address_proto);
3029 2925          } else {
3030 2926                  /* ... and outer-ports for Transport Mode. */
3031 2927                  newbie->ipsa_unique_id = SA_UNIQUE_ID(src->sin_port,
3032 2928                      dst->sin_port, dstext->sadb_address_proto, 0);
3033 2929                  newbie->ipsa_unique_mask = SA_UNIQUE_MASK(src->sin_port,
3034 2930                      dst->sin_port, dstext->sadb_address_proto, 0);
3035 2931          }
  
    | 
      ↓ open down ↓ | 
    502 lines elided | 
    
      ↑ open up ↑ | 
  
3036 2932          if (newbie->ipsa_unique_mask != (uint64_t)0)
3037 2933                  newbie->ipsa_flags |= IPSA_F_UNIQUE;
3038 2934  
3039 2935          sadb_nat_calculations(newbie,
3040 2936              (sadb_address_t *)ksi->ks_in_extv[SADB_X_EXT_ADDRESS_NATT_LOC],
3041 2937              (sadb_address_t *)ksi->ks_in_extv[SADB_X_EXT_ADDRESS_NATT_REM],
3042 2938              src_addr_ptr, dst_addr_ptr);
3043 2939  
3044 2940          newbie->ipsa_type = samsg->sadb_msg_satype;
3045 2941  
3046      -        ASSERT((assoc->sadb_sa_state == SADB_SASTATE_MATURE) ||
3047      -            (assoc->sadb_sa_state == SADB_X_SASTATE_ACTIVE_ELSEWHERE));
     2942 +        ASSERT(assoc->sadb_sa_state == SADB_SASTATE_MATURE);
3048 2943          newbie->ipsa_auth_alg = assoc->sadb_sa_auth;
3049 2944          newbie->ipsa_encr_alg = assoc->sadb_sa_encrypt;
3050 2945  
3051 2946          newbie->ipsa_flags |= assoc->sadb_sa_flags;
3052 2947          if (newbie->ipsa_flags & SADB_X_SAFLAGS_NATT_LOC &&
3053 2948              ksi->ks_in_extv[SADB_X_EXT_ADDRESS_NATT_LOC] == NULL) {
3054 2949                  mutex_exit(&newbie->ipsa_lock);
3055 2950                  *diagnostic = SADB_X_DIAGNOSTIC_MISSING_NATT_LOC;
3056 2951                  error = EINVAL;
3057 2952                  goto error;
3058 2953          }
3059 2954          if (newbie->ipsa_flags & SADB_X_SAFLAGS_NATT_REM &&
3060 2955              ksi->ks_in_extv[SADB_X_EXT_ADDRESS_NATT_REM] == NULL) {
3061 2956                  mutex_exit(&newbie->ipsa_lock);
3062 2957                  *diagnostic = SADB_X_DIAGNOSTIC_MISSING_NATT_REM;
3063 2958                  error = EINVAL;
3064 2959                  goto error;
3065 2960          }
3066 2961          if (newbie->ipsa_flags & SADB_X_SAFLAGS_TUNNEL &&
3067 2962              ksi->ks_in_extv[SADB_X_EXT_ADDRESS_INNER_SRC] == NULL) {
3068 2963                  mutex_exit(&newbie->ipsa_lock);
3069 2964                  *diagnostic = SADB_X_DIAGNOSTIC_MISSING_INNER_SRC;
3070 2965                  error = EINVAL;
3071 2966                  goto error;
3072 2967          }
3073 2968          /*
3074 2969           * If unspecified source address, force replay_wsize to 0.
3075 2970           * This is because an SA that has multiple sources of secure
3076 2971           * traffic cannot enforce a replay counter w/o synchronizing the
3077 2972           * senders.
3078 2973           */
3079 2974          if (ksi->ks_in_srctype != KS_IN_ADDR_UNSPEC)
3080 2975                  newbie->ipsa_replay_wsize = assoc->sadb_sa_replay;
3081 2976          else
3082 2977                  newbie->ipsa_replay_wsize = 0;
3083 2978  
3084 2979          newbie->ipsa_addtime = gethrestime_sec();
3085 2980  
3086 2981          if (kmcext != NULL) {
3087 2982                  newbie->ipsa_kmp = kmcext->sadb_x_kmc_proto;
3088 2983                  newbie->ipsa_kmc = kmcext->sadb_x_kmc_cookie;
3089 2984          }
3090 2985  
3091 2986          /*
3092 2987           * XXX CURRENT lifetime checks MAY BE needed for an UPDATE.
3093 2988           * The spec says that one can update current lifetimes, but
3094 2989           * that seems impractical, especially in the larval-to-mature
3095 2990           * update that this function performs.
3096 2991           */
3097 2992          if (soft != NULL) {
3098 2993                  newbie->ipsa_softaddlt = soft->sadb_lifetime_addtime;
3099 2994                  newbie->ipsa_softuselt = soft->sadb_lifetime_usetime;
3100 2995                  newbie->ipsa_softbyteslt = soft->sadb_lifetime_bytes;
3101 2996                  newbie->ipsa_softalloc = soft->sadb_lifetime_allocations;
3102 2997                  SET_EXPIRE(newbie, softaddlt, softexpiretime);
3103 2998          }
3104 2999          if (hard != NULL) {
3105 3000                  newbie->ipsa_hardaddlt = hard->sadb_lifetime_addtime;
3106 3001                  newbie->ipsa_harduselt = hard->sadb_lifetime_usetime;
3107 3002                  newbie->ipsa_hardbyteslt = hard->sadb_lifetime_bytes;
3108 3003                  newbie->ipsa_hardalloc = hard->sadb_lifetime_allocations;
3109 3004                  SET_EXPIRE(newbie, hardaddlt, hardexpiretime);
3110 3005          }
3111 3006          if (idle != NULL) {
3112 3007                  newbie->ipsa_idleaddlt = idle->sadb_lifetime_addtime;
3113 3008                  newbie->ipsa_idleuselt = idle->sadb_lifetime_usetime;
3114 3009                  newbie->ipsa_idleexpiretime = newbie->ipsa_addtime +
3115 3010                      newbie->ipsa_idleaddlt;
3116 3011                  newbie->ipsa_idletime = newbie->ipsa_idleaddlt;
3117 3012          }
3118 3013  
3119 3014          newbie->ipsa_authtmpl = NULL;
3120 3015          newbie->ipsa_encrtmpl = NULL;
3121 3016  
3122 3017  #ifdef IPSEC_LATENCY_TEST
3123 3018          if (akey != NULL && newbie->ipsa_auth_alg != SADB_AALG_NONE) {
3124 3019  #else
3125 3020          if (akey != NULL) {
3126 3021  #endif
3127 3022                  async = (ipss->ipsec_algs_exec_mode[IPSEC_ALG_AUTH] ==
3128 3023                      IPSEC_ALGS_EXEC_ASYNC);
3129 3024  
3130 3025                  newbie->ipsa_authkeybits = akey->sadb_key_bits;
3131 3026                  newbie->ipsa_authkeylen = SADB_1TO8(akey->sadb_key_bits);
3132 3027                  /* In case we have to round up to the next byte... */
3133 3028                  if ((akey->sadb_key_bits & 0x7) != 0)
3134 3029                          newbie->ipsa_authkeylen++;
3135 3030                  newbie->ipsa_authkey = kmem_alloc(newbie->ipsa_authkeylen,
3136 3031                      KM_NOSLEEP);
3137 3032                  if (newbie->ipsa_authkey == NULL) {
3138 3033                          error = ENOMEM;
3139 3034                          mutex_exit(&newbie->ipsa_lock);
3140 3035                          goto error;
3141 3036                  }
3142 3037                  bcopy(akey + 1, newbie->ipsa_authkey, newbie->ipsa_authkeylen);
3143 3038                  bzero(akey + 1, newbie->ipsa_authkeylen);
3144 3039  
3145 3040                  /*
3146 3041                   * Pre-initialize the kernel crypto framework key
3147 3042                   * structure.
3148 3043                   */
3149 3044                  newbie->ipsa_kcfauthkey.ck_format = CRYPTO_KEY_RAW;
3150 3045                  newbie->ipsa_kcfauthkey.ck_length = newbie->ipsa_authkeybits;
3151 3046                  newbie->ipsa_kcfauthkey.ck_data = newbie->ipsa_authkey;
3152 3047  
3153 3048                  mutex_enter(&ipss->ipsec_alg_lock);
3154 3049                  alg = ipss->ipsec_alglists[IPSEC_ALG_AUTH]
3155 3050                      [newbie->ipsa_auth_alg];
3156 3051                  if (alg != NULL && ALG_VALID(alg)) {
3157 3052                          newbie->ipsa_amech.cm_type = alg->alg_mech_type;
3158 3053                          newbie->ipsa_amech.cm_param =
3159 3054                              (char *)&newbie->ipsa_mac_len;
3160 3055                          newbie->ipsa_amech.cm_param_len = sizeof (size_t);
3161 3056                          newbie->ipsa_mac_len = (size_t)alg->alg_datalen;
3162 3057                  } else {
3163 3058                          newbie->ipsa_amech.cm_type = CRYPTO_MECHANISM_INVALID;
3164 3059                  }
3165 3060                  error = ipsec_create_ctx_tmpl(newbie, IPSEC_ALG_AUTH);
3166 3061                  mutex_exit(&ipss->ipsec_alg_lock);
3167 3062                  if (error != 0) {
3168 3063                          mutex_exit(&newbie->ipsa_lock);
3169 3064                          /*
3170 3065                           * An error here indicates that alg is the wrong type
3171 3066                           * (IE: not authentication) or its not in the alg tables
3172 3067                           * created by ipsecalgs(1m), or Kcf does not like the
3173 3068                           * parameters passed in with this algorithm, which is
3174 3069                           * probably a coding error!
3175 3070                           */
3176 3071                          *diagnostic = SADB_X_DIAGNOSTIC_BAD_CTX;
3177 3072  
3178 3073                          goto error;
3179 3074                  }
3180 3075          }
3181 3076  
3182 3077          if (ekey != NULL) {
3183 3078                  mutex_enter(&ipss->ipsec_alg_lock);
3184 3079                  async = async || (ipss->ipsec_algs_exec_mode[IPSEC_ALG_ENCR] ==
3185 3080                      IPSEC_ALGS_EXEC_ASYNC);
3186 3081                  alg = ipss->ipsec_alglists[IPSEC_ALG_ENCR]
3187 3082                      [newbie->ipsa_encr_alg];
3188 3083  
3189 3084                  if (alg != NULL && ALG_VALID(alg)) {
3190 3085                          newbie->ipsa_emech.cm_type = alg->alg_mech_type;
3191 3086                          newbie->ipsa_datalen = alg->alg_datalen;
3192 3087                          if (alg->alg_flags & ALG_FLAG_COUNTERMODE)
3193 3088                                  newbie->ipsa_flags |= IPSA_F_COUNTERMODE;
3194 3089  
3195 3090                          if (alg->alg_flags & ALG_FLAG_COMBINED) {
3196 3091                                  newbie->ipsa_flags |= IPSA_F_COMBINED;
3197 3092                                  newbie->ipsa_mac_len =  alg->alg_icvlen;
3198 3093                          }
3199 3094  
3200 3095                          if (alg->alg_flags & ALG_FLAG_CCM)
3201 3096                                  newbie->ipsa_noncefunc = ccm_params_init;
3202 3097                          else if (alg->alg_flags & ALG_FLAG_GCM)
3203 3098                                  newbie->ipsa_noncefunc = gcm_params_init;
3204 3099                          else newbie->ipsa_noncefunc = cbc_params_init;
3205 3100  
3206 3101                          newbie->ipsa_saltlen = alg->alg_saltlen;
3207 3102                          newbie->ipsa_saltbits = SADB_8TO1(newbie->ipsa_saltlen);
3208 3103                          newbie->ipsa_iv_len = alg->alg_ivlen;
3209 3104                          newbie->ipsa_nonce_len = newbie->ipsa_saltlen +
3210 3105                              newbie->ipsa_iv_len;
3211 3106                          newbie->ipsa_emech.cm_param = NULL;
3212 3107                          newbie->ipsa_emech.cm_param_len = 0;
3213 3108                  } else {
3214 3109                          newbie->ipsa_emech.cm_type = CRYPTO_MECHANISM_INVALID;
3215 3110                  }
3216 3111                  mutex_exit(&ipss->ipsec_alg_lock);
3217 3112  
3218 3113                  /*
3219 3114                   * The byte stream following the sadb_key_t is made up of:
3220 3115                   * key bytes, [salt bytes], [IV initial value]
3221 3116                   * All of these have variable length. The IV is typically
3222 3117                   * randomly generated by this function and not passed in.
3223 3118                   * By supporting the injection of a known IV, the whole
3224 3119                   * IPsec subsystem and the underlying crypto subsystem
3225 3120                   * can be tested with known test vectors.
3226 3121                   *
3227 3122                   * The keying material has been checked by ext_check()
3228 3123                   * and ipsec_valid_key_size(), after removing salt/IV
3229 3124                   * bits, whats left is the encryption key. If this is too
3230 3125                   * short, ipsec_create_ctx_tmpl() will fail and the SA
3231 3126                   * won't get created.
3232 3127                   *
3233 3128                   * set ipsa_encrkeylen to length of key only.
3234 3129                   */
3235 3130                  newbie->ipsa_encrkeybits = ekey->sadb_key_bits;
3236 3131                  newbie->ipsa_encrkeybits -= ekey->sadb_key_reserved;
3237 3132                  newbie->ipsa_encrkeybits -= newbie->ipsa_saltbits;
3238 3133                  newbie->ipsa_encrkeylen = SADB_1TO8(newbie->ipsa_encrkeybits);
3239 3134  
3240 3135                  /* In case we have to round up to the next byte... */
3241 3136                  if ((ekey->sadb_key_bits & 0x7) != 0)
3242 3137                          newbie->ipsa_encrkeylen++;
3243 3138  
3244 3139                  newbie->ipsa_encrkey = kmem_alloc(newbie->ipsa_encrkeylen,
3245 3140                      KM_NOSLEEP);
3246 3141                  if (newbie->ipsa_encrkey == NULL) {
3247 3142                          error = ENOMEM;
3248 3143                          mutex_exit(&newbie->ipsa_lock);
3249 3144                          goto error;
3250 3145                  }
3251 3146  
3252 3147                  buf_ptr = (uint8_t *)(ekey + 1);
3253 3148                  bcopy(buf_ptr, newbie->ipsa_encrkey, newbie->ipsa_encrkeylen);
3254 3149  
3255 3150                  if (newbie->ipsa_flags & IPSA_F_COMBINED) {
3256 3151                          /*
3257 3152                           * Combined mode algs need a nonce. Copy the salt and
3258 3153                           * IV into a buffer. The ipsa_nonce is a pointer into
3259 3154                           * this buffer, some bytes at the start of the buffer
3260 3155                           * may be unused, depends on the salt length. The IV
3261 3156                           * is 64 bit aligned so it can be incremented as a
3262 3157                           * uint64_t. Zero out key in samsg_t before freeing.
3263 3158                           */
3264 3159  
3265 3160                          newbie->ipsa_nonce_buf = kmem_alloc(
3266 3161                              sizeof (ipsec_nonce_t), KM_NOSLEEP);
3267 3162                          if (newbie->ipsa_nonce_buf == NULL) {
3268 3163                                  error = ENOMEM;
3269 3164                                  mutex_exit(&newbie->ipsa_lock);
3270 3165                                  goto error;
3271 3166                          }
3272 3167                          /*
3273 3168                           * Initialize nonce and salt pointers to point
3274 3169                           * to the nonce buffer. This is just in case we get
3275 3170                           * bad data, the pointers will be valid, the data
3276 3171                           * won't be.
3277 3172                           *
3278 3173                           * See sadb.h for layout of nonce.
3279 3174                           */
3280 3175                          newbie->ipsa_iv = &newbie->ipsa_nonce_buf->iv;
3281 3176                          newbie->ipsa_salt = (uint8_t *)newbie->ipsa_nonce_buf;
3282 3177                          newbie->ipsa_nonce = newbie->ipsa_salt;
3283 3178                          if (newbie->ipsa_saltlen != 0) {
3284 3179                                  salt_offset = MAXSALTSIZE -
3285 3180                                      newbie->ipsa_saltlen;
3286 3181                                  newbie->ipsa_salt = (uint8_t *)
3287 3182                                      &newbie->ipsa_nonce_buf->salt[salt_offset];
3288 3183                                  newbie->ipsa_nonce = newbie->ipsa_salt;
3289 3184                                  buf_ptr += newbie->ipsa_encrkeylen;
3290 3185                                  bcopy(buf_ptr, newbie->ipsa_salt,
3291 3186                                      newbie->ipsa_saltlen);
3292 3187                          }
3293 3188                          /*
3294 3189                           * The IV for CCM/GCM mode increments, it should not
3295 3190                           * repeat. Get a random value for the IV, make a
3296 3191                           * copy, the SA will expire when/if the IV ever
3297 3192                           * wraps back to the initial value. If an Initial IV
3298 3193                           * is passed in via PF_KEY, save this in the SA.
3299 3194                           * Initialising IV for inbound is pointless as its
3300 3195                           * taken from the inbound packet.
3301 3196                           */
3302 3197                          if (!is_inbound) {
3303 3198                                  if (ekey->sadb_key_reserved != 0) {
3304 3199                                          buf_ptr += newbie->ipsa_saltlen;
3305 3200                                          bcopy(buf_ptr, (uint8_t *)newbie->
3306 3201                                              ipsa_iv, SADB_1TO8(ekey->
3307 3202                                              sadb_key_reserved));
3308 3203                                  } else {
3309 3204                                          (void) random_get_pseudo_bytes(
3310 3205                                              (uint8_t *)newbie->ipsa_iv,
3311 3206                                              newbie->ipsa_iv_len);
3312 3207                                  }
3313 3208                                  newbie->ipsa_iv_softexpire =
3314 3209                                      (*newbie->ipsa_iv) << 9;
3315 3210                                  newbie->ipsa_iv_hardexpire = *newbie->ipsa_iv;
3316 3211                          }
3317 3212                  }
3318 3213                  bzero((ekey + 1), SADB_1TO8(ekey->sadb_key_bits));
3319 3214  
3320 3215                  /*
3321 3216                   * Pre-initialize the kernel crypto framework key
3322 3217                   * structure.
3323 3218                   */
3324 3219                  newbie->ipsa_kcfencrkey.ck_format = CRYPTO_KEY_RAW;
3325 3220                  newbie->ipsa_kcfencrkey.ck_length = newbie->ipsa_encrkeybits;
3326 3221                  newbie->ipsa_kcfencrkey.ck_data = newbie->ipsa_encrkey;
3327 3222  
3328 3223                  mutex_enter(&ipss->ipsec_alg_lock);
3329 3224                  error = ipsec_create_ctx_tmpl(newbie, IPSEC_ALG_ENCR);
3330 3225                  mutex_exit(&ipss->ipsec_alg_lock);
3331 3226                  if (error != 0) {
3332 3227                          mutex_exit(&newbie->ipsa_lock);
3333 3228                          /* See above for error explanation. */
3334 3229                          *diagnostic = SADB_X_DIAGNOSTIC_BAD_CTX;
3335 3230                          goto error;
3336 3231                  }
3337 3232          }
3338 3233  
3339 3234          if (async)
3340 3235                  newbie->ipsa_flags |= IPSA_F_ASYNC;
3341 3236  
3342 3237          /*
3343 3238           * Ptrs to processing functions.
3344 3239           */
3345 3240          if (newbie->ipsa_type == SADB_SATYPE_ESP)
3346 3241                  ipsecesp_init_funcs(newbie);
3347 3242          else
3348 3243                  ipsecah_init_funcs(newbie);
3349 3244          ASSERT(newbie->ipsa_output_func != NULL &&
3350 3245              newbie->ipsa_input_func != NULL);
3351 3246  
3352 3247          /*
3353 3248           * Certificate ID stuff.
3354 3249           */
3355 3250          if (ksi->ks_in_extv[SADB_EXT_IDENTITY_SRC] != NULL) {
3356 3251                  sadb_ident_t *id =
3357 3252                      (sadb_ident_t *)ksi->ks_in_extv[SADB_EXT_IDENTITY_SRC];
3358 3253  
3359 3254                  /*
3360 3255                   * Can assume strlen() will return okay because ext_check() in
3361 3256                   * keysock.c prepares the string for us.
3362 3257                   */
3363 3258                  newbie->ipsa_src_cid = ipsid_lookup(id->sadb_ident_type,
3364 3259                      (char *)(id+1), ns);
3365 3260                  if (newbie->ipsa_src_cid == NULL) {
3366 3261                          error = ENOMEM;
3367 3262                          mutex_exit(&newbie->ipsa_lock);
3368 3263                          goto error;
3369 3264                  }
3370 3265          }
3371 3266  
3372 3267          if (ksi->ks_in_extv[SADB_EXT_IDENTITY_DST] != NULL) {
3373 3268                  sadb_ident_t *id =
3374 3269                      (sadb_ident_t *)ksi->ks_in_extv[SADB_EXT_IDENTITY_DST];
3375 3270  
3376 3271                  /*
3377 3272                   * Can assume strlen() will return okay because ext_check() in
3378 3273                   * keysock.c prepares the string for us.
3379 3274                   */
3380 3275                  newbie->ipsa_dst_cid = ipsid_lookup(id->sadb_ident_type,
3381 3276                      (char *)(id+1), ns);
3382 3277                  if (newbie->ipsa_dst_cid == NULL) {
3383 3278                          error = ENOMEM;
3384 3279                          mutex_exit(&newbie->ipsa_lock);
3385 3280                          goto error;
3386 3281                  }
3387 3282          }
3388 3283  
3389 3284          /*
3390 3285           * sensitivity label handling code:
3391 3286           * Convert sens + bitmap into cred_t, and associate it
3392 3287           * with the new SA.
3393 3288           */
3394 3289          if (sens != NULL) {
3395 3290                  uint64_t *bitmap = (uint64_t *)(sens + 1);
3396 3291  
3397 3292                  newbie->ipsa_tsl = sadb_label_from_sens(sens, bitmap);
3398 3293          }
3399 3294  
3400 3295          /*
3401 3296           * Likewise for outer sensitivity.
3402 3297           */
3403 3298          if (osens != NULL) {
3404 3299                  uint64_t *bitmap = (uint64_t *)(osens + 1);
3405 3300                  ts_label_t *tsl, *effective_tsl;
3406 3301                  uint32_t *peer_addr_ptr;
3407 3302                  zoneid_t zoneid = GLOBAL_ZONEID;
3408 3303                  zone_t *zone;
3409 3304  
3410 3305                  peer_addr_ptr = is_inbound ? src_addr_ptr : dst_addr_ptr;
3411 3306  
3412 3307                  tsl = sadb_label_from_sens(osens, bitmap);
3413 3308                  newbie->ipsa_mac_exempt = CONN_MAC_DEFAULT;
3414 3309  
3415 3310                  if (osens->sadb_x_sens_flags & SADB_X_SENS_IMPLICIT) {
3416 3311                          newbie->ipsa_mac_exempt = CONN_MAC_IMPLICIT;
3417 3312                  }
3418 3313  
3419 3314                  error = tsol_check_dest(tsl, peer_addr_ptr,
3420 3315                      (af == AF_INET6)?IPV6_VERSION:IPV4_VERSION,
3421 3316                      newbie->ipsa_mac_exempt, B_TRUE, &effective_tsl);
3422 3317                  if (error != 0) {
3423 3318                          label_rele(tsl);
3424 3319                          mutex_exit(&newbie->ipsa_lock);
3425 3320                          goto error;
3426 3321                  }
3427 3322  
3428 3323                  if (effective_tsl != NULL) {
3429 3324                          label_rele(tsl);
3430 3325                          tsl = effective_tsl;
3431 3326                  }
3432 3327  
3433 3328                  newbie->ipsa_otsl = tsl;
3434 3329  
3435 3330                  zone = zone_find_by_label(tsl);
3436 3331                  if (zone != NULL) {
3437 3332                          zoneid = zone->zone_id;
3438 3333                          zone_rele(zone);
3439 3334                  }
3440 3335                  /*
3441 3336                   * For exclusive stacks we set the zoneid to zero to operate
3442 3337                   * as if in the global zone for tsol_compute_label_v4/v6
3443 3338                   */
3444 3339                  if (ipst->ips_netstack->netstack_stackid != GLOBAL_NETSTACKID)
3445 3340                          zoneid = GLOBAL_ZONEID;
3446 3341  
3447 3342                  if (af == AF_INET6) {
3448 3343                          error = tsol_compute_label_v6(tsl, zoneid,
3449 3344                              (in6_addr_t *)peer_addr_ptr,
3450 3345                              newbie->ipsa_opt_storage, ipst);
3451 3346                  } else {
3452 3347                          error = tsol_compute_label_v4(tsl, zoneid,
3453 3348                              *peer_addr_ptr, newbie->ipsa_opt_storage, ipst);
3454 3349                  }
3455 3350                  if (error != 0) {
3456 3351                          mutex_exit(&newbie->ipsa_lock);
3457 3352                          goto error;
3458 3353                  }
3459 3354          }
3460 3355  
3461 3356  
3462 3357          if (replayext != NULL) {
3463 3358                  if ((replayext->sadb_x_rc_replay32 == 0) &&
3464 3359                      (replayext->sadb_x_rc_replay64 != 0)) {
3465 3360                          error = EOPNOTSUPP;
3466 3361                          *diagnostic = SADB_X_DIAGNOSTIC_INVALID_REPLAY;
3467 3362                          mutex_exit(&newbie->ipsa_lock);
3468 3363                          goto error;
3469 3364                  }
3470 3365                  newbie->ipsa_replay = replayext->sadb_x_rc_replay32;
3471 3366          }
3472 3367  
3473 3368          /* now that the SA has been updated, set its new state */
3474 3369          newbie->ipsa_state = assoc->sadb_sa_state;
3475 3370  
3476 3371          if (clone) {
3477 3372                  newbie->ipsa_haspeer = B_TRUE;
3478 3373          } else {
3479 3374                  if (!is_inbound) {
3480 3375                          lifetime_fuzz(newbie);
3481 3376                  }
3482 3377          }
3483 3378          /*
3484 3379           * The less locks I hold when doing an insertion and possible cloning,
3485 3380           * the better!
3486 3381           */
3487 3382          mutex_exit(&newbie->ipsa_lock);
3488 3383  
3489 3384          if (clone) {
3490 3385                  newbie_clone = sadb_cloneassoc(newbie);
3491 3386  
3492 3387                  if (newbie_clone == NULL) {
3493 3388                          error = ENOMEM;
3494 3389                          goto error;
3495 3390                  }
3496 3391          }
3497 3392  
3498 3393          /*
3499 3394           * Enter the bucket locks.  The order of entry is outbound,
3500 3395           * inbound.  We map "primary" and "secondary" into outbound and inbound
3501 3396           * based on the destination address type.  If the destination address
3502 3397           * type is for a node that isn't mine (or potentially mine), the
3503 3398           * "primary" bucket is the outbound one.
3504 3399           */
3505 3400          if (!is_inbound) {
3506 3401                  /* primary == outbound */
3507 3402                  mutex_enter(&primary->isaf_lock);
3508 3403                  mutex_enter(&secondary->isaf_lock);
3509 3404          } else {
3510 3405                  /* primary == inbound */
3511 3406                  mutex_enter(&secondary->isaf_lock);
3512 3407                  mutex_enter(&primary->isaf_lock);
3513 3408          }
3514 3409  
3515 3410          /*
3516 3411           * sadb_insertassoc() doesn't increment the reference
3517 3412           * count.  We therefore have to increment the
3518 3413           * reference count one more time to reflect the
3519 3414           * pointers of the table that reference this SA.
3520 3415           */
3521 3416          IPSA_REFHOLD(newbie);
3522 3417  
3523 3418          if (isupdate) {
3524 3419                  /*
3525 3420                   * Unlink from larval holding cell in the "inbound" fanout.
3526 3421                   */
3527 3422                  ASSERT(newbie->ipsa_linklock == &primary->isaf_lock ||
3528 3423                      newbie->ipsa_linklock == &secondary->isaf_lock);
3529 3424                  sadb_unlinkassoc(newbie);
3530 3425          }
3531 3426  
3532 3427          mutex_enter(&newbie->ipsa_lock);
3533 3428          error = sadb_insertassoc(newbie, primary);
3534 3429          mutex_exit(&newbie->ipsa_lock);
3535 3430  
3536 3431          if (error != 0) {
3537 3432                  /*
3538 3433                   * Since sadb_insertassoc() failed, we must decrement the
3539 3434                   * refcount again so the cleanup code will actually free
3540 3435                   * the offending SA.
3541 3436                   */
3542 3437                  IPSA_REFRELE(newbie);
3543 3438                  goto error_unlock;
3544 3439          }
3545 3440  
3546 3441          if (newbie_clone != NULL) {
3547 3442                  mutex_enter(&newbie_clone->ipsa_lock);
3548 3443                  error = sadb_insertassoc(newbie_clone, secondary);
3549 3444                  mutex_exit(&newbie_clone->ipsa_lock);
3550 3445                  if (error != 0) {
3551 3446                          /* Collision in secondary table. */
3552 3447                          sadb_unlinkassoc(newbie);  /* This does REFRELE. */
3553 3448                          goto error_unlock;
3554 3449                  }
3555 3450                  IPSA_REFHOLD(newbie_clone);
3556 3451          } else {
3557 3452                  ASSERT(primary != secondary);
3558 3453                  scratch = ipsec_getassocbyspi(secondary, newbie->ipsa_spi,
3559 3454                      ALL_ZEROES_PTR, newbie->ipsa_dstaddr, af);
3560 3455                  if (scratch != NULL) {
3561 3456                          /* Collision in secondary table. */
3562 3457                          sadb_unlinkassoc(newbie);  /* This does REFRELE. */
3563 3458                          /* Set the error, since ipsec_getassocbyspi() can't. */
3564 3459                          error = EEXIST;
3565 3460                          goto error_unlock;
3566 3461                  }
3567 3462          }
3568 3463  
3569 3464          /* OKAY!  So let's do some reality check assertions. */
3570 3465  
3571 3466          ASSERT(MUTEX_NOT_HELD(&newbie->ipsa_lock));
3572 3467          ASSERT(newbie_clone == NULL ||
3573 3468              (MUTEX_NOT_HELD(&newbie_clone->ipsa_lock)));
3574 3469  
3575 3470  error_unlock:
3576 3471  
3577 3472          /*
3578 3473           * We can exit the locks in any order.  Only entrance needs to
3579 3474           * follow any protocol.
3580 3475           */
3581 3476          mutex_exit(&secondary->isaf_lock);
3582 3477          mutex_exit(&primary->isaf_lock);
3583 3478  
3584 3479          if (pair_ext != NULL && error == 0) {
3585 3480                  /* update pair_spi if it exists. */
3586 3481                  ipsa_query_t sq;
3587 3482  
3588 3483                  sq.spp = spp;           /* XXX param */
3589 3484                  error = sadb_form_query(ksi, IPSA_Q_DST, IPSA_Q_SRC|IPSA_Q_DST|
3590 3485                      IPSA_Q_SA|IPSA_Q_INBOUND|IPSA_Q_OUTBOUND, &sq, diagnostic);
3591 3486                  if (error)
3592 3487                          return (error);
3593 3488  
3594 3489                  error = get_ipsa_pair(&sq, &ipsapp, diagnostic);
3595 3490  
3596 3491                  if (error != 0)
3597 3492                          goto error;
3598 3493  
3599 3494                  if (ipsapp.ipsap_psa_ptr != NULL) {
3600 3495                          *diagnostic = SADB_X_DIAGNOSTIC_PAIR_ALREADY;
3601 3496                          error = EINVAL;
3602 3497                  } else {
3603 3498                          /* update_pairing() sets diagnostic */
3604 3499                          error = update_pairing(&ipsapp, &sq, ksi, diagnostic);
3605 3500                  }
3606 3501          }
3607 3502          /* Common error point for this routine. */
3608 3503  error:
3609 3504          if (newbie != NULL) {
3610 3505                  if (error != 0) {
3611 3506                          /* This SA is broken, let the reaper clean up. */
3612 3507                          mutex_enter(&newbie->ipsa_lock);
3613 3508                          newbie->ipsa_state = IPSA_STATE_DEAD;
3614 3509                          newbie->ipsa_hardexpiretime = 1;
3615 3510                          mutex_exit(&newbie->ipsa_lock);
3616 3511                  }
3617 3512                  IPSA_REFRELE(newbie);
3618 3513          }
3619 3514          if (newbie_clone != NULL) {
3620 3515                  IPSA_REFRELE(newbie_clone);
3621 3516          }
3622 3517  
3623 3518          if (error == 0) {
3624 3519                  /*
3625 3520                   * Construct favorable PF_KEY return message and send to
3626 3521                   * keysock. Update the flags in the original keysock message
3627 3522                   * to reflect the actual flags in the new SA.
3628 3523                   *  (Q:  Do I need to pass "newbie"?  If I do,
3629 3524                   * make sure to REFHOLD, call, then REFRELE.)
3630 3525                   */
3631 3526                  assoc->sadb_sa_flags = newbie->ipsa_flags;
3632 3527                  sadb_pfkey_echo(pfkey_q, mp, samsg, ksi, NULL);
3633 3528          }
3634 3529  
3635 3530          destroy_ipsa_pair(&ipsapp);
3636 3531          return (error);
3637 3532  }
3638 3533  
3639 3534  /*
3640 3535   * Set the time of first use for a security association.  Update any
3641 3536   * expiration times as a result.
3642 3537   */
3643 3538  void
3644 3539  sadb_set_usetime(ipsa_t *assoc)
3645 3540  {
3646 3541          time_t snapshot = gethrestime_sec();
3647 3542  
3648 3543          mutex_enter(&assoc->ipsa_lock);
3649 3544          assoc->ipsa_lastuse = snapshot;
3650 3545          assoc->ipsa_idleexpiretime = snapshot + assoc->ipsa_idletime;
3651 3546  
3652 3547          /*
3653 3548           * Caller does check usetime before calling me usually, and
3654 3549           * double-checking is better than a mutex_enter/exit hit.
3655 3550           */
3656 3551          if (assoc->ipsa_usetime == 0) {
3657 3552                  /*
3658 3553                   * This is redundant for outbound SA's, as
3659 3554                   * ipsec_getassocbyconn() sets the IPSA_F_USED flag already.
3660 3555                   * Inbound SAs, however, have no such protection.
3661 3556                   */
3662 3557                  assoc->ipsa_flags |= IPSA_F_USED;
3663 3558                  assoc->ipsa_usetime = snapshot;
3664 3559  
3665 3560                  /*
3666 3561                   * After setting the use time, see if we have a use lifetime
3667 3562                   * that would cause the actual SA expiration time to shorten.
3668 3563                   */
3669 3564                  UPDATE_EXPIRE(assoc, softuselt, softexpiretime);
3670 3565                  UPDATE_EXPIRE(assoc, harduselt, hardexpiretime);
3671 3566          }
3672 3567          mutex_exit(&assoc->ipsa_lock);
3673 3568  }
3674 3569  
3675 3570  /*
3676 3571   * Send up a PF_KEY expire message for this association.
3677 3572   */
3678 3573  static void
3679 3574  sadb_expire_assoc(queue_t *pfkey_q, ipsa_t *assoc)
3680 3575  {
3681 3576          mblk_t *mp, *mp1;
3682 3577          int alloclen, af;
3683 3578          sadb_msg_t *samsg;
3684 3579          sadb_lifetime_t *current, *expire;
3685 3580          sadb_sa_t *saext;
3686 3581          uint8_t *end;
3687 3582          boolean_t tunnel_mode;
3688 3583  
3689 3584          ASSERT(MUTEX_HELD(&assoc->ipsa_lock));
3690 3585  
3691 3586          /* Don't bother sending if there's no queue. */
3692 3587          if (pfkey_q == NULL)
3693 3588                  return;
3694 3589  
3695 3590          mp = sadb_keysock_out(0);
3696 3591          if (mp == NULL) {
3697 3592                  /* cmn_err(CE_WARN, */
3698 3593                  /*      "sadb_expire_assoc: Can't allocate KEYSOCK_OUT.\n"); */
3699 3594                  return;
3700 3595          }
3701 3596  
3702 3597          alloclen = sizeof (*samsg) + sizeof (*current) + sizeof (*expire) +
3703 3598              2 * sizeof (sadb_address_t) + sizeof (*saext);
3704 3599  
3705 3600          af = assoc->ipsa_addrfam;
3706 3601          switch (af) {
3707 3602          case AF_INET:
3708 3603                  alloclen += 2 * sizeof (struct sockaddr_in);
3709 3604                  break;
3710 3605          case AF_INET6:
3711 3606                  alloclen += 2 * sizeof (struct sockaddr_in6);
3712 3607                  break;
3713 3608          default:
3714 3609                  /* Won't happen unless there's a kernel bug. */
3715 3610                  freeb(mp);
3716 3611                  cmn_err(CE_WARN,
3717 3612                      "sadb_expire_assoc: Unknown address length.\n");
3718 3613                  return;
3719 3614          }
3720 3615  
3721 3616          tunnel_mode = (assoc->ipsa_flags & IPSA_F_TUNNEL);
3722 3617          if (tunnel_mode) {
3723 3618                  alloclen += 2 * sizeof (sadb_address_t);
3724 3619                  switch (assoc->ipsa_innerfam) {
3725 3620                  case AF_INET:
3726 3621                          alloclen += 2 * sizeof (struct sockaddr_in);
3727 3622                          break;
3728 3623                  case AF_INET6:
3729 3624                          alloclen += 2 * sizeof (struct sockaddr_in6);
3730 3625                          break;
3731 3626                  default:
3732 3627                          /* Won't happen unless there's a kernel bug. */
3733 3628                          freeb(mp);
3734 3629                          cmn_err(CE_WARN, "sadb_expire_assoc: "
3735 3630                              "Unknown inner address length.\n");
3736 3631                          return;
3737 3632                  }
3738 3633          }
3739 3634  
3740 3635          mp->b_cont = allocb(alloclen, BPRI_HI);
3741 3636          if (mp->b_cont == NULL) {
3742 3637                  freeb(mp);
3743 3638                  /* cmn_err(CE_WARN, */
3744 3639                  /*      "sadb_expire_assoc: Can't allocate message.\n"); */
3745 3640                  return;
3746 3641          }
3747 3642  
3748 3643          mp1 = mp;
3749 3644          mp = mp->b_cont;
3750 3645          end = mp->b_wptr + alloclen;
3751 3646  
3752 3647          samsg = (sadb_msg_t *)mp->b_wptr;
3753 3648          mp->b_wptr += sizeof (*samsg);
3754 3649          samsg->sadb_msg_version = PF_KEY_V2;
3755 3650          samsg->sadb_msg_type = SADB_EXPIRE;
3756 3651          samsg->sadb_msg_errno = 0;
3757 3652          samsg->sadb_msg_satype = assoc->ipsa_type;
3758 3653          samsg->sadb_msg_len = SADB_8TO64(alloclen);
3759 3654          samsg->sadb_msg_reserved = 0;
3760 3655          samsg->sadb_msg_seq = 0;
3761 3656          samsg->sadb_msg_pid = 0;
3762 3657  
3763 3658          saext = (sadb_sa_t *)mp->b_wptr;
3764 3659          mp->b_wptr += sizeof (*saext);
3765 3660          saext->sadb_sa_len = SADB_8TO64(sizeof (*saext));
3766 3661          saext->sadb_sa_exttype = SADB_EXT_SA;
3767 3662          saext->sadb_sa_spi = assoc->ipsa_spi;
3768 3663          saext->sadb_sa_replay = assoc->ipsa_replay_wsize;
3769 3664          saext->sadb_sa_state = assoc->ipsa_state;
3770 3665          saext->sadb_sa_auth = assoc->ipsa_auth_alg;
3771 3666          saext->sadb_sa_encrypt = assoc->ipsa_encr_alg;
3772 3667          saext->sadb_sa_flags = assoc->ipsa_flags;
3773 3668  
3774 3669          current = (sadb_lifetime_t *)mp->b_wptr;
3775 3670          mp->b_wptr += sizeof (sadb_lifetime_t);
3776 3671          current->sadb_lifetime_len = SADB_8TO64(sizeof (*current));
3777 3672          current->sadb_lifetime_exttype = SADB_EXT_LIFETIME_CURRENT;
3778 3673          /* We do not support the concept. */
3779 3674          current->sadb_lifetime_allocations = 0;
3780 3675          current->sadb_lifetime_bytes = assoc->ipsa_bytes;
3781 3676          current->sadb_lifetime_addtime = assoc->ipsa_addtime;
3782 3677          current->sadb_lifetime_usetime = assoc->ipsa_usetime;
3783 3678  
3784 3679          expire = (sadb_lifetime_t *)mp->b_wptr;
3785 3680          mp->b_wptr += sizeof (*expire);
3786 3681          expire->sadb_lifetime_len = SADB_8TO64(sizeof (*expire));
3787 3682  
3788 3683          if (assoc->ipsa_state == IPSA_STATE_DEAD) {
3789 3684                  expire->sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
3790 3685                  expire->sadb_lifetime_allocations = assoc->ipsa_hardalloc;
3791 3686                  expire->sadb_lifetime_bytes = assoc->ipsa_hardbyteslt;
3792 3687                  expire->sadb_lifetime_addtime = assoc->ipsa_hardaddlt;
3793 3688                  expire->sadb_lifetime_usetime = assoc->ipsa_harduselt;
3794 3689          } else if (assoc->ipsa_state == IPSA_STATE_DYING) {
3795 3690                  expire->sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;
3796 3691                  expire->sadb_lifetime_allocations = assoc->ipsa_softalloc;
3797 3692                  expire->sadb_lifetime_bytes = assoc->ipsa_softbyteslt;
3798 3693                  expire->sadb_lifetime_addtime = assoc->ipsa_softaddlt;
3799 3694                  expire->sadb_lifetime_usetime = assoc->ipsa_softuselt;
3800 3695          } else {
3801 3696                  ASSERT(assoc->ipsa_state == IPSA_STATE_MATURE);
3802 3697                  expire->sadb_lifetime_exttype = SADB_X_EXT_LIFETIME_IDLE;
3803 3698                  expire->sadb_lifetime_allocations = 0;
3804 3699                  expire->sadb_lifetime_bytes = 0;
3805 3700                  expire->sadb_lifetime_addtime = assoc->ipsa_idleaddlt;
3806 3701                  expire->sadb_lifetime_usetime = assoc->ipsa_idleuselt;
3807 3702          }
3808 3703  
3809 3704          mp->b_wptr = sadb_make_addr_ext(mp->b_wptr, end, SADB_EXT_ADDRESS_SRC,
3810 3705              af, assoc->ipsa_srcaddr, tunnel_mode ? 0 : SA_SRCPORT(assoc),
3811 3706              SA_PROTO(assoc), 0);
3812 3707          ASSERT(mp->b_wptr != NULL);
3813 3708  
3814 3709          mp->b_wptr = sadb_make_addr_ext(mp->b_wptr, end, SADB_EXT_ADDRESS_DST,
3815 3710              af, assoc->ipsa_dstaddr, tunnel_mode ? 0 : SA_DSTPORT(assoc),
3816 3711              SA_PROTO(assoc), 0);
3817 3712          ASSERT(mp->b_wptr != NULL);
3818 3713  
3819 3714          if (tunnel_mode) {
3820 3715                  mp->b_wptr = sadb_make_addr_ext(mp->b_wptr, end,
3821 3716                      SADB_X_EXT_ADDRESS_INNER_SRC, assoc->ipsa_innerfam,
3822 3717                      assoc->ipsa_innersrc, SA_SRCPORT(assoc), SA_IPROTO(assoc),
3823 3718                      assoc->ipsa_innersrcpfx);
3824 3719                  ASSERT(mp->b_wptr != NULL);
3825 3720                  mp->b_wptr = sadb_make_addr_ext(mp->b_wptr, end,
3826 3721                      SADB_X_EXT_ADDRESS_INNER_DST, assoc->ipsa_innerfam,
3827 3722                      assoc->ipsa_innerdst, SA_DSTPORT(assoc), SA_IPROTO(assoc),
3828 3723                      assoc->ipsa_innerdstpfx);
3829 3724                  ASSERT(mp->b_wptr != NULL);
3830 3725          }
3831 3726  
3832 3727          /* Can just putnext, we're ready to go! */
3833 3728          putnext(pfkey_q, mp1);
3834 3729  }
3835 3730  
3836 3731  /*
3837 3732   * "Age" the SA with the number of bytes that was used to protect traffic.
3838 3733   * Send an SADB_EXPIRE message if appropriate.  Return B_TRUE if there was
3839 3734   * enough "charge" left in the SA to protect the data.  Return B_FALSE
3840 3735   * otherwise.  (If B_FALSE is returned, the association either was, or became
3841 3736   * DEAD.)
3842 3737   */
3843 3738  boolean_t
3844 3739  sadb_age_bytes(queue_t *pfkey_q, ipsa_t *assoc, uint64_t bytes,
3845 3740      boolean_t sendmsg)
3846 3741  {
3847 3742          boolean_t rc = B_TRUE;
3848 3743          uint64_t newtotal;
3849 3744  
3850 3745          mutex_enter(&assoc->ipsa_lock);
3851 3746          newtotal = assoc->ipsa_bytes + bytes;
3852 3747          if (assoc->ipsa_hardbyteslt != 0 &&
3853 3748              newtotal >= assoc->ipsa_hardbyteslt) {
3854 3749                  if (assoc->ipsa_state != IPSA_STATE_DEAD) {
3855 3750                          /*
3856 3751                           * Send EXPIRE message to PF_KEY.  May wish to pawn
3857 3752                           * this off on another non-interrupt thread.  Also
3858 3753                           * unlink this SA immediately.
3859 3754                           */
3860 3755                          assoc->ipsa_state = IPSA_STATE_DEAD;
3861 3756                          if (sendmsg)
3862 3757                                  sadb_expire_assoc(pfkey_q, assoc);
3863 3758                          /*
3864 3759                           * Set non-zero expiration time so sadb_age_assoc()
3865 3760                           * will work when reaping.
3866 3761                           */
3867 3762                          assoc->ipsa_hardexpiretime = (time_t)1;
3868 3763                  } /* Else someone beat me to it! */
3869 3764                  rc = B_FALSE;
3870 3765          } else if (assoc->ipsa_softbyteslt != 0 &&
3871 3766              (newtotal >= assoc->ipsa_softbyteslt)) {
3872 3767                  if (assoc->ipsa_state < IPSA_STATE_DYING) {
3873 3768                          /*
3874 3769                           * Send EXPIRE message to PF_KEY.  May wish to pawn
3875 3770                           * this off on another non-interrupt thread.
3876 3771                           */
3877 3772                          assoc->ipsa_state = IPSA_STATE_DYING;
3878 3773                          assoc->ipsa_bytes = newtotal;
3879 3774                          if (sendmsg)
3880 3775                                  sadb_expire_assoc(pfkey_q, assoc);
3881 3776                  } /* Else someone beat me to it! */
3882 3777          }
3883 3778          if (rc == B_TRUE)
3884 3779                  assoc->ipsa_bytes = newtotal;
3885 3780          mutex_exit(&assoc->ipsa_lock);
3886 3781          return (rc);
3887 3782  }
3888 3783  
3889 3784  /*
3890 3785   * "Torch" an individual SA.  Returns NULL, so it can be tail-called from
3891 3786   *     sadb_age_assoc().
3892 3787   */
3893 3788  static ipsa_t *
3894 3789  sadb_torch_assoc(isaf_t *head, ipsa_t *sa)
3895 3790  {
3896 3791          ASSERT(MUTEX_HELD(&head->isaf_lock));
3897 3792          ASSERT(MUTEX_HELD(&sa->ipsa_lock));
3898 3793          ASSERT(sa->ipsa_state == IPSA_STATE_DEAD);
3899 3794  
3900 3795          /*
3901 3796           * Force cached SAs to be revalidated..
3902 3797           */
3903 3798          head->isaf_gen++;
3904 3799  
3905 3800          mutex_exit(&sa->ipsa_lock);
3906 3801          sadb_unlinkassoc(sa);
3907 3802  
3908 3803          return (NULL);
3909 3804  }
3910 3805  
3911 3806  /*
3912 3807   * Do various SA-is-idle activities depending on delta (the number of idle
3913 3808   * seconds on the SA) and/or other properties of the SA.
3914 3809   *
3915 3810   * Return B_TRUE if I've sent a packet, because I have to drop the
3916 3811   * association's mutex before sending a packet out the wire.
3917 3812   */
3918 3813  /* ARGSUSED */
3919 3814  static boolean_t
3920 3815  sadb_idle_activities(ipsa_t *assoc, time_t delta, boolean_t inbound)
3921 3816  {
3922 3817          ipsecesp_stack_t *espstack = assoc->ipsa_netstack->netstack_ipsecesp;
3923 3818          int nat_t_interval = espstack->ipsecesp_nat_keepalive_interval;
3924 3819  
3925 3820          ASSERT(MUTEX_HELD(&assoc->ipsa_lock));
3926 3821  
3927 3822          if (!inbound && (assoc->ipsa_flags & IPSA_F_NATT_LOC) &&
3928 3823              delta >= nat_t_interval &&
3929 3824              gethrestime_sec() - assoc->ipsa_last_nat_t_ka >= nat_t_interval) {
3930 3825                  ASSERT(assoc->ipsa_type == SADB_SATYPE_ESP);
3931 3826                  assoc->ipsa_last_nat_t_ka = gethrestime_sec();
3932 3827                  mutex_exit(&assoc->ipsa_lock);
3933 3828                  ipsecesp_send_keepalive(assoc);
3934 3829                  return (B_TRUE);
3935 3830          }
3936 3831          return (B_FALSE);
3937 3832  }
3938 3833  
3939 3834  /*
3940 3835   * Return "assoc" if haspeer is true and I send an expire.  This allows
3941 3836   * the consumers' aging functions to tidy up an expired SA's peer.
3942 3837   */
3943 3838  static ipsa_t *
  
    | 
      ↓ open down ↓ | 
    886 lines elided | 
    
      ↑ open up ↑ | 
  
3944 3839  sadb_age_assoc(isaf_t *head, queue_t *pfkey_q, ipsa_t *assoc,
3945 3840      time_t current, int reap_delay, boolean_t inbound)
3946 3841  {
3947 3842          ipsa_t *retval = NULL;
3948 3843          boolean_t dropped_mutex = B_FALSE;
3949 3844  
3950 3845          ASSERT(MUTEX_HELD(&head->isaf_lock));
3951 3846  
3952 3847          mutex_enter(&assoc->ipsa_lock);
3953 3848  
3954      -        if (((assoc->ipsa_state == IPSA_STATE_LARVAL) ||
3955      -            ((assoc->ipsa_state == IPSA_STATE_IDLE) ||
3956      -            (assoc->ipsa_state == IPSA_STATE_ACTIVE_ELSEWHERE) &&
3957      -            (assoc->ipsa_hardexpiretime != 0))) &&
3958      -            (assoc->ipsa_hardexpiretime <= current)) {
     3849 +        /*
     3850 +         * Be aggressive in reaping expired LARVAL SAs.
     3851 +         */
     3852 +        if (assoc->ipsa_state == IPSA_STATE_LARVAL &&
     3853 +            assoc->ipsa_hardexpiretime <= current) {
3959 3854                  assoc->ipsa_state = IPSA_STATE_DEAD;
3960 3855                  return (sadb_torch_assoc(head, assoc));
3961 3856          }
3962 3857  
3963 3858          /*
3964 3859           * Check lifetimes.  Fortunately, SA setup is done
3965 3860           * such that there are only two times to look at,
3966 3861           * softexpiretime, and hardexpiretime.
3967 3862           *
3968 3863           * Check hard first.
3969 3864           */
3970 3865  
3971 3866          if (assoc->ipsa_hardexpiretime != 0 &&
3972 3867              assoc->ipsa_hardexpiretime <= current) {
3973 3868                  if (assoc->ipsa_state == IPSA_STATE_DEAD)
3974 3869                          return (sadb_torch_assoc(head, assoc));
3975 3870  
3976 3871                  /*
3977 3872                   * Send SADB_EXPIRE with hard lifetime, delay for unlinking.
3978 3873                   */
3979 3874                  assoc->ipsa_state = IPSA_STATE_DEAD;
3980 3875                  if (assoc->ipsa_haspeer || assoc->ipsa_otherspi != 0) {
3981 3876                          /*
3982 3877                           * If the SA is paired or peered with another, put
3983 3878                           * a copy on a list which can be processed later, the
3984 3879                           * pair/peer SA needs to be updated so the both die
3985 3880                           * at the same time.
3986 3881                           *
3987 3882                           * If I return assoc, I have to bump up its reference
3988 3883                           * count to keep with the ipsa_t reference count
3989 3884                           * semantics.
3990 3885                           */
3991 3886                          IPSA_REFHOLD(assoc);
3992 3887                          retval = assoc;
3993 3888                  }
3994 3889                  sadb_expire_assoc(pfkey_q, assoc);
3995 3890                  assoc->ipsa_hardexpiretime = current + reap_delay;
3996 3891          } else if (assoc->ipsa_softexpiretime != 0 &&
3997 3892              assoc->ipsa_softexpiretime <= current &&
3998 3893              assoc->ipsa_state < IPSA_STATE_DYING) {
3999 3894                  /*
4000 3895                   * Send EXPIRE message to PF_KEY.  May wish to pawn
4001 3896                   * this off on another non-interrupt thread.
4002 3897                   */
4003 3898                  assoc->ipsa_state = IPSA_STATE_DYING;
4004 3899                  if (assoc->ipsa_haspeer) {
4005 3900                          /*
4006 3901                           * If the SA has a peer, update the peer's state
4007 3902                           * on SOFT_EXPIRE, this is mostly to prevent two
4008 3903                           * expire messages from effectively the same SA.
4009 3904                           *
4010 3905                           * Don't care about paired SA's, then can (and should)
4011 3906                           * be able to soft expire at different times.
4012 3907                           *
  
    | 
      ↓ open down ↓ | 
    44 lines elided | 
    
      ↑ open up ↑ | 
  
4013 3908                           * If I return assoc, I have to bump up its
4014 3909                           * reference count to keep with the ipsa_t reference
4015 3910                           * count semantics.
4016 3911                           */
4017 3912                          IPSA_REFHOLD(assoc);
4018 3913                          retval = assoc;
4019 3914                  }
4020 3915                  sadb_expire_assoc(pfkey_q, assoc);
4021 3916          } else if (assoc->ipsa_idletime != 0 &&
4022 3917              assoc->ipsa_idleexpiretime <= current) {
4023      -                if (assoc->ipsa_state == IPSA_STATE_ACTIVE_ELSEWHERE) {
4024      -                        assoc->ipsa_state = IPSA_STATE_IDLE;
4025      -                }
4026      -
4027      -                /*
4028      -                 * Need to handle Mature case
4029      -                 */
     3918 +                /* Only issue an IDLE expiration if we're in mature state. */
4030 3919                  if (assoc->ipsa_state == IPSA_STATE_MATURE) {
4031 3920                          sadb_expire_assoc(pfkey_q, assoc);
4032 3921                  }
4033 3922          } else {
4034 3923                  /* Check idle time activities. */
4035 3924                  dropped_mutex = sadb_idle_activities(assoc,
4036 3925                      current - assoc->ipsa_lastuse, inbound);
4037 3926          }
4038 3927  
4039 3928          if (!dropped_mutex)
4040 3929                  mutex_exit(&assoc->ipsa_lock);
4041 3930          return (retval);
4042 3931  }
4043 3932  
4044 3933  /*
4045 3934   * Called by a consumer protocol to do ther dirty work of reaping dead
4046 3935   * Security Associations.
4047 3936   *
4048 3937   * NOTE: sadb_age_assoc() marks expired SA's as DEAD but only removed
4049 3938   * SA's that are already marked DEAD, so expired SA's are only reaped
4050 3939   * the second time sadb_ager() runs.
4051 3940   */
4052 3941  void
4053 3942  sadb_ager(sadb_t *sp, queue_t *pfkey_q, int reap_delay, netstack_t *ns)
4054 3943  {
4055 3944          int i;
4056 3945          isaf_t *bucket;
4057 3946          ipsa_t *assoc, *spare;
4058 3947          iacqf_t *acqlist;
4059 3948          ipsacq_t *acqrec, *spareacq;
4060 3949          templist_t *haspeerlist, *newbie;
4061 3950          /* Snapshot current time now. */
4062 3951          time_t current = gethrestime_sec();
4063 3952          haspeerlist = NULL;
4064 3953  
4065 3954          /*
4066 3955           * Do my dirty work.  This includes aging real entries, aging
4067 3956           * larvals, and aging outstanding ACQUIREs.
4068 3957           *
4069 3958           * I hope I don't tie up resources for too long.
4070 3959           */
4071 3960  
4072 3961          /* Age acquires. */
4073 3962  
4074 3963          for (i = 0; i < sp->sdb_hashsize; i++) {
4075 3964                  acqlist = &sp->sdb_acq[i];
4076 3965                  mutex_enter(&acqlist->iacqf_lock);
4077 3966                  for (acqrec = acqlist->iacqf_ipsacq; acqrec != NULL;
4078 3967                      acqrec = spareacq) {
4079 3968                          spareacq = acqrec->ipsacq_next;
4080 3969                          if (current > acqrec->ipsacq_expire)
4081 3970                                  sadb_destroy_acquire(acqrec, ns);
4082 3971                  }
4083 3972                  mutex_exit(&acqlist->iacqf_lock);
4084 3973          }
4085 3974  
4086 3975          /* Age inbound associations. */
4087 3976          for (i = 0; i < sp->sdb_hashsize; i++) {
4088 3977                  bucket = &(sp->sdb_if[i]);
4089 3978                  mutex_enter(&bucket->isaf_lock);
4090 3979                  for (assoc = bucket->isaf_ipsa; assoc != NULL;
4091 3980                      assoc = spare) {
4092 3981                          spare = assoc->ipsa_next;
4093 3982                          if (sadb_age_assoc(bucket, pfkey_q, assoc, current,
4094 3983                              reap_delay, B_TRUE) != NULL) {
4095 3984                                  /*
4096 3985                                   * Put SA's which have a peer or SA's which
4097 3986                                   * are paired on a list for processing after
4098 3987                                   * all the hash tables have been walked.
4099 3988                                   *
4100 3989                                   * sadb_age_assoc() increments the refcnt,
4101 3990                                   * effectively doing an IPSA_REFHOLD().
4102 3991                                   */
4103 3992                                  newbie = kmem_alloc(sizeof (*newbie),
4104 3993                                      KM_NOSLEEP);
4105 3994                                  if (newbie == NULL) {
4106 3995                                          /*
4107 3996                                           * Don't forget to REFRELE().
4108 3997                                           */
4109 3998                                          IPSA_REFRELE(assoc);
4110 3999                                          continue;       /* for loop... */
4111 4000                                  }
4112 4001                                  newbie->next = haspeerlist;
4113 4002                                  newbie->ipsa = assoc;
4114 4003                                  haspeerlist = newbie;
4115 4004                          }
4116 4005                  }
4117 4006                  mutex_exit(&bucket->isaf_lock);
4118 4007          }
4119 4008  
4120 4009          age_pair_peer_list(haspeerlist, sp, B_FALSE);
4121 4010          haspeerlist = NULL;
4122 4011  
4123 4012          /* Age outbound associations. */
4124 4013          for (i = 0; i < sp->sdb_hashsize; i++) {
4125 4014                  bucket = &(sp->sdb_of[i]);
4126 4015                  mutex_enter(&bucket->isaf_lock);
4127 4016                  for (assoc = bucket->isaf_ipsa; assoc != NULL;
4128 4017                      assoc = spare) {
4129 4018                          spare = assoc->ipsa_next;
4130 4019                          if (sadb_age_assoc(bucket, pfkey_q, assoc, current,
4131 4020                              reap_delay, B_FALSE) != NULL) {
4132 4021                                  /*
4133 4022                                   * sadb_age_assoc() increments the refcnt,
4134 4023                                   * effectively doing an IPSA_REFHOLD().
4135 4024                                   */
4136 4025                                  newbie = kmem_alloc(sizeof (*newbie),
4137 4026                                      KM_NOSLEEP);
4138 4027                                  if (newbie == NULL) {
4139 4028                                          /*
4140 4029                                           * Don't forget to REFRELE().
4141 4030                                           */
4142 4031                                          IPSA_REFRELE(assoc);
4143 4032                                          continue;       /* for loop... */
4144 4033                                  }
4145 4034                                  newbie->next = haspeerlist;
4146 4035                                  newbie->ipsa = assoc;
4147 4036                                  haspeerlist = newbie;
4148 4037                          }
4149 4038                  }
4150 4039                  mutex_exit(&bucket->isaf_lock);
4151 4040          }
4152 4041  
4153 4042          age_pair_peer_list(haspeerlist, sp, B_TRUE);
4154 4043  
4155 4044          /*
4156 4045           * Run a GC pass to clean out dead identities.
4157 4046           */
4158 4047          ipsid_gc(ns);
4159 4048  }
4160 4049  
4161 4050  /*
4162 4051   * Figure out when to reschedule the ager.
4163 4052   */
4164 4053  timeout_id_t
4165 4054  sadb_retimeout(hrtime_t begin, queue_t *pfkey_q, void (*ager)(void *),
4166 4055      void *agerarg, uint_t *intp, uint_t intmax, short mid)
4167 4056  {
4168 4057          hrtime_t end = gethrtime();
4169 4058          uint_t interval = *intp;        /* "interval" is in ms. */
4170 4059  
4171 4060          /*
4172 4061           * See how long this took.  If it took too long, increase the
4173 4062           * aging interval.
4174 4063           */
4175 4064          if ((end - begin) > MSEC2NSEC(interval)) {
4176 4065                  if (interval >= intmax) {
4177 4066                          /* XXX Rate limit this?  Or recommend flush? */
4178 4067                          (void) strlog(mid, 0, 0, SL_ERROR | SL_WARN,
4179 4068                              "Too many SA's to age out in %d msec.\n",
4180 4069                              intmax);
4181 4070                  } else {
4182 4071                          /* Double by shifting by one bit. */
4183 4072                          interval <<= 1;
4184 4073                          interval = min(interval, intmax);
4185 4074                  }
4186 4075          } else if ((end - begin) <= (MSEC2NSEC(interval) / 2) &&
4187 4076              interval > SADB_AGE_INTERVAL_DEFAULT) {
4188 4077                  /*
4189 4078                   * If I took less than half of the interval, then I should
4190 4079                   * ratchet the interval back down.  Never automatically
4191 4080                   * shift below the default aging interval.
4192 4081                   *
4193 4082                   * NOTE:This even overrides manual setting of the age
4194 4083                   *      interval using NDD to lower the setting past the
4195 4084                   *      default.  In other words, if you set the interval
4196 4085                   *      lower than the default, and your SADB gets too big,
4197 4086                   *      the interval will only self-lower back to the default.
4198 4087                   */
4199 4088                  /* Halve by shifting one bit. */
4200 4089                  interval >>= 1;
4201 4090                  interval = max(interval, SADB_AGE_INTERVAL_DEFAULT);
4202 4091          }
4203 4092          *intp = interval;
4204 4093          return (qtimeout(pfkey_q, ager, agerarg,
4205 4094              drv_usectohz(interval * (MICROSEC / MILLISEC))));
4206 4095  }
4207 4096  
4208 4097  
4209 4098  /*
4210 4099   * Update the lifetime values of an SA.  This is the path an SADB_UPDATE
4211 4100   * message takes when updating a MATURE or DYING SA.
4212 4101   */
4213 4102  static void
4214 4103  sadb_update_lifetimes(ipsa_t *assoc, sadb_lifetime_t *hard,
4215 4104      sadb_lifetime_t *soft, sadb_lifetime_t *idle, boolean_t outbound)
4216 4105  {
4217 4106          mutex_enter(&assoc->ipsa_lock);
4218 4107  
4219 4108          /*
4220 4109           * XXX RFC 2367 mentions how an SADB_EXT_LIFETIME_CURRENT can be
4221 4110           * passed in during an update message.  We currently don't handle
4222 4111           * these.
4223 4112           */
4224 4113  
4225 4114          if (hard != NULL) {
4226 4115                  if (hard->sadb_lifetime_bytes != 0)
4227 4116                          assoc->ipsa_hardbyteslt = hard->sadb_lifetime_bytes;
4228 4117                  if (hard->sadb_lifetime_usetime != 0)
4229 4118                          assoc->ipsa_harduselt = hard->sadb_lifetime_usetime;
4230 4119                  if (hard->sadb_lifetime_addtime != 0)
4231 4120                          assoc->ipsa_hardaddlt = hard->sadb_lifetime_addtime;
4232 4121                  if (assoc->ipsa_hardaddlt != 0) {
4233 4122                          assoc->ipsa_hardexpiretime =
4234 4123                              assoc->ipsa_addtime + assoc->ipsa_hardaddlt;
4235 4124                  }
4236 4125                  if (assoc->ipsa_harduselt != 0 &&
4237 4126                      assoc->ipsa_flags & IPSA_F_USED) {
4238 4127                          UPDATE_EXPIRE(assoc, harduselt, hardexpiretime);
4239 4128                  }
4240 4129                  if (hard->sadb_lifetime_allocations != 0)
4241 4130                          assoc->ipsa_hardalloc = hard->sadb_lifetime_allocations;
4242 4131          }
4243 4132  
4244 4133          if (soft != NULL) {
4245 4134                  if (soft->sadb_lifetime_bytes != 0) {
4246 4135                          if (soft->sadb_lifetime_bytes >
4247 4136                              assoc->ipsa_hardbyteslt) {
4248 4137                                  assoc->ipsa_softbyteslt =
4249 4138                                      assoc->ipsa_hardbyteslt;
4250 4139                          } else {
4251 4140                                  assoc->ipsa_softbyteslt =
4252 4141                                      soft->sadb_lifetime_bytes;
4253 4142                          }
4254 4143                  }
4255 4144                  if (soft->sadb_lifetime_usetime != 0) {
4256 4145                          if (soft->sadb_lifetime_usetime >
4257 4146                              assoc->ipsa_harduselt) {
4258 4147                                  assoc->ipsa_softuselt =
4259 4148                                      assoc->ipsa_harduselt;
4260 4149                          } else {
4261 4150                                  assoc->ipsa_softuselt =
4262 4151                                      soft->sadb_lifetime_usetime;
4263 4152                          }
4264 4153                  }
4265 4154                  if (soft->sadb_lifetime_addtime != 0) {
4266 4155                          if (soft->sadb_lifetime_addtime >
4267 4156                              assoc->ipsa_hardexpiretime) {
4268 4157                                  assoc->ipsa_softexpiretime =
4269 4158                                      assoc->ipsa_hardexpiretime;
4270 4159                          } else {
4271 4160                                  assoc->ipsa_softaddlt =
4272 4161                                      soft->sadb_lifetime_addtime;
4273 4162                          }
4274 4163                  }
4275 4164                  if (assoc->ipsa_softaddlt != 0) {
4276 4165                          assoc->ipsa_softexpiretime =
4277 4166                              assoc->ipsa_addtime + assoc->ipsa_softaddlt;
4278 4167                  }
4279 4168                  if (assoc->ipsa_softuselt != 0 &&
4280 4169                      assoc->ipsa_flags & IPSA_F_USED) {
4281 4170                          UPDATE_EXPIRE(assoc, softuselt, softexpiretime);
4282 4171                  }
4283 4172                  if (outbound && assoc->ipsa_softexpiretime != 0) {
4284 4173                          if (assoc->ipsa_state == IPSA_STATE_MATURE)
4285 4174                                  lifetime_fuzz(assoc);
4286 4175                  }
4287 4176  
4288 4177                  if (soft->sadb_lifetime_allocations != 0)
4289 4178                          assoc->ipsa_softalloc = soft->sadb_lifetime_allocations;
4290 4179          }
4291 4180  
4292 4181          if (idle != NULL) {
4293 4182                  time_t current = gethrestime_sec();
4294 4183                  if ((assoc->ipsa_idleexpiretime <= current) &&
4295 4184                      (assoc->ipsa_idleaddlt == idle->sadb_lifetime_addtime)) {
4296 4185                          assoc->ipsa_idleexpiretime =
4297 4186                              current + assoc->ipsa_idleaddlt;
4298 4187                  }
4299 4188                  if (idle->sadb_lifetime_addtime != 0)
4300 4189                          assoc->ipsa_idleaddlt = idle->sadb_lifetime_addtime;
4301 4190                  if (idle->sadb_lifetime_usetime != 0)
4302 4191                          assoc->ipsa_idleuselt = idle->sadb_lifetime_usetime;
4303 4192                  if (assoc->ipsa_idleaddlt != 0) {
4304 4193                          assoc->ipsa_idleexpiretime =
4305 4194                              current + idle->sadb_lifetime_addtime;
4306 4195                          assoc->ipsa_idletime = idle->sadb_lifetime_addtime;
4307 4196                  }
4308 4197                  if (assoc->ipsa_idleuselt != 0) {
4309 4198                          if (assoc->ipsa_idletime != 0) {
4310 4199                                  assoc->ipsa_idletime = min(assoc->ipsa_idletime,
4311 4200                                      assoc->ipsa_idleuselt);
4312 4201                          assoc->ipsa_idleexpiretime =
4313 4202                              current + assoc->ipsa_idletime;
  
    | 
      ↓ open down ↓ | 
    274 lines elided | 
    
      ↑ open up ↑ | 
  
4314 4203                          } else {
4315 4204                                  assoc->ipsa_idleexpiretime =
4316 4205                                      current + assoc->ipsa_idleuselt;
4317 4206                                  assoc->ipsa_idletime = assoc->ipsa_idleuselt;
4318 4207                          }
4319 4208                  }
4320 4209          }
4321 4210          mutex_exit(&assoc->ipsa_lock);
4322 4211  }
4323 4212  
4324      -static int
4325      -sadb_update_state(ipsa_t *assoc, uint_t new_state, mblk_t **ipkt_lst)
4326      -{
4327      -        int rcode = 0;
4328      -        time_t current = gethrestime_sec();
4329      -
4330      -        mutex_enter(&assoc->ipsa_lock);
4331      -
4332      -        switch (new_state) {
4333      -        case SADB_X_SASTATE_ACTIVE_ELSEWHERE:
4334      -                if (assoc->ipsa_state == SADB_X_SASTATE_IDLE) {
4335      -                        assoc->ipsa_state = IPSA_STATE_ACTIVE_ELSEWHERE;
4336      -                        assoc->ipsa_idleexpiretime =
4337      -                            current + assoc->ipsa_idletime;
4338      -                }
4339      -                break;
4340      -        case SADB_X_SASTATE_IDLE:
4341      -                if (assoc->ipsa_state == SADB_X_SASTATE_ACTIVE_ELSEWHERE) {
4342      -                        assoc->ipsa_state = IPSA_STATE_IDLE;
4343      -                        assoc->ipsa_idleexpiretime =
4344      -                            current + assoc->ipsa_idletime;
4345      -                } else {
4346      -                        rcode = EINVAL;
4347      -                }
4348      -                break;
4349      -
4350      -        case SADB_X_SASTATE_ACTIVE:
4351      -                if (assoc->ipsa_state != SADB_X_SASTATE_IDLE) {
4352      -                        rcode = EINVAL;
4353      -                        break;
4354      -                }
4355      -                assoc->ipsa_state = IPSA_STATE_MATURE;
4356      -                assoc->ipsa_idleexpiretime = current + assoc->ipsa_idletime;
4357      -
4358      -                if (ipkt_lst == NULL) {
4359      -                        break;
4360      -                }
4361      -
4362      -                if (assoc->ipsa_bpkt_head != NULL) {
4363      -                        *ipkt_lst = assoc->ipsa_bpkt_head;
4364      -                        assoc->ipsa_bpkt_head = assoc->ipsa_bpkt_tail = NULL;
4365      -                        assoc->ipsa_mblkcnt = 0;
4366      -                } else {
4367      -                        *ipkt_lst = NULL;
4368      -                }
4369      -                break;
4370      -        default:
4371      -                rcode = EINVAL;
4372      -                break;
4373      -        }
4374      -
4375      -        mutex_exit(&assoc->ipsa_lock);
4376      -        return (rcode);
4377      -}
4378      -
4379 4213  /*
4380 4214   * Check a proposed KMC update for sanity.
4381 4215   */
4382 4216  static int
4383 4217  sadb_check_kmc(ipsa_query_t *sq, ipsa_t *sa, int *diagnostic)
4384 4218  {
4385 4219          uint32_t kmp = sq->kmp;
4386 4220          uint32_t kmc = sq->kmc;
4387 4221  
4388 4222          if (sa == NULL)
4389 4223                  return (0);
4390 4224  
4391 4225          if (sa->ipsa_state == IPSA_STATE_DEAD)
4392 4226                  return (ESRCH); /* DEAD == Not there, in this case. */
4393 4227  
4394 4228          if ((kmp != 0) && ((sa->ipsa_kmp != 0) || (sa->ipsa_kmp != kmp))) {
4395 4229                  *diagnostic = SADB_X_DIAGNOSTIC_DUPLICATE_KMP;
4396 4230                  return (EINVAL);
4397 4231          }
4398 4232  
4399 4233          if ((kmc != 0) && ((sa->ipsa_kmc != 0) || (sa->ipsa_kmc != kmc))) {
4400 4234                  *diagnostic = SADB_X_DIAGNOSTIC_DUPLICATE_KMC;
4401 4235                  return (EINVAL);
4402 4236          }
4403 4237  
4404 4238          return (0);
4405 4239  }
4406 4240  
4407 4241  /*
4408 4242   * Actually update the KMC info.
4409 4243   */
4410 4244  static void
4411 4245  sadb_update_kmc(ipsa_query_t *sq, ipsa_t *sa)
4412 4246  {
4413 4247          uint32_t kmp = sq->kmp;
4414 4248          uint32_t kmc = sq->kmc;
4415 4249  
4416 4250          if (kmp != 0)
  
    | 
      ↓ open down ↓ | 
    28 lines elided | 
    
      ↑ open up ↑ | 
  
4417 4251                  sa->ipsa_kmp = kmp;
4418 4252          if (kmc != 0)
4419 4253                  sa->ipsa_kmc = kmc;
4420 4254  }
4421 4255  
4422 4256  /*
4423 4257   * Common code to update an SA.
4424 4258   */
4425 4259  
4426 4260  int
4427      -sadb_update_sa(mblk_t *mp, keysock_in_t *ksi, mblk_t **ipkt_lst,
     4261 +sadb_update_sa(mblk_t *mp, keysock_in_t *ksi,
4428 4262      sadbp_t *spp, int *diagnostic, queue_t *pfkey_q,
4429 4263      int (*add_sa_func)(mblk_t *, keysock_in_t *, int *, netstack_t *),
4430 4264      netstack_t *ns, uint8_t sadb_msg_type)
4431 4265  {
4432 4266          sadb_key_t *akey = (sadb_key_t *)ksi->ks_in_extv[SADB_EXT_KEY_AUTH];
4433 4267          sadb_key_t *ekey = (sadb_key_t *)ksi->ks_in_extv[SADB_EXT_KEY_ENCRYPT];
4434      -        sadb_x_replay_ctr_t *replext =
4435      -            (sadb_x_replay_ctr_t *)ksi->ks_in_extv[SADB_X_EXT_REPLAY_VALUE];
4436 4268          sadb_lifetime_t *soft =
4437 4269              (sadb_lifetime_t *)ksi->ks_in_extv[SADB_EXT_LIFETIME_SOFT];
4438 4270          sadb_lifetime_t *hard =
4439 4271              (sadb_lifetime_t *)ksi->ks_in_extv[SADB_EXT_LIFETIME_HARD];
4440 4272          sadb_lifetime_t *idle =
4441 4273              (sadb_lifetime_t *)ksi->ks_in_extv[SADB_X_EXT_LIFETIME_IDLE];
4442 4274          sadb_x_pair_t *pair_ext =
4443 4275              (sadb_x_pair_t *)ksi->ks_in_extv[SADB_X_EXT_PAIR];
4444 4276          ipsa_t *echo_target = NULL;
4445 4277          ipsap_t ipsapp;
4446 4278          ipsa_query_t sq;
4447      -        time_t current = gethrestime_sec();
4448 4279  
4449 4280          sq.spp = spp;           /* XXX param */
4450 4281          int error = sadb_form_query(ksi, IPSA_Q_SRC|IPSA_Q_DST|IPSA_Q_SA,
4451 4282              IPSA_Q_SRC|IPSA_Q_DST|IPSA_Q_SA|IPSA_Q_INBOUND|IPSA_Q_OUTBOUND,
4452 4283              &sq, diagnostic);
4453 4284  
4454 4285          if (error != 0)
4455 4286                  return (error);
4456 4287  
4457 4288          error = get_ipsa_pair(&sq, &ipsapp, diagnostic);
4458 4289          if (error != 0)
4459 4290                  return (error);
4460 4291  
4461 4292          if (ipsapp.ipsap_psa_ptr == NULL && ipsapp.ipsap_sa_ptr != NULL) {
4462 4293                  if (ipsapp.ipsap_sa_ptr->ipsa_state == IPSA_STATE_LARVAL) {
4463 4294                          /*
4464 4295                           * REFRELE the target and let the add_sa_func()
4465 4296                           * deal with updating a larval SA.
4466 4297                           */
4467 4298                          destroy_ipsa_pair(&ipsapp);
4468 4299                          return (add_sa_func(mp, ksi, diagnostic, ns));
4469 4300                  }
4470 4301          }
4471 4302  
4472 4303          /*
4473 4304           * At this point we have an UPDATE to a MATURE SA. There should
4474 4305           * not be any keying material present.
4475 4306           */
4476 4307          if (akey != NULL) {
  
    | 
      ↓ open down ↓ | 
    19 lines elided | 
    
      ↑ open up ↑ | 
  
4477 4308                  *diagnostic = SADB_X_DIAGNOSTIC_AKEY_PRESENT;
4478 4309                  error = EINVAL;
4479 4310                  goto bail;
4480 4311          }
4481 4312          if (ekey != NULL) {
4482 4313                  *diagnostic = SADB_X_DIAGNOSTIC_EKEY_PRESENT;
4483 4314                  error = EINVAL;
4484 4315                  goto bail;
4485 4316          }
4486 4317  
4487      -        if (sq.assoc->sadb_sa_state == SADB_X_SASTATE_ACTIVE_ELSEWHERE) {
4488      -                if (ipsapp.ipsap_sa_ptr != NULL &&
4489      -                    ipsapp.ipsap_sa_ptr->ipsa_state == IPSA_STATE_IDLE) {
4490      -                        if ((error = sadb_update_state(ipsapp.ipsap_sa_ptr,
4491      -                            sq.assoc->sadb_sa_state, NULL)) != 0) {
4492      -                                *diagnostic = SADB_X_DIAGNOSTIC_BAD_SASTATE;
4493      -                                goto bail;
4494      -                        }
4495      -                }
4496      -                if (ipsapp.ipsap_psa_ptr != NULL &&
4497      -                    ipsapp.ipsap_psa_ptr->ipsa_state == IPSA_STATE_IDLE) {
4498      -                        if ((error = sadb_update_state(ipsapp.ipsap_psa_ptr,
4499      -                            sq.assoc->sadb_sa_state, NULL)) != 0) {
4500      -                                *diagnostic = SADB_X_DIAGNOSTIC_BAD_SASTATE;
4501      -                                goto bail;
4502      -                        }
4503      -                }
4504      -        }
4505      -        if (sq.assoc->sadb_sa_state == SADB_X_SASTATE_ACTIVE) {
4506      -                if (ipsapp.ipsap_sa_ptr != NULL) {
4507      -                        error = sadb_update_state(ipsapp.ipsap_sa_ptr,
4508      -                            sq.assoc->sadb_sa_state,
4509      -                            (ipsapp.ipsap_sa_ptr->ipsa_flags &
4510      -                            IPSA_F_INBOUND) ? ipkt_lst : NULL);
4511      -                        if (error) {
4512      -                                *diagnostic = SADB_X_DIAGNOSTIC_BAD_SASTATE;
4513      -                                goto bail;
4514      -                        }
4515      -                }
4516      -                if (ipsapp.ipsap_psa_ptr != NULL) {
4517      -                        error = sadb_update_state(ipsapp.ipsap_psa_ptr,
4518      -                            sq.assoc->sadb_sa_state,
4519      -                            (ipsapp.ipsap_psa_ptr->ipsa_flags &
4520      -                            IPSA_F_INBOUND) ? ipkt_lst : NULL);
4521      -                        if (error) {
4522      -                                *diagnostic = SADB_X_DIAGNOSTIC_BAD_SASTATE;
4523      -                                goto bail;
4524      -                        }
4525      -                }
4526      -                sadb_pfkey_echo(pfkey_q, mp, (sadb_msg_t *)mp->b_cont->b_rptr,
4527      -                    ksi, echo_target);
4528      -                goto bail;
4529      -        }
4530      -
4531 4318          /*
4532 4319           * Reality checks for updates of active associations.
4533 4320           * Sundry first-pass UPDATE-specific reality checks.
4534 4321           * Have to do the checks here, because it's after the add_sa code.
4535 4322           * XXX STATS : logging/stats here?
4536 4323           */
4537 4324  
4538      -        if (!((sq.assoc->sadb_sa_state == SADB_SASTATE_MATURE) ||
4539      -            (sq.assoc->sadb_sa_state == SADB_X_SASTATE_ACTIVE_ELSEWHERE))) {
     4325 +        if (sq.assoc->sadb_sa_state != SADB_SASTATE_MATURE) {
4540 4326                  *diagnostic = SADB_X_DIAGNOSTIC_BAD_SASTATE;
4541 4327                  error = EINVAL;
4542 4328                  goto bail;
4543 4329          }
4544 4330          if (sq.assoc->sadb_sa_flags & ~spp->s_updateflags) {
4545 4331                  *diagnostic = SADB_X_DIAGNOSTIC_BAD_SAFLAGS;
4546 4332                  error = EINVAL;
4547 4333                  goto bail;
4548 4334          }
4549 4335          if (ksi->ks_in_extv[SADB_EXT_LIFETIME_CURRENT] != NULL) {
4550 4336                  *diagnostic = SADB_X_DIAGNOSTIC_MISSING_LIFETIME;
4551 4337                  error = EOPNOTSUPP;
4552 4338                  goto bail;
4553 4339          }
4554 4340  
4555 4341          if ((*diagnostic = sadb_hardsoftchk(hard, soft, idle)) != 0) {
4556 4342                  error = EINVAL;
4557 4343                  goto bail;
4558 4344          }
4559 4345  
4560 4346          if ((*diagnostic = sadb_labelchk(ksi)) != 0)
  
    | 
      ↓ open down ↓ | 
    11 lines elided | 
    
      ↑ open up ↑ | 
  
4561 4347                  return (EINVAL);
4562 4348  
4563 4349          error = sadb_check_kmc(&sq, ipsapp.ipsap_sa_ptr, diagnostic);
4564 4350          if (error != 0)
4565 4351                  goto bail;
4566 4352  
4567 4353          error = sadb_check_kmc(&sq, ipsapp.ipsap_psa_ptr, diagnostic);
4568 4354          if (error != 0)
4569 4355                  goto bail;
4570 4356  
4571      -
4572 4357          if (ipsapp.ipsap_sa_ptr != NULL) {
4573      -                /*
4574      -                 * Do not allow replay value change for MATURE or LARVAL SA.
4575      -                 */
4576      -
4577      -                if ((replext != NULL) &&
4578      -                    ((ipsapp.ipsap_sa_ptr->ipsa_state == IPSA_STATE_LARVAL) ||
4579      -                    (ipsapp.ipsap_sa_ptr->ipsa_state == IPSA_STATE_MATURE))) {
4580      -                        *diagnostic = SADB_X_DIAGNOSTIC_BAD_SASTATE;
4581      -                        error = EINVAL;
4582      -                        goto bail;
4583      -                }
4584      -        }
4585      -
4586      -
4587      -        if (ipsapp.ipsap_sa_ptr != NULL) {
4588 4358                  sadb_update_lifetimes(ipsapp.ipsap_sa_ptr, hard, soft,
4589 4359                      idle, B_TRUE);
4590 4360                  sadb_update_kmc(&sq, ipsapp.ipsap_sa_ptr);
4591      -                if ((replext != NULL) &&
4592      -                    (ipsapp.ipsap_sa_ptr->ipsa_replay_wsize != 0)) {
4593      -                        /*
4594      -                         * If an inbound SA, update the replay counter
4595      -                         * and check off all the other sequence number
4596      -                         */
4597      -                        if (ksi->ks_in_dsttype == KS_IN_ADDR_ME) {
4598      -                                if (!sadb_replay_check(ipsapp.ipsap_sa_ptr,
4599      -                                    replext->sadb_x_rc_replay32)) {
4600      -                                        *diagnostic =
4601      -                                            SADB_X_DIAGNOSTIC_INVALID_REPLAY;
4602      -                                        error = EINVAL;
4603      -                                        goto bail;
4604      -                                }
4605      -                                mutex_enter(&ipsapp.ipsap_sa_ptr->ipsa_lock);
4606      -                                ipsapp.ipsap_sa_ptr->ipsa_idleexpiretime =
4607      -                                    current +
4608      -                                    ipsapp.ipsap_sa_ptr->ipsa_idletime;
4609      -                                mutex_exit(&ipsapp.ipsap_sa_ptr->ipsa_lock);
4610      -                        } else {
4611      -                                mutex_enter(&ipsapp.ipsap_sa_ptr->ipsa_lock);
4612      -                                ipsapp.ipsap_sa_ptr->ipsa_replay =
4613      -                                    replext->sadb_x_rc_replay32;
4614      -                                ipsapp.ipsap_sa_ptr->ipsa_idleexpiretime =
4615      -                                    current +
4616      -                                    ipsapp.ipsap_sa_ptr->ipsa_idletime;
4617      -                                mutex_exit(&ipsapp.ipsap_sa_ptr->ipsa_lock);
4618      -                        }
4619      -                }
4620 4361          }
4621 4362  
4622 4363          if (sadb_msg_type == SADB_X_UPDATEPAIR) {
4623 4364                  if (ipsapp.ipsap_psa_ptr != NULL) {
4624 4365                          sadb_update_lifetimes(ipsapp.ipsap_psa_ptr, hard, soft,
4625 4366                              idle, B_FALSE);
4626 4367                          sadb_update_kmc(&sq, ipsapp.ipsap_psa_ptr);
4627 4368                  } else {
4628 4369                          *diagnostic = SADB_X_DIAGNOSTIC_PAIR_SA_NOTFOUND;
4629 4370                          error = ESRCH;
4630 4371                          goto bail;
4631 4372                  }
4632 4373          }
4633 4374  
4634 4375          if (pair_ext != NULL)
4635 4376                  error = update_pairing(&ipsapp, &sq, ksi, diagnostic);
4636 4377  
4637 4378          if (error == 0)
4638 4379                  sadb_pfkey_echo(pfkey_q, mp, (sadb_msg_t *)mp->b_cont->b_rptr,
4639 4380                      ksi, echo_target);
4640 4381  bail:
4641 4382  
4642 4383          destroy_ipsa_pair(&ipsapp);
4643 4384  
4644 4385          return (error);
4645 4386  }
4646 4387  
4647 4388  
4648 4389  static int
4649 4390  update_pairing(ipsap_t *ipsapp, ipsa_query_t *sq, keysock_in_t *ksi,
4650 4391      int *diagnostic)
4651 4392  {
4652 4393          sadb_sa_t *assoc = (sadb_sa_t *)ksi->ks_in_extv[SADB_EXT_SA];
4653 4394          sadb_x_pair_t *pair_ext =
4654 4395              (sadb_x_pair_t *)ksi->ks_in_extv[SADB_X_EXT_PAIR];
4655 4396          int error = 0;
4656 4397          ipsap_t oipsapp;
4657 4398          boolean_t undo_pair = B_FALSE;
4658 4399          uint32_t ipsa_flags;
4659 4400  
4660 4401          if (pair_ext->sadb_x_pair_spi == 0 || pair_ext->sadb_x_pair_spi ==
4661 4402              assoc->sadb_sa_spi) {
4662 4403                  *diagnostic = SADB_X_DIAGNOSTIC_PAIR_INAPPROPRIATE;
4663 4404                  return (EINVAL);
4664 4405          }
4665 4406  
4666 4407          /*
4667 4408           * Assume for now that the spi value provided in the SADB_UPDATE
4668 4409           * message was valid, update the SA with its pair spi value.
4669 4410           * If the spi turns out to be bogus or the SA no longer exists
4670 4411           * then this will be detected when the reverse update is made
4671 4412           * below.
4672 4413           */
4673 4414          mutex_enter(&ipsapp->ipsap_sa_ptr->ipsa_lock);
4674 4415          ipsapp->ipsap_sa_ptr->ipsa_flags |= IPSA_F_PAIRED;
4675 4416          ipsapp->ipsap_sa_ptr->ipsa_otherspi = pair_ext->sadb_x_pair_spi;
4676 4417          mutex_exit(&ipsapp->ipsap_sa_ptr->ipsa_lock);
4677 4418  
4678 4419          /*
4679 4420           * After updating the ipsa_otherspi element of the SA, get_ipsa_pair()
4680 4421           * should now return pointers to the SA *AND* its pair, if this is not
4681 4422           * the case, the "otherspi" either did not exist or was deleted. Also
4682 4423           * check that "otherspi" is not already paired. If everything looks
4683 4424           * good, complete the update. IPSA_REFRELE the first pair_pointer
4684 4425           * after this update to ensure its not deleted until we are done.
4685 4426           */
4686 4427          error = get_ipsa_pair(sq, &oipsapp, diagnostic);
4687 4428          if (error != 0) {
4688 4429                  /*
4689 4430                   * This should never happen, calling function still has
4690 4431                   * IPSA_REFHELD on the SA we just updated.
4691 4432                   */
4692 4433                  return (error); /* XXX EINVAL instead of ESRCH? */
4693 4434          }
4694 4435  
4695 4436          if (oipsapp.ipsap_psa_ptr == NULL) {
4696 4437                  *diagnostic = SADB_X_DIAGNOSTIC_PAIR_INAPPROPRIATE;
4697 4438                  error = EINVAL;
4698 4439                  undo_pair = B_TRUE;
4699 4440          } else {
4700 4441                  ipsa_flags = oipsapp.ipsap_psa_ptr->ipsa_flags;
4701 4442                  if ((oipsapp.ipsap_psa_ptr->ipsa_state == IPSA_STATE_DEAD) ||
4702 4443                      (oipsapp.ipsap_psa_ptr->ipsa_state == IPSA_STATE_DYING)) {
4703 4444                          /* Its dead Jim! */
4704 4445                          *diagnostic = SADB_X_DIAGNOSTIC_PAIR_INAPPROPRIATE;
4705 4446                          undo_pair = B_TRUE;
4706 4447                  } else if ((ipsa_flags & (IPSA_F_OUTBOUND | IPSA_F_INBOUND)) ==
4707 4448                      (IPSA_F_OUTBOUND | IPSA_F_INBOUND)) {
4708 4449                          /* This SA is in both hashtables. */
4709 4450                          *diagnostic = SADB_X_DIAGNOSTIC_PAIR_INAPPROPRIATE;
4710 4451                          undo_pair = B_TRUE;
4711 4452                  } else if (ipsa_flags & IPSA_F_PAIRED) {
4712 4453                          /* This SA is already paired with another. */
4713 4454                          *diagnostic = SADB_X_DIAGNOSTIC_PAIR_ALREADY;
4714 4455                          undo_pair = B_TRUE;
4715 4456                  }
4716 4457          }
4717 4458  
4718 4459          if (undo_pair) {
4719 4460                  /* The pair SA does not exist. */
4720 4461                  mutex_enter(&ipsapp->ipsap_sa_ptr->ipsa_lock);
4721 4462                  ipsapp->ipsap_sa_ptr->ipsa_flags &= ~IPSA_F_PAIRED;
4722 4463                  ipsapp->ipsap_sa_ptr->ipsa_otherspi = 0;
4723 4464                  mutex_exit(&ipsapp->ipsap_sa_ptr->ipsa_lock);
4724 4465          } else {
4725 4466                  mutex_enter(&oipsapp.ipsap_psa_ptr->ipsa_lock);
4726 4467                  oipsapp.ipsap_psa_ptr->ipsa_otherspi = assoc->sadb_sa_spi;
4727 4468                  oipsapp.ipsap_psa_ptr->ipsa_flags |= IPSA_F_PAIRED;
4728 4469                  mutex_exit(&oipsapp.ipsap_psa_ptr->ipsa_lock);
4729 4470          }
4730 4471  
4731 4472          destroy_ipsa_pair(&oipsapp);
4732 4473          return (error);
4733 4474  }
4734 4475  
4735 4476  /*
4736 4477   * The following functions deal with ACQUIRE LISTS.  An ACQUIRE list is
4737 4478   * a list of outstanding SADB_ACQUIRE messages.  If ipsec_getassocbyconn() fails
4738 4479   * for an outbound datagram, that datagram is queued up on an ACQUIRE record,
4739 4480   * and an SADB_ACQUIRE message is sent up.  Presumably, a user-space key
4740 4481   * management daemon will process the ACQUIRE, use a SADB_GETSPI to reserve
4741 4482   * an SPI value and a larval SA, then SADB_UPDATE the larval SA, and ADD the
4742 4483   * other direction's SA.
4743 4484   */
4744 4485  
4745 4486  /*
4746 4487   * Check the ACQUIRE lists.  If there's an existing ACQUIRE record,
4747 4488   * grab it, lock it, and return it.  Otherwise return NULL.
4748 4489   *
4749 4490   * XXX MLS number of arguments getting unwieldy here
4750 4491   */
4751 4492  static ipsacq_t *
4752 4493  sadb_checkacquire(iacqf_t *bucket, ipsec_action_t *ap, ipsec_policy_t *pp,
4753 4494      uint32_t *src, uint32_t *dst, uint32_t *isrc, uint32_t *idst,
4754 4495      uint64_t unique_id, ts_label_t *tsl)
4755 4496  {
4756 4497          ipsacq_t *walker;
4757 4498          sa_family_t fam;
4758 4499          uint32_t blank_address[4] = {0, 0, 0, 0};
4759 4500  
4760 4501          if (isrc == NULL) {
4761 4502                  ASSERT(idst == NULL);
4762 4503                  isrc = idst = blank_address;
4763 4504          }
4764 4505  
4765 4506          /*
4766 4507           * Scan list for duplicates.  Check for UNIQUE, src/dest, policy.
4767 4508           *
4768 4509           * XXX May need search for duplicates based on other things too!
4769 4510           */
4770 4511          for (walker = bucket->iacqf_ipsacq; walker != NULL;
4771 4512              walker = walker->ipsacq_next) {
4772 4513                  mutex_enter(&walker->ipsacq_lock);
4773 4514                  fam = walker->ipsacq_addrfam;
4774 4515                  if (IPSA_ARE_ADDR_EQUAL(dst, walker->ipsacq_dstaddr, fam) &&
4775 4516                      IPSA_ARE_ADDR_EQUAL(src, walker->ipsacq_srcaddr, fam) &&
4776 4517                      ip_addr_match((uint8_t *)isrc, walker->ipsacq_innersrcpfx,
4777 4518                      (in6_addr_t *)walker->ipsacq_innersrc) &&
4778 4519                      ip_addr_match((uint8_t *)idst, walker->ipsacq_innerdstpfx,
4779 4520                      (in6_addr_t *)walker->ipsacq_innerdst) &&
4780 4521                      (ap == walker->ipsacq_act) &&
4781 4522                      (pp == walker->ipsacq_policy) &&
4782 4523                      /* XXX do deep compares of ap/pp? */
4783 4524                      (unique_id == walker->ipsacq_unique_id) &&
4784 4525                      (ipsec_label_match(tsl, walker->ipsacq_tsl)))
4785 4526                          break;                  /* everything matched */
4786 4527                  mutex_exit(&walker->ipsacq_lock);
4787 4528          }
4788 4529  
4789 4530          return (walker);
4790 4531  }
4791 4532  
4792 4533  /*
4793 4534   * For this mblk, insert a new acquire record.  Assume bucket contains addrs
4794 4535   * of all of the same length.  Give up (and drop) if memory
4795 4536   * cannot be allocated for a new one; otherwise, invoke callback to
4796 4537   * send the acquire up..
4797 4538   *
4798 4539   * In cases where we need both AH and ESP, add the SA to the ESP ACQUIRE
4799 4540   * list.  The ah_add_sa_finish() routines can look at the packet's attached
4800 4541   * attributes and handle this case specially.
4801 4542   */
4802 4543  void
4803 4544  sadb_acquire(mblk_t *datamp, ip_xmit_attr_t *ixa, boolean_t need_ah,
4804 4545      boolean_t need_esp)
4805 4546  {
4806 4547          mblk_t  *asyncmp;
4807 4548          sadbp_t *spp;
4808 4549          sadb_t *sp;
4809 4550          ipsacq_t *newbie;
4810 4551          iacqf_t *bucket;
4811 4552          mblk_t *extended;
4812 4553          ipha_t *ipha = (ipha_t *)datamp->b_rptr;
4813 4554          ip6_t *ip6h = (ip6_t *)datamp->b_rptr;
4814 4555          uint32_t *src, *dst, *isrc, *idst;
4815 4556          ipsec_policy_t *pp = ixa->ixa_ipsec_policy;
4816 4557          ipsec_action_t *ap = ixa->ixa_ipsec_action;
4817 4558          sa_family_t af;
4818 4559          int hashoffset;
4819 4560          uint32_t seq;
4820 4561          uint64_t unique_id = 0;
4821 4562          ipsec_selector_t sel;
4822 4563          boolean_t tunnel_mode = (ixa->ixa_flags & IXAF_IPSEC_TUNNEL) != 0;
4823 4564          ts_label_t      *tsl = NULL;
4824 4565          netstack_t      *ns = ixa->ixa_ipst->ips_netstack;
4825 4566          ipsec_stack_t   *ipss = ns->netstack_ipsec;
4826 4567          sadb_sens_t     *sens = NULL;
4827 4568          int             sens_len;
4828 4569  
4829 4570          ASSERT((pp != NULL) || (ap != NULL));
4830 4571  
4831 4572          ASSERT(need_ah != NULL || need_esp != NULL);
4832 4573  
4833 4574          /* Assign sadb pointers */
4834 4575          if (need_esp) { /* ESP for AH+ESP */
4835 4576                  ipsecesp_stack_t *espstack = ns->netstack_ipsecesp;
4836 4577  
4837 4578                  spp = &espstack->esp_sadb;
4838 4579          } else {
4839 4580                  ipsecah_stack_t *ahstack = ns->netstack_ipsecah;
4840 4581  
4841 4582                  spp = &ahstack->ah_sadb;
4842 4583          }
4843 4584          sp = (ixa->ixa_flags & IXAF_IS_IPV4) ? &spp->s_v4 : &spp->s_v6;
4844 4585  
4845 4586          if (is_system_labeled())
4846 4587                  tsl = ixa->ixa_tsl;
4847 4588  
4848 4589          if (ap == NULL)
4849 4590                  ap = pp->ipsp_act;
4850 4591  
4851 4592          ASSERT(ap != NULL);
4852 4593  
4853 4594          if (ap->ipa_act.ipa_apply.ipp_use_unique || tunnel_mode)
4854 4595                  unique_id = SA_FORM_UNIQUE_ID(ixa);
4855 4596  
4856 4597          /*
4857 4598           * Set up an ACQUIRE record.
4858 4599           *
4859 4600           * Immediately, make sure the ACQUIRE sequence number doesn't slip
4860 4601           * below the lowest point allowed in the kernel.  (In other words,
4861 4602           * make sure the high bit on the sequence number is set.)
4862 4603           */
4863 4604  
4864 4605          seq = keysock_next_seq(ns) | IACQF_LOWEST_SEQ;
4865 4606  
4866 4607          if (IPH_HDR_VERSION(ipha) == IP_VERSION) {
4867 4608                  src = (uint32_t *)&ipha->ipha_src;
4868 4609                  dst = (uint32_t *)&ipha->ipha_dst;
4869 4610                  af = AF_INET;
4870 4611                  hashoffset = OUTBOUND_HASH_V4(sp, ipha->ipha_dst);
4871 4612                  ASSERT(ixa->ixa_flags & IXAF_IS_IPV4);
4872 4613          } else {
4873 4614                  ASSERT(IPH_HDR_VERSION(ipha) == IPV6_VERSION);
4874 4615                  src = (uint32_t *)&ip6h->ip6_src;
4875 4616                  dst = (uint32_t *)&ip6h->ip6_dst;
4876 4617                  af = AF_INET6;
4877 4618                  hashoffset = OUTBOUND_HASH_V6(sp, ip6h->ip6_dst);
4878 4619                  ASSERT(!(ixa->ixa_flags & IXAF_IS_IPV4));
4879 4620          }
4880 4621  
4881 4622          if (tunnel_mode) {
4882 4623                  if (pp == NULL) {
4883 4624                          /*
4884 4625                           * Tunnel mode with no policy pointer means this is a
4885 4626                           * reflected ICMP (like a ECHO REQUEST) that came in
4886 4627                           * with self-encapsulated protection.  Until we better
4887 4628                           * support this, drop the packet.
4888 4629                           */
4889 4630                          ip_drop_packet(datamp, B_FALSE, NULL,
4890 4631                              DROPPER(ipss, ipds_spd_got_selfencap),
4891 4632                              &ipss->ipsec_spd_dropper);
4892 4633                          return;
4893 4634                  }
4894 4635                  /* Snag inner addresses. */
4895 4636                  isrc = ixa->ixa_ipsec_insrc;
4896 4637                  idst = ixa->ixa_ipsec_indst;
4897 4638          } else {
4898 4639                  isrc = idst = NULL;
4899 4640          }
4900 4641  
4901 4642          /*
4902 4643           * Check buckets to see if there is an existing entry.  If so,
4903 4644           * grab it.  sadb_checkacquire locks newbie if found.
4904 4645           */
4905 4646          bucket = &(sp->sdb_acq[hashoffset]);
4906 4647          mutex_enter(&bucket->iacqf_lock);
4907 4648          newbie = sadb_checkacquire(bucket, ap, pp, src, dst, isrc, idst,
4908 4649              unique_id, tsl);
4909 4650  
4910 4651          if (newbie == NULL) {
4911 4652                  /*
4912 4653                   * Otherwise, allocate a new one.
4913 4654                   */
4914 4655                  newbie = kmem_zalloc(sizeof (*newbie), KM_NOSLEEP);
4915 4656                  if (newbie == NULL) {
4916 4657                          mutex_exit(&bucket->iacqf_lock);
4917 4658                          ip_drop_packet(datamp, B_FALSE, NULL,
4918 4659                              DROPPER(ipss, ipds_sadb_acquire_nomem),
4919 4660                              &ipss->ipsec_sadb_dropper);
4920 4661                          return;
4921 4662                  }
4922 4663                  newbie->ipsacq_policy = pp;
4923 4664                  if (pp != NULL) {
4924 4665                          IPPOL_REFHOLD(pp);
4925 4666                  }
4926 4667                  IPACT_REFHOLD(ap);
4927 4668                  newbie->ipsacq_act = ap;
4928 4669                  newbie->ipsacq_linklock = &bucket->iacqf_lock;
4929 4670                  newbie->ipsacq_next = bucket->iacqf_ipsacq;
4930 4671                  newbie->ipsacq_ptpn = &bucket->iacqf_ipsacq;
4931 4672                  if (newbie->ipsacq_next != NULL)
4932 4673                          newbie->ipsacq_next->ipsacq_ptpn = &newbie->ipsacq_next;
4933 4674  
4934 4675                  bucket->iacqf_ipsacq = newbie;
4935 4676                  mutex_init(&newbie->ipsacq_lock, NULL, MUTEX_DEFAULT, NULL);
4936 4677                  mutex_enter(&newbie->ipsacq_lock);
4937 4678          }
4938 4679  
4939 4680          /*
4940 4681           * XXX MLS does it actually help us to drop the bucket lock here?
4941 4682           * we have inserted a half-built, locked acquire record into the
4942 4683           * bucket.  any competing thread will now be able to lock the bucket
4943 4684           * to scan it, but will immediately pile up on the new acquire
4944 4685           * record's lock; I don't think we gain anything here other than to
4945 4686           * disperse blame for lock contention.
4946 4687           *
4947 4688           * we might be able to dispense with acquire record locks entirely..
4948 4689           * just use the bucket locks..
4949 4690           */
4950 4691  
4951 4692          mutex_exit(&bucket->iacqf_lock);
4952 4693  
4953 4694          /*
4954 4695           * This assert looks silly for now, but we may need to enter newbie's
4955 4696           * mutex during a search.
4956 4697           */
4957 4698          ASSERT(MUTEX_HELD(&newbie->ipsacq_lock));
4958 4699  
4959 4700          /*
4960 4701           * Make the ip_xmit_attr_t into something we can queue.
4961 4702           * If no memory it frees datamp.
4962 4703           */
4963 4704          asyncmp = ip_xmit_attr_to_mblk(ixa);
4964 4705          if (asyncmp != NULL)
4965 4706                  linkb(asyncmp, datamp);
4966 4707  
4967 4708          /* Queue up packet.  Use b_next. */
4968 4709  
4969 4710          if (asyncmp == NULL) {
4970 4711                  /* Statistics for allocation failure */
4971 4712                  if (ixa->ixa_flags & IXAF_IS_IPV4) {
4972 4713                          BUMP_MIB(&ixa->ixa_ipst->ips_ip_mib,
4973 4714                              ipIfStatsOutDiscards);
4974 4715                  } else {
4975 4716                          BUMP_MIB(&ixa->ixa_ipst->ips_ip6_mib,
4976 4717                              ipIfStatsOutDiscards);
4977 4718                  }
4978 4719                  ip_drop_output("No memory for asyncmp", datamp, NULL);
4979 4720                  freemsg(datamp);
4980 4721          } else if (newbie->ipsacq_numpackets == 0) {
4981 4722                  /* First one. */
4982 4723                  newbie->ipsacq_mp = asyncmp;
4983 4724                  newbie->ipsacq_numpackets = 1;
4984 4725                  newbie->ipsacq_expire = gethrestime_sec();
4985 4726                  /*
4986 4727                   * Extended ACQUIRE with both AH+ESP will use ESP's timeout
4987 4728                   * value.
4988 4729                   */
4989 4730                  newbie->ipsacq_expire += *spp->s_acquire_timeout;
4990 4731                  newbie->ipsacq_seq = seq;
4991 4732                  newbie->ipsacq_addrfam = af;
4992 4733  
4993 4734                  newbie->ipsacq_srcport = ixa->ixa_ipsec_src_port;
4994 4735                  newbie->ipsacq_dstport = ixa->ixa_ipsec_dst_port;
4995 4736                  newbie->ipsacq_icmp_type = ixa->ixa_ipsec_icmp_type;
4996 4737                  newbie->ipsacq_icmp_code = ixa->ixa_ipsec_icmp_code;
4997 4738                  if (tunnel_mode) {
4998 4739                          newbie->ipsacq_inneraddrfam = ixa->ixa_ipsec_inaf;
4999 4740                          newbie->ipsacq_proto = ixa->ixa_ipsec_inaf == AF_INET6 ?
5000 4741                              IPPROTO_IPV6 : IPPROTO_ENCAP;
5001 4742                          newbie->ipsacq_innersrcpfx = ixa->ixa_ipsec_insrcpfx;
5002 4743                          newbie->ipsacq_innerdstpfx = ixa->ixa_ipsec_indstpfx;
5003 4744                          IPSA_COPY_ADDR(newbie->ipsacq_innersrc,
5004 4745                              ixa->ixa_ipsec_insrc, ixa->ixa_ipsec_inaf);
5005 4746                          IPSA_COPY_ADDR(newbie->ipsacq_innerdst,
5006 4747                              ixa->ixa_ipsec_indst, ixa->ixa_ipsec_inaf);
5007 4748                  } else {
5008 4749                          newbie->ipsacq_proto = ixa->ixa_ipsec_proto;
5009 4750                  }
5010 4751                  newbie->ipsacq_unique_id = unique_id;
5011 4752  
5012 4753                  if (ixa->ixa_tsl != NULL) {
5013 4754                          label_hold(ixa->ixa_tsl);
5014 4755                          newbie->ipsacq_tsl = ixa->ixa_tsl;
5015 4756                  }
5016 4757          } else {
5017 4758                  /* Scan to the end of the list & insert. */
5018 4759                  mblk_t *lastone = newbie->ipsacq_mp;
5019 4760  
5020 4761                  while (lastone->b_next != NULL)
5021 4762                          lastone = lastone->b_next;
5022 4763                  lastone->b_next = asyncmp;
5023 4764                  if (newbie->ipsacq_numpackets++ == ipsacq_maxpackets) {
5024 4765                          newbie->ipsacq_numpackets = ipsacq_maxpackets;
5025 4766                          lastone = newbie->ipsacq_mp;
5026 4767                          newbie->ipsacq_mp = lastone->b_next;
5027 4768                          lastone->b_next = NULL;
5028 4769  
5029 4770                          /* Freeing the async message */
5030 4771                          lastone = ip_xmit_attr_free_mblk(lastone);
5031 4772                          ip_drop_packet(lastone, B_FALSE, NULL,
5032 4773                              DROPPER(ipss, ipds_sadb_acquire_toofull),
5033 4774                              &ipss->ipsec_sadb_dropper);
5034 4775                  } else {
5035 4776                          IP_ACQUIRE_STAT(ipss, qhiwater,
5036 4777                              newbie->ipsacq_numpackets);
5037 4778                  }
5038 4779          }
5039 4780  
5040 4781          /*
5041 4782           * Reset addresses.  Set them to the most recently added mblk chain,
5042 4783           * so that the address pointers in the acquire record will point
5043 4784           * at an mblk still attached to the acquire list.
5044 4785           */
5045 4786  
5046 4787          newbie->ipsacq_srcaddr = src;
5047 4788          newbie->ipsacq_dstaddr = dst;
5048 4789  
5049 4790          /*
5050 4791           * If the acquire record has more than one queued packet, we've
5051 4792           * already sent an ACQUIRE, and don't need to repeat ourself.
5052 4793           */
5053 4794          if (newbie->ipsacq_seq != seq || newbie->ipsacq_numpackets > 1) {
5054 4795                  /* I have an acquire outstanding already! */
5055 4796                  mutex_exit(&newbie->ipsacq_lock);
5056 4797                  return;
5057 4798          }
5058 4799  
5059 4800          if (!keysock_extended_reg(ns))
5060 4801                  goto punt_extended;
5061 4802          /*
5062 4803           * Construct an extended ACQUIRE.  There are logging
5063 4804           * opportunities here in failure cases.
5064 4805           */
5065 4806          bzero(&sel, sizeof (sel));
5066 4807          sel.ips_isv4 = (ixa->ixa_flags & IXAF_IS_IPV4) != 0;
5067 4808          if (tunnel_mode) {
5068 4809                  sel.ips_protocol = (ixa->ixa_ipsec_inaf == AF_INET) ?
5069 4810                      IPPROTO_ENCAP : IPPROTO_IPV6;
5070 4811          } else {
5071 4812                  sel.ips_protocol = ixa->ixa_ipsec_proto;
5072 4813                  sel.ips_local_port = ixa->ixa_ipsec_src_port;
5073 4814                  sel.ips_remote_port = ixa->ixa_ipsec_dst_port;
5074 4815          }
5075 4816          sel.ips_icmp_type = ixa->ixa_ipsec_icmp_type;
5076 4817          sel.ips_icmp_code = ixa->ixa_ipsec_icmp_code;
5077 4818          sel.ips_is_icmp_inv_acq = 0;
5078 4819          if (af == AF_INET) {
5079 4820                  sel.ips_local_addr_v4 = ipha->ipha_src;
5080 4821                  sel.ips_remote_addr_v4 = ipha->ipha_dst;
5081 4822          } else {
5082 4823                  sel.ips_local_addr_v6 = ip6h->ip6_src;
5083 4824                  sel.ips_remote_addr_v6 = ip6h->ip6_dst;
5084 4825          }
5085 4826  
5086 4827          extended = sadb_keysock_out(0);
5087 4828          if (extended == NULL)
5088 4829                  goto punt_extended;
5089 4830  
5090 4831          if (ixa->ixa_tsl != NULL) {
5091 4832                  /*
5092 4833                   * XXX MLS correct condition here?
5093 4834                   * XXX MLS other credential attributes in acquire?
5094 4835                   * XXX malloc failure?  don't fall back to original?
5095 4836                   */
5096 4837                  sens = sadb_make_sens_ext(ixa->ixa_tsl, &sens_len);
5097 4838  
5098 4839                  if (sens == NULL) {
5099 4840                          freeb(extended);
5100 4841                          goto punt_extended;
5101 4842                  }
5102 4843          }
5103 4844  
5104 4845          extended->b_cont = sadb_extended_acquire(&sel, pp, ap, tunnel_mode,
5105 4846              seq, 0, sens, ns);
5106 4847  
5107 4848          if (sens != NULL)
5108 4849                  kmem_free(sens, sens_len);
5109 4850  
5110 4851          if (extended->b_cont == NULL) {
5111 4852                  freeb(extended);
5112 4853                  goto punt_extended;
5113 4854          }
5114 4855  
5115 4856          /*
5116 4857           * Send an ACQUIRE message (and possible an extended ACQUIRE) based on
5117 4858           * this new record.  The send-acquire callback assumes that acqrec is
5118 4859           * already locked.
5119 4860           */
5120 4861          (*spp->s_acqfn)(newbie, extended, ns);
5121 4862          return;
5122 4863  
5123 4864  punt_extended:
5124 4865          (*spp->s_acqfn)(newbie, NULL, ns);
5125 4866  }
5126 4867  
5127 4868  /*
5128 4869   * Unlink and free an acquire record.
5129 4870   */
5130 4871  void
5131 4872  sadb_destroy_acquire(ipsacq_t *acqrec, netstack_t *ns)
5132 4873  {
5133 4874          mblk_t          *mp;
5134 4875          ipsec_stack_t   *ipss = ns->netstack_ipsec;
5135 4876  
5136 4877          ASSERT(MUTEX_HELD(acqrec->ipsacq_linklock));
5137 4878  
5138 4879          if (acqrec->ipsacq_policy != NULL) {
5139 4880                  IPPOL_REFRELE(acqrec->ipsacq_policy);
5140 4881          }
5141 4882          if (acqrec->ipsacq_act != NULL) {
5142 4883                  IPACT_REFRELE(acqrec->ipsacq_act);
5143 4884          }
5144 4885  
5145 4886          /* Unlink */
5146 4887          *(acqrec->ipsacq_ptpn) = acqrec->ipsacq_next;
5147 4888          if (acqrec->ipsacq_next != NULL)
5148 4889                  acqrec->ipsacq_next->ipsacq_ptpn = acqrec->ipsacq_ptpn;
5149 4890  
5150 4891          if (acqrec->ipsacq_tsl != NULL) {
5151 4892                  label_rele(acqrec->ipsacq_tsl);
5152 4893                  acqrec->ipsacq_tsl = NULL;
5153 4894          }
5154 4895  
5155 4896          /*
5156 4897           * Free hanging mp's.
5157 4898           *
5158 4899           * XXX Instead of freemsg(), perhaps use IPSEC_REQ_FAILED.
5159 4900           */
5160 4901  
5161 4902          mutex_enter(&acqrec->ipsacq_lock);
5162 4903          while (acqrec->ipsacq_mp != NULL) {
5163 4904                  mp = acqrec->ipsacq_mp;
5164 4905                  acqrec->ipsacq_mp = mp->b_next;
5165 4906                  mp->b_next = NULL;
5166 4907                  /* Freeing the async message */
5167 4908                  mp = ip_xmit_attr_free_mblk(mp);
5168 4909                  ip_drop_packet(mp, B_FALSE, NULL,
5169 4910                      DROPPER(ipss, ipds_sadb_acquire_timeout),
5170 4911                      &ipss->ipsec_sadb_dropper);
5171 4912          }
5172 4913          mutex_exit(&acqrec->ipsacq_lock);
5173 4914  
5174 4915          /* Free */
5175 4916          mutex_destroy(&acqrec->ipsacq_lock);
5176 4917          kmem_free(acqrec, sizeof (*acqrec));
5177 4918  }
5178 4919  
5179 4920  /*
5180 4921   * Destroy an acquire list fanout.
5181 4922   */
5182 4923  static void
5183 4924  sadb_destroy_acqlist(iacqf_t **listp, uint_t numentries, boolean_t forever,
5184 4925      netstack_t *ns)
5185 4926  {
5186 4927          int i;
5187 4928          iacqf_t *list = *listp;
5188 4929  
5189 4930          if (list == NULL)
5190 4931                  return;
5191 4932  
5192 4933          for (i = 0; i < numentries; i++) {
5193 4934                  mutex_enter(&(list[i].iacqf_lock));
5194 4935                  while (list[i].iacqf_ipsacq != NULL)
5195 4936                          sadb_destroy_acquire(list[i].iacqf_ipsacq, ns);
5196 4937                  mutex_exit(&(list[i].iacqf_lock));
5197 4938                  if (forever)
5198 4939                          mutex_destroy(&(list[i].iacqf_lock));
5199 4940          }
5200 4941  
5201 4942          if (forever) {
5202 4943                  *listp = NULL;
5203 4944                  kmem_free(list, numentries * sizeof (*list));
5204 4945          }
5205 4946  }
5206 4947  
5207 4948  /*
5208 4949   * Create an algorithm descriptor for an extended ACQUIRE.  Filter crypto
5209 4950   * framework's view of reality vs. IPsec's.  EF's wins, BTW.
5210 4951   */
5211 4952  static uint8_t *
5212 4953  sadb_new_algdesc(uint8_t *start, uint8_t *limit,
5213 4954      sadb_x_ecomb_t *ecomb, uint8_t satype, uint8_t algtype,
5214 4955      uint8_t alg, uint16_t minbits, uint16_t maxbits, ipsec_stack_t *ipss)
5215 4956  {
5216 4957          uint8_t *cur = start;
5217 4958          ipsec_alginfo_t *algp;
5218 4959          sadb_x_algdesc_t *algdesc = (sadb_x_algdesc_t *)cur;
5219 4960  
5220 4961          cur += sizeof (*algdesc);
5221 4962          if (cur >= limit)
5222 4963                  return (NULL);
5223 4964  
5224 4965          ecomb->sadb_x_ecomb_numalgs++;
5225 4966  
5226 4967          /*
5227 4968           * Normalize vs. crypto framework's limits.  This way, you can specify
5228 4969           * a stronger policy, and when the framework loads a stronger version,
5229 4970           * you can just keep plowing w/o rewhacking your SPD.
5230 4971           */
5231 4972          mutex_enter(&ipss->ipsec_alg_lock);
5232 4973          algp = ipss->ipsec_alglists[(algtype == SADB_X_ALGTYPE_AUTH) ?
5233 4974              IPSEC_ALG_AUTH : IPSEC_ALG_ENCR][alg];
5234 4975          if (algp == NULL) {
5235 4976                  mutex_exit(&ipss->ipsec_alg_lock);
5236 4977                  return (NULL);  /* Algorithm doesn't exist.  Fail gracefully. */
5237 4978          }
5238 4979          if (minbits < algp->alg_ef_minbits)
5239 4980                  minbits = algp->alg_ef_minbits;
5240 4981          if (maxbits > algp->alg_ef_maxbits)
5241 4982                  maxbits = algp->alg_ef_maxbits;
5242 4983          mutex_exit(&ipss->ipsec_alg_lock);
5243 4984  
5244 4985          algdesc->sadb_x_algdesc_reserved = SADB_8TO1(algp->alg_saltlen);
5245 4986          algdesc->sadb_x_algdesc_satype = satype;
5246 4987          algdesc->sadb_x_algdesc_algtype = algtype;
5247 4988          algdesc->sadb_x_algdesc_alg = alg;
5248 4989          algdesc->sadb_x_algdesc_minbits = minbits;
5249 4990          algdesc->sadb_x_algdesc_maxbits = maxbits;
5250 4991  
5251 4992          return (cur);
5252 4993  }
5253 4994  
5254 4995  /*
5255 4996   * Convert the given ipsec_action_t into an ecomb starting at *ecomb
5256 4997   * which must fit before *limit
5257 4998   *
5258 4999   * return NULL if we ran out of room or a pointer to the end of the ecomb.
5259 5000   */
5260 5001  static uint8_t *
5261 5002  sadb_action_to_ecomb(uint8_t *start, uint8_t *limit, ipsec_action_t *act,
5262 5003      netstack_t *ns)
5263 5004  {
5264 5005          uint8_t *cur = start;
5265 5006          sadb_x_ecomb_t *ecomb = (sadb_x_ecomb_t *)cur;
5266 5007          ipsec_prot_t *ipp;
5267 5008          ipsec_stack_t *ipss = ns->netstack_ipsec;
5268 5009  
5269 5010          cur += sizeof (*ecomb);
5270 5011          if (cur >= limit)
5271 5012                  return (NULL);
5272 5013  
5273 5014          ASSERT(act->ipa_act.ipa_type == IPSEC_ACT_APPLY);
5274 5015  
5275 5016          ipp = &act->ipa_act.ipa_apply;
5276 5017  
5277 5018          ecomb->sadb_x_ecomb_numalgs = 0;
5278 5019          ecomb->sadb_x_ecomb_reserved = 0;
5279 5020          ecomb->sadb_x_ecomb_reserved2 = 0;
5280 5021          /*
5281 5022           * No limits on allocations, since we really don't support that
5282 5023           * concept currently.
5283 5024           */
5284 5025          ecomb->sadb_x_ecomb_soft_allocations = 0;
5285 5026          ecomb->sadb_x_ecomb_hard_allocations = 0;
5286 5027  
5287 5028          /*
5288 5029           * XXX TBD: Policy or global parameters will eventually be
5289 5030           * able to fill in some of these.
5290 5031           */
5291 5032          ecomb->sadb_x_ecomb_flags = 0;
5292 5033          ecomb->sadb_x_ecomb_soft_bytes = 0;
5293 5034          ecomb->sadb_x_ecomb_hard_bytes = 0;
5294 5035          ecomb->sadb_x_ecomb_soft_addtime = 0;
5295 5036          ecomb->sadb_x_ecomb_hard_addtime = 0;
5296 5037          ecomb->sadb_x_ecomb_soft_usetime = 0;
5297 5038          ecomb->sadb_x_ecomb_hard_usetime = 0;
5298 5039  
5299 5040          if (ipp->ipp_use_ah) {
5300 5041                  cur = sadb_new_algdesc(cur, limit, ecomb,
5301 5042                      SADB_SATYPE_AH, SADB_X_ALGTYPE_AUTH, ipp->ipp_auth_alg,
5302 5043                      ipp->ipp_ah_minbits, ipp->ipp_ah_maxbits, ipss);
5303 5044                  if (cur == NULL)
5304 5045                          return (NULL);
5305 5046                  ipsecah_fill_defs(ecomb, ns);
5306 5047          }
5307 5048  
5308 5049          if (ipp->ipp_use_esp) {
5309 5050                  if (ipp->ipp_use_espa) {
5310 5051                          cur = sadb_new_algdesc(cur, limit, ecomb,
5311 5052                              SADB_SATYPE_ESP, SADB_X_ALGTYPE_AUTH,
5312 5053                              ipp->ipp_esp_auth_alg,
5313 5054                              ipp->ipp_espa_minbits,
5314 5055                              ipp->ipp_espa_maxbits, ipss);
5315 5056                          if (cur == NULL)
5316 5057                                  return (NULL);
5317 5058                  }
5318 5059  
5319 5060                  cur = sadb_new_algdesc(cur, limit, ecomb,
5320 5061                      SADB_SATYPE_ESP, SADB_X_ALGTYPE_CRYPT,
5321 5062                      ipp->ipp_encr_alg,
5322 5063                      ipp->ipp_espe_minbits,
5323 5064                      ipp->ipp_espe_maxbits, ipss);
5324 5065                  if (cur == NULL)
5325 5066                          return (NULL);
5326 5067                  /* Fill in lifetimes if and only if AH didn't already... */
5327 5068                  if (!ipp->ipp_use_ah)
5328 5069                          ipsecesp_fill_defs(ecomb, ns);
5329 5070          }
5330 5071  
5331 5072          return (cur);
5332 5073  }
5333 5074  
5334 5075  #include <sys/tsol/label_macro.h> /* XXX should not need this */
5335 5076  
5336 5077  /*
5337 5078   * From a cred_t, construct a sensitivity label extension
5338 5079   *
5339 5080   * We send up a fixed-size sensitivity label bitmap, and are perhaps
5340 5081   * overly chummy with the underlying data structures here.
5341 5082   */
5342 5083  
5343 5084  /* ARGSUSED */
5344 5085  int
5345 5086  sadb_sens_len_from_label(ts_label_t *tsl)
5346 5087  {
5347 5088          int baselen = sizeof (sadb_sens_t) + _C_LEN * 4;
5348 5089          return (roundup(baselen, sizeof (uint64_t)));
5349 5090  }
5350 5091  
5351 5092  void
5352 5093  sadb_sens_from_label(sadb_sens_t *sens, int exttype, ts_label_t *tsl,
5353 5094      int senslen)
5354 5095  {
5355 5096          uint8_t *bitmap;
5356 5097          bslabel_t *sl;
5357 5098  
5358 5099          /* LINTED */
5359 5100          ASSERT((_C_LEN & 1) == 0);
5360 5101          ASSERT((senslen & 7) == 0);
5361 5102  
5362 5103          sl = label2bslabel(tsl);
5363 5104  
5364 5105          sens->sadb_sens_exttype = exttype;
5365 5106          sens->sadb_sens_len = SADB_8TO64(senslen);
5366 5107  
5367 5108          sens->sadb_sens_dpd = tsl->tsl_doi;
5368 5109          sens->sadb_sens_sens_level = LCLASS(sl);
5369 5110          sens->sadb_sens_integ_level = 0; /* TBD */
5370 5111          sens->sadb_sens_sens_len = _C_LEN >> 1;
5371 5112          sens->sadb_sens_integ_len = 0; /* TBD */
5372 5113          sens->sadb_x_sens_flags = 0;
5373 5114  
5374 5115          bitmap = (uint8_t *)(sens + 1);
5375 5116          bcopy(&(((_bslabel_impl_t *)sl)->compartments), bitmap, _C_LEN * 4);
5376 5117  }
5377 5118  
5378 5119  static sadb_sens_t *
5379 5120  sadb_make_sens_ext(ts_label_t *tsl, int *len)
5380 5121  {
5381 5122          /* XXX allocation failure? */
5382 5123          int sens_len = sadb_sens_len_from_label(tsl);
5383 5124  
5384 5125          sadb_sens_t *sens = kmem_alloc(sens_len, KM_SLEEP);
5385 5126  
5386 5127          sadb_sens_from_label(sens, SADB_EXT_SENSITIVITY, tsl, sens_len);
5387 5128  
5388 5129          *len = sens_len;
5389 5130  
5390 5131          return (sens);
5391 5132  }
5392 5133  
5393 5134  /*
5394 5135   * Okay, how do we report errors/invalid labels from this?
5395 5136   * With a special designated "not a label" cred_t ?
5396 5137   */
5397 5138  /* ARGSUSED */
5398 5139  ts_label_t *
5399 5140  sadb_label_from_sens(sadb_sens_t *sens, uint64_t *bitmap)
5400 5141  {
5401 5142          int bitmap_len = SADB_64TO8(sens->sadb_sens_sens_len);
5402 5143          bslabel_t sl;
5403 5144          ts_label_t *tsl;
5404 5145  
5405 5146          if (sens->sadb_sens_integ_level != 0)
5406 5147                  return (NULL);
5407 5148          if (sens->sadb_sens_integ_len != 0)
5408 5149                  return (NULL);
5409 5150          if (bitmap_len > _C_LEN * 4)
5410 5151                  return (NULL);
5411 5152  
5412 5153          bsllow(&sl);
5413 5154          LCLASS_SET((_bslabel_impl_t *)&sl, sens->sadb_sens_sens_level);
5414 5155          bcopy(bitmap, &((_bslabel_impl_t *)&sl)->compartments,
5415 5156              bitmap_len);
5416 5157  
5417 5158          tsl = labelalloc(&sl, sens->sadb_sens_dpd, KM_NOSLEEP);
5418 5159          if (tsl == NULL)
5419 5160                  return (NULL);
5420 5161  
5421 5162          if (sens->sadb_x_sens_flags & SADB_X_SENS_UNLABELED)
5422 5163                  tsl->tsl_flags |= TSLF_UNLABELED;
5423 5164          return (tsl);
5424 5165  }
5425 5166  
5426 5167  /* End XXX label-library-leakage */
5427 5168  
5428 5169  /*
5429 5170   * Construct an extended ACQUIRE message based on a selector and the resulting
5430 5171   * IPsec action.
5431 5172   *
5432 5173   * NOTE: This is used by both inverse ACQUIRE and actual ACQUIRE
5433 5174   * generation. As a consequence, expect this function to evolve
5434 5175   * rapidly.
5435 5176   */
5436 5177  static mblk_t *
5437 5178  sadb_extended_acquire(ipsec_selector_t *sel, ipsec_policy_t *pol,
5438 5179      ipsec_action_t *act, boolean_t tunnel_mode, uint32_t seq, uint32_t pid,
5439 5180      sadb_sens_t *sens, netstack_t *ns)
5440 5181  {
5441 5182          mblk_t *mp;
5442 5183          sadb_msg_t *samsg;
5443 5184          uint8_t *start, *cur, *end;
5444 5185          uint32_t *saddrptr, *daddrptr;
5445 5186          sa_family_t af;
5446 5187          sadb_prop_t *eprop;
5447 5188          ipsec_action_t *ap, *an;
5448 5189          ipsec_selkey_t *ipsl;
5449 5190          uint8_t proto, pfxlen;
5450 5191          uint16_t lport, rport;
5451 5192          uint32_t kmp, kmc;
5452 5193  
5453 5194          /*
5454 5195           * Find the action we want sooner rather than later..
5455 5196           */
5456 5197          an = NULL;
5457 5198          if (pol == NULL) {
5458 5199                  ap = act;
5459 5200          } else {
5460 5201                  ap = pol->ipsp_act;
5461 5202  
5462 5203                  if (ap != NULL)
5463 5204                          an = ap->ipa_next;
5464 5205          }
5465 5206  
5466 5207          /*
5467 5208           * Just take a swag for the allocation for now.  We can always
5468 5209           * alter it later.
5469 5210           */
5470 5211  #define SADB_EXTENDED_ACQUIRE_SIZE      4096
5471 5212          mp = allocb(SADB_EXTENDED_ACQUIRE_SIZE, BPRI_HI);
5472 5213          if (mp == NULL)
5473 5214                  return (NULL);
5474 5215  
5475 5216          start = mp->b_rptr;
5476 5217          end = start + SADB_EXTENDED_ACQUIRE_SIZE;
5477 5218  
5478 5219          cur = start;
5479 5220  
5480 5221          samsg = (sadb_msg_t *)cur;
5481 5222          cur += sizeof (*samsg);
5482 5223  
5483 5224          samsg->sadb_msg_version = PF_KEY_V2;
5484 5225          samsg->sadb_msg_type = SADB_ACQUIRE;
5485 5226          samsg->sadb_msg_errno = 0;
5486 5227          samsg->sadb_msg_reserved = 0;
5487 5228          samsg->sadb_msg_satype = 0;
5488 5229          samsg->sadb_msg_seq = seq;
5489 5230          samsg->sadb_msg_pid = pid;
5490 5231  
5491 5232          if (tunnel_mode) {
5492 5233                  /*
5493 5234                   * Form inner address extensions based NOT on the inner
5494 5235                   * selectors (i.e. the packet data), but on the policy's
5495 5236                   * selector key (i.e. the policy's selector information).
5496 5237                   *
5497 5238                   * NOTE:  The position of IPv4 and IPv6 addresses is the
5498 5239                   * same in ipsec_selkey_t (unless the compiler does very
5499 5240                   * strange things with unions, consult your local C language
5500 5241                   * lawyer for details).
5501 5242                   */
5502 5243                  ASSERT(pol != NULL);
5503 5244  
5504 5245                  ipsl = &(pol->ipsp_sel->ipsl_key);
5505 5246                  if (ipsl->ipsl_valid & IPSL_IPV4) {
5506 5247                          af = AF_INET;
5507 5248                          ASSERT(sel->ips_protocol == IPPROTO_ENCAP);
5508 5249                          ASSERT(!(ipsl->ipsl_valid & IPSL_IPV6));
5509 5250                  } else {
5510 5251                          af = AF_INET6;
5511 5252                          ASSERT(sel->ips_protocol == IPPROTO_IPV6);
5512 5253                          ASSERT(ipsl->ipsl_valid & IPSL_IPV6);
5513 5254                  }
5514 5255  
5515 5256                  if (ipsl->ipsl_valid & IPSL_LOCAL_ADDR) {
5516 5257                          saddrptr = (uint32_t *)(&ipsl->ipsl_local);
5517 5258                          pfxlen = ipsl->ipsl_local_pfxlen;
5518 5259                  } else {
5519 5260                          saddrptr = (uint32_t *)(&ipv6_all_zeros);
5520 5261                          pfxlen = 0;
5521 5262                  }
5522 5263                  /* XXX What about ICMP type/code? */
5523 5264                  lport = (ipsl->ipsl_valid & IPSL_LOCAL_PORT) ?
5524 5265                      ipsl->ipsl_lport : 0;
5525 5266                  proto = (ipsl->ipsl_valid & IPSL_PROTOCOL) ?
5526 5267                      ipsl->ipsl_proto : 0;
5527 5268  
5528 5269                  cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_INNER_SRC,
5529 5270                      af, saddrptr, lport, proto, pfxlen);
5530 5271                  if (cur == NULL) {
5531 5272                          freeb(mp);
5532 5273                          return (NULL);
5533 5274                  }
5534 5275  
5535 5276                  if (ipsl->ipsl_valid & IPSL_REMOTE_ADDR) {
5536 5277                          daddrptr = (uint32_t *)(&ipsl->ipsl_remote);
5537 5278                          pfxlen = ipsl->ipsl_remote_pfxlen;
5538 5279                  } else {
5539 5280                          daddrptr = (uint32_t *)(&ipv6_all_zeros);
5540 5281                          pfxlen = 0;
5541 5282                  }
5542 5283                  /* XXX What about ICMP type/code? */
5543 5284                  rport = (ipsl->ipsl_valid & IPSL_REMOTE_PORT) ?
5544 5285                      ipsl->ipsl_rport : 0;
5545 5286  
5546 5287                  cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_INNER_DST,
5547 5288                      af, daddrptr, rport, proto, pfxlen);
5548 5289                  if (cur == NULL) {
5549 5290                          freeb(mp);
5550 5291                          return (NULL);
5551 5292                  }
5552 5293                  /*
5553 5294                   * TODO  - if we go to 3408's dream of transport mode IP-in-IP
5554 5295                   * _with_ inner-packet address selectors, we'll need to further
5555 5296                   * distinguish tunnel mode here.  For now, having inner
5556 5297                   * addresses and/or ports is sufficient.
5557 5298                   *
5558 5299                   * Meanwhile, whack proto/ports to reflect IP-in-IP for the
5559 5300                   * outer addresses.
5560 5301                   */
5561 5302                  proto = sel->ips_protocol;      /* Either _ENCAP or _IPV6 */
5562 5303                  lport = rport = 0;
5563 5304          } else if ((ap != NULL) && (!ap->ipa_want_unique)) {
5564 5305                  proto = 0;
5565 5306                  lport = 0;
5566 5307                  rport = 0;
5567 5308                  if (pol != NULL) {
5568 5309                          ipsl = &(pol->ipsp_sel->ipsl_key);
5569 5310                          if (ipsl->ipsl_valid & IPSL_PROTOCOL)
5570 5311                                  proto = ipsl->ipsl_proto;
5571 5312                          if (ipsl->ipsl_valid & IPSL_REMOTE_PORT)
5572 5313                                  rport = ipsl->ipsl_rport;
5573 5314                          if (ipsl->ipsl_valid & IPSL_LOCAL_PORT)
5574 5315                                  lport = ipsl->ipsl_lport;
5575 5316                  }
5576 5317          } else {
5577 5318                  proto = sel->ips_protocol;
5578 5319                  lport = sel->ips_local_port;
5579 5320                  rport = sel->ips_remote_port;
5580 5321          }
5581 5322  
5582 5323          af = sel->ips_isv4 ? AF_INET : AF_INET6;
5583 5324  
5584 5325          /*
5585 5326           * NOTE:  The position of IPv4 and IPv6 addresses is the same in
5586 5327           * ipsec_selector_t.
5587 5328           */
5588 5329          cur = sadb_make_addr_ext(cur, end, SADB_EXT_ADDRESS_SRC, af,
5589 5330              (uint32_t *)(&sel->ips_local_addr_v6), lport, proto, 0);
5590 5331  
5591 5332          if (cur == NULL) {
5592 5333                  freeb(mp);
5593 5334                  return (NULL);
5594 5335          }
5595 5336  
5596 5337          cur = sadb_make_addr_ext(cur, end, SADB_EXT_ADDRESS_DST, af,
5597 5338              (uint32_t *)(&sel->ips_remote_addr_v6), rport, proto, 0);
5598 5339  
5599 5340          if (cur == NULL) {
5600 5341                  freeb(mp);
5601 5342                  return (NULL);
5602 5343          }
5603 5344  
5604 5345          if (sens != NULL) {
5605 5346                  uint8_t *sensext = cur;
5606 5347                  int senslen = SADB_64TO8(sens->sadb_sens_len);
5607 5348  
5608 5349                  cur += senslen;
5609 5350                  if (cur > end) {
5610 5351                          freeb(mp);
5611 5352                          return (NULL);
5612 5353                  }
5613 5354                  bcopy(sens, sensext, senslen);
5614 5355          }
5615 5356  
5616 5357          /*
5617 5358           * This section will change a lot as policy evolves.
5618 5359           * For now, it'll be relatively simple.
5619 5360           */
5620 5361          eprop = (sadb_prop_t *)cur;
5621 5362          cur += sizeof (*eprop);
5622 5363          if (cur > end) {
5623 5364                  /* no space left */
5624 5365                  freeb(mp);
5625 5366                  return (NULL);
5626 5367          }
5627 5368  
5628 5369          eprop->sadb_prop_exttype = SADB_X_EXT_EPROP;
5629 5370          eprop->sadb_x_prop_ereserved = 0;
5630 5371          eprop->sadb_x_prop_numecombs = 0;
5631 5372          eprop->sadb_prop_replay = 32;   /* default */
5632 5373  
5633 5374          kmc = kmp = 0;
5634 5375  
5635 5376          for (; ap != NULL; ap = an) {
5636 5377                  an = (pol != NULL) ? ap->ipa_next : NULL;
5637 5378  
5638 5379                  /*
5639 5380                   * Skip non-IPsec policies
5640 5381                   */
5641 5382                  if (ap->ipa_act.ipa_type != IPSEC_ACT_APPLY)
5642 5383                          continue;
5643 5384  
5644 5385                  if (ap->ipa_act.ipa_apply.ipp_km_proto)
5645 5386                          kmp = ap->ipa_act.ipa_apply.ipp_km_proto;
5646 5387                  if (ap->ipa_act.ipa_apply.ipp_km_cookie)
5647 5388                          kmc = ap->ipa_act.ipa_apply.ipp_km_cookie;
5648 5389                  if (ap->ipa_act.ipa_apply.ipp_replay_depth) {
5649 5390                          eprop->sadb_prop_replay =
5650 5391                              ap->ipa_act.ipa_apply.ipp_replay_depth;
5651 5392                  }
5652 5393  
5653 5394                  cur = sadb_action_to_ecomb(cur, end, ap, ns);
5654 5395                  if (cur == NULL) { /* no space */
5655 5396                          freeb(mp);
5656 5397                          return (NULL);
5657 5398                  }
5658 5399                  eprop->sadb_x_prop_numecombs++;
5659 5400          }
5660 5401  
5661 5402          if (eprop->sadb_x_prop_numecombs == 0) {
5662 5403                  /*
5663 5404                   * This will happen if we fail to find a policy
5664 5405                   * allowing for IPsec processing.
5665 5406                   * Construct an error message.
5666 5407                   */
5667 5408                  samsg->sadb_msg_len = SADB_8TO64(sizeof (*samsg));
5668 5409                  samsg->sadb_msg_errno = ENOENT;
5669 5410                  samsg->sadb_x_msg_diagnostic = 0;
5670 5411                  return (mp);
5671 5412          }
5672 5413  
5673 5414          if ((kmp != 0) || (kmc != 0)) {
5674 5415                  cur = sadb_make_kmc_ext(cur, end, kmp, kmc);
5675 5416                  if (cur == NULL) {
5676 5417                          freeb(mp);
5677 5418                          return (NULL);
5678 5419                  }
5679 5420          }
5680 5421  
5681 5422          eprop->sadb_prop_len = SADB_8TO64(cur - (uint8_t *)eprop);
5682 5423          samsg->sadb_msg_len = SADB_8TO64(cur - start);
5683 5424          mp->b_wptr = cur;
5684 5425  
5685 5426          return (mp);
5686 5427  }
5687 5428  
5688 5429  /*
5689 5430   * Generic setup of an RFC 2367 ACQUIRE message.  Caller sets satype.
5690 5431   *
5691 5432   * NOTE: This function acquires alg_lock as a side-effect if-and-only-if we
5692 5433   * succeed (i.e. return non-NULL).  Caller MUST release it.  This is to
5693 5434   * maximize code consolidation while preventing algorithm changes from messing
5694 5435   * with the callers finishing touches on the ACQUIRE itself.
5695 5436   */
5696 5437  mblk_t *
5697 5438  sadb_setup_acquire(ipsacq_t *acqrec, uint8_t satype, ipsec_stack_t *ipss)
5698 5439  {
5699 5440          uint_t allocsize;
5700 5441          mblk_t *pfkeymp, *msgmp;
5701 5442          sa_family_t af;
5702 5443          uint8_t *cur, *end;
5703 5444          sadb_msg_t *samsg;
5704 5445          uint16_t sport_typecode;
5705 5446          uint16_t dport_typecode;
5706 5447          uint8_t check_proto;
5707 5448          boolean_t tunnel_mode = (acqrec->ipsacq_inneraddrfam != 0);
5708 5449  
5709 5450          ASSERT(MUTEX_HELD(&acqrec->ipsacq_lock));
5710 5451  
5711 5452          pfkeymp = sadb_keysock_out(0);
5712 5453          if (pfkeymp == NULL)
5713 5454                  return (NULL);
5714 5455  
5715 5456          /*
5716 5457           * First, allocate a basic ACQUIRE message
5717 5458           */
5718 5459          allocsize = sizeof (sadb_msg_t) + sizeof (sadb_address_t) +
5719 5460              sizeof (sadb_address_t) + sizeof (sadb_prop_t);
5720 5461  
5721 5462          /* Make sure there's enough to cover both AF_INET and AF_INET6. */
5722 5463          allocsize += 2 * sizeof (struct sockaddr_in6);
5723 5464  
5724 5465          mutex_enter(&ipss->ipsec_alg_lock);
5725 5466          /* NOTE:  The lock is now held through to this function's return. */
5726 5467          allocsize += ipss->ipsec_nalgs[IPSEC_ALG_AUTH] *
5727 5468              ipss->ipsec_nalgs[IPSEC_ALG_ENCR] * sizeof (sadb_comb_t);
5728 5469  
5729 5470          if (tunnel_mode) {
5730 5471                  /* Tunnel mode! */
5731 5472                  allocsize += 2 * sizeof (sadb_address_t);
5732 5473                  /* Enough to cover both AF_INET and AF_INET6. */
5733 5474                  allocsize += 2 * sizeof (struct sockaddr_in6);
5734 5475          }
5735 5476  
5736 5477          msgmp = allocb(allocsize, BPRI_HI);
5737 5478          if (msgmp == NULL) {
5738 5479                  freeb(pfkeymp);
5739 5480                  mutex_exit(&ipss->ipsec_alg_lock);
5740 5481                  return (NULL);
5741 5482          }
5742 5483  
5743 5484          pfkeymp->b_cont = msgmp;
5744 5485          cur = msgmp->b_rptr;
5745 5486          end = cur + allocsize;
5746 5487          samsg = (sadb_msg_t *)cur;
5747 5488          cur += sizeof (sadb_msg_t);
5748 5489  
5749 5490          af = acqrec->ipsacq_addrfam;
5750 5491          switch (af) {
5751 5492          case AF_INET:
5752 5493                  check_proto = IPPROTO_ICMP;
5753 5494                  break;
5754 5495          case AF_INET6:
5755 5496                  check_proto = IPPROTO_ICMPV6;
5756 5497                  break;
5757 5498          default:
5758 5499                  /* This should never happen unless we have kernel bugs. */
5759 5500                  cmn_err(CE_WARN,
5760 5501                      "sadb_setup_acquire:  corrupt ACQUIRE record.\n");
5761 5502                  ASSERT(0);
5762 5503                  mutex_exit(&ipss->ipsec_alg_lock);
5763 5504                  return (NULL);
5764 5505          }
5765 5506  
5766 5507          samsg->sadb_msg_version = PF_KEY_V2;
5767 5508          samsg->sadb_msg_type = SADB_ACQUIRE;
5768 5509          samsg->sadb_msg_satype = satype;
5769 5510          samsg->sadb_msg_errno = 0;
5770 5511          samsg->sadb_msg_pid = 0;
5771 5512          samsg->sadb_msg_reserved = 0;
5772 5513          samsg->sadb_msg_seq = acqrec->ipsacq_seq;
5773 5514  
5774 5515          ASSERT(MUTEX_HELD(&acqrec->ipsacq_lock));
5775 5516  
5776 5517          if ((acqrec->ipsacq_proto == check_proto) || tunnel_mode) {
5777 5518                  sport_typecode = dport_typecode = 0;
5778 5519          } else {
5779 5520                  sport_typecode = acqrec->ipsacq_srcport;
5780 5521                  dport_typecode = acqrec->ipsacq_dstport;
5781 5522          }
5782 5523  
5783 5524          cur = sadb_make_addr_ext(cur, end, SADB_EXT_ADDRESS_SRC, af,
5784 5525              acqrec->ipsacq_srcaddr, sport_typecode, acqrec->ipsacq_proto, 0);
5785 5526  
5786 5527          cur = sadb_make_addr_ext(cur, end, SADB_EXT_ADDRESS_DST, af,
5787 5528              acqrec->ipsacq_dstaddr, dport_typecode, acqrec->ipsacq_proto, 0);
5788 5529  
5789 5530          if (tunnel_mode) {
5790 5531                  sport_typecode = acqrec->ipsacq_srcport;
5791 5532                  dport_typecode = acqrec->ipsacq_dstport;
5792 5533                  cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_INNER_SRC,
5793 5534                      acqrec->ipsacq_inneraddrfam, acqrec->ipsacq_innersrc,
5794 5535                      sport_typecode, acqrec->ipsacq_inner_proto,
5795 5536                      acqrec->ipsacq_innersrcpfx);
5796 5537                  cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_INNER_DST,
5797 5538                      acqrec->ipsacq_inneraddrfam, acqrec->ipsacq_innerdst,
5798 5539                      dport_typecode, acqrec->ipsacq_inner_proto,
5799 5540                      acqrec->ipsacq_innerdstpfx);
5800 5541          }
5801 5542  
5802 5543          /* XXX Insert identity information here. */
5803 5544  
5804 5545          /* XXXMLS Insert sensitivity information here. */
5805 5546  
5806 5547          if (cur != NULL)
5807 5548                  samsg->sadb_msg_len = SADB_8TO64(cur - msgmp->b_rptr);
5808 5549          else
5809 5550                  mutex_exit(&ipss->ipsec_alg_lock);
5810 5551  
5811 5552          return (pfkeymp);
5812 5553  }
5813 5554  
  
    | 
      ↓ open down ↓ | 
    1184 lines elided | 
    
      ↑ open up ↑ | 
  
5814 5555  /*
5815 5556   * Given an SADB_GETSPI message, find an appropriately ranged SA and
5816 5557   * allocate an SA.  If there are message improprieties, return (ipsa_t *)-1.
5817 5558   * If there was a memory allocation error, return NULL.  (Assume NULL !=
5818 5559   * (ipsa_t *)-1).
5819 5560   *
5820 5561   * master_spi is passed in host order.
5821 5562   */
5822 5563  ipsa_t *
5823 5564  sadb_getspi(keysock_in_t *ksi, uint32_t master_spi, int *diagnostic,
5824      -    netstack_t *ns, uint_t sa_type)
     5565 +    netstack_t *ns)
5825 5566  {
5826 5567          sadb_address_t *src =
5827 5568              (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_SRC],
5828 5569              *dst = (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_DST];
5829 5570          sadb_spirange_t *range =
5830 5571              (sadb_spirange_t *)ksi->ks_in_extv[SADB_EXT_SPIRANGE];
5831 5572          struct sockaddr_in *ssa, *dsa;
5832 5573          struct sockaddr_in6 *ssa6, *dsa6;
5833 5574          uint32_t *srcaddr, *dstaddr;
5834 5575          sa_family_t af;
5835 5576          uint32_t add, min, max;
5836 5577  
5837 5578          if (src == NULL) {
5838 5579                  *diagnostic = SADB_X_DIAGNOSTIC_MISSING_SRC;
5839 5580                  return ((ipsa_t *)-1);
5840 5581          }
5841 5582          if (dst == NULL) {
5842 5583                  *diagnostic = SADB_X_DIAGNOSTIC_MISSING_DST;
5843 5584                  return ((ipsa_t *)-1);
5844 5585          }
5845 5586          if (range == NULL) {
5846 5587                  *diagnostic = SADB_X_DIAGNOSTIC_MISSING_RANGE;
5847 5588                  return ((ipsa_t *)-1);
5848 5589          }
5849 5590  
5850 5591          min = ntohl(range->sadb_spirange_min);
5851 5592          max = ntohl(range->sadb_spirange_max);
5852 5593          dsa = (struct sockaddr_in *)(dst + 1);
5853 5594          dsa6 = (struct sockaddr_in6 *)dsa;
5854 5595  
5855 5596          ssa = (struct sockaddr_in *)(src + 1);
5856 5597          ssa6 = (struct sockaddr_in6 *)ssa;
5857 5598          ASSERT(dsa->sin_family == ssa->sin_family);
5858 5599  
5859 5600          srcaddr = ALL_ZEROES_PTR;
5860 5601          af = dsa->sin_family;
5861 5602          switch (af) {
5862 5603          case AF_INET:
5863 5604                  if (src != NULL)
5864 5605                          srcaddr = (uint32_t *)(&ssa->sin_addr);
5865 5606                  dstaddr = (uint32_t *)(&dsa->sin_addr);
5866 5607                  break;
5867 5608          case AF_INET6:
5868 5609                  if (src != NULL)
5869 5610                          srcaddr = (uint32_t *)(&ssa6->sin6_addr);
5870 5611                  dstaddr = (uint32_t *)(&dsa6->sin6_addr);
5871 5612                  break;
5872 5613          default:
5873 5614                  *diagnostic = SADB_X_DIAGNOSTIC_BAD_DST_AF;
5874 5615                  return ((ipsa_t *)-1);
5875 5616          }
5876 5617  
5877 5618          if (master_spi < min || master_spi > max) {
5878 5619                  /* Return a random value in the range. */
5879 5620                  (void) random_get_pseudo_bytes((uint8_t *)&add, sizeof (add));
5880 5621                  master_spi = min + (add % (max - min + 1));
5881 5622          }
5882 5623  
5883 5624          /*
5884 5625           * Since master_spi is passed in host order, we need to htonl() it
5885 5626           * for the purposes of creating a new SA.
5886 5627           */
5887 5628          return (sadb_makelarvalassoc(htonl(master_spi), srcaddr, dstaddr, af,
5888 5629              ns));
5889 5630  }
5890 5631  
5891 5632  /*
5892 5633   *
5893 5634   * Locate an ACQUIRE and nuke it.  If I have an samsg that's larger than the
5894 5635   * base header, just ignore it.  Otherwise, lock down the whole ACQUIRE list
5895 5636   * and scan for the sequence number in question.  I may wish to accept an
5896 5637   * address pair with it, for easier searching.
5897 5638   *
5898 5639   * Caller frees the message, so we don't have to here.
5899 5640   *
5900 5641   * NOTE:        The pfkey_q parameter may be used in the future for ACQUIRE
5901 5642   *              failures.
5902 5643   */
5903 5644  /* ARGSUSED */
5904 5645  void
5905 5646  sadb_in_acquire(sadb_msg_t *samsg, sadbp_t *sp, queue_t *pfkey_q,
5906 5647      netstack_t *ns)
5907 5648  {
5908 5649          int i;
5909 5650          ipsacq_t *acqrec;
5910 5651          iacqf_t *bucket;
5911 5652  
5912 5653          /*
5913 5654           * I only accept the base header for this!
5914 5655           * Though to be honest, requiring the dst address would help
5915 5656           * immensely.
5916 5657           *
5917 5658           * XXX  There are already cases where I can get the dst address.
5918 5659           */
5919 5660          if (samsg->sadb_msg_len > SADB_8TO64(sizeof (*samsg)))
5920 5661                  return;
5921 5662  
5922 5663          /*
5923 5664           * Using the samsg->sadb_msg_seq, find the ACQUIRE record, delete it,
5924 5665           * (and in the future send a message to IP with the appropriate error
5925 5666           * number).
5926 5667           *
5927 5668           * Q: Do I want to reject if pid != 0?
5928 5669           */
5929 5670  
5930 5671          for (i = 0; i < sp->s_v4.sdb_hashsize; i++) {
5931 5672                  bucket = &sp->s_v4.sdb_acq[i];
5932 5673                  mutex_enter(&bucket->iacqf_lock);
5933 5674                  for (acqrec = bucket->iacqf_ipsacq; acqrec != NULL;
5934 5675                      acqrec = acqrec->ipsacq_next) {
5935 5676                          if (samsg->sadb_msg_seq == acqrec->ipsacq_seq)
5936 5677                                  break;  /* for acqrec... loop. */
5937 5678                  }
5938 5679                  if (acqrec != NULL)
5939 5680                          break;  /* for i = 0... loop. */
5940 5681  
5941 5682                  mutex_exit(&bucket->iacqf_lock);
5942 5683          }
5943 5684  
5944 5685          if (acqrec == NULL) {
5945 5686                  for (i = 0; i < sp->s_v6.sdb_hashsize; i++) {
5946 5687                          bucket = &sp->s_v6.sdb_acq[i];
5947 5688                          mutex_enter(&bucket->iacqf_lock);
5948 5689                          for (acqrec = bucket->iacqf_ipsacq; acqrec != NULL;
5949 5690                              acqrec = acqrec->ipsacq_next) {
5950 5691                                  if (samsg->sadb_msg_seq == acqrec->ipsacq_seq)
5951 5692                                          break;  /* for acqrec... loop. */
5952 5693                          }
5953 5694                          if (acqrec != NULL)
5954 5695                                  break;  /* for i = 0... loop. */
5955 5696  
5956 5697                          mutex_exit(&bucket->iacqf_lock);
5957 5698                  }
5958 5699          }
5959 5700  
5960 5701  
5961 5702          if (acqrec == NULL)
5962 5703                  return;
5963 5704  
5964 5705          /*
5965 5706           * What do I do with the errno and IP?  I may need mp's services a
5966 5707           * little more.  See sadb_destroy_acquire() for future directions
5967 5708           * beyond free the mblk chain on the acquire record.
5968 5709           */
5969 5710  
5970 5711          ASSERT(&bucket->iacqf_lock == acqrec->ipsacq_linklock);
5971 5712          sadb_destroy_acquire(acqrec, ns);
5972 5713          /* Have to exit mutex here, because of breaking out of for loop. */
5973 5714          mutex_exit(&bucket->iacqf_lock);
5974 5715  }
5975 5716  
5976 5717  /*
5977 5718   * The following functions work with the replay windows of an SA.  They assume
5978 5719   * the ipsa->ipsa_replay_arr is an array of uint64_t, and that the bit vector
5979 5720   * represents the highest sequence number packet received, and back
5980 5721   * (ipsa->ipsa_replay_wsize) packets.
5981 5722   */
5982 5723  
5983 5724  /*
5984 5725   * Is the replay bit set?
5985 5726   */
5986 5727  static boolean_t
5987 5728  ipsa_is_replay_set(ipsa_t *ipsa, uint32_t offset)
5988 5729  {
5989 5730          uint64_t bit = (uint64_t)1 << (uint64_t)(offset & 63);
5990 5731  
5991 5732          return ((bit & ipsa->ipsa_replay_arr[offset >> 6]) ? B_TRUE : B_FALSE);
5992 5733  }
5993 5734  
5994 5735  /*
5995 5736   * Shift the bits of the replay window over.
5996 5737   */
5997 5738  static void
5998 5739  ipsa_shift_replay(ipsa_t *ipsa, uint32_t shift)
5999 5740  {
6000 5741          int i;
6001 5742          int jump = ((shift - 1) >> 6) + 1;
6002 5743  
6003 5744          if (shift == 0)
6004 5745                  return;
6005 5746  
6006 5747          for (i = (ipsa->ipsa_replay_wsize - 1) >> 6; i >= 0; i--) {
6007 5748                  if (i + jump <= (ipsa->ipsa_replay_wsize - 1) >> 6) {
6008 5749                          ipsa->ipsa_replay_arr[i + jump] |=
6009 5750                              ipsa->ipsa_replay_arr[i] >> (64 - (shift & 63));
6010 5751                  }
6011 5752                  ipsa->ipsa_replay_arr[i] <<= shift;
6012 5753          }
6013 5754  }
6014 5755  
6015 5756  /*
6016 5757   * Set a bit in the bit vector.
6017 5758   */
6018 5759  static void
6019 5760  ipsa_set_replay(ipsa_t *ipsa, uint32_t offset)
6020 5761  {
6021 5762          uint64_t bit = (uint64_t)1 << (uint64_t)(offset & 63);
6022 5763  
6023 5764          ipsa->ipsa_replay_arr[offset >> 6] |= bit;
6024 5765  }
6025 5766  
6026 5767  #define SADB_MAX_REPLAY_VALUE 0xffffffff
6027 5768  
6028 5769  /*
6029 5770   * Assume caller has NOT done ntohl() already on seq.  Check to see
6030 5771   * if replay sequence number "seq" has been seen already.
6031 5772   */
6032 5773  boolean_t
6033 5774  sadb_replay_check(ipsa_t *ipsa, uint32_t seq)
6034 5775  {
6035 5776          boolean_t rc;
6036 5777          uint32_t diff;
6037 5778  
6038 5779          if (ipsa->ipsa_replay_wsize == 0)
6039 5780                  return (B_TRUE);
6040 5781  
6041 5782          /*
6042 5783           * NOTE:  I've already checked for 0 on the wire in sadb_replay_peek().
6043 5784           */
6044 5785  
6045 5786          /* Convert sequence number into host order before holding the mutex. */
6046 5787          seq = ntohl(seq);
6047 5788  
6048 5789          mutex_enter(&ipsa->ipsa_lock);
6049 5790  
6050 5791          /* Initialize inbound SA's ipsa_replay field to last one received. */
6051 5792          if (ipsa->ipsa_replay == 0)
6052 5793                  ipsa->ipsa_replay = 1;
6053 5794  
6054 5795          if (seq > ipsa->ipsa_replay) {
6055 5796                  /*
6056 5797                   * I have received a new "highest value received".  Shift
6057 5798                   * the replay window over.
6058 5799                   */
6059 5800                  diff = seq - ipsa->ipsa_replay;
6060 5801                  if (diff < ipsa->ipsa_replay_wsize) {
6061 5802                          /* In replay window, shift bits over. */
6062 5803                          ipsa_shift_replay(ipsa, diff);
6063 5804                  } else {
6064 5805                          /* WAY FAR AHEAD, clear bits and start again. */
6065 5806                          bzero(ipsa->ipsa_replay_arr,
6066 5807                              sizeof (ipsa->ipsa_replay_arr));
6067 5808                  }
6068 5809                  ipsa_set_replay(ipsa, 0);
6069 5810                  ipsa->ipsa_replay = seq;
6070 5811                  rc = B_TRUE;
6071 5812                  goto done;
6072 5813          }
6073 5814          diff = ipsa->ipsa_replay - seq;
6074 5815          if (diff >= ipsa->ipsa_replay_wsize || ipsa_is_replay_set(ipsa, diff)) {
6075 5816                  rc = B_FALSE;
6076 5817                  goto done;
6077 5818          }
6078 5819          /* Set this packet as seen. */
6079 5820          ipsa_set_replay(ipsa, diff);
6080 5821  
6081 5822          rc = B_TRUE;
6082 5823  done:
6083 5824          mutex_exit(&ipsa->ipsa_lock);
6084 5825          return (rc);
6085 5826  }
6086 5827  
6087 5828  /*
6088 5829   * "Peek" and see if we should even bother going through the effort of
6089 5830   * running an authentication check on the sequence number passed in.
6090 5831   * this takes into account packets that are below the replay window,
6091 5832   * and collisions with already replayed packets.  Return B_TRUE if it
6092 5833   * is okay to proceed, B_FALSE if this packet should be dropped immediately.
6093 5834   * Assume same byte-ordering as sadb_replay_check.
6094 5835   */
6095 5836  boolean_t
6096 5837  sadb_replay_peek(ipsa_t *ipsa, uint32_t seq)
6097 5838  {
6098 5839          boolean_t rc = B_FALSE;
6099 5840          uint32_t diff;
6100 5841  
6101 5842          if (ipsa->ipsa_replay_wsize == 0)
6102 5843                  return (B_TRUE);
6103 5844  
6104 5845          /*
6105 5846           * 0 is 0, regardless of byte order... :)
6106 5847           *
6107 5848           * If I get 0 on the wire (and there is a replay window) then the
6108 5849           * sender most likely wrapped.  This ipsa may need to be marked or
6109 5850           * something.
6110 5851           */
6111 5852          if (seq == 0)
6112 5853                  return (B_FALSE);
6113 5854  
6114 5855          seq = ntohl(seq);
6115 5856          mutex_enter(&ipsa->ipsa_lock);
6116 5857          if (seq < ipsa->ipsa_replay - ipsa->ipsa_replay_wsize &&
6117 5858              ipsa->ipsa_replay >= ipsa->ipsa_replay_wsize)
6118 5859                  goto done;
6119 5860  
6120 5861          /*
6121 5862           * If I've hit 0xffffffff, then quite honestly, I don't need to
6122 5863           * bother with formalities.  I'm not accepting any more packets
6123 5864           * on this SA.
6124 5865           */
6125 5866          if (ipsa->ipsa_replay == SADB_MAX_REPLAY_VALUE) {
6126 5867                  /*
6127 5868                   * Since we're already holding the lock, update the
6128 5869                   * expire time ala. sadb_replay_delete() and return.
6129 5870                   */
6130 5871                  ipsa->ipsa_hardexpiretime = (time_t)1;
6131 5872                  goto done;
6132 5873          }
6133 5874  
6134 5875          if (seq <= ipsa->ipsa_replay) {
6135 5876                  /*
6136 5877                   * This seq is in the replay window.  I'm not below it,
6137 5878                   * because I already checked for that above!
6138 5879                   */
6139 5880                  diff = ipsa->ipsa_replay - seq;
6140 5881                  if (ipsa_is_replay_set(ipsa, diff))
6141 5882                          goto done;
6142 5883          }
6143 5884          /* Else return B_TRUE, I'm going to advance the window. */
6144 5885  
6145 5886          rc = B_TRUE;
6146 5887  done:
6147 5888          mutex_exit(&ipsa->ipsa_lock);
6148 5889          return (rc);
6149 5890  }
6150 5891  
6151 5892  /*
6152 5893   * Delete a single SA.
6153 5894   *
6154 5895   * For now, use the quick-and-dirty trick of making the association's
6155 5896   * hard-expire lifetime (time_t)1, ensuring deletion by the *_ager().
6156 5897   */
6157 5898  void
6158 5899  sadb_replay_delete(ipsa_t *assoc)
6159 5900  {
6160 5901          mutex_enter(&assoc->ipsa_lock);
6161 5902          assoc->ipsa_hardexpiretime = (time_t)1;
6162 5903          mutex_exit(&assoc->ipsa_lock);
6163 5904  }
6164 5905  
6165 5906  /*
6166 5907   * Special front-end to ipsec_rl_strlog() dealing with SA failure.
6167 5908   * this is designed to take only a format string with "* %x * %s *", so
6168 5909   * that "spi" is printed first, then "addr" is converted using inet_pton().
6169 5910   *
6170 5911   * This is abstracted out to save the stack space for only when inet_pton()
6171 5912   * is called.  Make sure "spi" is in network order; it usually is when this
6172 5913   * would get called.
6173 5914   */
6174 5915  void
6175 5916  ipsec_assocfailure(short mid, short sid, char level, ushort_t sl, char *fmt,
6176 5917      uint32_t spi, void *addr, int af, netstack_t *ns)
6177 5918  {
6178 5919          char buf[INET6_ADDRSTRLEN];
6179 5920  
6180 5921          ASSERT(af == AF_INET6 || af == AF_INET);
6181 5922  
6182 5923          ipsec_rl_strlog(ns, mid, sid, level, sl, fmt, ntohl(spi),
6183 5924              inet_ntop(af, addr, buf, sizeof (buf)));
6184 5925  }
6185 5926  
6186 5927  /*
6187 5928   * Fills in a reference to the policy, if any, from the conn, in *ppp
6188 5929   */
6189 5930  static void
6190 5931  ipsec_conn_pol(ipsec_selector_t *sel, conn_t *connp, ipsec_policy_t **ppp)
6191 5932  {
6192 5933          ipsec_policy_t  *pp;
6193 5934          ipsec_latch_t   *ipl = connp->conn_latch;
6194 5935  
6195 5936          if ((ipl != NULL) && (connp->conn_ixa->ixa_ipsec_policy != NULL)) {
6196 5937                  pp = connp->conn_ixa->ixa_ipsec_policy;
6197 5938                  IPPOL_REFHOLD(pp);
6198 5939          } else {
6199 5940                  pp = ipsec_find_policy(IPSEC_TYPE_OUTBOUND, connp, sel,
6200 5941                      connp->conn_netstack);
6201 5942          }
6202 5943          *ppp = pp;
6203 5944  }
6204 5945  
6205 5946  /*
6206 5947   * The following functions scan through active conn_t structures
6207 5948   * and return a reference to the best-matching policy it can find.
6208 5949   * Caller must release the reference.
6209 5950   */
6210 5951  static void
6211 5952  ipsec_udp_pol(ipsec_selector_t *sel, ipsec_policy_t **ppp, ip_stack_t *ipst)
6212 5953  {
6213 5954          connf_t *connfp;
6214 5955          conn_t *connp = NULL;
6215 5956          ipsec_selector_t portonly;
6216 5957  
6217 5958          bzero((void *)&portonly, sizeof (portonly));
6218 5959  
6219 5960          if (sel->ips_local_port == 0)
6220 5961                  return;
6221 5962  
6222 5963          connfp = &ipst->ips_ipcl_udp_fanout[IPCL_UDP_HASH(sel->ips_local_port,
6223 5964              ipst)];
6224 5965          mutex_enter(&connfp->connf_lock);
6225 5966  
6226 5967          if (sel->ips_isv4) {
6227 5968                  connp = connfp->connf_head;
6228 5969                  while (connp != NULL) {
6229 5970                          if (IPCL_UDP_MATCH(connp, sel->ips_local_port,
6230 5971                              sel->ips_local_addr_v4, sel->ips_remote_port,
6231 5972                              sel->ips_remote_addr_v4))
6232 5973                                  break;
6233 5974                          connp = connp->conn_next;
6234 5975                  }
6235 5976  
6236 5977                  if (connp == NULL) {
6237 5978                          /* Try port-only match in IPv6. */
6238 5979                          portonly.ips_local_port = sel->ips_local_port;
6239 5980                          sel = &portonly;
6240 5981                  }
6241 5982          }
6242 5983  
6243 5984          if (connp == NULL) {
6244 5985                  connp = connfp->connf_head;
6245 5986                  while (connp != NULL) {
6246 5987                          if (IPCL_UDP_MATCH_V6(connp, sel->ips_local_port,
6247 5988                              sel->ips_local_addr_v6, sel->ips_remote_port,
6248 5989                              sel->ips_remote_addr_v6))
6249 5990                                  break;
6250 5991                          connp = connp->conn_next;
6251 5992                  }
6252 5993  
6253 5994                  if (connp == NULL) {
6254 5995                          mutex_exit(&connfp->connf_lock);
6255 5996                          return;
6256 5997                  }
6257 5998          }
6258 5999  
6259 6000          CONN_INC_REF(connp);
6260 6001          mutex_exit(&connfp->connf_lock);
6261 6002  
6262 6003          ipsec_conn_pol(sel, connp, ppp);
6263 6004          CONN_DEC_REF(connp);
6264 6005  }
6265 6006  
6266 6007  static conn_t *
6267 6008  ipsec_find_listen_conn(uint16_t *pptr, ipsec_selector_t *sel, ip_stack_t *ipst)
6268 6009  {
6269 6010          connf_t *connfp;
6270 6011          conn_t *connp = NULL;
6271 6012          const in6_addr_t *v6addrmatch = &sel->ips_local_addr_v6;
6272 6013  
6273 6014          if (sel->ips_local_port == 0)
6274 6015                  return (NULL);
6275 6016  
6276 6017          connfp = &ipst->ips_ipcl_bind_fanout[
6277 6018              IPCL_BIND_HASH(sel->ips_local_port, ipst)];
6278 6019          mutex_enter(&connfp->connf_lock);
6279 6020  
6280 6021          if (sel->ips_isv4) {
6281 6022                  connp = connfp->connf_head;
6282 6023                  while (connp != NULL) {
6283 6024                          if (IPCL_BIND_MATCH(connp, IPPROTO_TCP,
6284 6025                              sel->ips_local_addr_v4, pptr[1]))
6285 6026                                  break;
6286 6027                          connp = connp->conn_next;
6287 6028                  }
6288 6029  
6289 6030                  if (connp == NULL) {
6290 6031                          /* Match to all-zeroes. */
6291 6032                          v6addrmatch = &ipv6_all_zeros;
6292 6033                  }
6293 6034          }
6294 6035  
6295 6036          if (connp == NULL) {
6296 6037                  connp = connfp->connf_head;
6297 6038                  while (connp != NULL) {
6298 6039                          if (IPCL_BIND_MATCH_V6(connp, IPPROTO_TCP,
6299 6040                              *v6addrmatch, pptr[1]))
6300 6041                                  break;
6301 6042                          connp = connp->conn_next;
6302 6043                  }
6303 6044  
6304 6045                  if (connp == NULL) {
6305 6046                          mutex_exit(&connfp->connf_lock);
6306 6047                          return (NULL);
6307 6048                  }
6308 6049          }
6309 6050  
6310 6051          CONN_INC_REF(connp);
6311 6052          mutex_exit(&connfp->connf_lock);
6312 6053          return (connp);
6313 6054  }
6314 6055  
6315 6056  static void
6316 6057  ipsec_tcp_pol(ipsec_selector_t *sel, ipsec_policy_t **ppp, ip_stack_t *ipst)
6317 6058  {
6318 6059          connf_t         *connfp;
6319 6060          conn_t          *connp;
6320 6061          uint32_t        ports;
6321 6062          uint16_t        *pptr = (uint16_t *)&ports;
6322 6063  
6323 6064          /*
6324 6065           * Find TCP state in the following order:
6325 6066           * 1.) Connected conns.
6326 6067           * 2.) Listeners.
6327 6068           *
6328 6069           * Even though #2 will be the common case for inbound traffic, only
6329 6070           * following this order insures correctness.
6330 6071           */
6331 6072  
6332 6073          if (sel->ips_local_port == 0)
6333 6074                  return;
6334 6075  
6335 6076          /*
6336 6077           * 0 should be fport, 1 should be lport.  SRC is the local one here.
6337 6078           * See ipsec_construct_inverse_acquire() for details.
6338 6079           */
6339 6080          pptr[0] = sel->ips_remote_port;
6340 6081          pptr[1] = sel->ips_local_port;
6341 6082  
6342 6083          connfp = &ipst->ips_ipcl_conn_fanout[
6343 6084              IPCL_CONN_HASH(sel->ips_remote_addr_v4, ports, ipst)];
6344 6085          mutex_enter(&connfp->connf_lock);
6345 6086          connp = connfp->connf_head;
6346 6087  
6347 6088          if (sel->ips_isv4) {
6348 6089                  while (connp != NULL) {
6349 6090                          if (IPCL_CONN_MATCH(connp, IPPROTO_TCP,
6350 6091                              sel->ips_remote_addr_v4, sel->ips_local_addr_v4,
6351 6092                              ports))
6352 6093                                  break;
6353 6094                          connp = connp->conn_next;
6354 6095                  }
6355 6096          } else {
6356 6097                  while (connp != NULL) {
6357 6098                          if (IPCL_CONN_MATCH_V6(connp, IPPROTO_TCP,
6358 6099                              sel->ips_remote_addr_v6, sel->ips_local_addr_v6,
6359 6100                              ports))
6360 6101                                  break;
6361 6102                          connp = connp->conn_next;
6362 6103                  }
6363 6104          }
6364 6105  
6365 6106          if (connp != NULL) {
6366 6107                  CONN_INC_REF(connp);
6367 6108                  mutex_exit(&connfp->connf_lock);
6368 6109          } else {
6369 6110                  mutex_exit(&connfp->connf_lock);
6370 6111  
6371 6112                  /* Try the listen hash. */
6372 6113                  if ((connp = ipsec_find_listen_conn(pptr, sel, ipst)) == NULL)
6373 6114                          return;
6374 6115          }
6375 6116  
6376 6117          ipsec_conn_pol(sel, connp, ppp);
6377 6118          CONN_DEC_REF(connp);
6378 6119  }
6379 6120  
6380 6121  static void
6381 6122  ipsec_sctp_pol(ipsec_selector_t *sel, ipsec_policy_t **ppp,
6382 6123      ip_stack_t *ipst)
6383 6124  {
6384 6125          conn_t          *connp;
6385 6126          uint32_t        ports;
6386 6127          uint16_t        *pptr = (uint16_t *)&ports;
6387 6128  
6388 6129          /*
6389 6130           * Find SCP state in the following order:
6390 6131           * 1.) Connected conns.
6391 6132           * 2.) Listeners.
6392 6133           *
6393 6134           * Even though #2 will be the common case for inbound traffic, only
6394 6135           * following this order insures correctness.
6395 6136           */
6396 6137  
6397 6138          if (sel->ips_local_port == 0)
6398 6139                  return;
6399 6140  
6400 6141          /*
6401 6142           * 0 should be fport, 1 should be lport.  SRC is the local one here.
6402 6143           * See ipsec_construct_inverse_acquire() for details.
6403 6144           */
6404 6145          pptr[0] = sel->ips_remote_port;
6405 6146          pptr[1] = sel->ips_local_port;
6406 6147  
6407 6148          /*
6408 6149           * For labeled systems, there's no need to check the
6409 6150           * label here.  It's known to be good as we checked
6410 6151           * before allowing the connection to become bound.
6411 6152           */
6412 6153          if (sel->ips_isv4) {
6413 6154                  in6_addr_t      src, dst;
6414 6155  
6415 6156                  IN6_IPADDR_TO_V4MAPPED(sel->ips_remote_addr_v4, &dst);
6416 6157                  IN6_IPADDR_TO_V4MAPPED(sel->ips_local_addr_v4, &src);
6417 6158                  connp = sctp_find_conn(&dst, &src, ports, ALL_ZONES,
6418 6159                      0, ipst->ips_netstack->netstack_sctp);
6419 6160          } else {
6420 6161                  connp = sctp_find_conn(&sel->ips_remote_addr_v6,
6421 6162                      &sel->ips_local_addr_v6, ports, ALL_ZONES,
6422 6163                      0, ipst->ips_netstack->netstack_sctp);
6423 6164          }
6424 6165          if (connp == NULL)
6425 6166                  return;
6426 6167          ipsec_conn_pol(sel, connp, ppp);
6427 6168          CONN_DEC_REF(connp);
6428 6169  }
6429 6170  
6430 6171  /*
6431 6172   * Fill in a query for the SPD (in "sel") using two PF_KEY address extensions.
6432 6173   * Returns 0 or errno, and always sets *diagnostic to something appropriate
6433 6174   * to PF_KEY.
6434 6175   *
6435 6176   * NOTE:  For right now, this function (and ipsec_selector_t for that matter),
6436 6177   * ignore prefix lengths in the address extension.  Since we match on first-
6437 6178   * entered policies, this shouldn't matter.  Also, since we normalize prefix-
6438 6179   * set addresses to mask out the lower bits, we should get a suitable search
6439 6180   * key for the SPD anyway.  This is the function to change if the assumption
6440 6181   * about suitable search keys is wrong.
6441 6182   */
6442 6183  static int
6443 6184  ipsec_get_inverse_acquire_sel(ipsec_selector_t *sel, sadb_address_t *srcext,
6444 6185      sadb_address_t *dstext, int *diagnostic)
6445 6186  {
6446 6187          struct sockaddr_in *src, *dst;
6447 6188          struct sockaddr_in6 *src6, *dst6;
6448 6189  
6449 6190          *diagnostic = 0;
6450 6191  
6451 6192          bzero(sel, sizeof (*sel));
6452 6193          sel->ips_protocol = srcext->sadb_address_proto;
6453 6194          dst = (struct sockaddr_in *)(dstext + 1);
6454 6195          if (dst->sin_family == AF_INET6) {
6455 6196                  dst6 = (struct sockaddr_in6 *)dst;
6456 6197                  src6 = (struct sockaddr_in6 *)(srcext + 1);
6457 6198                  if (src6->sin6_family != AF_INET6) {
6458 6199                          *diagnostic = SADB_X_DIAGNOSTIC_AF_MISMATCH;
6459 6200                          return (EINVAL);
6460 6201                  }
6461 6202                  sel->ips_remote_addr_v6 = dst6->sin6_addr;
6462 6203                  sel->ips_local_addr_v6 = src6->sin6_addr;
6463 6204                  if (sel->ips_protocol == IPPROTO_ICMPV6) {
6464 6205                          sel->ips_is_icmp_inv_acq = 1;
6465 6206                  } else {
6466 6207                          sel->ips_remote_port = dst6->sin6_port;
6467 6208                          sel->ips_local_port = src6->sin6_port;
6468 6209                  }
6469 6210                  sel->ips_isv4 = B_FALSE;
6470 6211          } else {
6471 6212                  src = (struct sockaddr_in *)(srcext + 1);
6472 6213                  if (src->sin_family != AF_INET) {
6473 6214                          *diagnostic = SADB_X_DIAGNOSTIC_AF_MISMATCH;
6474 6215                          return (EINVAL);
6475 6216                  }
6476 6217                  sel->ips_remote_addr_v4 = dst->sin_addr.s_addr;
6477 6218                  sel->ips_local_addr_v4 = src->sin_addr.s_addr;
6478 6219                  if (sel->ips_protocol == IPPROTO_ICMP) {
6479 6220                          sel->ips_is_icmp_inv_acq = 1;
6480 6221                  } else {
6481 6222                          sel->ips_remote_port = dst->sin_port;
6482 6223                          sel->ips_local_port = src->sin_port;
6483 6224                  }
6484 6225                  sel->ips_isv4 = B_TRUE;
6485 6226          }
6486 6227          return (0);
6487 6228  }
6488 6229  
6489 6230  /*
6490 6231   * We have encapsulation.
6491 6232   * - Lookup tun_t by address and look for an associated
6492 6233   *   tunnel policy
6493 6234   * - If there are inner selectors
6494 6235   *   - check ITPF_P_TUNNEL and ITPF_P_ACTIVE
6495 6236   *   - Look up tunnel policy based on selectors
6496 6237   * - Else
6497 6238   *   - Sanity check the negotation
6498 6239   *   - If appropriate, fall through to global policy
6499 6240   */
6500 6241  static int
6501 6242  ipsec_tun_pol(ipsec_selector_t *sel, ipsec_policy_t **ppp,
6502 6243      sadb_address_t *innsrcext, sadb_address_t *inndstext, ipsec_tun_pol_t *itp,
6503 6244      int *diagnostic)
6504 6245  {
6505 6246          int err;
6506 6247          ipsec_policy_head_t *polhead;
6507 6248  
6508 6249          *diagnostic = 0;
6509 6250  
6510 6251          /* Check for inner selectors and act appropriately */
6511 6252  
6512 6253          if (innsrcext != NULL) {
6513 6254                  /* Inner selectors present */
6514 6255                  ASSERT(inndstext != NULL);
6515 6256                  if ((itp == NULL) ||
6516 6257                      (itp->itp_flags & (ITPF_P_ACTIVE | ITPF_P_TUNNEL)) !=
6517 6258                      (ITPF_P_ACTIVE | ITPF_P_TUNNEL)) {
6518 6259                          /*
6519 6260                           * If inner packet selectors, we must have negotiate
6520 6261                           * tunnel and active policy.  If the tunnel has
6521 6262                           * transport-mode policy set on it, or has no policy,
6522 6263                           * fail.
6523 6264                           */
6524 6265                          return (ENOENT);
6525 6266                  } else {
6526 6267                          /*
6527 6268                           * Reset "sel" to indicate inner selectors.  Pass
6528 6269                           * inner PF_KEY address extensions for this to happen.
6529 6270                           */
6530 6271                          if ((err = ipsec_get_inverse_acquire_sel(sel,
6531 6272                              innsrcext, inndstext, diagnostic)) != 0)
6532 6273                                  return (err);
6533 6274                          /*
6534 6275                           * Now look for a tunnel policy based on those inner
6535 6276                           * selectors.  (Common code is below.)
6536 6277                           */
6537 6278                  }
6538 6279          } else {
6539 6280                  /* No inner selectors present */
6540 6281                  if ((itp == NULL) || !(itp->itp_flags & ITPF_P_ACTIVE)) {
6541 6282                          /*
6542 6283                           * Transport mode negotiation with no tunnel policy
6543 6284                           * configured - return to indicate a global policy
6544 6285                           * check is needed.
6545 6286                           */
6546 6287                          return (0);
6547 6288                  } else if (itp->itp_flags & ITPF_P_TUNNEL) {
6548 6289                          /* Tunnel mode set with no inner selectors. */
6549 6290                          return (ENOENT);
6550 6291                  }
6551 6292                  /*
6552 6293                   * Else, this is a tunnel policy configured with ifconfig(1m)
6553 6294                   * or "negotiate transport" with ipsecconf(1m).  We have an
6554 6295                   * itp with policy set based on any match, so don't bother
6555 6296                   * changing fields in "sel".
6556 6297                   */
6557 6298          }
6558 6299  
6559 6300          ASSERT(itp != NULL);
6560 6301          polhead = itp->itp_policy;
6561 6302          ASSERT(polhead != NULL);
6562 6303          rw_enter(&polhead->iph_lock, RW_READER);
6563 6304          *ppp = ipsec_find_policy_head(NULL, polhead, IPSEC_TYPE_INBOUND, sel);
6564 6305          rw_exit(&polhead->iph_lock);
6565 6306  
6566 6307          /*
6567 6308           * Don't default to global if we didn't find a matching policy entry.
6568 6309           * Instead, send ENOENT, just like if we hit a transport-mode tunnel.
6569 6310           */
6570 6311          if (*ppp == NULL)
6571 6312                  return (ENOENT);
6572 6313  
6573 6314          return (0);
6574 6315  }
6575 6316  
6576 6317  /*
6577 6318   * For sctp conn_faddr is the primary address, hence this is of limited
6578 6319   * use for sctp.
6579 6320   */
6580 6321  static void
6581 6322  ipsec_oth_pol(ipsec_selector_t *sel, ipsec_policy_t **ppp,
6582 6323      ip_stack_t *ipst)
6583 6324  {
6584 6325          boolean_t       isv4 = sel->ips_isv4;
6585 6326          connf_t         *connfp;
6586 6327          conn_t          *connp;
6587 6328  
6588 6329          if (isv4) {
6589 6330                  connfp = &ipst->ips_ipcl_proto_fanout_v4[sel->ips_protocol];
6590 6331          } else {
6591 6332                  connfp = &ipst->ips_ipcl_proto_fanout_v6[sel->ips_protocol];
6592 6333          }
6593 6334  
6594 6335          mutex_enter(&connfp->connf_lock);
6595 6336          for (connp = connfp->connf_head; connp != NULL;
6596 6337              connp = connp->conn_next) {
6597 6338                  if (isv4) {
6598 6339                          if ((connp->conn_laddr_v4 == INADDR_ANY ||
6599 6340                              connp->conn_laddr_v4 == sel->ips_local_addr_v4) &&
6600 6341                              (connp->conn_faddr_v4 == INADDR_ANY ||
6601 6342                              connp->conn_faddr_v4 == sel->ips_remote_addr_v4))
6602 6343                                  break;
6603 6344                  } else {
6604 6345                          if ((IN6_IS_ADDR_UNSPECIFIED(&connp->conn_laddr_v6) ||
6605 6346                              IN6_ARE_ADDR_EQUAL(&connp->conn_laddr_v6,
6606 6347                              &sel->ips_local_addr_v6)) &&
6607 6348                              (IN6_IS_ADDR_UNSPECIFIED(&connp->conn_faddr_v6) ||
6608 6349                              IN6_ARE_ADDR_EQUAL(&connp->conn_faddr_v6,
6609 6350                              &sel->ips_remote_addr_v6)))
6610 6351                                  break;
6611 6352                  }
6612 6353          }
6613 6354          if (connp == NULL) {
6614 6355                  mutex_exit(&connfp->connf_lock);
6615 6356                  return;
6616 6357          }
6617 6358  
6618 6359          CONN_INC_REF(connp);
6619 6360          mutex_exit(&connfp->connf_lock);
6620 6361  
6621 6362          ipsec_conn_pol(sel, connp, ppp);
6622 6363          CONN_DEC_REF(connp);
6623 6364  }
6624 6365  
6625 6366  /*
6626 6367   * Construct an inverse ACQUIRE reply based on:
6627 6368   *
6628 6369   * 1.) Current global policy.
6629 6370   * 2.) An conn_t match depending on what all was passed in the extv[].
6630 6371   * 3.) A tunnel's policy head.
6631 6372   * ...
6632 6373   * N.) Other stuff TBD (e.g. identities)
6633 6374   *
6634 6375   * If there is an error, set sadb_msg_errno and sadb_x_msg_diagnostic
6635 6376   * in this function so the caller can extract them where appropriately.
6636 6377   *
6637 6378   * The SRC address is the local one - just like an outbound ACQUIRE message.
6638 6379   *
6639 6380   * XXX MLS: key management supplies a label which we just reflect back up
6640 6381   * again.  clearly we need to involve the label in the rest of the checks.
6641 6382   */
6642 6383  mblk_t *
6643 6384  ipsec_construct_inverse_acquire(sadb_msg_t *samsg, sadb_ext_t *extv[],
6644 6385      netstack_t *ns)
6645 6386  {
6646 6387          int err;
6647 6388          int diagnostic;
6648 6389          sadb_address_t *srcext = (sadb_address_t *)extv[SADB_EXT_ADDRESS_SRC],
6649 6390              *dstext = (sadb_address_t *)extv[SADB_EXT_ADDRESS_DST],
6650 6391              *innsrcext = (sadb_address_t *)extv[SADB_X_EXT_ADDRESS_INNER_SRC],
6651 6392              *inndstext = (sadb_address_t *)extv[SADB_X_EXT_ADDRESS_INNER_DST];
6652 6393          sadb_sens_t *sens = (sadb_sens_t *)extv[SADB_EXT_SENSITIVITY];
6653 6394          struct sockaddr_in6 *src, *dst;
6654 6395          struct sockaddr_in6 *isrc, *idst;
6655 6396          ipsec_tun_pol_t *itp = NULL;
6656 6397          ipsec_policy_t *pp = NULL;
6657 6398          ipsec_selector_t sel, isel;
6658 6399          mblk_t *retmp = NULL;
6659 6400          ip_stack_t      *ipst = ns->netstack_ip;
6660 6401  
6661 6402  
6662 6403          /* Normalize addresses */
6663 6404          if (sadb_addrcheck(NULL, (mblk_t *)samsg, (sadb_ext_t *)srcext, 0, ns)
6664 6405              == KS_IN_ADDR_UNKNOWN) {
6665 6406                  err = EINVAL;
6666 6407                  diagnostic = SADB_X_DIAGNOSTIC_BAD_SRC;
6667 6408                  goto bail;
6668 6409          }
6669 6410          src = (struct sockaddr_in6 *)(srcext + 1);
6670 6411          if (sadb_addrcheck(NULL, (mblk_t *)samsg, (sadb_ext_t *)dstext, 0, ns)
6671 6412              == KS_IN_ADDR_UNKNOWN) {
6672 6413                  err = EINVAL;
6673 6414                  diagnostic = SADB_X_DIAGNOSTIC_BAD_DST;
6674 6415                  goto bail;
6675 6416          }
6676 6417          dst = (struct sockaddr_in6 *)(dstext + 1);
6677 6418          if (src->sin6_family != dst->sin6_family) {
6678 6419                  err = EINVAL;
6679 6420                  diagnostic = SADB_X_DIAGNOSTIC_AF_MISMATCH;
6680 6421                  goto bail;
6681 6422          }
6682 6423  
6683 6424          /* Check for tunnel mode and act appropriately */
6684 6425          if (innsrcext != NULL) {
6685 6426                  if (inndstext == NULL) {
6686 6427                          err = EINVAL;
6687 6428                          diagnostic = SADB_X_DIAGNOSTIC_MISSING_INNER_DST;
6688 6429                          goto bail;
6689 6430                  }
6690 6431                  if (sadb_addrcheck(NULL, (mblk_t *)samsg,
6691 6432                      (sadb_ext_t *)innsrcext, 0, ns) == KS_IN_ADDR_UNKNOWN) {
6692 6433                          err = EINVAL;
6693 6434                          diagnostic = SADB_X_DIAGNOSTIC_MALFORMED_INNER_SRC;
6694 6435                          goto bail;
6695 6436                  }
6696 6437                  isrc = (struct sockaddr_in6 *)(innsrcext + 1);
6697 6438                  if (sadb_addrcheck(NULL, (mblk_t *)samsg,
6698 6439                      (sadb_ext_t *)inndstext, 0, ns) == KS_IN_ADDR_UNKNOWN) {
6699 6440                          err = EINVAL;
6700 6441                          diagnostic = SADB_X_DIAGNOSTIC_MALFORMED_INNER_DST;
6701 6442                          goto bail;
6702 6443                  }
6703 6444                  idst = (struct sockaddr_in6 *)(inndstext + 1);
6704 6445                  if (isrc->sin6_family != idst->sin6_family) {
6705 6446                          err = EINVAL;
6706 6447                          diagnostic = SADB_X_DIAGNOSTIC_INNER_AF_MISMATCH;
6707 6448                          goto bail;
6708 6449                  }
6709 6450                  if (isrc->sin6_family != AF_INET &&
6710 6451                      isrc->sin6_family != AF_INET6) {
6711 6452                          err = EINVAL;
6712 6453                          diagnostic = SADB_X_DIAGNOSTIC_BAD_INNER_SRC_AF;
6713 6454                          goto bail;
6714 6455                  }
6715 6456          } else if (inndstext != NULL) {
6716 6457                  err = EINVAL;
6717 6458                  diagnostic = SADB_X_DIAGNOSTIC_MISSING_INNER_SRC;
6718 6459                  goto bail;
6719 6460          }
6720 6461  
6721 6462          /* Get selectors first, based on outer addresses */
6722 6463          err = ipsec_get_inverse_acquire_sel(&sel, srcext, dstext, &diagnostic);
6723 6464          if (err != 0)
6724 6465                  goto bail;
6725 6466  
6726 6467          /* Check for tunnel mode mismatches. */
6727 6468          if (innsrcext != NULL &&
6728 6469              ((isrc->sin6_family == AF_INET &&
6729 6470              sel.ips_protocol != IPPROTO_ENCAP && sel.ips_protocol != 0) ||
6730 6471              (isrc->sin6_family == AF_INET6 &&
6731 6472              sel.ips_protocol != IPPROTO_IPV6 && sel.ips_protocol != 0))) {
6732 6473                  err = EPROTOTYPE;
6733 6474                  goto bail;
6734 6475          }
6735 6476  
6736 6477          /*
6737 6478           * Okay, we have the addresses and other selector information.
6738 6479           * Let's first find a conn...
6739 6480           */
6740 6481          pp = NULL;
6741 6482          switch (sel.ips_protocol) {
6742 6483          case IPPROTO_TCP:
6743 6484                  ipsec_tcp_pol(&sel, &pp, ipst);
6744 6485                  break;
6745 6486          case IPPROTO_UDP:
6746 6487                  ipsec_udp_pol(&sel, &pp, ipst);
6747 6488                  break;
6748 6489          case IPPROTO_SCTP:
6749 6490                  ipsec_sctp_pol(&sel, &pp, ipst);
6750 6491                  break;
6751 6492          case IPPROTO_ENCAP:
6752 6493          case IPPROTO_IPV6:
6753 6494                  /*
6754 6495                   * Assume sel.ips_remote_addr_* has the right address at
6755 6496                   * that exact position.
6756 6497                   */
6757 6498                  itp = itp_get_byaddr((uint32_t *)(&sel.ips_local_addr_v6),
6758 6499                      (uint32_t *)(&sel.ips_remote_addr_v6), src->sin6_family,
6759 6500                      ipst);
6760 6501  
6761 6502                  if (innsrcext == NULL) {
6762 6503                          /*
6763 6504                           * Transport-mode tunnel, make sure we fake out isel
6764 6505                           * to contain something based on the outer protocol.
6765 6506                           */
6766 6507                          bzero(&isel, sizeof (isel));
6767 6508                          isel.ips_isv4 = (sel.ips_protocol == IPPROTO_ENCAP);
6768 6509                  } /* Else isel is initialized by ipsec_tun_pol(). */
6769 6510                  err = ipsec_tun_pol(&isel, &pp, innsrcext, inndstext, itp,
6770 6511                      &diagnostic);
6771 6512                  /*
6772 6513                   * NOTE:  isel isn't used for now, but in RFC 430x IPsec, it
6773 6514                   * may be.
6774 6515                   */
6775 6516                  if (err != 0)
6776 6517                          goto bail;
6777 6518                  break;
6778 6519          default:
6779 6520                  ipsec_oth_pol(&sel, &pp, ipst);
6780 6521                  break;
6781 6522          }
6782 6523  
6783 6524          /*
6784 6525           * If we didn't find a matching conn_t or other policy head, take a
6785 6526           * look in the global policy.
6786 6527           */
6787 6528          if (pp == NULL) {
6788 6529                  pp = ipsec_find_policy(IPSEC_TYPE_OUTBOUND, NULL, &sel, ns);
6789 6530                  if (pp == NULL) {
6790 6531                          /* There's no global policy. */
6791 6532                          err = ENOENT;
6792 6533                          diagnostic = 0;
6793 6534                          goto bail;
6794 6535                  }
6795 6536          }
6796 6537  
6797 6538          /*
6798 6539           * Now that we have a policy entry/widget, construct an ACQUIRE
6799 6540           * message based on that, fix fields where appropriate,
6800 6541           * and return the message.
6801 6542           */
6802 6543          retmp = sadb_extended_acquire(&sel, pp, NULL,
6803 6544              (itp != NULL && (itp->itp_flags & ITPF_P_TUNNEL)),
6804 6545              samsg->sadb_msg_seq, samsg->sadb_msg_pid, sens, ns);
6805 6546          if (pp != NULL) {
6806 6547                  IPPOL_REFRELE(pp);
6807 6548          }
6808 6549          ASSERT(err == 0 && diagnostic == 0);
6809 6550          if (retmp == NULL)
6810 6551                  err = ENOMEM;
6811 6552  bail:
6812 6553          if (itp != NULL) {
6813 6554                  ITP_REFRELE(itp, ns);
6814 6555          }
6815 6556          samsg->sadb_msg_errno = (uint8_t)err;
6816 6557          samsg->sadb_x_msg_diagnostic = (uint16_t)diagnostic;
6817 6558          return (retmp);
6818 6559  }
6819 6560  
6820 6561  /*
6821 6562   * ipsa_lpkt is a one-element queue, only manipulated by the next two
6822 6563   * functions.  They have to hold the ipsa_lock because of potential races
6823 6564   * between key management using SADB_UPDATE, and inbound packets that may
6824 6565   * queue up on the larval SA (hence the 'l' in "lpkt").
6825 6566   */
6826 6567  
6827 6568  /*
6828 6569   * sadb_set_lpkt:
6829 6570   *
6830 6571   * Returns the passed-in packet if the SA is no longer larval.
6831 6572   *
6832 6573   * Returns NULL if the SA is larval, and needs to be swapped into the SA for
6833 6574   * processing after an SADB_UPDATE.
6834 6575   */
6835 6576  mblk_t *
6836 6577  sadb_set_lpkt(ipsa_t *ipsa, mblk_t *npkt, ip_recv_attr_t *ira)
6837 6578  {
6838 6579          mblk_t          *opkt;
6839 6580  
6840 6581          mutex_enter(&ipsa->ipsa_lock);
6841 6582          opkt = ipsa->ipsa_lpkt;
6842 6583          if (ipsa->ipsa_state == IPSA_STATE_LARVAL) {
6843 6584                  /*
6844 6585                   * Consume npkt and place it in the LARVAL SA's inbound
6845 6586                   * packet slot.
6846 6587                   */
6847 6588                  mblk_t  *attrmp;
6848 6589  
6849 6590                  attrmp = ip_recv_attr_to_mblk(ira);
6850 6591                  if (attrmp == NULL) {
6851 6592                          ill_t *ill = ira->ira_ill;
6852 6593  
6853 6594                          BUMP_MIB(ill->ill_ip_mib, ipIfStatsInDiscards);
6854 6595                          ip_drop_input("ipIfStatsInDiscards", npkt, ill);
6855 6596                          freemsg(npkt);
6856 6597                          opkt = NULL;
6857 6598                  } else {
6858 6599                          ASSERT(attrmp->b_cont == NULL);
6859 6600                          attrmp->b_cont = npkt;
6860 6601                          ipsa->ipsa_lpkt = attrmp;
6861 6602                  }
6862 6603                  npkt = NULL;
6863 6604          } else {
6864 6605                  /*
6865 6606                   * If not larval, we lost the race.  NOTE: ipsa_lpkt may still
6866 6607                   * have been non-NULL in the non-larval case, because of
6867 6608                   * inbound packets arriving prior to sadb_common_add()
6868 6609                   * transferring the SA completely out of larval state, but
6869 6610                   * after lpkt was grabbed by the AH/ESP-specific add routines.
6870 6611                   * We should clear the old ipsa_lpkt in this case to make sure
6871 6612                   * that it doesn't linger on the now-MATURE IPsec SA, or get
6872 6613                   * picked up as an out-of-order packet.
6873 6614                   */
6874 6615                  ipsa->ipsa_lpkt = NULL;
6875 6616          }
6876 6617          mutex_exit(&ipsa->ipsa_lock);
6877 6618  
6878 6619          if (opkt != NULL) {
6879 6620                  ipsec_stack_t   *ipss;
6880 6621  
6881 6622                  ipss = ira->ira_ill->ill_ipst->ips_netstack->netstack_ipsec;
6882 6623                  opkt = ip_recv_attr_free_mblk(opkt);
6883 6624                  ip_drop_packet(opkt, B_TRUE, ira->ira_ill,
6884 6625                      DROPPER(ipss, ipds_sadb_inlarval_replace),
6885 6626                      &ipss->ipsec_sadb_dropper);
6886 6627          }
6887 6628          return (npkt);
6888 6629  }
6889 6630  
6890 6631  /*
6891 6632   * sadb_clear_lpkt: Atomically clear ipsa->ipsa_lpkt and return the
6892 6633   * previous value.
6893 6634   */
6894 6635  mblk_t *
6895 6636  sadb_clear_lpkt(ipsa_t *ipsa)
6896 6637  {
  
    | 
      ↓ open down ↓ | 
    1062 lines elided | 
    
      ↑ open up ↑ | 
  
6897 6638          mblk_t *opkt;
6898 6639  
6899 6640          mutex_enter(&ipsa->ipsa_lock);
6900 6641          opkt = ipsa->ipsa_lpkt;
6901 6642          ipsa->ipsa_lpkt = NULL;
6902 6643          mutex_exit(&ipsa->ipsa_lock);
6903 6644          return (opkt);
6904 6645  }
6905 6646  
6906 6647  /*
6907      - * Buffer a packet that's in IDLE state as set by Solaris Clustering.
6908      - */
6909      -void
6910      -sadb_buf_pkt(ipsa_t *ipsa, mblk_t *bpkt, ip_recv_attr_t *ira)
6911      -{
6912      -        netstack_t      *ns = ira->ira_ill->ill_ipst->ips_netstack;
6913      -        ipsec_stack_t   *ipss = ns->netstack_ipsec;
6914      -
6915      -        ASSERT(ipsa->ipsa_state == IPSA_STATE_IDLE);
6916      -
6917      -        ip_drop_packet(bpkt, B_TRUE, ira->ira_ill,
6918      -            DROPPER(ipss, ipds_sadb_inidle_overflow),
6919      -            &ipss->ipsec_sadb_dropper);
6920      -        return;
6921      -}
6922      -
6923      -/*
6924      - * Stub function that taskq_dispatch() invokes to take the mblk (in arg)
6925      - * and put into STREAMS again.
6926      - */
6927      -void
6928      -sadb_clear_buf_pkt(void *ipkt)
6929      -{
6930      -        mblk_t  *tmp, *buf_pkt;
6931      -        ip_recv_attr_t  iras;
6932      -
6933      -        buf_pkt = (mblk_t *)ipkt;
6934      -
6935      -        while (buf_pkt != NULL) {
6936      -                mblk_t *data_mp;
6937      -
6938      -                tmp = buf_pkt->b_next;
6939      -                buf_pkt->b_next = NULL;
6940      -
6941      -                data_mp = buf_pkt->b_cont;
6942      -                buf_pkt->b_cont = NULL;
6943      -                if (!ip_recv_attr_from_mblk(buf_pkt, &iras)) {
6944      -                        /* The ill or ip_stack_t disappeared on us. */
6945      -                        ip_drop_input("ip_recv_attr_from_mblk", data_mp, NULL);
6946      -                        freemsg(data_mp);
6947      -                } else {
6948      -                        ip_input_post_ipsec(data_mp, &iras);
6949      -                }
6950      -                ira_cleanup(&iras, B_TRUE);
6951      -                buf_pkt = tmp;
6952      -        }
6953      -}
6954      -/*
6955 6648   * Walker callback used by sadb_alg_update() to free/create crypto
6956 6649   * context template when a crypto software provider is removed or
6957 6650   * added.
6958 6651   */
6959 6652  
6960 6653  struct sadb_update_alg_state {
6961 6654          ipsec_algtype_t alg_type;
6962 6655          uint8_t alg_id;
6963 6656          boolean_t is_added;
6964 6657          boolean_t async_auth;
6965 6658          boolean_t async_encr;
6966 6659  };
6967 6660  
6968 6661  static void
6969 6662  sadb_alg_update_cb(isaf_t *head, ipsa_t *entry, void *cookie)
6970 6663  {
6971 6664          struct sadb_update_alg_state *update_state =
6972 6665              (struct sadb_update_alg_state *)cookie;
6973 6666          crypto_ctx_template_t *ctx_tmpl = NULL;
6974 6667  
6975 6668          ASSERT(MUTEX_HELD(&head->isaf_lock));
6976 6669  
6977 6670          if (entry->ipsa_state == IPSA_STATE_LARVAL)
6978 6671                  return;
6979 6672  
6980 6673          mutex_enter(&entry->ipsa_lock);
6981 6674  
6982 6675          if ((entry->ipsa_encr_alg != SADB_EALG_NONE && entry->ipsa_encr_alg !=
6983 6676              SADB_EALG_NULL && update_state->async_encr) ||
6984 6677              (entry->ipsa_auth_alg != SADB_AALG_NONE &&
6985 6678              update_state->async_auth)) {
6986 6679                  entry->ipsa_flags |= IPSA_F_ASYNC;
6987 6680          } else {
6988 6681                  entry->ipsa_flags &= ~IPSA_F_ASYNC;
6989 6682          }
6990 6683  
6991 6684          switch (update_state->alg_type) {
6992 6685          case IPSEC_ALG_AUTH:
6993 6686                  if (entry->ipsa_auth_alg == update_state->alg_id)
6994 6687                          ctx_tmpl = &entry->ipsa_authtmpl;
6995 6688                  break;
6996 6689          case IPSEC_ALG_ENCR:
6997 6690                  if (entry->ipsa_encr_alg == update_state->alg_id)
6998 6691                          ctx_tmpl = &entry->ipsa_encrtmpl;
6999 6692                  break;
7000 6693          default:
7001 6694                  ctx_tmpl = NULL;
7002 6695          }
7003 6696  
7004 6697          if (ctx_tmpl == NULL) {
7005 6698                  mutex_exit(&entry->ipsa_lock);
7006 6699                  return;
7007 6700          }
7008 6701  
7009 6702          /*
7010 6703           * The context template of the SA may be affected by the change
7011 6704           * of crypto provider.
7012 6705           */
7013 6706          if (update_state->is_added) {
7014 6707                  /* create the context template if not already done */
7015 6708                  if (*ctx_tmpl == NULL) {
7016 6709                          (void) ipsec_create_ctx_tmpl(entry,
7017 6710                              update_state->alg_type);
7018 6711                  }
7019 6712          } else {
7020 6713                  /*
7021 6714                   * The crypto provider was removed. If the context template
7022 6715                   * exists but it is no longer valid, free it.
7023 6716                   */
7024 6717                  if (*ctx_tmpl != NULL)
7025 6718                          ipsec_destroy_ctx_tmpl(entry, update_state->alg_type);
7026 6719          }
7027 6720  
7028 6721          mutex_exit(&entry->ipsa_lock);
7029 6722  }
7030 6723  
7031 6724  /*
7032 6725   * Invoked by IP when an software crypto provider has been updated, or if
7033 6726   * the crypto synchrony changes.  The type and id of the corresponding
7034 6727   * algorithm is passed as argument.  The type is set to ALL in the case of
7035 6728   * a synchrony change.
7036 6729   *
7037 6730   * is_added is B_TRUE if the provider was added, B_FALSE if it was
7038 6731   * removed. The function updates the SADB and free/creates the
7039 6732   * context templates associated with SAs if needed.
7040 6733   */
7041 6734  
7042 6735  #define SADB_ALG_UPDATE_WALK(sadb, table) \
7043 6736      sadb_walker((sadb).table, (sadb).sdb_hashsize, sadb_alg_update_cb, \
7044 6737          &update_state)
7045 6738  
7046 6739  void
7047 6740  sadb_alg_update(ipsec_algtype_t alg_type, uint8_t alg_id, boolean_t is_added,
7048 6741      netstack_t *ns)
7049 6742  {
7050 6743          struct sadb_update_alg_state update_state;
7051 6744          ipsecah_stack_t *ahstack = ns->netstack_ipsecah;
7052 6745          ipsecesp_stack_t        *espstack = ns->netstack_ipsecesp;
7053 6746          ipsec_stack_t *ipss = ns->netstack_ipsec;
7054 6747  
7055 6748          update_state.alg_type = alg_type;
7056 6749          update_state.alg_id = alg_id;
7057 6750          update_state.is_added = is_added;
7058 6751          update_state.async_auth = ipss->ipsec_algs_exec_mode[IPSEC_ALG_AUTH] ==
7059 6752              IPSEC_ALGS_EXEC_ASYNC;
7060 6753          update_state.async_encr = ipss->ipsec_algs_exec_mode[IPSEC_ALG_ENCR] ==
7061 6754              IPSEC_ALGS_EXEC_ASYNC;
7062 6755  
7063 6756          if (alg_type == IPSEC_ALG_AUTH || alg_type == IPSEC_ALG_ALL) {
7064 6757                  /* walk the AH tables only for auth. algorithm changes */
7065 6758                  SADB_ALG_UPDATE_WALK(ahstack->ah_sadb.s_v4, sdb_of);
7066 6759                  SADB_ALG_UPDATE_WALK(ahstack->ah_sadb.s_v4, sdb_if);
7067 6760                  SADB_ALG_UPDATE_WALK(ahstack->ah_sadb.s_v6, sdb_of);
7068 6761                  SADB_ALG_UPDATE_WALK(ahstack->ah_sadb.s_v6, sdb_if);
7069 6762          }
7070 6763  
7071 6764          /* walk the ESP tables */
7072 6765          SADB_ALG_UPDATE_WALK(espstack->esp_sadb.s_v4, sdb_of);
7073 6766          SADB_ALG_UPDATE_WALK(espstack->esp_sadb.s_v4, sdb_if);
7074 6767          SADB_ALG_UPDATE_WALK(espstack->esp_sadb.s_v6, sdb_of);
7075 6768          SADB_ALG_UPDATE_WALK(espstack->esp_sadb.s_v6, sdb_if);
7076 6769  }
7077 6770  
7078 6771  /*
7079 6772   * Creates a context template for the specified SA. This function
7080 6773   * is called when an SA is created and when a context template needs
7081 6774   * to be created due to a change of software provider.
7082 6775   */
7083 6776  int
7084 6777  ipsec_create_ctx_tmpl(ipsa_t *sa, ipsec_algtype_t alg_type)
7085 6778  {
7086 6779          ipsec_alginfo_t *alg;
7087 6780          crypto_mechanism_t mech;
7088 6781          crypto_key_t *key;
7089 6782          crypto_ctx_template_t *sa_tmpl;
7090 6783          int rv;
7091 6784          ipsec_stack_t   *ipss = sa->ipsa_netstack->netstack_ipsec;
7092 6785  
7093 6786          ASSERT(MUTEX_HELD(&ipss->ipsec_alg_lock));
7094 6787          ASSERT(MUTEX_HELD(&sa->ipsa_lock));
7095 6788  
7096 6789          /* get pointers to the algorithm info, context template, and key */
7097 6790          switch (alg_type) {
7098 6791          case IPSEC_ALG_AUTH:
7099 6792                  key = &sa->ipsa_kcfauthkey;
7100 6793                  sa_tmpl = &sa->ipsa_authtmpl;
7101 6794                  alg = ipss->ipsec_alglists[alg_type][sa->ipsa_auth_alg];
7102 6795                  break;
7103 6796          case IPSEC_ALG_ENCR:
7104 6797                  key = &sa->ipsa_kcfencrkey;
7105 6798                  sa_tmpl = &sa->ipsa_encrtmpl;
7106 6799                  alg = ipss->ipsec_alglists[alg_type][sa->ipsa_encr_alg];
7107 6800                  break;
7108 6801          default:
7109 6802                  alg = NULL;
7110 6803          }
7111 6804  
7112 6805          if (alg == NULL || !ALG_VALID(alg))
7113 6806                  return (EINVAL);
7114 6807  
7115 6808          /* initialize the mech info structure for the framework */
7116 6809          ASSERT(alg->alg_mech_type != CRYPTO_MECHANISM_INVALID);
7117 6810          mech.cm_type = alg->alg_mech_type;
7118 6811          mech.cm_param = NULL;
7119 6812          mech.cm_param_len = 0;
7120 6813  
7121 6814          /* create a new context template */
7122 6815          rv = crypto_create_ctx_template(&mech, key, sa_tmpl, KM_NOSLEEP);
7123 6816  
7124 6817          /*
7125 6818           * CRYPTO_MECH_NOT_SUPPORTED can be returned if only hardware
7126 6819           * providers are available for that mechanism. In that case
7127 6820           * we don't fail, and will generate the context template from
7128 6821           * the framework callback when a software provider for that
7129 6822           * mechanism registers.
7130 6823           *
7131 6824           * The context template is assigned the special value
7132 6825           * IPSEC_CTX_TMPL_ALLOC if the allocation failed due to a
7133 6826           * lack of memory. No attempt will be made to use
7134 6827           * the context template if it is set to this value.
7135 6828           */
7136 6829          if (rv == CRYPTO_HOST_MEMORY) {
7137 6830                  *sa_tmpl = IPSEC_CTX_TMPL_ALLOC;
7138 6831          } else if (rv != CRYPTO_SUCCESS) {
7139 6832                  *sa_tmpl = NULL;
7140 6833                  if (rv != CRYPTO_MECH_NOT_SUPPORTED)
7141 6834                          return (EINVAL);
7142 6835          }
7143 6836  
7144 6837          return (0);
7145 6838  }
7146 6839  
7147 6840  /*
7148 6841   * Destroy the context template of the specified algorithm type
7149 6842   * of the specified SA. Must be called while holding the SA lock.
7150 6843   */
7151 6844  void
7152 6845  ipsec_destroy_ctx_tmpl(ipsa_t *sa, ipsec_algtype_t alg_type)
7153 6846  {
7154 6847          ASSERT(MUTEX_HELD(&sa->ipsa_lock));
7155 6848  
7156 6849          if (alg_type == IPSEC_ALG_AUTH) {
7157 6850                  if (sa->ipsa_authtmpl == IPSEC_CTX_TMPL_ALLOC)
7158 6851                          sa->ipsa_authtmpl = NULL;
7159 6852                  else if (sa->ipsa_authtmpl != NULL) {
7160 6853                          crypto_destroy_ctx_template(sa->ipsa_authtmpl);
7161 6854                          sa->ipsa_authtmpl = NULL;
7162 6855                  }
7163 6856          } else {
7164 6857                  ASSERT(alg_type == IPSEC_ALG_ENCR);
7165 6858                  if (sa->ipsa_encrtmpl == IPSEC_CTX_TMPL_ALLOC)
7166 6859                          sa->ipsa_encrtmpl = NULL;
7167 6860                  else if (sa->ipsa_encrtmpl != NULL) {
7168 6861                          crypto_destroy_ctx_template(sa->ipsa_encrtmpl);
7169 6862                          sa->ipsa_encrtmpl = NULL;
7170 6863                  }
7171 6864          }
7172 6865  }
7173 6866  
7174 6867  /*
7175 6868   * Use the kernel crypto framework to check the validity of a key received
7176 6869   * via keysock. Returns 0 if the key is OK, -1 otherwise.
7177 6870   */
7178 6871  int
7179 6872  ipsec_check_key(crypto_mech_type_t mech_type, sadb_key_t *sadb_key,
7180 6873      boolean_t is_auth, int *diag)
7181 6874  {
7182 6875          crypto_mechanism_t mech;
7183 6876          crypto_key_t crypto_key;
7184 6877          int crypto_rc;
7185 6878  
7186 6879          mech.cm_type = mech_type;
7187 6880          mech.cm_param = NULL;
7188 6881          mech.cm_param_len = 0;
7189 6882  
7190 6883          crypto_key.ck_format = CRYPTO_KEY_RAW;
7191 6884          crypto_key.ck_data = sadb_key + 1;
7192 6885          crypto_key.ck_length = sadb_key->sadb_key_bits;
7193 6886  
7194 6887          crypto_rc = crypto_key_check(&mech, &crypto_key);
7195 6888  
7196 6889          switch (crypto_rc) {
7197 6890          case CRYPTO_SUCCESS:
7198 6891                  return (0);
7199 6892          case CRYPTO_MECHANISM_INVALID:
7200 6893          case CRYPTO_MECH_NOT_SUPPORTED:
7201 6894                  *diag = is_auth ? SADB_X_DIAGNOSTIC_BAD_AALG :
7202 6895                      SADB_X_DIAGNOSTIC_BAD_EALG;
7203 6896                  break;
7204 6897          case CRYPTO_KEY_SIZE_RANGE:
7205 6898                  *diag = is_auth ? SADB_X_DIAGNOSTIC_BAD_AKEYBITS :
7206 6899                      SADB_X_DIAGNOSTIC_BAD_EKEYBITS;
7207 6900                  break;
7208 6901          case CRYPTO_WEAK_KEY:
7209 6902                  *diag = is_auth ? SADB_X_DIAGNOSTIC_WEAK_AKEY :
7210 6903                      SADB_X_DIAGNOSTIC_WEAK_EKEY;
7211 6904                  break;
7212 6905          }
7213 6906  
7214 6907          return (-1);
7215 6908  }
7216 6909  
7217 6910  /*
7218 6911   * Whack options in the outer IP header when ipsec changes the outer label
7219 6912   *
7220 6913   * This is inelegant and really could use refactoring.
7221 6914   */
7222 6915  mblk_t *
7223 6916  sadb_whack_label_v4(mblk_t *mp, ipsa_t *assoc, kstat_named_t *counter,
7224 6917      ipdropper_t *dropper)
7225 6918  {
7226 6919          int delta;
7227 6920          int plen;
7228 6921          dblk_t *db;
7229 6922          int hlen;
7230 6923          uint8_t *opt_storage = assoc->ipsa_opt_storage;
7231 6924          ipha_t *ipha = (ipha_t *)mp->b_rptr;
7232 6925  
7233 6926          plen = ntohs(ipha->ipha_length);
7234 6927  
7235 6928          delta = tsol_remove_secopt(ipha, MBLKL(mp));
7236 6929          mp->b_wptr += delta;
7237 6930          plen += delta;
7238 6931  
7239 6932          /* XXX XXX code copied from tsol_check_label */
7240 6933  
7241 6934          /* Make sure we have room for the worst-case addition */
7242 6935          hlen = IPH_HDR_LENGTH(ipha) + opt_storage[IPOPT_OLEN];
7243 6936          hlen = (hlen + 3) & ~3;
7244 6937          if (hlen > IP_MAX_HDR_LENGTH)
7245 6938                  hlen = IP_MAX_HDR_LENGTH;
7246 6939          hlen -= IPH_HDR_LENGTH(ipha);
7247 6940  
7248 6941          db = mp->b_datap;
7249 6942          if ((db->db_ref != 1) || (mp->b_wptr + hlen > db->db_lim)) {
7250 6943                  int copylen;
7251 6944                  mblk_t *new_mp;
7252 6945  
7253 6946                  /* allocate enough to be meaningful, but not *too* much */
7254 6947                  copylen = MBLKL(mp);
7255 6948                  if (copylen > 256)
7256 6949                          copylen = 256;
7257 6950                  new_mp = allocb_tmpl(hlen + copylen +
7258 6951                      (mp->b_rptr - mp->b_datap->db_base), mp);
7259 6952  
7260 6953                  if (new_mp == NULL) {
7261 6954                          ip_drop_packet(mp, B_FALSE, NULL, counter,  dropper);
7262 6955                          return (NULL);
7263 6956                  }
7264 6957  
7265 6958                  /* keep the bias */
7266 6959                  new_mp->b_rptr += mp->b_rptr - mp->b_datap->db_base;
7267 6960                  new_mp->b_wptr = new_mp->b_rptr + copylen;
7268 6961                  bcopy(mp->b_rptr, new_mp->b_rptr, copylen);
7269 6962                  new_mp->b_cont = mp;
7270 6963                  if ((mp->b_rptr += copylen) >= mp->b_wptr) {
7271 6964                          new_mp->b_cont = mp->b_cont;
7272 6965                          freeb(mp);
7273 6966                  }
7274 6967                  mp = new_mp;
7275 6968                  ipha = (ipha_t *)mp->b_rptr;
7276 6969          }
7277 6970  
7278 6971          delta = tsol_prepend_option(assoc->ipsa_opt_storage, ipha, MBLKL(mp));
7279 6972  
7280 6973          ASSERT(delta != -1);
7281 6974  
7282 6975          plen += delta;
7283 6976          mp->b_wptr += delta;
7284 6977  
7285 6978          /*
7286 6979           * Paranoia
7287 6980           */
7288 6981          db = mp->b_datap;
7289 6982  
7290 6983          ASSERT3P(mp->b_wptr, <=, db->db_lim);
7291 6984          ASSERT3P(mp->b_rptr, <=, db->db_lim);
7292 6985  
7293 6986          ASSERT3P(mp->b_wptr, >=, db->db_base);
7294 6987          ASSERT3P(mp->b_rptr, >=, db->db_base);
7295 6988          /* End paranoia */
7296 6989  
7297 6990          ipha->ipha_length = htons(plen);
7298 6991  
7299 6992          return (mp);
7300 6993  }
7301 6994  
7302 6995  mblk_t *
7303 6996  sadb_whack_label_v6(mblk_t *mp, ipsa_t *assoc, kstat_named_t *counter,
7304 6997      ipdropper_t *dropper)
7305 6998  {
7306 6999          int delta;
7307 7000          int plen;
7308 7001          dblk_t *db;
7309 7002          int hlen;
7310 7003          uint8_t *opt_storage = assoc->ipsa_opt_storage;
7311 7004          uint_t sec_opt_len; /* label option length not including type, len */
7312 7005          ip6_t *ip6h = (ip6_t *)mp->b_rptr;
7313 7006  
7314 7007          plen = ntohs(ip6h->ip6_plen);
7315 7008  
7316 7009          delta = tsol_remove_secopt_v6(ip6h, MBLKL(mp));
7317 7010          mp->b_wptr += delta;
7318 7011          plen += delta;
7319 7012  
7320 7013          /* XXX XXX code copied from tsol_check_label_v6 */
7321 7014          /*
7322 7015           * Make sure we have room for the worst-case addition. Add 2 bytes for
7323 7016           * the hop-by-hop ext header's next header and length fields. Add
7324 7017           * another 2 bytes for the label option type, len and then round
7325 7018           * up to the next 8-byte multiple.
7326 7019           */
7327 7020          sec_opt_len = opt_storage[1];
7328 7021  
7329 7022          db = mp->b_datap;
7330 7023          hlen = (4 + sec_opt_len + 7) & ~7;
7331 7024  
7332 7025          if ((db->db_ref != 1) || (mp->b_wptr + hlen > db->db_lim)) {
7333 7026                  int copylen;
7334 7027                  mblk_t *new_mp;
7335 7028                  uint16_t hdr_len;
7336 7029  
7337 7030                  hdr_len = ip_hdr_length_v6(mp, ip6h);
7338 7031                  /*
7339 7032                   * Allocate enough to be meaningful, but not *too* much.
7340 7033                   * Also all the IPv6 extension headers must be in the same mblk
7341 7034                   */
7342 7035                  copylen = MBLKL(mp);
7343 7036                  if (copylen > 256)
7344 7037                          copylen = 256;
7345 7038                  if (copylen < hdr_len)
7346 7039                          copylen = hdr_len;
7347 7040                  new_mp = allocb_tmpl(hlen + copylen +
7348 7041                      (mp->b_rptr - mp->b_datap->db_base), mp);
7349 7042                  if (new_mp == NULL) {
7350 7043                          ip_drop_packet(mp, B_FALSE, NULL, counter,  dropper);
7351 7044                          return (NULL);
7352 7045                  }
7353 7046  
7354 7047                  /* keep the bias */
7355 7048                  new_mp->b_rptr += mp->b_rptr - mp->b_datap->db_base;
7356 7049                  new_mp->b_wptr = new_mp->b_rptr + copylen;
7357 7050                  bcopy(mp->b_rptr, new_mp->b_rptr, copylen);
7358 7051                  new_mp->b_cont = mp;
7359 7052                  if ((mp->b_rptr += copylen) >= mp->b_wptr) {
7360 7053                          new_mp->b_cont = mp->b_cont;
7361 7054                          freeb(mp);
7362 7055                  }
7363 7056                  mp = new_mp;
7364 7057                  ip6h = (ip6_t *)mp->b_rptr;
7365 7058          }
7366 7059  
7367 7060          delta = tsol_prepend_option_v6(assoc->ipsa_opt_storage,
7368 7061              ip6h, MBLKL(mp));
7369 7062  
7370 7063          ASSERT(delta != -1);
7371 7064  
7372 7065          plen += delta;
7373 7066          mp->b_wptr += delta;
7374 7067  
7375 7068          /*
7376 7069           * Paranoia
7377 7070           */
7378 7071          db = mp->b_datap;
7379 7072  
7380 7073          ASSERT3P(mp->b_wptr, <=, db->db_lim);
7381 7074          ASSERT3P(mp->b_rptr, <=, db->db_lim);
7382 7075  
7383 7076          ASSERT3P(mp->b_wptr, >=, db->db_base);
7384 7077          ASSERT3P(mp->b_rptr, >=, db->db_base);
7385 7078          /* End paranoia */
7386 7079  
7387 7080          ip6h->ip6_plen = htons(plen);
7388 7081  
7389 7082          return (mp);
7390 7083  }
7391 7084  
7392 7085  /* Whack the labels and update ip_xmit_attr_t as needed */
7393 7086  mblk_t *
7394 7087  sadb_whack_label(mblk_t *mp, ipsa_t *assoc, ip_xmit_attr_t *ixa,
7395 7088      kstat_named_t *counter, ipdropper_t *dropper)
7396 7089  {
7397 7090          int adjust;
7398 7091          int iplen;
7399 7092  
7400 7093          if (ixa->ixa_flags & IXAF_IS_IPV4) {
7401 7094                  ipha_t          *ipha = (ipha_t *)mp->b_rptr;
7402 7095  
7403 7096                  ASSERT(IPH_HDR_VERSION(ipha) == IPV4_VERSION);
7404 7097                  iplen = ntohs(ipha->ipha_length);
7405 7098                  mp = sadb_whack_label_v4(mp, assoc, counter, dropper);
7406 7099                  if (mp == NULL)
7407 7100                          return (NULL);
7408 7101  
7409 7102                  ipha = (ipha_t *)mp->b_rptr;
7410 7103                  ASSERT(IPH_HDR_VERSION(ipha) == IPV4_VERSION);
7411 7104                  adjust = (int)ntohs(ipha->ipha_length) - iplen;
7412 7105          } else {
7413 7106                  ip6_t           *ip6h = (ip6_t *)mp->b_rptr;
7414 7107  
7415 7108                  ASSERT(IPH_HDR_VERSION(ip6h) == IPV6_VERSION);
7416 7109                  iplen = ntohs(ip6h->ip6_plen);
7417 7110                  mp = sadb_whack_label_v6(mp, assoc, counter, dropper);
7418 7111                  if (mp == NULL)
7419 7112                          return (NULL);
7420 7113  
7421 7114                  ip6h = (ip6_t *)mp->b_rptr;
7422 7115                  ASSERT(IPH_HDR_VERSION(ip6h) == IPV6_VERSION);
7423 7116                  adjust = (int)ntohs(ip6h->ip6_plen) - iplen;
7424 7117          }
7425 7118          ixa->ixa_pktlen += adjust;
7426 7119          ixa->ixa_ip_hdr_length += adjust;
7427 7120          return (mp);
7428 7121  }
7429 7122  
7430 7123  /*
7431 7124   * If this is an outgoing SA then add some fuzz to the
7432 7125   * SOFT EXPIRE time. The reason for this is to stop
7433 7126   * peers trying to renegotiate SOFT expiring SA's at
7434 7127   * the same time. The amount of fuzz needs to be at
7435 7128   * least 8 seconds which is the typical interval
7436 7129   * sadb_ager(), although this is only a guide as it
7437 7130   * selftunes.
7438 7131   */
7439 7132  static void
7440 7133  lifetime_fuzz(ipsa_t *assoc)
7441 7134  {
7442 7135          uint8_t rnd;
7443 7136  
7444 7137          if (assoc->ipsa_softaddlt == 0)
7445 7138                  return;
7446 7139  
7447 7140          (void) random_get_pseudo_bytes(&rnd, sizeof (rnd));
7448 7141          rnd = (rnd & 0xF) + 8;
7449 7142          assoc->ipsa_softexpiretime -= rnd;
7450 7143          assoc->ipsa_softaddlt -= rnd;
7451 7144  }
7452 7145  
7453 7146  static void
7454 7147  destroy_ipsa_pair(ipsap_t *ipsapp)
7455 7148  {
7456 7149          /*
7457 7150           * Because of the multi-line macro nature of IPSA_REFRELE, keep
7458 7151           * them in { }.
7459 7152           */
7460 7153          if (ipsapp->ipsap_sa_ptr != NULL) {
7461 7154                  IPSA_REFRELE(ipsapp->ipsap_sa_ptr);
7462 7155          }
7463 7156          if (ipsapp->ipsap_psa_ptr != NULL) {
7464 7157                  IPSA_REFRELE(ipsapp->ipsap_psa_ptr);
7465 7158          }
7466 7159          init_ipsa_pair(ipsapp);
7467 7160  }
7468 7161  
7469 7162  static void
7470 7163  init_ipsa_pair(ipsap_t *ipsapp)
7471 7164  {
7472 7165          ipsapp->ipsap_bucket = NULL;
7473 7166          ipsapp->ipsap_sa_ptr = NULL;
7474 7167          ipsapp->ipsap_pbucket = NULL;
7475 7168          ipsapp->ipsap_psa_ptr = NULL;
7476 7169  }
7477 7170  
7478 7171  /*
7479 7172   * The sadb_ager() function walks through the hash tables of SA's and ages
7480 7173   * them, if the SA expires as a result, its marked as DEAD and will be reaped
7481 7174   * the next time sadb_ager() runs. SA's which are paired or have a peer (same
7482 7175   * SA appears in both the inbound and outbound tables because its not possible
7483 7176   * to determine its direction) are placed on a list when they expire. This is
7484 7177   * to ensure that pair/peer SA's are reaped at the same time, even if they
7485 7178   * expire at different times.
7486 7179   *
7487 7180   * This function is called twice by sadb_ager(), one after processing the
7488 7181   * inbound table, then again after processing the outbound table.
7489 7182   */
7490 7183  void
7491 7184  age_pair_peer_list(templist_t *haspeerlist, sadb_t *sp, boolean_t outbound)
7492 7185  {
7493 7186          templist_t *listptr;
7494 7187          int outhash;
7495 7188          isaf_t *bucket;
7496 7189          boolean_t haspeer;
7497 7190          ipsa_t *peer_assoc, *dying;
7498 7191          /*
7499 7192           * Haspeer cases will contain both IPv4 and IPv6.  This code
7500 7193           * is address independent.
7501 7194           */
7502 7195          while (haspeerlist != NULL) {
7503 7196                  /* "dying" contains the SA that has a peer. */
7504 7197                  dying = haspeerlist->ipsa;
7505 7198                  haspeer = (dying->ipsa_haspeer);
7506 7199                  listptr = haspeerlist;
7507 7200                  haspeerlist = listptr->next;
7508 7201                  kmem_free(listptr, sizeof (*listptr));
7509 7202                  /*
7510 7203                   * Pick peer bucket based on addrfam.
7511 7204                   */
7512 7205                  if (outbound) {
7513 7206                          if (haspeer)
7514 7207                                  bucket = INBOUND_BUCKET(sp, dying->ipsa_spi);
7515 7208                          else
7516 7209                                  bucket = INBOUND_BUCKET(sp,
7517 7210                                      dying->ipsa_otherspi);
7518 7211                  } else { /* inbound */
7519 7212                          if (haspeer) {
7520 7213                                  if (dying->ipsa_addrfam == AF_INET6) {
7521 7214                                          outhash = OUTBOUND_HASH_V6(sp,
7522 7215                                              *((in6_addr_t *)&dying->
7523 7216                                              ipsa_dstaddr));
7524 7217                                  } else {
7525 7218                                          outhash = OUTBOUND_HASH_V4(sp,
7526 7219                                              *((ipaddr_t *)&dying->
7527 7220                                              ipsa_dstaddr));
7528 7221                                  }
7529 7222                          } else if (dying->ipsa_addrfam == AF_INET6) {
7530 7223                                  outhash = OUTBOUND_HASH_V6(sp,
7531 7224                                      *((in6_addr_t *)&dying->
7532 7225                                      ipsa_srcaddr));
7533 7226                          } else {
7534 7227                                  outhash = OUTBOUND_HASH_V4(sp,
7535 7228                                      *((ipaddr_t *)&dying->
7536 7229                                      ipsa_srcaddr));
7537 7230                          }
7538 7231                          bucket = &(sp->sdb_of[outhash]);
7539 7232                  }
7540 7233  
7541 7234                  mutex_enter(&bucket->isaf_lock);
7542 7235                  /*
7543 7236                   * "haspeer" SA's have the same src/dst address ordering,
7544 7237                   * "paired" SA's have the src/dst addresses reversed.
7545 7238                   */
7546 7239                  if (haspeer) {
7547 7240                          peer_assoc = ipsec_getassocbyspi(bucket,
7548 7241                              dying->ipsa_spi, dying->ipsa_srcaddr,
7549 7242                              dying->ipsa_dstaddr, dying->ipsa_addrfam);
7550 7243                  } else {
7551 7244                          peer_assoc = ipsec_getassocbyspi(bucket,
7552 7245                              dying->ipsa_otherspi, dying->ipsa_dstaddr,
7553 7246                              dying->ipsa_srcaddr, dying->ipsa_addrfam);
7554 7247                  }
7555 7248  
7556 7249                  mutex_exit(&bucket->isaf_lock);
7557 7250                  if (peer_assoc != NULL) {
7558 7251                          mutex_enter(&peer_assoc->ipsa_lock);
7559 7252                          mutex_enter(&dying->ipsa_lock);
7560 7253                          if (!haspeer) {
7561 7254                                  /*
7562 7255                                   * Only SA's which have a "peer" or are
7563 7256                                   * "paired" end up on this list, so this
7564 7257                                   * must be a "paired" SA, update the flags
7565 7258                                   * to break the pair.
7566 7259                                   */
7567 7260                                  peer_assoc->ipsa_otherspi = 0;
7568 7261                                  peer_assoc->ipsa_flags &= ~IPSA_F_PAIRED;
7569 7262                                  dying->ipsa_otherspi = 0;
7570 7263                                  dying->ipsa_flags &= ~IPSA_F_PAIRED;
7571 7264                          }
7572 7265                          if (haspeer || outbound) {
7573 7266                                  /*
7574 7267                                   * Update the state of the "inbound" SA when
7575 7268                                   * the "outbound" SA has expired. Don't update
7576 7269                                   * the "outbound" SA when the "inbound" SA
7577 7270                                   * SA expires because setting the hard_addtime
7578 7271                                   * below will cause this to happen.
7579 7272                                   */
7580 7273                                  peer_assoc->ipsa_state = dying->ipsa_state;
7581 7274                          }
7582 7275                          if (dying->ipsa_state == IPSA_STATE_DEAD)
7583 7276                                  peer_assoc->ipsa_hardexpiretime = 1;
7584 7277  
7585 7278                          mutex_exit(&dying->ipsa_lock);
7586 7279                          mutex_exit(&peer_assoc->ipsa_lock);
7587 7280                          IPSA_REFRELE(peer_assoc);
7588 7281                  }
7589 7282                  IPSA_REFRELE(dying);
7590 7283          }
7591 7284  }
7592 7285  
7593 7286  /*
7594 7287   * Ensure that the IV used for CCM mode never repeats. The IV should
7595 7288   * only be updated by this function. Also check to see if the IV
7596 7289   * is about to wrap and generate a SOFT Expire. This function is only
7597 7290   * called for outgoing packets, the IV for incomming packets is taken
7598 7291   * from the wire. If the outgoing SA needs to be expired, update
7599 7292   * the matching incomming SA.
7600 7293   */
7601 7294  boolean_t
7602 7295  update_iv(uint8_t *iv_ptr, queue_t *pfkey_q, ipsa_t *assoc,
7603 7296      ipsecesp_stack_t *espstack)
7604 7297  {
7605 7298          boolean_t rc = B_TRUE;
7606 7299          isaf_t *inbound_bucket;
7607 7300          sadb_t *sp;
7608 7301          ipsa_t *pair_sa = NULL;
7609 7302          int sa_new_state = 0;
7610 7303  
7611 7304          /* For non counter modes, the IV is random data. */
7612 7305          if (!(assoc->ipsa_flags & IPSA_F_COUNTERMODE)) {
7613 7306                  (void) random_get_pseudo_bytes(iv_ptr, assoc->ipsa_iv_len);
7614 7307                  return (rc);
7615 7308          }
7616 7309  
7617 7310          mutex_enter(&assoc->ipsa_lock);
7618 7311  
7619 7312          (*assoc->ipsa_iv)++;
7620 7313  
7621 7314          if (*assoc->ipsa_iv == assoc->ipsa_iv_hardexpire) {
7622 7315                  sa_new_state = IPSA_STATE_DEAD;
7623 7316                  rc = B_FALSE;
7624 7317          } else if (*assoc->ipsa_iv == assoc->ipsa_iv_softexpire) {
7625 7318                  if (assoc->ipsa_state != IPSA_STATE_DYING) {
7626 7319                          /*
7627 7320                           * This SA may have already been expired when its
7628 7321                           * PAIR_SA expired.
7629 7322                           */
7630 7323                          sa_new_state = IPSA_STATE_DYING;
7631 7324                  }
7632 7325          }
7633 7326          if (sa_new_state) {
7634 7327                  /*
7635 7328                   * If there is a state change, we need to update this SA
7636 7329                   * and its "pair", we can find the bucket for the "pair" SA
7637 7330                   * while holding the ipsa_t mutex, but we won't actually
7638 7331                   * update anything untill the ipsa_t mutex has been released
7639 7332                   * for _this_ SA.
7640 7333                   */
7641 7334                  assoc->ipsa_state = sa_new_state;
7642 7335                  if (assoc->ipsa_addrfam == AF_INET6) {
7643 7336                          sp = &espstack->esp_sadb.s_v6;
7644 7337                  } else {
7645 7338                          sp = &espstack->esp_sadb.s_v4;
7646 7339                  }
7647 7340                  inbound_bucket = INBOUND_BUCKET(sp, assoc->ipsa_otherspi);
7648 7341                  sadb_expire_assoc(pfkey_q, assoc);
7649 7342          }
7650 7343          if (rc == B_TRUE)
7651 7344                  bcopy(assoc->ipsa_iv, iv_ptr, assoc->ipsa_iv_len);
7652 7345  
7653 7346          mutex_exit(&assoc->ipsa_lock);
7654 7347  
7655 7348          if (sa_new_state) {
7656 7349                  /* Find the inbound SA, need to lock hash bucket. */
7657 7350                  mutex_enter(&inbound_bucket->isaf_lock);
7658 7351                  pair_sa = ipsec_getassocbyspi(inbound_bucket,
7659 7352                      assoc->ipsa_otherspi, assoc->ipsa_dstaddr,
7660 7353                      assoc->ipsa_srcaddr, assoc->ipsa_addrfam);
7661 7354                  mutex_exit(&inbound_bucket->isaf_lock);
7662 7355                  if (pair_sa != NULL) {
7663 7356                          mutex_enter(&pair_sa->ipsa_lock);
7664 7357                          pair_sa->ipsa_state = sa_new_state;
7665 7358                          mutex_exit(&pair_sa->ipsa_lock);
7666 7359                          IPSA_REFRELE(pair_sa);
7667 7360                  }
7668 7361          }
7669 7362  
7670 7363          return (rc);
7671 7364  }
7672 7365  
7673 7366  void
7674 7367  ccm_params_init(ipsa_t *assoc, uchar_t *esph, uint_t data_len, uchar_t *iv_ptr,
7675 7368      ipsa_cm_mech_t *cm_mech, crypto_data_t *crypto_data)
7676 7369  {
7677 7370          uchar_t *nonce;
7678 7371          crypto_mechanism_t *combined_mech;
7679 7372          CK_AES_CCM_PARAMS *params;
7680 7373  
7681 7374          combined_mech = (crypto_mechanism_t *)cm_mech;
7682 7375          params = (CK_AES_CCM_PARAMS *)(combined_mech + 1);
7683 7376          nonce = (uchar_t *)(params + 1);
7684 7377          params->ulMACSize = assoc->ipsa_mac_len;
7685 7378          params->ulNonceSize = assoc->ipsa_nonce_len;
7686 7379          params->ulAuthDataSize = sizeof (esph_t);
7687 7380          params->ulDataSize = data_len;
7688 7381          params->nonce = nonce;
7689 7382          params->authData = esph;
7690 7383  
7691 7384          cm_mech->combined_mech.cm_type = assoc->ipsa_emech.cm_type;
7692 7385          cm_mech->combined_mech.cm_param_len = sizeof (CK_AES_CCM_PARAMS);
7693 7386          cm_mech->combined_mech.cm_param = (caddr_t)params;
7694 7387          /* See gcm_params_init() for comments. */
7695 7388          bcopy(assoc->ipsa_nonce, nonce, assoc->ipsa_saltlen);
7696 7389          nonce += assoc->ipsa_saltlen;
7697 7390          bcopy(iv_ptr, nonce, assoc->ipsa_iv_len);
7698 7391          crypto_data->cd_miscdata = NULL;
7699 7392  }
7700 7393  
7701 7394  /* ARGSUSED */
7702 7395  void
7703 7396  cbc_params_init(ipsa_t *assoc, uchar_t *esph, uint_t data_len, uchar_t *iv_ptr,
7704 7397      ipsa_cm_mech_t *cm_mech, crypto_data_t *crypto_data)
7705 7398  {
7706 7399          cm_mech->combined_mech.cm_type = assoc->ipsa_emech.cm_type;
7707 7400          cm_mech->combined_mech.cm_param_len = 0;
7708 7401          cm_mech->combined_mech.cm_param = NULL;
7709 7402          crypto_data->cd_miscdata = (char *)iv_ptr;
7710 7403  }
7711 7404  
7712 7405  /* ARGSUSED */
7713 7406  void
7714 7407  gcm_params_init(ipsa_t *assoc, uchar_t *esph, uint_t data_len, uchar_t *iv_ptr,
7715 7408      ipsa_cm_mech_t *cm_mech, crypto_data_t *crypto_data)
7716 7409  {
7717 7410          uchar_t *nonce;
7718 7411          crypto_mechanism_t *combined_mech;
7719 7412          CK_AES_GCM_PARAMS *params;
7720 7413  
7721 7414          combined_mech = (crypto_mechanism_t *)cm_mech;
7722 7415          params = (CK_AES_GCM_PARAMS *)(combined_mech + 1);
7723 7416          nonce = (uchar_t *)(params + 1);
7724 7417  
7725 7418          params->pIv = nonce;
7726 7419          params->ulIvLen = assoc->ipsa_nonce_len;
7727 7420          params->ulIvBits = SADB_8TO1(assoc->ipsa_nonce_len);
7728 7421          params->pAAD = esph;
7729 7422          params->ulAADLen = sizeof (esph_t);
7730 7423          params->ulTagBits = SADB_8TO1(assoc->ipsa_mac_len);
7731 7424  
7732 7425          cm_mech->combined_mech.cm_type = assoc->ipsa_emech.cm_type;
7733 7426          cm_mech->combined_mech.cm_param_len = sizeof (CK_AES_GCM_PARAMS);
7734 7427          cm_mech->combined_mech.cm_param = (caddr_t)params;
7735 7428          /*
7736 7429           * Create the nonce, which is made up of the salt and the IV.
7737 7430           * Copy the salt from the SA and the IV from the packet.
7738 7431           * For inbound packets we copy the IV from the packet because it
7739 7432           * was set by the sending system, for outbound packets we copy the IV
7740 7433           * from the packet because the IV in the SA may be changed by another
7741 7434           * thread, the IV in the packet was created while holding a mutex.
7742 7435           */
7743 7436          bcopy(assoc->ipsa_nonce, nonce, assoc->ipsa_saltlen);
7744 7437          nonce += assoc->ipsa_saltlen;
7745 7438          bcopy(iv_ptr, nonce, assoc->ipsa_iv_len);
7746 7439          crypto_data->cd_miscdata = NULL;
7747 7440  }
  
    | 
      ↓ open down ↓ | 
    783 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX