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

@@ -19,10 +19,11 @@
  * CDDL HEADER END
  */
 /*
  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ * Copyright (c) 2012 Nexenta Systems, Inc. All rights reserved.
  */
 
 #include <sys/types.h>
 #include <sys/stream.h>
 #include <sys/stropts.h>

@@ -93,24 +94,10 @@
         { 0,    0xffffffffU,            28800,  "ipsecah_default_hard_addtime"},
         { 0,    0xffffffffU,            0,      "ipsecah_default_soft_usetime"},
         { 0,    0xffffffffU,            0,      "ipsecah_default_hard_usetime"},
         { 0,    1,                      0,      "ipsecah_log_unknown_spi"},
 };
-#define ipsecah_debug                   ipsecah_params[0].ipsecah_param_value
-#define ipsecah_age_interval            ipsecah_params[1].ipsecah_param_value
-#define ipsecah_age_int_max             ipsecah_params[1].ipsecah_param_max
-#define ipsecah_reap_delay              ipsecah_params[2].ipsecah_param_value
-#define ipsecah_replay_size             ipsecah_params[3].ipsecah_param_value
-#define ipsecah_acquire_timeout         ipsecah_params[4].ipsecah_param_value
-#define ipsecah_larval_timeout          ipsecah_params[5].ipsecah_param_value
-#define ipsecah_default_soft_bytes      ipsecah_params[6].ipsecah_param_value
-#define ipsecah_default_hard_bytes      ipsecah_params[7].ipsecah_param_value
-#define ipsecah_default_soft_addtime    ipsecah_params[8].ipsecah_param_value
-#define ipsecah_default_hard_addtime    ipsecah_params[9].ipsecah_param_value
-#define ipsecah_default_soft_usetime    ipsecah_params[10].ipsecah_param_value
-#define ipsecah_default_hard_usetime    ipsecah_params[11].ipsecah_param_value
-#define ipsecah_log_unknown_spi         ipsecah_params[12].ipsecah_param_value
 
 #define ah0dbg(a)       printf a
 /* NOTE:  != 0 instead of > 0 so lint doesn't complain. */
 #define ah1dbg(ahstack, a)      if (ahstack->ipsecah_debug != 0) printf a
 #define ah2dbg(ahstack, a)      if (ahstack->ipsecah_debug > 1) printf a

@@ -146,11 +133,10 @@
 static void ah_outbound_finish(mblk_t *, ip_xmit_attr_t *);
 
 static int ipsecah_open(queue_t *, dev_t *, int, int, cred_t *);
 static int ipsecah_close(queue_t *);
 static void ipsecah_wput(queue_t *, mblk_t *);
-static void ah_send_acquire(ipsacq_t *, mblk_t *, netstack_t *);
 static boolean_t ah_register_out(uint32_t, uint32_t, uint_t, ipsecah_stack_t *,
     cred_t *);
 static void     *ipsecah_stack_init(netstackid_t stackid, netstack_t *ns);
 static void     ipsecah_stack_fini(netstackid_t stackid, void *arg);
 

@@ -245,13 +231,13 @@
                 netstack_rele(ns);
                 return (-1);
         }
         ekp = (ah_kstats_t *)kp->ks_data;
 
-        mutex_enter(&ipss->ipsec_alg_lock);
+        rw_enter(&ipss->ipsec_alg_lock, RW_READER);
         ekp->ah_stat_num_aalgs.value.ui64 = ipss->ipsec_nalgs[IPSEC_ALG_AUTH];
-        mutex_exit(&ipss->ipsec_alg_lock);
+        rw_exit(&ipss->ipsec_alg_lock);
 
         netstack_rele(ns);
         return (0);
 }
 

@@ -417,11 +403,10 @@
             A_CNT(lcl_param_arr));
 
         (void) ah_kstat_init(ahstack, stackid);
 
         ahstack->ah_sadb.s_acquire_timeout = &ahstack->ipsecah_acquire_timeout;
-        ahstack->ah_sadb.s_acqfn = ah_send_acquire;
         sadbp_init("AH", &ahstack->ah_sadb, SADB_SATYPE_AH, ah_hash_size,
             ahstack->ipsecah_netstack);
 
         mutex_init(&ahstack->ipsecah_param_lock, NULL, MUTEX_DEFAULT, 0);
 

@@ -448,11 +433,10 @@
         ipsecah_stack_t *ahstack = (ipsecah_stack_t *)arg;
 
         if (ahstack->ah_pfkey_q != NULL) {
                 (void) quntimeout(ahstack->ah_pfkey_q, ahstack->ah_event);
         }
-        ahstack->ah_sadb.s_acqfn = NULL;
         ahstack->ah_sadb.s_acquire_timeout = NULL;
         sadbp_destroy(&ahstack->ah_sadb, ahstack->ipsecah_netstack);
         ip_drop_unregister(&ahstack->ah_dropper);
         mutex_destroy(&ahstack->ipsecah_param_lock);
         nd_free(&ahstack->ipsecah_g_nd);

@@ -571,11 +555,11 @@
          * Allocate the PF_KEY message that follows KEYSOCK_OUT.
          * The alg reader lock needs to be held while allocating
          * the variable part (i.e. the algorithms) of the message.
          */
 
-        mutex_enter(&ipss->ipsec_alg_lock);
+        rw_enter(&ipss->ipsec_alg_lock, RW_READER);
 
         /*
          * Return only valid algorithms, so the number of algorithms
          * to send up may be less than the number of algorithm entries
          * in the table.

@@ -593,11 +577,11 @@
                 allocsize += (num_aalgs * sizeof (*saalg));
                 allocsize += sizeof (*sasupp);
         }
         mp->b_cont = allocb(allocsize, BPRI_HI);
         if (mp->b_cont == NULL) {
-                mutex_exit(&ipss->ipsec_alg_lock);
+                rw_exit(&ipss->ipsec_alg_lock);
                 freemsg(mp);
                 return (B_FALSE);
         }
 
         mp->b_cont->b_wptr += allocsize;

@@ -640,11 +624,11 @@
                                     "ah_register_out()!  Missed #%d.\n", i);
 #endif /* DEBUG */
                 nextext = (sadb_ext_t *)saalg;
         }
 
-        mutex_exit(&ipss->ipsec_alg_lock);
+        rw_exit(&ipss->ipsec_alg_lock);
 
         if (sens_tsl != NULL) {
                 sens = (sadb_sens_t *)nextext;
                 sadb_sens_from_label(sens, SADB_EXT_SENSITIVITY,
                     sens_tsl, sens_len);

@@ -1121,36 +1105,36 @@
          * if I did, I'd do them here, before I sent the weak key
          * check up to the algorithm.
          */
 
         /* verify that there is a mapping for the specified algorithm */
-        mutex_enter(&ipss->ipsec_alg_lock);
+        rw_enter(&ipss->ipsec_alg_lock, RW_READER);
         aalg = ipss->ipsec_alglists[IPSEC_ALG_AUTH][assoc->sadb_sa_auth];
         if (aalg == NULL || !ALG_VALID(aalg)) {
-                mutex_exit(&ipss->ipsec_alg_lock);
+                rw_exit(&ipss->ipsec_alg_lock);
                 ah1dbg(ahstack, ("Couldn't find auth alg #%d.\n",
                     assoc->sadb_sa_auth));
                 *diagnostic = SADB_X_DIAGNOSTIC_BAD_AALG;
                 return (EINVAL);
         }
         ASSERT(aalg->alg_mech_type != CRYPTO_MECHANISM_INVALID);
 
         /* sanity check key sizes */
         if (!ipsec_valid_key_size(key->sadb_key_bits, aalg)) {
-                mutex_exit(&ipss->ipsec_alg_lock);
+                rw_exit(&ipss->ipsec_alg_lock);
                 *diagnostic = SADB_X_DIAGNOSTIC_BAD_AKEYBITS;
                 return (EINVAL);
         }
 
         /* check key and fix parity if needed */
         if (ipsec_check_key(aalg->alg_mech_type, key, B_TRUE,
             diagnostic) != 0) {
-                mutex_exit(&ipss->ipsec_alg_lock);
+                rw_exit(&ipss->ipsec_alg_lock);
                 return (EINVAL);
         }
 
-        mutex_exit(&ipss->ipsec_alg_lock);
+        rw_exit(&ipss->ipsec_alg_lock);
 
         return (ah_add_sa_finish(mp, (sadb_msg_t *)mp->b_cont->b_rptr, ksi,
             diagnostic, ahstack));
 }
 

@@ -1733,164 +1717,10 @@
         }
 
         return (inrc && outrc);
 }
 
-/*
- * Perform the really difficult work of inserting the proposed situation.
- * Called while holding the algorithm lock.
- */
-static void
-ah_insert_prop(sadb_prop_t *prop, ipsacq_t *acqrec, uint_t combs,
-    netstack_t *ns)
-{
-        sadb_comb_t *comb = (sadb_comb_t *)(prop + 1);
-        ipsec_action_t *ap;
-        ipsec_prot_t *prot;
-        ipsecah_stack_t *ahstack = ns->netstack_ipsecah;
-        ipsec_stack_t   *ipss = ns->netstack_ipsec;
-
-        ASSERT(MUTEX_HELD(&ipss->ipsec_alg_lock));
-
-        prop->sadb_prop_exttype = SADB_EXT_PROPOSAL;
-        prop->sadb_prop_len = SADB_8TO64(sizeof (sadb_prop_t));
-        *(uint32_t *)(&prop->sadb_prop_replay) = 0;     /* Quick zero-out! */
-
-        prop->sadb_prop_replay = ahstack->ipsecah_replay_size;
-
-        /*
-         * Based upon algorithm properties, and what-not, prioritize a
-         * proposal, based on the ordering of the AH algorithms in the
-         * alternatives in the policy rule or socket that was placed
-         * in the acquire record.
-         */
-
-        for (ap = acqrec->ipsacq_act; ap != NULL;
-            ap = ap->ipa_next) {
-                ipsec_alginfo_t *aalg;
-
-                if ((ap->ipa_act.ipa_type != IPSEC_POLICY_APPLY) ||
-                    (!ap->ipa_act.ipa_apply.ipp_use_ah))
-                        continue;
-
-                prot = &ap->ipa_act.ipa_apply;
-
-                ASSERT(prot->ipp_auth_alg > 0);
-
-                aalg = ipss->ipsec_alglists[IPSEC_ALG_AUTH]
-                    [prot->ipp_auth_alg];
-                if (aalg == NULL || !ALG_VALID(aalg))
-                        continue;
-
-                /* XXX check aalg for duplicates??.. */
-
-                comb->sadb_comb_flags = 0;
-                comb->sadb_comb_reserved = 0;
-                comb->sadb_comb_encrypt = 0;
-                comb->sadb_comb_encrypt_minbits = 0;
-                comb->sadb_comb_encrypt_maxbits = 0;
-
-                comb->sadb_comb_auth = aalg->alg_id;
-                comb->sadb_comb_auth_minbits =
-                    MAX(prot->ipp_ah_minbits, aalg->alg_ef_minbits);
-                comb->sadb_comb_auth_maxbits =
-                    MIN(prot->ipp_ah_maxbits, aalg->alg_ef_maxbits);
-
-                /*
-                 * The following may be based on algorithm
-                 * properties, but in the meantime, we just pick
-                 * some good, sensible numbers.  Key mgmt. can
-                 * (and perhaps should) be the place to finalize
-                 * such decisions.
-                 */
-
-                /*
-                 * No limits on allocations, since we really don't
-                 * support that concept currently.
-                 */
-                comb->sadb_comb_soft_allocations = 0;
-                comb->sadb_comb_hard_allocations = 0;
-
-                /*
-                 * These may want to come from policy rule..
-                 */
-                comb->sadb_comb_soft_bytes =
-                    ahstack->ipsecah_default_soft_bytes;
-                comb->sadb_comb_hard_bytes =
-                    ahstack->ipsecah_default_hard_bytes;
-                comb->sadb_comb_soft_addtime =
-                    ahstack->ipsecah_default_soft_addtime;
-                comb->sadb_comb_hard_addtime =
-                    ahstack->ipsecah_default_hard_addtime;
-                comb->sadb_comb_soft_usetime =
-                    ahstack->ipsecah_default_soft_usetime;
-                comb->sadb_comb_hard_usetime =
-                    ahstack->ipsecah_default_hard_usetime;
-
-                prop->sadb_prop_len += SADB_8TO64(sizeof (*comb));
-                if (--combs == 0)
-                        return; /* out of space.. */
-                comb++;
-        }
-}
-
-/*
- * Prepare and actually send the SADB_ACQUIRE message to PF_KEY.
- */
-static void
-ah_send_acquire(ipsacq_t *acqrec, mblk_t *extended, netstack_t *ns)
-{
-        uint_t combs;
-        sadb_msg_t *samsg;
-        sadb_prop_t *prop;
-        mblk_t *pfkeymp, *msgmp;
-        ipsecah_stack_t *ahstack = ns->netstack_ipsecah;
-        ipsec_stack_t   *ipss = ns->netstack_ipsec;
-
-        AH_BUMP_STAT(ahstack, acquire_requests);
-
-        if (ahstack->ah_pfkey_q == NULL) {
-                mutex_exit(&acqrec->ipsacq_lock);
-                return;
-        }
-
-        /* Set up ACQUIRE. */
-        pfkeymp = sadb_setup_acquire(acqrec, SADB_SATYPE_AH,
-            ns->netstack_ipsec);
-        if (pfkeymp == NULL) {
-                ah0dbg(("sadb_setup_acquire failed.\n"));
-                mutex_exit(&acqrec->ipsacq_lock);
-                return;
-        }
-        ASSERT(MUTEX_HELD(&ipss->ipsec_alg_lock));
-        combs = ipss->ipsec_nalgs[IPSEC_ALG_AUTH];
-        msgmp = pfkeymp->b_cont;
-        samsg = (sadb_msg_t *)(msgmp->b_rptr);
-
-        /* Insert proposal here. */
-
-        prop = (sadb_prop_t *)(((uint64_t *)samsg) + samsg->sadb_msg_len);
-        ah_insert_prop(prop, acqrec, combs, ns);
-        samsg->sadb_msg_len += prop->sadb_prop_len;
-        msgmp->b_wptr += SADB_64TO8(samsg->sadb_msg_len);
-
-        mutex_exit(&ipss->ipsec_alg_lock);
-
-        /*
-         * Must mutex_exit() before sending PF_KEY message up, in
-         * order to avoid recursive mutex_enter() if there are no registered
-         * listeners.
-         *
-         * Once I've sent the message, I'm cool anyway.
-         */
-        mutex_exit(&acqrec->ipsacq_lock);
-        if (extended != NULL) {
-                putnext(ahstack->ah_pfkey_q, extended);
-        }
-        putnext(ahstack->ah_pfkey_q, pfkeymp);
-}
-
 /* Refactor me */
 /*
  * Handle the SADB_GETSPI message.  Create a larval SA.
  */
 static void