Print this page
8381 Convert ipsec_alg_lock from mutex to rwlock


   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>


 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,


 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;


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


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




   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>


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


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


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


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


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


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