Print this page
8529 Extended and regular SADB_ACQUIREs should share address extension code
Portions contributed by: Bayard Bell <buffer.g.overflow@gmail.com>


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


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


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




  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 = {


 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


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);