summaryrefslogtreecommitdiffstats
path: root/sys/netipsec
diff options
context:
space:
mode:
authorLuiz Otavio O Souza <luiz@netgate.com>2015-09-15 12:29:57 -0500
committerLuiz Otavio O Souza <luiz@netgate.com>2015-10-20 11:32:58 -0500
commite778bc828bb26f886d4405003534b0c83aae21be (patch)
tree6cdef9723b23ad84bdae680b423ef1796777a0ec /sys/netipsec
parent2d697711142c82967bd7d519bf253f9462bbc573 (diff)
downloadFreeBSD-src-e778bc828bb26f886d4405003534b0c83aae21be.zip
FreeBSD-src-e778bc828bb26f886d4405003534b0c83aae21be.tar.gz
Revert IPSEC patches.
Revert "Importing pfSense patch ipsec_improvement.diff" This reverts commit 29b5f15dd163f4c415bb883fef4a53cf17f9e4e2. TAG: IPSEC-HEAD Issue: #4841
Diffstat (limited to 'sys/netipsec')
-rw-r--r--sys/netipsec/key.c290
-rw-r--r--sys/netipsec/keydb.h1
2 files changed, 142 insertions, 149 deletions
diff --git a/sys/netipsec/key.c b/sys/netipsec/key.c
index 17bbab6..a3e3d76 100644
--- a/sys/netipsec/key.c
+++ b/sys/netipsec/key.c
@@ -139,18 +139,6 @@ static VNET_DEFINE(int, key_preferred_oldsa) = 1;
static VNET_DEFINE(u_int32_t, acq_seq) = 0;
#define V_acq_seq VNET(acq_seq)
- /* SPD cache */
-struct secpolicycache {
- struct secpolicy *policy;
- struct secpolicyindex spidx;
- u_int32_t genid;
-};
-#define SPCACHESIZE 8192
-static VNET_DEFINE(struct secpolicycache, spcache[2][SPCACHESIZE]);
-#define V_spcache VNET(spcache)
-static VNET_DEFINE(u_int32_t, spcache_genid) = 0;
-#define V_spcache_genid VNET(spcache_genid)
-
/* SPD */
static VNET_DEFINE(LIST_HEAD(_sptree, secpolicy), sptree[IPSEC_DIR_MAX]);
#define V_sptree VNET(sptree)
@@ -163,13 +151,8 @@ static struct mtx sptree_lock;
#define SPTREE_UNLOCK() mtx_unlock(&sptree_lock)
#define SPTREE_LOCK_ASSERT() mtx_assert(&sptree_lock, MA_OWNED)
-#define SPIHASHSIZE 1024
-#define SPIHASH(x) (((x) + ((x) >> 16)) % SPIHASHSIZE)
-
static VNET_DEFINE(LIST_HEAD(_sahtree, secashead), sahtree); /* SAD */
#define V_sahtree VNET(sahtree)
-static VNET_DEFINE(LIST_HEAD(_spihash, secasvar), spihash[SPIHASHSIZE]);
-#define V_spihash VNET(spihash)
static struct mtx sahtree_lock;
#define SAHTREE_LOCK_INIT() \
mtx_init(&sahtree_lock, "sahtree", \
@@ -346,8 +329,6 @@ SYSCTL_VNET_INT(_net_key, KEYCTL_PREFERED_OLDSA,
#define __LIST_CHAINED(elm) \
(!((elm)->chain.le_next == NULL && (elm)->chain.le_prev == NULL))
-#define __LIST_SPIHASHED(elm) \
- (!((elm)->spihash.le_next == NULL && (elm)->spihash.le_prev == NULL))
#define LIST_INSERT_TAIL(head, elm, type, field) \
do {\
struct type *curelm = LIST_FIRST(head); \
@@ -456,11 +437,11 @@ static u_int key_getspreqmsglen(struct secpolicy *);
static int key_spdexpire(struct secpolicy *);
static struct secashead *key_newsah(struct secasindex *);
static void key_delsah(struct secashead *);
-static struct secasvar *key_newsav(u_int32_t, struct mbuf *,
+static struct secasvar *key_newsav(struct mbuf *,
const struct sadb_msghdr *, struct secashead *, int *,
const char*, int);
-#define KEY_NEWSAV(spi, m, sadb, sah, e) \
- key_newsav(spi, m, sadb, sah, e, __FILE__, __LINE__)
+#define KEY_NEWSAV(m, sadb, sah, e) \
+ key_newsav(m, sadb, sah, e, __FILE__, __LINE__)
static void key_delsav(struct secasvar *);
static struct secashead *key_getsah(struct secasindex *);
static struct secasvar *key_checkspidup(struct secasindex *, u_int32_t);
@@ -630,12 +611,16 @@ key_havesp(u_int dir)
* OUT: NULL: not found
* others: found and return the pointer.
*/
-static struct secpolicy *
-key_allocsp_slow(struct secpolicyindex *spidx, u_int dir, const char* where,
+struct secpolicy *
+key_allocsp(struct secpolicyindex *spidx, u_int dir, const char* where,
int tag)
{
struct secpolicy *sp;
+ IPSEC_ASSERT(spidx != NULL, ("null spidx"));
+ IPSEC_ASSERT(dir == IPSEC_DIR_INBOUND || dir == IPSEC_DIR_OUTBOUND,
+ ("invalid direction %u", dir));
+
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
printf("DP %s from %s:%u\n", __func__, where, tag));
@@ -644,7 +629,7 @@ key_allocsp_slow(struct secpolicyindex *spidx, u_int dir, const char* where,
printf("*** objects\n");
kdebug_secpolicyindex(spidx));
- SPTREE_LOCK_ASSERT();
+ SPTREE_LOCK();
LIST_FOREACH(sp, &V_sptree[dir], chain) {
KEYDEBUG(KEYDEBUG_IPSEC_DATA,
printf("*** in SPD\n");
@@ -657,45 +642,6 @@ key_allocsp_slow(struct secpolicyindex *spidx, u_int dir, const char* where,
}
sp = NULL;
found:
-
- KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
- printf("DP %s return SP:%p (ID=%u) refcnt %u\n", __func__,
- sp, sp ? sp->id : 0, sp ? sp->refcnt : 0));
- return sp;
-}
-
-static Fnv32_t key_hash_spidx(struct secpolicyindex *spidx)
-{
- Fnv32_t hash = FNV1_32_INIT;
- hash = fnv_32_buf(&spidx->src.sa, spidx->src.sa.sa_len, hash);
- hash = fnv_32_buf(&spidx->dst.sa, spidx->dst.sa.sa_len, hash);
- hash = fnv_32_buf(&spidx->ul_proto, sizeof(spidx->ul_proto), hash);
- return hash;
-}
-
-struct secpolicy *
-key_allocsp(struct secpolicyindex *spidx, u_int dir, const char* where, int tag)
-{
- struct secpolicy *sp;
- Fnv32_t hash;
- int hdir;
-
- IPSEC_ASSERT(spidx != NULL, ("null spidx"));
- IPSEC_ASSERT(dir == IPSEC_DIR_INBOUND || dir == IPSEC_DIR_OUTBOUND,
- ("invalid direction %u", dir));
-
- SPTREE_LOCK();
- hdir = (dir == IPSEC_DIR_INBOUND);
- hash = key_hash_spidx(spidx) % SPCACHESIZE;
- if (V_spcache[hdir][hash].genid == V_spcache_genid &&
- key_cmpspidx_exactly(&V_spcache[hdir][hash].spidx, spidx)) {
- sp = V_spcache[hdir][hash].policy;
- } else {
- sp = key_allocsp_slow(spidx, dir, where, tag);
- V_spcache[hdir][hash].policy = sp;
- V_spcache[hdir][hash].spidx = *spidx;
- V_spcache[hdir][hash].genid = V_spcache_genid;
- }
if (sp) {
/* sanity check */
KEY_CHKSPDIR(sp->spidx.dir, dir, __func__);
@@ -706,6 +652,9 @@ key_allocsp(struct secpolicyindex *spidx, u_int dir, const char* where, int tag)
}
SPTREE_UNLOCK();
+ KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
+ printf("DP %s return SP:%p (ID=%u) refcnt %u\n", __func__,
+ sp, sp ? sp->id : 0, sp ? sp->refcnt : 0));
return sp;
}
@@ -1128,7 +1077,10 @@ struct secasvar *
key_allocsa(union sockaddr_union *dst, u_int proto, u_int32_t spi,
const char* where, int tag)
{
+ struct secashead *sah;
struct secasvar *sav;
+ u_int stateidx, arraysize, state;
+ const u_int *saorder_state_valid;
#ifdef IPSEC_NAT_T
int natt_chkport;
#endif
@@ -1151,32 +1103,54 @@ key_allocsa(union sockaddr_union *dst, u_int proto, u_int32_t spi,
* encrypted so we can't check internal IP header.
*/
SAHTREE_LOCK();
- LIST_FOREACH(sav, &spihash[SPIHASH(spi)], spihash) {
+ if (V_key_preferred_oldsa) {
+ saorder_state_valid = saorder_state_valid_prefer_old;
+ arraysize = _ARRAYLEN(saorder_state_valid_prefer_old);
+ } else {
+ saorder_state_valid = saorder_state_valid_prefer_new;
+ arraysize = _ARRAYLEN(saorder_state_valid_prefer_new);
+ }
+ LIST_FOREACH(sah, &V_sahtree, chain) {
int checkport;
- if (sav->state != SADB_SASTATE_MATURE &&
- sav->state != SADB_SASTATE_DYING)
- continue;
- if (proto != sav->sah->saidx.proto)
- continue;
- if (spi != sav->spi)
- continue;
-
- checkport = 0;
+ /* search valid state */
+ for (stateidx = 0; stateidx < arraysize; stateidx++) {
+ state = saorder_state_valid[stateidx];
+ LIST_FOREACH(sav, &sah->savtree[state], chain) {
+ /* sanity check */
+ KEY_CHKSASTATE(sav->state, state, __func__);
+ /* do not return entries w/ unusable state */
+ if (sav->state != SADB_SASTATE_MATURE &&
+ sav->state != SADB_SASTATE_DYING)
+ continue;
+ if (proto != sav->sah->saidx.proto)
+ continue;
+ if (spi != sav->spi)
+ continue;
+ checkport = 0;
#ifdef IPSEC_NAT_T
- /*
- * Really only check ports when this is a NAT-T
- * SA. Otherwise other lookups providing ports
- * might suffer.
- */
- if (sav->natt_type && natt_chkport)
- checkport = 1;
+ /*
+ * Really only check ports when this is a NAT-T
+ * SA. Otherwise other lookups providing ports
+ * might suffer.
+ */
+ if (sav->natt_type && natt_chkport)
+ checkport = 1;
#endif
- /* check dst address */
- if (key_sockaddrcmp(&dst->sa, &sav->sah->saidx.dst.sa, checkport) != 0)
- continue;
- sa_addref(sav);
- goto done;
+#if 0 /* don't check src */
+ /* check src address */
+ if (key_sockaddrcmp(&src->sa,
+ &sav->sah->saidx.src.sa, checkport) != 0)
+ continue;
+#endif
+ /* check dst address */
+ if (key_sockaddrcmp(&dst->sa,
+ &sav->sah->saidx.dst.sa, checkport) != 0)
+ continue;
+ sa_addref(sav);
+ goto done;
+ }
+ }
}
sav = NULL;
done:
@@ -1309,8 +1283,6 @@ key_delsp(struct secpolicy *sp)
IPSEC_ASSERT(sp != NULL, ("null sp"));
SPTREE_LOCK_ASSERT();
- if (sp->state != IPSEC_SPSTATE_DEAD)
- V_spcache_genid++;
sp->state = IPSEC_SPSTATE_DEAD;
IPSEC_ASSERT(sp->refcnt == 0,
@@ -1958,7 +1930,6 @@ key_spdadd(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
newsp->refcnt = 1; /* do not reclaim until I say I do */
newsp->state = IPSEC_SPSTATE_ALIVE;
LIST_INSERT_TAIL(&V_sptree[newsp->spidx.dir], newsp, secpolicy, chain);
- V_spcache_genid++;
/* delete the entry in spacqtree */
if (mhp->msg->sadb_msg_type == SADB_X_SPDUPDATE) {
@@ -2397,7 +2368,6 @@ key_spdflush(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
SPTREE_LOCK();
LIST_FOREACH(sp, &V_sptree[dir], chain)
sp->state = IPSEC_SPSTATE_DEAD;
- V_spcache_genid++;
SPTREE_UNLOCK();
}
@@ -2777,16 +2747,16 @@ key_delsah(struct secashead *sah)
* does not modify mbuf. does not free mbuf on error.
*/
static struct secasvar *
-key_newsav(u_int32_t spi, struct mbuf *m, const struct sadb_msghdr *mhp,
+key_newsav(struct mbuf *m, const struct sadb_msghdr *mhp,
struct secashead *sah, int *errp, const char *where, int tag)
{
struct secasvar *newsav;
+ const struct sadb_sa *xsa;
IPSEC_ASSERT(m != NULL, ("null mbuf"));
IPSEC_ASSERT(mhp != NULL, ("null msghdr"));
IPSEC_ASSERT(mhp->msg != NULL, ("null msg"));
IPSEC_ASSERT(sah != NULL, ("null secashead"));
- SAHTREE_LOCK_ASSERT();
newsav = malloc(sizeof(struct secasvar), M_IPSEC_SA, M_NOWAIT|M_ZERO);
if (newsav == NULL) {
@@ -2795,20 +2765,41 @@ key_newsav(u_int32_t spi, struct mbuf *m, const struct sadb_msghdr *mhp,
goto done;
}
+ switch (mhp->msg->sadb_msg_type) {
+ case SADB_GETSPI:
+ newsav->spi = 0;
#ifdef IPSEC_DOSEQCHECK
- /* sync sequence number */
- if (mhp->msg->sadb_msg_type == SADB_GETSPI &&
- mhp->msg->sadb_msg_seq == 0)
- newsav->seq =
- (V_acq_seq = (V_acq_seq == ~0 ? 1 : ++V_acq_seq));
- else
+ /* sync sequence number */
+ if (mhp->msg->sadb_msg_seq == 0)
+ newsav->seq =
+ (V_acq_seq = (V_acq_seq == ~0 ? 1 : ++V_acq_seq));
+ else
#endif
+ newsav->seq = mhp->msg->sadb_msg_seq;
+ break;
+
+ case SADB_ADD:
+ /* sanity check */
+ if (mhp->ext[SADB_EXT_SA] == NULL) {
+ free(newsav, M_IPSEC_SA);
+ newsav = NULL;
+ ipseclog((LOG_DEBUG, "%s: invalid message is passed.\n",
+ __func__));
+ *errp = EINVAL;
+ goto done;
+ }
+ xsa = (const struct sadb_sa *)mhp->ext[SADB_EXT_SA];
+ newsav->spi = xsa->sadb_sa_spi;
newsav->seq = mhp->msg->sadb_msg_seq;
+ break;
+ default:
+ free(newsav, M_IPSEC_SA);
+ newsav = NULL;
+ *errp = EINVAL;
+ goto done;
+ }
- newsav->created = time_second;
- newsav->pid = mhp->msg->sadb_msg_pid;
- newsav->spi = spi;
/* copy sav values */
if (mhp->msg->sadb_msg_type != SADB_GETSPI) {
@@ -2820,20 +2811,21 @@ key_newsav(u_int32_t spi, struct mbuf *m, const struct sadb_msghdr *mhp,
}
}
+ SECASVAR_LOCK_INIT(newsav);
+
/* reset created */
+ newsav->created = time_second;
newsav->pid = mhp->msg->sadb_msg_pid;
- newsav->spi = spi;
/* add to satree */
newsav->sah = sah;
sa_initref(newsav);
newsav->state = SADB_SASTATE_LARVAL;
+ SAHTREE_LOCK();
LIST_INSERT_TAIL(&sah->savtree[SADB_SASTATE_LARVAL], newsav,
secasvar, chain);
- if (spi)
- LIST_INSERT_HEAD(&spihash[SPIHASH(spi)], newsav, spihash);
-
+ SAHTREE_UNLOCK();
done:
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
printf("DP %s from %s:%u return SP:%p\n", __func__,
@@ -2909,9 +2901,8 @@ key_delsav(struct secasvar *sav)
/* remove from SA header */
if (__LIST_CHAINED(sav))
LIST_REMOVE(sav, chain);
- if (__LIST_SPIHASHED(sav))
- LIST_REMOVE(sav, spihash);
key_cleansav(sav);
+ SECASVAR_LOCK_DESTROY(sav);
free(sav, M_IPSEC_SA);
}
@@ -2940,6 +2931,7 @@ key_getsah(struct secasindex *saidx)
/*
* check not to be duplicated SPI.
+ * NOTE: this function is too slow due to searching all SAD.
* OUT:
* NULL : not found
* others : found, pointer to a SA.
@@ -2947,10 +2939,9 @@ key_getsah(struct secasindex *saidx)
static struct secasvar *
key_checkspidup(struct secasindex *saidx, u_int32_t spi)
{
+ struct secashead *sah;
struct secasvar *sav;
- SAHTREE_LOCK_ASSERT();
-
/* check address family */
if (saidx->src.sa.sa_family != saidx->dst.sa.sa_family) {
ipseclog((LOG_DEBUG, "%s: address family mismatched.\n",
@@ -2959,11 +2950,16 @@ key_checkspidup(struct secasindex *saidx, u_int32_t spi)
}
sav = NULL;
- LIST_FOREACH(sav, &spihash[SPIHASH(spi)], spihash) {
- if (sav->spi == spi &&
- key_ismyaddr((struct sockaddr *)&sav->sah->saidx.dst))
+ /* check all SAD */
+ SAHTREE_LOCK();
+ LIST_FOREACH(sah, &V_sahtree, chain) {
+ if (!key_ismyaddr((struct sockaddr *)&sah->saidx.dst))
+ continue;
+ sav = key_getsavbyspi(sah, spi);
+ if (sav != NULL)
break;
}
+ SAHTREE_UNLOCK();
return sav;
}
@@ -2978,20 +2974,27 @@ static struct secasvar *
key_getsavbyspi(struct secashead *sah, u_int32_t spi)
{
struct secasvar *sav;
- u_int stateidx;
+ u_int stateidx, state;
sav = NULL;
SAHTREE_LOCK_ASSERT();
- LIST_FOREACH(sav, &spihash[SPIHASH(spi)], spihash) {
- if (sav->sah != sah)
- continue;
- if (sav->spi != spi)
- continue;
+ /* search all status */
+ for (stateidx = 0;
+ stateidx < _ARRAYLEN(saorder_state_alive);
+ stateidx++) {
- for (stateidx = 0;
- stateidx < _ARRAYLEN(saorder_state_alive);
- stateidx++) {
- if (sav->state == saorder_state_alive[stateidx])
+ state = saorder_state_alive[stateidx];
+ LIST_FOREACH(sav, &sah->savtree[state], chain) {
+
+ /* sanity check */
+ if (sav->state != state) {
+ ipseclog((LOG_DEBUG, "%s: "
+ "invalid sav->state (queue: %d SA: %d)\n",
+ __func__, state, sav->state));
+ continue;
+ }
+
+ if (sav->spi == spi)
return sav;
}
}
@@ -4254,7 +4257,6 @@ restart:
if ((sp->lifetime && now - sp->created > sp->lifetime)
|| (sp->validtime && now - sp->lastused > sp->validtime)) {
sp->state = IPSEC_SPSTATE_DEAD;
- V_spcache_genid++;
SPTREE_UNLOCK();
key_spdexpire(sp);
goto restart;
@@ -4676,6 +4678,12 @@ key_getspi(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
}
#endif
+ /* SPI allocation */
+ spi = key_do_getnewspi((struct sadb_spirange *)mhp->ext[SADB_EXT_SPIRANGE],
+ &saidx);
+ if (spi == 0)
+ return key_senderror(so, m, EINVAL);
+
/* get a SA index */
if ((newsah = key_getsah(&saidx)) == NULL) {
/* create a new SA index */
@@ -4685,24 +4693,16 @@ key_getspi(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
}
}
- /* SPI allocation */
- SAHTREE_LOCK();
- spi = key_do_getnewspi((struct sadb_spirange *)mhp->ext[SADB_EXT_SPIRANGE],
- &saidx);
- if (spi == 0) {
- SAHTREE_UNLOCK();
- return key_senderror(so, m, EINVAL);
- }
-
/* get a new SA */
/* XXX rewrite */
- newsav = KEY_NEWSAV(spi, m, mhp, newsah, &error);
+ newsav = KEY_NEWSAV(m, mhp, newsah, &error);
if (newsav == NULL) {
/* XXX don't free new SA index allocated in above. */
- SAHTREE_UNLOCK();
return key_senderror(so, m, error);
}
- SAHTREE_UNLOCK();
+
+ /* set spi */
+ newsav->spi = htonl(spi);
/* delete the entry in acqtree */
if (mhp->msg->sadb_msg_seq != 0) {
@@ -4745,7 +4745,7 @@ key_getspi(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
m_sa = (struct sadb_sa *)(mtod(n, caddr_t) + off);
m_sa->sadb_sa_len = PFKEY_UNIT64(sizeof(struct sadb_sa));
m_sa->sadb_sa_exttype = SADB_EXT_SA;
- m_sa->sadb_sa_spi = spi;
+ m_sa->sadb_sa_spi = htonl(spi);
off += PFKEY_ALIGN8(sizeof(struct sadb_sa));
IPSEC_ASSERT(off == len,
@@ -4792,8 +4792,6 @@ key_do_getnewspi(struct sadb_spirange *spirange, struct secasindex *saidx)
u_int32_t min, max;
int count = V_key_spi_trycnt;
- SAHTREE_LOCK_ASSERT();
-
/* set spi range to allocate */
if (spirange != NULL) {
min = spirange->sadb_spirange_min;
@@ -4815,15 +4813,15 @@ key_do_getnewspi(struct sadb_spirange *spirange, struct secasindex *saidx)
}
if (min == max) {
- newspi = htonl(min);
-
- if (key_checkspidup(saidx, newspi) != NULL) {
+ if (key_checkspidup(saidx, min) != NULL) {
ipseclog((LOG_DEBUG, "%s: SPI %u exists already.\n",
__func__, min));
return 0;
}
count--; /* taking one cost. */
+ newspi = min;
+
} else {
/* init SPI */
@@ -4832,7 +4830,7 @@ key_do_getnewspi(struct sadb_spirange *spirange, struct secasindex *saidx)
/* when requesting to allocate spi ranged */
while (count--) {
/* generate pseudo-random SPI value ranged. */
- newspi = htonl(min + (key_random() % (max - min + 1)));
+ newspi = min + (key_random() % (max - min + 1));
if (key_checkspidup(saidx, newspi) == NULL)
break;
@@ -5305,14 +5303,12 @@ key_add(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
/* We can create new SA only if SPI is differenct. */
SAHTREE_LOCK();
newsav = key_getsavbyspi(newsah, sa0->sadb_sa_spi);
+ SAHTREE_UNLOCK();
if (newsav != NULL) {
- SAHTREE_UNLOCK();
ipseclog((LOG_DEBUG, "%s: SA already exists.\n", __func__));
return key_senderror(so, m, EEXIST);
}
- newsav = KEY_NEWSAV(sa0->sadb_sa_spi, m, mhp, newsah, &error);
- SAHTREE_UNLOCK();
-
+ newsav = KEY_NEWSAV(m, mhp, newsah, &error);
if (newsav == NULL) {
return key_senderror(so, m, error);
}
@@ -7662,8 +7658,6 @@ key_init(void)
LIST_INIT(&V_sptree[i]);
LIST_INIT(&V_sahtree);
- for (i = 0; i < SPIHASHSIZE; i++)
- LIST_INIT(&V_spihash[i]);
for (i = 0; i <= SADB_SATYPE_MAX; i++)
LIST_INIT(&V_regtree[i]);
diff --git a/sys/netipsec/keydb.h b/sys/netipsec/keydb.h
index a8b813f..56f44fc 100644
--- a/sys/netipsec/keydb.h
+++ b/sys/netipsec/keydb.h
@@ -111,7 +111,6 @@ struct comp_algo;
/* Security Association */
struct secasvar {
LIST_ENTRY(secasvar) chain;
- LIST_ENTRY(secasvar) spihash;
struct mtx lock; /* update/access lock */
u_int refcnt; /* reference count */
OpenPOWER on IntegriCloud