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