Print this page
Bayard's initial drop, needs finishing, or at least testing.


   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.

  24  */
  25 
  26 #include <sys/types.h>
  27 #include <sys/stream.h>
  28 #include <sys/stropts.h>
  29 #include <sys/errno.h>
  30 #include <sys/strlog.h>
  31 #include <sys/tihdr.h>
  32 #include <sys/socket.h>
  33 #include <sys/ddi.h>
  34 #include <sys/sunddi.h>
  35 #include <sys/mkdev.h>
  36 #include <sys/kmem.h>
  37 #include <sys/zone.h>
  38 #include <sys/sysmacros.h>
  39 #include <sys/cmn_err.h>
  40 #include <sys/vtrace.h>
  41 #include <sys/debug.h>
  42 #include <sys/atomic.h>
  43 #include <sys/strsun.h>


  78  * ipsecah_g_nd in ipsecah_init_nd.
  79  * All of these are alterable, within the min/max values given, at run time.
  80  */
  81 static  ipsecahparam_t  lcl_param_arr[] = {
  82         /* min  max                     value   name */
  83         { 0,    3,                      0,      "ipsecah_debug"},
  84         { 125,  32000, SADB_AGE_INTERVAL_DEFAULT,       "ipsecah_age_interval"},
  85         { 1,    10,                     1,      "ipsecah_reap_delay"},
  86         { 1,    SADB_MAX_REPLAY,        64,     "ipsecah_replay_size"},
  87         { 1,    300,                    15,     "ipsecah_acquire_timeout"},
  88         { 1,    1800,                   90,     "ipsecah_larval_timeout"},
  89         /* Default lifetime values for ACQUIRE messages. */
  90         { 0,    0xffffffffU,            0,      "ipsecah_default_soft_bytes"},
  91         { 0,    0xffffffffU,            0,      "ipsecah_default_hard_bytes"},
  92         { 0,    0xffffffffU,            24000,  "ipsecah_default_soft_addtime"},
  93         { 0,    0xffffffffU,            28800,  "ipsecah_default_hard_addtime"},
  94         { 0,    0xffffffffU,            0,      "ipsecah_default_soft_usetime"},
  95         { 0,    0xffffffffU,            0,      "ipsecah_default_hard_usetime"},
  96         { 0,    1,                      0,      "ipsecah_log_unknown_spi"},
  97 };
  98 #define ipsecah_debug                   ipsecah_params[0].ipsecah_param_value
  99 #define ipsecah_age_interval            ipsecah_params[1].ipsecah_param_value
 100 #define ipsecah_age_int_max             ipsecah_params[1].ipsecah_param_max
 101 #define ipsecah_reap_delay              ipsecah_params[2].ipsecah_param_value
 102 #define ipsecah_replay_size             ipsecah_params[3].ipsecah_param_value
 103 #define ipsecah_acquire_timeout         ipsecah_params[4].ipsecah_param_value
 104 #define ipsecah_larval_timeout          ipsecah_params[5].ipsecah_param_value
 105 #define ipsecah_default_soft_bytes      ipsecah_params[6].ipsecah_param_value
 106 #define ipsecah_default_hard_bytes      ipsecah_params[7].ipsecah_param_value
 107 #define ipsecah_default_soft_addtime    ipsecah_params[8].ipsecah_param_value
 108 #define ipsecah_default_hard_addtime    ipsecah_params[9].ipsecah_param_value
 109 #define ipsecah_default_soft_usetime    ipsecah_params[10].ipsecah_param_value
 110 #define ipsecah_default_hard_usetime    ipsecah_params[11].ipsecah_param_value
 111 #define ipsecah_log_unknown_spi         ipsecah_params[12].ipsecah_param_value
 112 
 113 #define ah0dbg(a)       printf a
 114 /* NOTE:  != 0 instead of > 0 so lint doesn't complain. */
 115 #define ah1dbg(ahstack, a)      if (ahstack->ipsecah_debug != 0) printf a
 116 #define ah2dbg(ahstack, a)      if (ahstack->ipsecah_debug > 1) printf a
 117 #define ah3dbg(ahstack, a)      if (ahstack->ipsecah_debug > 2) printf a
 118 
 119 /*
 120  * XXX This is broken. Padding should be determined dynamically
 121  * depending on the ICV size and IP version number so that the
 122  * total AH header size is a multiple of 32 bits or 64 bits
 123  * for V4 and V6 respectively. For 96bit ICVs we have no problems.
 124  * Anything different from that, we need to fix our code.
 125  */
 126 #define IPV4_PADDING_ALIGN      0x04    /* Multiple of 32 bits */
 127 #define IPV6_PADDING_ALIGN      0x04    /* Multiple of 32 bits */
 128 
 129 /*
 130  * Helper macro. Avoids a call to msgdsize if there is only one
 131  * mblk in the chain.
 132  */
 133 #define AH_MSGSIZE(mp) ((mp)->b_cont != NULL ? msgdsize(mp) : MBLKL(mp))
 134 
 135 
 136 static mblk_t *ah_auth_out_done(mblk_t *, ip_xmit_attr_t *, ipsec_crypto_t *);
 137 static mblk_t *ah_auth_in_done(mblk_t *, ip_recv_attr_t *, ipsec_crypto_t *);
 138 static mblk_t *ah_process_ip_options_v4(mblk_t *, ipsa_t *, int *, uint_t,
 139     boolean_t, ipsecah_stack_t *);
 140 static mblk_t *ah_process_ip_options_v6(mblk_t *, ipsa_t *, int *, uint_t,
 141     boolean_t, ipsecah_stack_t *);
 142 static void ah_getspi(mblk_t *, keysock_in_t *, ipsecah_stack_t *);
 143 static void ah_inbound_restart(mblk_t *, ip_recv_attr_t *);
 144 
 145 static mblk_t *ah_outbound(mblk_t *, ip_xmit_attr_t *);
 146 static void ah_outbound_finish(mblk_t *, ip_xmit_attr_t *);
 147 
 148 static int ipsecah_open(queue_t *, dev_t *, int, int, cred_t *);
 149 static int ipsecah_close(queue_t *);
 150 static void ipsecah_wput(queue_t *, mblk_t *);
 151 static void ah_send_acquire(ipsacq_t *, mblk_t *, netstack_t *);
 152 static boolean_t ah_register_out(uint32_t, uint32_t, uint_t, ipsecah_stack_t *,
 153     cred_t *);
 154 static void     *ipsecah_stack_init(netstackid_t stackid, netstack_t *ns);
 155 static void     ipsecah_stack_fini(netstackid_t stackid, void *arg);
 156 
 157 /* Setable in /etc/system */
 158 uint32_t ah_hash_size = IPSEC_DEFAULT_HASH_SIZE;
 159 
 160 static taskq_t *ah_taskq;
 161 
 162 static struct module_info info = {
 163         5136, "ipsecah", 0, INFPSZ, 65536, 1024
 164 };
 165 
 166 static struct qinit rinit = {
 167         (pfi_t)putnext, NULL, ipsecah_open, ipsecah_close, NULL, &info,
 168         NULL
 169 };
 170 
 171 static struct qinit winit = {


 230         netstackid_t    stackid = (netstackid_t)(uintptr_t)kp->ks_private;
 231         netstack_t      *ns;
 232         ipsec_stack_t   *ipss;
 233 
 234         if ((kp == NULL) || (kp->ks_data == NULL))
 235                 return (EIO);
 236 
 237         if (rw == KSTAT_WRITE)
 238                 return (EACCES);
 239 
 240         ns = netstack_find_by_stackid(stackid);
 241         if (ns == NULL)
 242                 return (-1);
 243         ipss = ns->netstack_ipsec;
 244         if (ipss == NULL) {
 245                 netstack_rele(ns);
 246                 return (-1);
 247         }
 248         ekp = (ah_kstats_t *)kp->ks_data;
 249 
 250         mutex_enter(&ipss->ipsec_alg_lock);
 251         ekp->ah_stat_num_aalgs.value.ui64 = ipss->ipsec_nalgs[IPSEC_ALG_AUTH];
 252         mutex_exit(&ipss->ipsec_alg_lock);
 253 
 254         netstack_rele(ns);
 255         return (0);
 256 }
 257 
 258 /*
 259  * Don't have to lock ipsec_age_interval, as only one thread will access it at
 260  * a time, because I control the one function that does a qtimeout() on
 261  * ah_pfkey_q.
 262  */
 263 static void
 264 ah_ager(void *arg)
 265 {
 266         ipsecah_stack_t *ahstack = (ipsecah_stack_t *)arg;
 267         netstack_t      *ns = ahstack->ipsecah_netstack;
 268         hrtime_t begin = gethrtime();
 269 
 270         sadb_ager(&ahstack->ah_sadb.s_v4, ahstack->ah_pfkey_q,
 271             ahstack->ipsecah_reap_delay, ns);
 272         sadb_ager(&ahstack->ah_sadb.s_v6, ahstack->ah_pfkey_q,


 402  */
 403 static void *
 404 ipsecah_stack_init(netstackid_t stackid, netstack_t *ns)
 405 {
 406         ipsecah_stack_t *ahstack;
 407         ipsecahparam_t  *ahp;
 408 
 409         ahstack = (ipsecah_stack_t *)kmem_zalloc(sizeof (*ahstack), KM_SLEEP);
 410         ahstack->ipsecah_netstack = ns;
 411 
 412         ahp = (ipsecahparam_t *)kmem_alloc(sizeof (lcl_param_arr), KM_SLEEP);
 413         ahstack->ipsecah_params = ahp;
 414         bcopy(lcl_param_arr, ahp, sizeof (lcl_param_arr));
 415 
 416         (void) ipsecah_param_register(&ahstack->ipsecah_g_nd, ahp,
 417             A_CNT(lcl_param_arr));
 418 
 419         (void) ah_kstat_init(ahstack, stackid);
 420 
 421         ahstack->ah_sadb.s_acquire_timeout = &ahstack->ipsecah_acquire_timeout;
 422         ahstack->ah_sadb.s_acqfn = ah_send_acquire;
 423         sadbp_init("AH", &ahstack->ah_sadb, SADB_SATYPE_AH, ah_hash_size,
 424             ahstack->ipsecah_netstack);
 425 
 426         mutex_init(&ahstack->ipsecah_param_lock, NULL, MUTEX_DEFAULT, 0);
 427 
 428         ip_drop_register(&ahstack->ah_dropper, "IPsec AH");
 429         return (ahstack);
 430 }
 431 
 432 /*
 433  * Destroy things for AH at module unload time.
 434  */
 435 void
 436 ipsecah_ddi_destroy(void)
 437 {
 438         netstack_unregister(NS_IPSECAH);
 439         taskq_destroy(ah_taskq);
 440 }
 441 
 442 /*
 443  * Destroy things for AH for one stack... Never called?
 444  */
 445 static void
 446 ipsecah_stack_fini(netstackid_t stackid, void *arg)
 447 {
 448         ipsecah_stack_t *ahstack = (ipsecah_stack_t *)arg;
 449 
 450         if (ahstack->ah_pfkey_q != NULL) {
 451                 (void) quntimeout(ahstack->ah_pfkey_q, ahstack->ah_event);
 452         }
 453         ahstack->ah_sadb.s_acqfn = NULL;
 454         ahstack->ah_sadb.s_acquire_timeout = NULL;
 455         sadbp_destroy(&ahstack->ah_sadb, ahstack->ipsecah_netstack);
 456         ip_drop_unregister(&ahstack->ah_dropper);
 457         mutex_destroy(&ahstack->ipsecah_param_lock);
 458         nd_free(&ahstack->ipsecah_g_nd);
 459 
 460         kmem_free(ahstack->ipsecah_params, sizeof (lcl_param_arr));
 461         ahstack->ipsecah_params = NULL;
 462         kstat_delete_netstack(ahstack->ah_ksp, stackid);
 463         ahstack->ah_ksp = NULL;
 464         ahstack->ah_kstats = NULL;
 465 
 466         kmem_free(ahstack, sizeof (*ahstack));
 467 }
 468 
 469 /*
 470  * AH module open routine, which is here for keysock plumbing.
 471  * Keysock is pushed over {AH,ESP} which is an artifact from the Bad Old
 472  * Days of export control, and fears that ESP would not be allowed
 473  * to be shipped at all by default.  Eventually, keysock should


 556         mp = sadb_keysock_out(serial);
 557         if (mp == NULL) {
 558                 ah0dbg(("ah_register_out: couldn't allocate mblk.\n"));
 559                 return (B_FALSE);
 560         }
 561 
 562         if (is_system_labeled() && (cr != NULL)) {
 563                 sens_tsl = crgetlabel(cr);
 564                 if (sens_tsl != NULL) {
 565                         sens_len = sadb_sens_len_from_label(sens_tsl);
 566                         allocsize += sens_len;
 567                 }
 568         }
 569 
 570         /*
 571          * Allocate the PF_KEY message that follows KEYSOCK_OUT.
 572          * The alg reader lock needs to be held while allocating
 573          * the variable part (i.e. the algorithms) of the message.
 574          */
 575 
 576         mutex_enter(&ipss->ipsec_alg_lock);
 577 
 578         /*
 579          * Return only valid algorithms, so the number of algorithms
 580          * to send up may be less than the number of algorithm entries
 581          * in the table.
 582          */
 583         authalgs = ipss->ipsec_alglists[IPSEC_ALG_AUTH];
 584         for (num_aalgs = 0, i = 0; i < IPSEC_MAX_ALGS; i++)
 585                 if (authalgs[i] != NULL && ALG_VALID(authalgs[i]))
 586                         num_aalgs++;
 587 
 588         /*
 589          * Fill SADB_REGISTER message's algorithm descriptors.  Hold
 590          * down the lock while filling it.
 591          */
 592         if (num_aalgs != 0) {
 593                 allocsize += (num_aalgs * sizeof (*saalg));
 594                 allocsize += sizeof (*sasupp);
 595         }
 596         mp->b_cont = allocb(allocsize, BPRI_HI);
 597         if (mp->b_cont == NULL) {
 598                 mutex_exit(&ipss->ipsec_alg_lock);
 599                 freemsg(mp);
 600                 return (B_FALSE);
 601         }
 602 
 603         mp->b_cont->b_wptr += allocsize;
 604         nextext = (sadb_ext_t *)(mp->b_cont->b_rptr + sizeof (*samsg));
 605 
 606         if (num_aalgs != 0) {
 607 
 608                 saalg = (sadb_alg_t *)(((uint8_t *)nextext) + sizeof (*sasupp));
 609                 ASSERT(((ulong_t)saalg & 0x7) == 0);
 610 
 611                 numalgs_snap = 0;
 612                 for (i = 0;
 613                     ((i < IPSEC_MAX_ALGS) && (numalgs_snap < num_aalgs));
 614                     i++) {
 615                         if (authalgs[i] == NULL || !ALG_VALID(authalgs[i]))
 616                                 continue;
 617 
 618                         saalg->sadb_alg_id = authalgs[i]->alg_id;


 625                         ASSERT(authalgs[i]->alg_saltlen == 0);
 626                         saalg->sadb_x_alg_saltbits =
 627                             SADB_8TO1(authalgs[i]->alg_saltlen);
 628                         numalgs_snap++;
 629                         saalg++;
 630                 }
 631                 ASSERT(numalgs_snap == num_aalgs);
 632 #ifdef DEBUG
 633                 /*
 634                  * Reality check to make sure I snagged all of the
 635                  * algorithms.
 636                  */
 637                 for (; i < IPSEC_MAX_ALGS; i++)
 638                         if (authalgs[i] != NULL && ALG_VALID(authalgs[i]))
 639                                 cmn_err(CE_PANIC,
 640                                     "ah_register_out()!  Missed #%d.\n", i);
 641 #endif /* DEBUG */
 642                 nextext = (sadb_ext_t *)saalg;
 643         }
 644 
 645         mutex_exit(&ipss->ipsec_alg_lock);
 646 
 647         if (sens_tsl != NULL) {
 648                 sens = (sadb_sens_t *)nextext;
 649                 sadb_sens_from_label(sens, SADB_EXT_SENSITIVITY,
 650                     sens_tsl, sens_len);
 651 
 652                 nextext = (sadb_ext_t *)(((uint8_t *)sens) + sens_len);
 653         }
 654 
 655         /* Now fill the restof the SADB_REGISTER message. */
 656 
 657         samsg = (sadb_msg_t *)mp->b_cont->b_rptr;
 658         samsg->sadb_msg_version = PF_KEY_V2;
 659         samsg->sadb_msg_type = SADB_REGISTER;
 660         samsg->sadb_msg_errno = 0;
 661         samsg->sadb_msg_satype = SADB_SATYPE_AH;
 662         samsg->sadb_msg_len = SADB_8TO64(allocsize);
 663         samsg->sadb_msg_reserved = 0;
 664         /*
 665          * Assume caller has sufficient sequence/pid number info.  If it's one


1106         /* Stuff I don't support, for now.  XXX Diagnostic? */
1107         if (ksi->ks_in_extv[SADB_EXT_LIFETIME_CURRENT] != NULL)
1108                 return (EOPNOTSUPP);
1109 
1110         if (ksi->ks_in_extv[SADB_EXT_SENSITIVITY] != NULL) {
1111                 if (!is_system_labeled())
1112                         return (EOPNOTSUPP);
1113         }
1114 
1115         if (ksi->ks_in_extv[SADB_X_EXT_OUTER_SENS] != NULL) {
1116                 if (!is_system_labeled())
1117                         return (EOPNOTSUPP);
1118         }
1119         /*
1120          * XXX Policy : I'm not checking identities at this time, but
1121          * if I did, I'd do them here, before I sent the weak key
1122          * check up to the algorithm.
1123          */
1124 
1125         /* verify that there is a mapping for the specified algorithm */
1126         mutex_enter(&ipss->ipsec_alg_lock);
1127         aalg = ipss->ipsec_alglists[IPSEC_ALG_AUTH][assoc->sadb_sa_auth];
1128         if (aalg == NULL || !ALG_VALID(aalg)) {
1129                 mutex_exit(&ipss->ipsec_alg_lock);
1130                 ah1dbg(ahstack, ("Couldn't find auth alg #%d.\n",
1131                     assoc->sadb_sa_auth));
1132                 *diagnostic = SADB_X_DIAGNOSTIC_BAD_AALG;
1133                 return (EINVAL);
1134         }
1135         ASSERT(aalg->alg_mech_type != CRYPTO_MECHANISM_INVALID);
1136 
1137         /* sanity check key sizes */
1138         if (!ipsec_valid_key_size(key->sadb_key_bits, aalg)) {
1139                 mutex_exit(&ipss->ipsec_alg_lock);
1140                 *diagnostic = SADB_X_DIAGNOSTIC_BAD_AKEYBITS;
1141                 return (EINVAL);
1142         }
1143 
1144         /* check key and fix parity if needed */
1145         if (ipsec_check_key(aalg->alg_mech_type, key, B_TRUE,
1146             diagnostic) != 0) {
1147                 mutex_exit(&ipss->ipsec_alg_lock);
1148                 return (EINVAL);
1149         }
1150 
1151         mutex_exit(&ipss->ipsec_alg_lock);
1152 
1153         return (ah_add_sa_finish(mp, (sadb_msg_t *)mp->b_cont->b_rptr, ksi,
1154             diagnostic, ahstack));
1155 }
1156 
1157 /* Refactor me */
1158 /*
1159  * Update a security association.  Updates come in two varieties.  The first
1160  * is an update of lifetimes on a non-larval SA.  The second is an update of
1161  * a larval SA, which ends up looking a lot more like an add.
1162  */
1163 static int
1164 ah_update_sa(mblk_t *mp, keysock_in_t *ksi, int *diagnostic,
1165     ipsecah_stack_t *ahstack, uint8_t sadb_msg_type)
1166 {
1167         sadb_sa_t *assoc = (sadb_sa_t *)ksi->ks_in_extv[SADB_EXT_SA];
1168         sadb_address_t *dstext =
1169             (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_DST];
1170         mblk_t  *buf_pkt;
1171         int rcode;


1718         }
1719 
1720         inrc = sadb_age_bytes(ahstack->ah_pfkey_q, inassoc, bytes, B_TRUE);
1721         outrc = sadb_age_bytes(ahstack->ah_pfkey_q, outassoc, bytes, B_FALSE);
1722 
1723         /*
1724          * REFRELE any peer SA.
1725          *
1726          * Because of the multi-line macro nature of IPSA_REFRELE, keep
1727          * them in { }.
1728          */
1729         if (inbound) {
1730                 IPSA_REFRELE(outassoc);
1731         } else {
1732                 IPSA_REFRELE(inassoc);
1733         }
1734 
1735         return (inrc && outrc);
1736 }
1737 
1738 /*
1739  * Perform the really difficult work of inserting the proposed situation.
1740  * Called while holding the algorithm lock.
1741  */
1742 static void
1743 ah_insert_prop(sadb_prop_t *prop, ipsacq_t *acqrec, uint_t combs,
1744     netstack_t *ns)
1745 {
1746         sadb_comb_t *comb = (sadb_comb_t *)(prop + 1);
1747         ipsec_action_t *ap;
1748         ipsec_prot_t *prot;
1749         ipsecah_stack_t *ahstack = ns->netstack_ipsecah;
1750         ipsec_stack_t   *ipss = ns->netstack_ipsec;
1751 
1752         ASSERT(MUTEX_HELD(&ipss->ipsec_alg_lock));
1753 
1754         prop->sadb_prop_exttype = SADB_EXT_PROPOSAL;
1755         prop->sadb_prop_len = SADB_8TO64(sizeof (sadb_prop_t));
1756         *(uint32_t *)(&prop->sadb_prop_replay) = 0;      /* Quick zero-out! */
1757 
1758         prop->sadb_prop_replay = ahstack->ipsecah_replay_size;
1759 
1760         /*
1761          * Based upon algorithm properties, and what-not, prioritize a
1762          * proposal, based on the ordering of the AH algorithms in the
1763          * alternatives in the policy rule or socket that was placed
1764          * in the acquire record.
1765          */
1766 
1767         for (ap = acqrec->ipsacq_act; ap != NULL;
1768             ap = ap->ipa_next) {
1769                 ipsec_alginfo_t *aalg;
1770 
1771                 if ((ap->ipa_act.ipa_type != IPSEC_POLICY_APPLY) ||
1772                     (!ap->ipa_act.ipa_apply.ipp_use_ah))
1773                         continue;
1774 
1775                 prot = &ap->ipa_act.ipa_apply;
1776 
1777                 ASSERT(prot->ipp_auth_alg > 0);
1778 
1779                 aalg = ipss->ipsec_alglists[IPSEC_ALG_AUTH]
1780                     [prot->ipp_auth_alg];
1781                 if (aalg == NULL || !ALG_VALID(aalg))
1782                         continue;
1783 
1784                 /* XXX check aalg for duplicates??.. */
1785 
1786                 comb->sadb_comb_flags = 0;
1787                 comb->sadb_comb_reserved = 0;
1788                 comb->sadb_comb_encrypt = 0;
1789                 comb->sadb_comb_encrypt_minbits = 0;
1790                 comb->sadb_comb_encrypt_maxbits = 0;
1791 
1792                 comb->sadb_comb_auth = aalg->alg_id;
1793                 comb->sadb_comb_auth_minbits =
1794                     MAX(prot->ipp_ah_minbits, aalg->alg_ef_minbits);
1795                 comb->sadb_comb_auth_maxbits =
1796                     MIN(prot->ipp_ah_maxbits, aalg->alg_ef_maxbits);
1797 
1798                 /*
1799                  * The following may be based on algorithm
1800                  * properties, but in the meantime, we just pick
1801                  * some good, sensible numbers.  Key mgmt. can
1802                  * (and perhaps should) be the place to finalize
1803                  * such decisions.
1804                  */
1805 
1806                 /*
1807                  * No limits on allocations, since we really don't
1808                  * support that concept currently.
1809                  */
1810                 comb->sadb_comb_soft_allocations = 0;
1811                 comb->sadb_comb_hard_allocations = 0;
1812 
1813                 /*
1814                  * These may want to come from policy rule..
1815                  */
1816                 comb->sadb_comb_soft_bytes =
1817                     ahstack->ipsecah_default_soft_bytes;
1818                 comb->sadb_comb_hard_bytes =
1819                     ahstack->ipsecah_default_hard_bytes;
1820                 comb->sadb_comb_soft_addtime =
1821                     ahstack->ipsecah_default_soft_addtime;
1822                 comb->sadb_comb_hard_addtime =
1823                     ahstack->ipsecah_default_hard_addtime;
1824                 comb->sadb_comb_soft_usetime =
1825                     ahstack->ipsecah_default_soft_usetime;
1826                 comb->sadb_comb_hard_usetime =
1827                     ahstack->ipsecah_default_hard_usetime;
1828 
1829                 prop->sadb_prop_len += SADB_8TO64(sizeof (*comb));
1830                 if (--combs == 0)
1831                         return; /* out of space.. */
1832                 comb++;
1833         }
1834 }
1835 
1836 /*
1837  * Prepare and actually send the SADB_ACQUIRE message to PF_KEY.
1838  */
1839 static void
1840 ah_send_acquire(ipsacq_t *acqrec, mblk_t *extended, netstack_t *ns)
1841 {
1842         uint_t combs;
1843         sadb_msg_t *samsg;
1844         sadb_prop_t *prop;
1845         mblk_t *pfkeymp, *msgmp;
1846         ipsecah_stack_t *ahstack = ns->netstack_ipsecah;
1847         ipsec_stack_t   *ipss = ns->netstack_ipsec;
1848 
1849         AH_BUMP_STAT(ahstack, acquire_requests);
1850 
1851         if (ahstack->ah_pfkey_q == NULL) {
1852                 mutex_exit(&acqrec->ipsacq_lock);
1853                 return;
1854         }
1855 
1856         /* Set up ACQUIRE. */
1857         pfkeymp = sadb_setup_acquire(acqrec, SADB_SATYPE_AH,
1858             ns->netstack_ipsec);
1859         if (pfkeymp == NULL) {
1860                 ah0dbg(("sadb_setup_acquire failed.\n"));
1861                 mutex_exit(&acqrec->ipsacq_lock);
1862                 return;
1863         }
1864         ASSERT(MUTEX_HELD(&ipss->ipsec_alg_lock));
1865         combs = ipss->ipsec_nalgs[IPSEC_ALG_AUTH];
1866         msgmp = pfkeymp->b_cont;
1867         samsg = (sadb_msg_t *)(msgmp->b_rptr);
1868 
1869         /* Insert proposal here. */
1870 
1871         prop = (sadb_prop_t *)(((uint64_t *)samsg) + samsg->sadb_msg_len);
1872         ah_insert_prop(prop, acqrec, combs, ns);
1873         samsg->sadb_msg_len += prop->sadb_prop_len;
1874         msgmp->b_wptr += SADB_64TO8(samsg->sadb_msg_len);
1875 
1876         mutex_exit(&ipss->ipsec_alg_lock);
1877 
1878         /*
1879          * Must mutex_exit() before sending PF_KEY message up, in
1880          * order to avoid recursive mutex_enter() if there are no registered
1881          * listeners.
1882          *
1883          * Once I've sent the message, I'm cool anyway.
1884          */
1885         mutex_exit(&acqrec->ipsacq_lock);
1886         if (extended != NULL) {
1887                 putnext(ahstack->ah_pfkey_q, extended);
1888         }
1889         putnext(ahstack->ah_pfkey_q, pfkeymp);
1890 }
1891 
1892 /* Refactor me */
1893 /*
1894  * Handle the SADB_GETSPI message.  Create a larval SA.
1895  */
1896 static void
1897 ah_getspi(mblk_t *mp, keysock_in_t *ksi, ipsecah_stack_t *ahstack)
1898 {
1899         ipsa_t *newbie, *target;
1900         isaf_t *outbound, *inbound;
1901         int rc, diagnostic;
1902         sadb_sa_t *assoc;
1903         keysock_out_t *kso;
1904         uint32_t newspi;
1905 
1906         /*
1907          * Randomly generate a proposed SPI value.
1908          */
1909         if (cl_inet_getspi != NULL) {
1910                 cl_inet_getspi(ahstack->ipsecah_netstack->netstack_stackid,
1911                     IPPROTO_AH, (uint8_t *)&newspi, sizeof (uint32_t), NULL);




   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  * Copyright (c) 2012 Nexenta Systems, Inc. All rights reserved.
  25  */
  26 
  27 #include <sys/types.h>
  28 #include <sys/stream.h>
  29 #include <sys/stropts.h>
  30 #include <sys/errno.h>
  31 #include <sys/strlog.h>
  32 #include <sys/tihdr.h>
  33 #include <sys/socket.h>
  34 #include <sys/ddi.h>
  35 #include <sys/sunddi.h>
  36 #include <sys/mkdev.h>
  37 #include <sys/kmem.h>
  38 #include <sys/zone.h>
  39 #include <sys/sysmacros.h>
  40 #include <sys/cmn_err.h>
  41 #include <sys/vtrace.h>
  42 #include <sys/debug.h>
  43 #include <sys/atomic.h>
  44 #include <sys/strsun.h>


  79  * ipsecah_g_nd in ipsecah_init_nd.
  80  * All of these are alterable, within the min/max values given, at run time.
  81  */
  82 static  ipsecahparam_t  lcl_param_arr[] = {
  83         /* min  max                     value   name */
  84         { 0,    3,                      0,      "ipsecah_debug"},
  85         { 125,  32000, SADB_AGE_INTERVAL_DEFAULT,       "ipsecah_age_interval"},
  86         { 1,    10,                     1,      "ipsecah_reap_delay"},
  87         { 1,    SADB_MAX_REPLAY,        64,     "ipsecah_replay_size"},
  88         { 1,    300,                    15,     "ipsecah_acquire_timeout"},
  89         { 1,    1800,                   90,     "ipsecah_larval_timeout"},
  90         /* Default lifetime values for ACQUIRE messages. */
  91         { 0,    0xffffffffU,            0,      "ipsecah_default_soft_bytes"},
  92         { 0,    0xffffffffU,            0,      "ipsecah_default_hard_bytes"},
  93         { 0,    0xffffffffU,            24000,  "ipsecah_default_soft_addtime"},
  94         { 0,    0xffffffffU,            28800,  "ipsecah_default_hard_addtime"},
  95         { 0,    0xffffffffU,            0,      "ipsecah_default_soft_usetime"},
  96         { 0,    0xffffffffU,            0,      "ipsecah_default_hard_usetime"},
  97         { 0,    1,                      0,      "ipsecah_log_unknown_spi"},
  98 };














  99 
 100 #define ah0dbg(a)       printf a
 101 /* NOTE:  != 0 instead of > 0 so lint doesn't complain. */
 102 #define ah1dbg(ahstack, a)      if (ahstack->ipsecah_debug != 0) printf a
 103 #define ah2dbg(ahstack, a)      if (ahstack->ipsecah_debug > 1) printf a
 104 #define ah3dbg(ahstack, a)      if (ahstack->ipsecah_debug > 2) printf a
 105 
 106 /*
 107  * XXX This is broken. Padding should be determined dynamically
 108  * depending on the ICV size and IP version number so that the
 109  * total AH header size is a multiple of 32 bits or 64 bits
 110  * for V4 and V6 respectively. For 96bit ICVs we have no problems.
 111  * Anything different from that, we need to fix our code.
 112  */
 113 #define IPV4_PADDING_ALIGN      0x04    /* Multiple of 32 bits */
 114 #define IPV6_PADDING_ALIGN      0x04    /* Multiple of 32 bits */
 115 
 116 /*
 117  * Helper macro. Avoids a call to msgdsize if there is only one
 118  * mblk in the chain.
 119  */
 120 #define AH_MSGSIZE(mp) ((mp)->b_cont != NULL ? msgdsize(mp) : MBLKL(mp))
 121 
 122 
 123 static mblk_t *ah_auth_out_done(mblk_t *, ip_xmit_attr_t *, ipsec_crypto_t *);
 124 static mblk_t *ah_auth_in_done(mblk_t *, ip_recv_attr_t *, ipsec_crypto_t *);
 125 static mblk_t *ah_process_ip_options_v4(mblk_t *, ipsa_t *, int *, uint_t,
 126     boolean_t, ipsecah_stack_t *);
 127 static mblk_t *ah_process_ip_options_v6(mblk_t *, ipsa_t *, int *, uint_t,
 128     boolean_t, ipsecah_stack_t *);
 129 static void ah_getspi(mblk_t *, keysock_in_t *, ipsecah_stack_t *);
 130 static void ah_inbound_restart(mblk_t *, ip_recv_attr_t *);
 131 
 132 static mblk_t *ah_outbound(mblk_t *, ip_xmit_attr_t *);
 133 static void ah_outbound_finish(mblk_t *, ip_xmit_attr_t *);
 134 
 135 static int ipsecah_open(queue_t *, dev_t *, int, int, cred_t *);
 136 static int ipsecah_close(queue_t *);
 137 static void ipsecah_wput(queue_t *, mblk_t *);

 138 static boolean_t ah_register_out(uint32_t, uint32_t, uint_t, ipsecah_stack_t *,
 139     cred_t *);
 140 static void     *ipsecah_stack_init(netstackid_t stackid, netstack_t *ns);
 141 static void     ipsecah_stack_fini(netstackid_t stackid, void *arg);
 142 
 143 /* Setable in /etc/system */
 144 uint32_t ah_hash_size = IPSEC_DEFAULT_HASH_SIZE;
 145 
 146 static taskq_t *ah_taskq;
 147 
 148 static struct module_info info = {
 149         5136, "ipsecah", 0, INFPSZ, 65536, 1024
 150 };
 151 
 152 static struct qinit rinit = {
 153         (pfi_t)putnext, NULL, ipsecah_open, ipsecah_close, NULL, &info,
 154         NULL
 155 };
 156 
 157 static struct qinit winit = {


 216         netstackid_t    stackid = (netstackid_t)(uintptr_t)kp->ks_private;
 217         netstack_t      *ns;
 218         ipsec_stack_t   *ipss;
 219 
 220         if ((kp == NULL) || (kp->ks_data == NULL))
 221                 return (EIO);
 222 
 223         if (rw == KSTAT_WRITE)
 224                 return (EACCES);
 225 
 226         ns = netstack_find_by_stackid(stackid);
 227         if (ns == NULL)
 228                 return (-1);
 229         ipss = ns->netstack_ipsec;
 230         if (ipss == NULL) {
 231                 netstack_rele(ns);
 232                 return (-1);
 233         }
 234         ekp = (ah_kstats_t *)kp->ks_data;
 235 
 236         rw_enter(&ipss->ipsec_alg_lock, RW_READER);
 237         ekp->ah_stat_num_aalgs.value.ui64 = ipss->ipsec_nalgs[IPSEC_ALG_AUTH];
 238         rw_exit(&ipss->ipsec_alg_lock);
 239 
 240         netstack_rele(ns);
 241         return (0);
 242 }
 243 
 244 /*
 245  * Don't have to lock ipsec_age_interval, as only one thread will access it at
 246  * a time, because I control the one function that does a qtimeout() on
 247  * ah_pfkey_q.
 248  */
 249 static void
 250 ah_ager(void *arg)
 251 {
 252         ipsecah_stack_t *ahstack = (ipsecah_stack_t *)arg;
 253         netstack_t      *ns = ahstack->ipsecah_netstack;
 254         hrtime_t begin = gethrtime();
 255 
 256         sadb_ager(&ahstack->ah_sadb.s_v4, ahstack->ah_pfkey_q,
 257             ahstack->ipsecah_reap_delay, ns);
 258         sadb_ager(&ahstack->ah_sadb.s_v6, ahstack->ah_pfkey_q,


 388  */
 389 static void *
 390 ipsecah_stack_init(netstackid_t stackid, netstack_t *ns)
 391 {
 392         ipsecah_stack_t *ahstack;
 393         ipsecahparam_t  *ahp;
 394 
 395         ahstack = (ipsecah_stack_t *)kmem_zalloc(sizeof (*ahstack), KM_SLEEP);
 396         ahstack->ipsecah_netstack = ns;
 397 
 398         ahp = (ipsecahparam_t *)kmem_alloc(sizeof (lcl_param_arr), KM_SLEEP);
 399         ahstack->ipsecah_params = ahp;
 400         bcopy(lcl_param_arr, ahp, sizeof (lcl_param_arr));
 401 
 402         (void) ipsecah_param_register(&ahstack->ipsecah_g_nd, ahp,
 403             A_CNT(lcl_param_arr));
 404 
 405         (void) ah_kstat_init(ahstack, stackid);
 406 
 407         ahstack->ah_sadb.s_acquire_timeout = &ahstack->ipsecah_acquire_timeout;

 408         sadbp_init("AH", &ahstack->ah_sadb, SADB_SATYPE_AH, ah_hash_size,
 409             ahstack->ipsecah_netstack);
 410 
 411         mutex_init(&ahstack->ipsecah_param_lock, NULL, MUTEX_DEFAULT, 0);
 412 
 413         ip_drop_register(&ahstack->ah_dropper, "IPsec AH");
 414         return (ahstack);
 415 }
 416 
 417 /*
 418  * Destroy things for AH at module unload time.
 419  */
 420 void
 421 ipsecah_ddi_destroy(void)
 422 {
 423         netstack_unregister(NS_IPSECAH);
 424         taskq_destroy(ah_taskq);
 425 }
 426 
 427 /*
 428  * Destroy things for AH for one stack... Never called?
 429  */
 430 static void
 431 ipsecah_stack_fini(netstackid_t stackid, void *arg)
 432 {
 433         ipsecah_stack_t *ahstack = (ipsecah_stack_t *)arg;
 434 
 435         if (ahstack->ah_pfkey_q != NULL) {
 436                 (void) quntimeout(ahstack->ah_pfkey_q, ahstack->ah_event);
 437         }

 438         ahstack->ah_sadb.s_acquire_timeout = NULL;
 439         sadbp_destroy(&ahstack->ah_sadb, ahstack->ipsecah_netstack);
 440         ip_drop_unregister(&ahstack->ah_dropper);
 441         mutex_destroy(&ahstack->ipsecah_param_lock);
 442         nd_free(&ahstack->ipsecah_g_nd);
 443 
 444         kmem_free(ahstack->ipsecah_params, sizeof (lcl_param_arr));
 445         ahstack->ipsecah_params = NULL;
 446         kstat_delete_netstack(ahstack->ah_ksp, stackid);
 447         ahstack->ah_ksp = NULL;
 448         ahstack->ah_kstats = NULL;
 449 
 450         kmem_free(ahstack, sizeof (*ahstack));
 451 }
 452 
 453 /*
 454  * AH module open routine, which is here for keysock plumbing.
 455  * Keysock is pushed over {AH,ESP} which is an artifact from the Bad Old
 456  * Days of export control, and fears that ESP would not be allowed
 457  * to be shipped at all by default.  Eventually, keysock should


 540         mp = sadb_keysock_out(serial);
 541         if (mp == NULL) {
 542                 ah0dbg(("ah_register_out: couldn't allocate mblk.\n"));
 543                 return (B_FALSE);
 544         }
 545 
 546         if (is_system_labeled() && (cr != NULL)) {
 547                 sens_tsl = crgetlabel(cr);
 548                 if (sens_tsl != NULL) {
 549                         sens_len = sadb_sens_len_from_label(sens_tsl);
 550                         allocsize += sens_len;
 551                 }
 552         }
 553 
 554         /*
 555          * Allocate the PF_KEY message that follows KEYSOCK_OUT.
 556          * The alg reader lock needs to be held while allocating
 557          * the variable part (i.e. the algorithms) of the message.
 558          */
 559 
 560         rw_enter(&ipss->ipsec_alg_lock, RW_READER);
 561 
 562         /*
 563          * Return only valid algorithms, so the number of algorithms
 564          * to send up may be less than the number of algorithm entries
 565          * in the table.
 566          */
 567         authalgs = ipss->ipsec_alglists[IPSEC_ALG_AUTH];
 568         for (num_aalgs = 0, i = 0; i < IPSEC_MAX_ALGS; i++)
 569                 if (authalgs[i] != NULL && ALG_VALID(authalgs[i]))
 570                         num_aalgs++;
 571 
 572         /*
 573          * Fill SADB_REGISTER message's algorithm descriptors.  Hold
 574          * down the lock while filling it.
 575          */
 576         if (num_aalgs != 0) {
 577                 allocsize += (num_aalgs * sizeof (*saalg));
 578                 allocsize += sizeof (*sasupp);
 579         }
 580         mp->b_cont = allocb(allocsize, BPRI_HI);
 581         if (mp->b_cont == NULL) {
 582                 rw_exit(&ipss->ipsec_alg_lock);
 583                 freemsg(mp);
 584                 return (B_FALSE);
 585         }
 586 
 587         mp->b_cont->b_wptr += allocsize;
 588         nextext = (sadb_ext_t *)(mp->b_cont->b_rptr + sizeof (*samsg));
 589 
 590         if (num_aalgs != 0) {
 591 
 592                 saalg = (sadb_alg_t *)(((uint8_t *)nextext) + sizeof (*sasupp));
 593                 ASSERT(((ulong_t)saalg & 0x7) == 0);
 594 
 595                 numalgs_snap = 0;
 596                 for (i = 0;
 597                     ((i < IPSEC_MAX_ALGS) && (numalgs_snap < num_aalgs));
 598                     i++) {
 599                         if (authalgs[i] == NULL || !ALG_VALID(authalgs[i]))
 600                                 continue;
 601 
 602                         saalg->sadb_alg_id = authalgs[i]->alg_id;


 609                         ASSERT(authalgs[i]->alg_saltlen == 0);
 610                         saalg->sadb_x_alg_saltbits =
 611                             SADB_8TO1(authalgs[i]->alg_saltlen);
 612                         numalgs_snap++;
 613                         saalg++;
 614                 }
 615                 ASSERT(numalgs_snap == num_aalgs);
 616 #ifdef DEBUG
 617                 /*
 618                  * Reality check to make sure I snagged all of the
 619                  * algorithms.
 620                  */
 621                 for (; i < IPSEC_MAX_ALGS; i++)
 622                         if (authalgs[i] != NULL && ALG_VALID(authalgs[i]))
 623                                 cmn_err(CE_PANIC,
 624                                     "ah_register_out()!  Missed #%d.\n", i);
 625 #endif /* DEBUG */
 626                 nextext = (sadb_ext_t *)saalg;
 627         }
 628 
 629         rw_exit(&ipss->ipsec_alg_lock);
 630 
 631         if (sens_tsl != NULL) {
 632                 sens = (sadb_sens_t *)nextext;
 633                 sadb_sens_from_label(sens, SADB_EXT_SENSITIVITY,
 634                     sens_tsl, sens_len);
 635 
 636                 nextext = (sadb_ext_t *)(((uint8_t *)sens) + sens_len);
 637         }
 638 
 639         /* Now fill the restof the SADB_REGISTER message. */
 640 
 641         samsg = (sadb_msg_t *)mp->b_cont->b_rptr;
 642         samsg->sadb_msg_version = PF_KEY_V2;
 643         samsg->sadb_msg_type = SADB_REGISTER;
 644         samsg->sadb_msg_errno = 0;
 645         samsg->sadb_msg_satype = SADB_SATYPE_AH;
 646         samsg->sadb_msg_len = SADB_8TO64(allocsize);
 647         samsg->sadb_msg_reserved = 0;
 648         /*
 649          * Assume caller has sufficient sequence/pid number info.  If it's one


1090         /* Stuff I don't support, for now.  XXX Diagnostic? */
1091         if (ksi->ks_in_extv[SADB_EXT_LIFETIME_CURRENT] != NULL)
1092                 return (EOPNOTSUPP);
1093 
1094         if (ksi->ks_in_extv[SADB_EXT_SENSITIVITY] != NULL) {
1095                 if (!is_system_labeled())
1096                         return (EOPNOTSUPP);
1097         }
1098 
1099         if (ksi->ks_in_extv[SADB_X_EXT_OUTER_SENS] != NULL) {
1100                 if (!is_system_labeled())
1101                         return (EOPNOTSUPP);
1102         }
1103         /*
1104          * XXX Policy : I'm not checking identities at this time, but
1105          * if I did, I'd do them here, before I sent the weak key
1106          * check up to the algorithm.
1107          */
1108 
1109         /* verify that there is a mapping for the specified algorithm */
1110         rw_enter(&ipss->ipsec_alg_lock, RW_READER);
1111         aalg = ipss->ipsec_alglists[IPSEC_ALG_AUTH][assoc->sadb_sa_auth];
1112         if (aalg == NULL || !ALG_VALID(aalg)) {
1113                 rw_exit(&ipss->ipsec_alg_lock);
1114                 ah1dbg(ahstack, ("Couldn't find auth alg #%d.\n",
1115                     assoc->sadb_sa_auth));
1116                 *diagnostic = SADB_X_DIAGNOSTIC_BAD_AALG;
1117                 return (EINVAL);
1118         }
1119         ASSERT(aalg->alg_mech_type != CRYPTO_MECHANISM_INVALID);
1120 
1121         /* sanity check key sizes */
1122         if (!ipsec_valid_key_size(key->sadb_key_bits, aalg)) {
1123                 rw_exit(&ipss->ipsec_alg_lock);
1124                 *diagnostic = SADB_X_DIAGNOSTIC_BAD_AKEYBITS;
1125                 return (EINVAL);
1126         }
1127 
1128         /* check key and fix parity if needed */
1129         if (ipsec_check_key(aalg->alg_mech_type, key, B_TRUE,
1130             diagnostic) != 0) {
1131                 rw_exit(&ipss->ipsec_alg_lock);
1132                 return (EINVAL);
1133         }
1134 
1135         rw_exit(&ipss->ipsec_alg_lock);
1136 
1137         return (ah_add_sa_finish(mp, (sadb_msg_t *)mp->b_cont->b_rptr, ksi,
1138             diagnostic, ahstack));
1139 }
1140 
1141 /* Refactor me */
1142 /*
1143  * Update a security association.  Updates come in two varieties.  The first
1144  * is an update of lifetimes on a non-larval SA.  The second is an update of
1145  * a larval SA, which ends up looking a lot more like an add.
1146  */
1147 static int
1148 ah_update_sa(mblk_t *mp, keysock_in_t *ksi, int *diagnostic,
1149     ipsecah_stack_t *ahstack, uint8_t sadb_msg_type)
1150 {
1151         sadb_sa_t *assoc = (sadb_sa_t *)ksi->ks_in_extv[SADB_EXT_SA];
1152         sadb_address_t *dstext =
1153             (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_DST];
1154         mblk_t  *buf_pkt;
1155         int rcode;


1702         }
1703 
1704         inrc = sadb_age_bytes(ahstack->ah_pfkey_q, inassoc, bytes, B_TRUE);
1705         outrc = sadb_age_bytes(ahstack->ah_pfkey_q, outassoc, bytes, B_FALSE);
1706 
1707         /*
1708          * REFRELE any peer SA.
1709          *
1710          * Because of the multi-line macro nature of IPSA_REFRELE, keep
1711          * them in { }.
1712          */
1713         if (inbound) {
1714                 IPSA_REFRELE(outassoc);
1715         } else {
1716                 IPSA_REFRELE(inassoc);
1717         }
1718 
1719         return (inrc && outrc);
1720 }
1721 


























































































































































1722 /* Refactor me */
1723 /*
1724  * Handle the SADB_GETSPI message.  Create a larval SA.
1725  */
1726 static void
1727 ah_getspi(mblk_t *mp, keysock_in_t *ksi, ipsecah_stack_t *ahstack)
1728 {
1729         ipsa_t *newbie, *target;
1730         isaf_t *outbound, *inbound;
1731         int rc, diagnostic;
1732         sadb_sa_t *assoc;
1733         keysock_out_t *kso;
1734         uint32_t newspi;
1735 
1736         /*
1737          * Randomly generate a proposed SPI value.
1738          */
1739         if (cl_inet_getspi != NULL) {
1740                 cl_inet_getspi(ahstack->ipsecah_netstack->netstack_stackid,
1741                     IPPROTO_AH, (uint8_t *)&newspi, sizeof (uint32_t), NULL);