PERFORCE change 34866 for review
Sam Leffler
sam at FreeBSD.org
Tue Jul 22 18:40:06 PDT 2003
http://perforce.freebsd.org/chv.cgi?CH=34866
Change 34866 by sam at sam_ebb on 2003/07/22 18:39:12
fast ipsec locking (needs revisiting)
Affected files ...
.. //depot/projects/netperf/sys/netipsec/ipsec.c#2 edit
.. //depot/projects/netperf/sys/netipsec/ipsec.h#2 edit
.. //depot/projects/netperf/sys/netipsec/ipsec_input.c#2 edit
.. //depot/projects/netperf/sys/netipsec/ipsec_output.c#2 edit
.. //depot/projects/netperf/sys/netipsec/key.c#2 edit
.. //depot/projects/netperf/sys/netipsec/key.h#2 edit
.. //depot/projects/netperf/sys/netipsec/keydb.h#2 edit
.. //depot/projects/netperf/sys/netipsec/xform_ah.c#2 edit
.. //depot/projects/netperf/sys/netipsec/xform_esp.c#2 edit
.. //depot/projects/netperf/sys/netipsec/xform_ipcomp.c#2 edit
Differences ...
==== //depot/projects/netperf/sys/netipsec/ipsec.c#2 (text+ko) ====
@@ -202,6 +202,8 @@
static void vshiftl __P((unsigned char *, int, int));
static size_t ipsec_hdrsiz __P((struct secpolicy *));
+MALLOC_DEFINE(M_IPSEC_INPCB, "inpcbpolicy", "inpcb-resident ipsec policy");
+
/*
* Return a held reference to the default SP.
*/
@@ -836,7 +838,7 @@
ipsec_delpcbpolicy(p)
struct inpcbpolicy *p;
{
- free(p, M_SECA);
+ free(p, M_IPSEC_INPCB);
}
/* initialize policy in PCB */
@@ -852,7 +854,7 @@
panic("ipsec_init_policy: NULL pointer was passed.\n");
new = (struct inpcbpolicy *) malloc(sizeof(struct inpcbpolicy),
- M_SECA, M_NOWAIT|M_ZERO);
+ M_IPSEC_INPCB, M_NOWAIT|M_ZERO);
if (new == NULL) {
ipseclog((LOG_DEBUG, "ipsec_init_policy: No more memory.\n"));
return ENOBUFS;
@@ -909,6 +911,24 @@
return 0;
}
+struct ipsecrequest *
+ipsec_newisr(void)
+{
+ struct ipsecrequest *p;
+
+ p = malloc(sizeof(struct ipsecrequest), M_IPSEC_SR, M_NOWAIT|M_ZERO);
+ if (p != NULL)
+ mtx_init(&p->lock, "ipsec request", NULL, MTX_DEF);
+ return p;
+}
+
+void
+ipsec_delisr(struct ipsecrequest *p)
+{
+ mtx_destroy(&p->lock);
+ free(p, M_IPSEC_SR);
+}
+
/* deep-copy a policy in PCB */
static struct secpolicy *
ipsec_deepcopy_policy(src)
@@ -932,13 +952,9 @@
*/
q = &newchain;
for (p = src->req; p; p = p->next) {
- *q = (struct ipsecrequest *)malloc(sizeof(struct ipsecrequest),
- M_SECA, M_NOWAIT);
+ *q = ipsec_newisr();
if (*q == NULL)
goto fail;
- bzero(*q, sizeof(**q));
- (*q)->next = NULL;
-
(*q)->saidx.proto = p->saidx.proto;
(*q)->saidx.mode = p->saidx.mode;
(*q)->level = p->level;
@@ -947,7 +963,6 @@
bcopy(&p->saidx.src, &(*q)->saidx.src, sizeof((*q)->saidx.src));
bcopy(&p->saidx.dst, &(*q)->saidx.dst, sizeof((*q)->saidx.dst));
- (*q)->sav = NULL;
(*q)->sp = dst;
q = &((*q)->next);
@@ -963,7 +978,7 @@
fail:
for (p = newchain; p; p = r) {
r = p->next;
- free(p, M_SECA);
+ ipsec_delisr(p);
p = NULL;
}
return NULL;
==== //depot/projects/netperf/sys/netipsec/ipsec.h#2 (text+ko) ====
@@ -71,6 +71,7 @@
/* Security Policy Data Base */
struct secpolicy {
LIST_ENTRY(secpolicy) chain;
+ struct mtx lock;
u_int refcnt; /* reference count */
struct secpolicyindex spidx; /* selector */
@@ -108,6 +109,7 @@
struct secasvar *sav; /* place holder of SA for use */
struct secpolicy *sp; /* back pointer to SP */
+ struct mtx lock; /* to interlock updates */
};
/* security policy in PCB */
@@ -322,6 +324,9 @@
/* for openbsd compatibility */
#define DPRINTF(x) do { if (ipsec_debug) printf x; } while (0)
+extern struct ipsecrequest *ipsec_newisr(void);
+extern void ipsec_delisr(struct ipsecrequest *);
+
struct tdb_ident;
extern struct secpolicy *ipsec_getpolicy __P((struct tdb_ident*, u_int));
struct inpcb;
==== //depot/projects/netperf/sys/netipsec/ipsec_input.c#2 (text+ko) ====
@@ -108,7 +108,7 @@
union sockaddr_union dst_address;
struct secasvar *sav;
u_int32_t spi;
- int s, error;
+ int error;
IPSEC_ISTAT(sproto, espstat.esps_input, ahstat.ahs_input,
ipcompstat.ipcomps_input);
@@ -178,8 +178,6 @@
return EPFNOSUPPORT;
}
- s = splnet();
-
/* NB: only pass dst since key_allocsa follows RFC2401 */
sav = KEY_ALLOCSA(&dst_address, sproto, spi);
if (sav == NULL) {
@@ -189,7 +187,6 @@
(u_long) ntohl(spi), sproto));
IPSEC_ISTAT(sproto, espstat.esps_notdb, ahstat.ahs_notdb,
ipcompstat.ipcomps_notdb);
- splx(s);
m_freem(m);
return ENOENT;
}
@@ -202,7 +199,6 @@
IPSEC_ISTAT(sproto, espstat.esps_noxform, ahstat.ahs_noxform,
ipcompstat.ipcomps_noxform);
KEY_FREESAV(&sav);
- splx(s);
m_freem(m);
return ENXIO;
}
@@ -213,7 +209,6 @@
*/
error = (*sav->tdb_xform->xf_input)(m, sav, skip, protoff);
KEY_FREESAV(&sav);
- splx(s);
return error;
}
==== //depot/projects/netperf/sys/netipsec/ipsec_output.c#2 (text+ko) ====
@@ -345,12 +345,12 @@
struct secasindex saidx;
struct secasvar *sav;
struct ip *ip;
- int s, error, i, off;
+ int error, i, off;
KASSERT(m != NULL, ("ipsec4_process_packet: null mbuf"));
KASSERT(isr != NULL, ("ipsec4_process_packet: null isr"));
- s = splnet(); /* insure SA contents don't change */
+ mtx_lock(&isr->lock); /* insure SA contents don't change */
isr = ipsec_nextisr(m, isr, AF_INET, &saidx, &error);
if (isr == NULL)
@@ -469,10 +469,10 @@
} else {
error = ipsec_process_done(m, isr);
}
- splx(s);
+ mtx_unlock(&isr->lock);
return error;
bad:
- splx(s);
+ mtx_unlock(&isr->lock);
if (m)
m_freem(m);
return error;
==== //depot/projects/netperf/sys/netipsec/key.c#2 (text+ko) ====
@@ -42,6 +42,8 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
#include <sys/mbuf.h>
#include <sys/domain.h>
#include <sys/protosw.h>
@@ -122,16 +124,18 @@
static int key_prefered_oldsa = 1; /* prefered old sa rather than new sa.*/
static u_int32_t acq_seq = 0;
-static int key_tick_init_random = 0;
static LIST_HEAD(_sptree, secpolicy) sptree[IPSEC_DIR_MAX]; /* SPD */
+static struct mtx sptree_lock;
static LIST_HEAD(_sahtree, secashead) sahtree; /* SAD */
+static struct mtx sahtree_lock;
+ /* registed list */
static LIST_HEAD(_regtree, secreg) regtree[SADB_SATYPE_MAX + 1];
- /* registed list */
-#ifndef IPSEC_NONBLOCK_ACQUIRE
+static struct mtx regtree_lock;
static LIST_HEAD(_acqtree, secacq) acqtree; /* acquiring list */
-#endif
+static struct mtx acq_lock;
static LIST_HEAD(_spacqtree, secspacq) spacqtree; /* SP acquiring list */
+static struct mtx spacq_lock;
/* search order for SAs */
static u_int saorder_state_valid[] = {
@@ -286,28 +290,14 @@
} \
} while (0)
-MALLOC_DEFINE(M_SECA, "key mgmt", "security associations, key management");
+MALLOC_DEFINE(M_IPSEC_SA, "secasvar", "ipsec security association");
+MALLOC_DEFINE(M_IPSEC_SAH, "sahead", "ipsec sa head");
+MALLOC_DEFINE(M_IPSEC_SP, "ipsecpolicy", "ipsec security policy");
+MALLOC_DEFINE(M_IPSEC_SR, "ipsecrequest", "ipsec security request");
+MALLOC_DEFINE(M_IPSEC_MISC, "ipsec-misc", "ipsec miscellaneous");
+MALLOC_DEFINE(M_IPSEC_SAQ, "ipsec-saq", "ipsec sa acquire");
+MALLOC_DEFINE(M_IPSEC_SAR, "ipsec-reg", "ipsec sa acquire");
-#if 1
-#define KMALLOC(p, t, n) \
- ((p) = (t) malloc((unsigned long)(n), M_SECA, M_NOWAIT))
-#define KFREE(p) \
- free((caddr_t)(p), M_SECA)
-#else
-#define KMALLOC(p, t, n) \
-do { \
- ((p) = (t)malloc((unsigned long)(n), M_SECA, M_NOWAIT)); \
- printf("%s %d: %p <- KMALLOC(%s, %d)\n", \
- __FILE__, __LINE__, (p), #t, n); \
-} while (0)
-
-#define KFREE(p) \
- do { \
- printf("%s %d: %p -> KFREE()\n", __FILE__, __LINE__, (p)); \
- free((caddr_t)(p), M_SECA); \
- } while (0)
-#endif
-
/*
* set parameters into secpolicyindex buffer.
* Must allocate secpolicyindex buffer passed to this function.
@@ -354,6 +344,7 @@
static struct secasvar *key_do_allocsa_policy __P((struct secashead *, u_int));
static void key_delsp __P((struct secpolicy *));
static struct secpolicy *key_getsp __P((struct secpolicyindex *));
+static void _key_delsp(struct secpolicy *sp);
static struct secpolicy *key_getspbyid __P((u_int32_t));
static u_int32_t key_newreqid __P((void));
static struct mbuf *key_gather_mbuf __P((struct mbuf *,
@@ -396,14 +387,10 @@
static struct mbuf *key_setsadbsa __P((struct secasvar *));
static struct mbuf *key_setsadbaddr __P((u_int16_t,
const struct sockaddr *, u_int8_t, u_int16_t));
-#if 0
-static struct mbuf *key_setsadbident __P((u_int16_t, u_int16_t, caddr_t,
- int, u_int64_t));
-#endif
static struct mbuf *key_setsadbxsa2 __P((u_int8_t, u_int32_t, u_int32_t));
static struct mbuf *key_setsadbxpolicy __P((u_int16_t, u_int8_t,
u_int32_t));
-static void *key_newbuf __P((const void *, u_int));
+static void *key_dup(const void *, u_int, struct malloc_type *);
#ifdef INET6
static int key_ismyaddr6 __P((struct sockaddr_in6 *));
#endif
@@ -422,7 +409,6 @@
__P((struct secpolicyindex *, struct secpolicyindex *));
static int key_sockaddrcmp __P((const struct sockaddr *, const struct sockaddr *, int));
static int key_bbcmp __P((const void *, const void *, u_int));
-static void key_srandom __P((void));
static u_int16_t key_satype2proto __P((u_int8_t));
static u_int8_t key_proto2satype __P((u_int16_t));
@@ -453,11 +439,9 @@
static struct mbuf *key_getprop __P((const struct secasindex *));
static int key_acquire __P((const struct secasindex *, struct secpolicy *));
-#ifndef IPSEC_NONBLOCK_ACQUIRE
static struct secacq *key_newacq __P((const struct secasindex *));
static struct secacq *key_getacq __P((const struct secasindex *));
static struct secacq *key_getacqbyseq __P((u_int32_t));
-#endif
static struct secspacq *key_newspacq __P((struct secpolicyindex *));
static struct secspacq *key_getspacq __P((struct secpolicyindex *));
static int key_acquire2 __P((struct socket *, struct mbuf *,
@@ -526,7 +510,6 @@
key_allocsp(struct secpolicyindex *spidx, u_int dir, const char* where, int tag)
{
struct secpolicy *sp;
- int s;
KASSERT(spidx != NULL, ("key_allocsp: null spidx"));
KASSERT(dir == IPSEC_DIR_INBOUND || dir == IPSEC_DIR_OUTBOUND,
@@ -536,11 +519,11 @@
printf("DP key_allocsp from %s:%u\n", where, tag));
/* get a SP entry */
- s = splnet(); /*called from softclock()*/
KEYDEBUG(KEYDEBUG_IPSEC_DATA,
printf("*** objects\n");
kdebug_secpolicyindex(spidx));
+ mtx_lock(&sptree_lock);
LIST_FOREACH(sp, &sptree[dir], chain) {
KEYDEBUG(KEYDEBUG_IPSEC_DATA,
printf("*** in SPD\n");
@@ -561,7 +544,7 @@
sp->lastused = time_second;
SP_ADDREF(sp);
}
- splx(s);
+ mtx_unlock(&sptree_lock);
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
printf("DP key_allocsp return SP:%p (ID=%u) refcnt %u\n",
@@ -583,7 +566,6 @@
const char* where, int tag)
{
struct secpolicy *sp;
- int s;
KASSERT(dst != NULL, ("key_allocsp2: null dst"));
KASSERT(dir == IPSEC_DIR_INBOUND || dir == IPSEC_DIR_OUTBOUND,
@@ -593,12 +575,12 @@
printf("DP key_allocsp2 from %s:%u\n", where, tag));
/* get a SP entry */
- s = splnet(); /*called from softclock()*/
KEYDEBUG(KEYDEBUG_IPSEC_DATA,
printf("*** objects\n");
printf("spi %u proto %u dir %u\n", spi, proto, dir);
kdebug_sockaddr(&dst->sa));
+ mtx_lock(&sptree_lock);
LIST_FOREACH(sp, &sptree[dir], chain) {
KEYDEBUG(KEYDEBUG_IPSEC_DATA,
printf("*** in SPD\n");
@@ -625,7 +607,7 @@
sp->lastused = time_second;
SP_ADDREF(sp);
}
- splx(s);
+ mtx_unlock(&sptree_lock);
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
printf("DP key_allocsp2 return SP:%p (ID=%u) refcnt %u\n",
@@ -646,7 +628,6 @@
{
struct secpolicy *sp;
const int dir = IPSEC_DIR_INBOUND;
- int s;
struct ipsecrequest *r1, *r2, *p;
struct secpolicyindex spidx;
@@ -660,7 +641,7 @@
goto done;
}
- s = splnet(); /*called from softclock()*/
+ mtx_lock(&sptree_lock);
LIST_FOREACH(sp, &sptree[dir], chain) {
if (sp->state == IPSEC_SPSTATE_DEAD)
continue;
@@ -702,7 +683,7 @@
sp->lastused = time_second;
SP_ADDREF(sp);
}
- splx(s);
+ mtx_unlock(&sptree_lock);
done:
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
printf("DP key_gettunnel return SP:%p (ID=%u) refcnt %u\n",
@@ -728,19 +709,17 @@
saidx->mode == IPSEC_MODE_TUNNEL,
("key_checkrequest: unexpected policy %u", saidx->mode));
- /* get current level */
- level = ipsec_get_reqlevel(isr);
-
/*
* XXX guard against protocol callbacks from the crypto
* thread as they reference ipsecrequest.sav which we
* temporarily null out below. Need to rethink how we
* handle bundled SA's in the callback thread.
*/
+ mtx_assert(&isr->lock, MA_OWNED);
+
+ /* get current level */
+ level = ipsec_get_reqlevel(isr);
#if 0
- SPLASSERT(net, "key_checkrequest");
-#endif
-#if 0
/*
* We do allocate new SA only if the state of SA in the holder is
* SADB_SASTATE_DEAD. The SA for outbound must be the oldest.
@@ -819,12 +798,16 @@
struct secasvar *sav;
u_int stateidx, state;
+ mtx_lock(&sahtree_lock);
LIST_FOREACH(sah, &sahtree, chain) {
if (sah->state == SADB_SASTATE_DEAD)
continue;
- if (key_cmpsaidx(&sah->saidx, saidx, CMP_MODE_REQID))
+ if (key_cmpsaidx(&sah->saidx, saidx, CMP_MODE_REQID)) {
+ mtx_unlock(&sahtree_lock); /* XXX??? */
goto found;
+ }
}
+ mtx_unlock(&sahtree_lock);
return NULL;
@@ -860,6 +843,7 @@
/* initilize */
candidate = NULL;
+ mtx_lock(&sahtree_lock);
for (sav = LIST_FIRST(&sah->savtree[state]);
sav != NULL;
sav = nextsav) {
@@ -962,7 +946,6 @@
KEY_FREESAV(&d);
}
}
-
if (candidate) {
SA_ADDREF(candidate);
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
@@ -970,6 +953,8 @@
"refcnt++:%d SA:%p\n",
candidate->refcnt, candidate));
}
+ mtx_unlock(&sahtree_lock);
+
return candidate;
}
@@ -998,7 +983,6 @@
struct secashead *sah;
struct secasvar *sav;
u_int stateidx, state;
- int s;
KASSERT(dst != NULL, ("key_allocsa: null dst address"));
@@ -1011,7 +995,7 @@
* IPsec tunnel packet is received. But ESP tunnel mode is
* encrypted so we can't check internal IP header.
*/
- s = splnet(); /*called from softclock()*/
+ mtx_lock(&sahtree_lock);
LIST_FOREACH(sah, &sahtree, chain) {
/* search valid state */
for (stateidx = 0;
@@ -1044,7 +1028,7 @@
}
sav = NULL;
done:
- splx(s);
+ mtx_unlock(&sahtree_lock);
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
printf("DP key_allocsa return SA:%p; refcnt %u\n",
@@ -1063,6 +1047,7 @@
KASSERT(sp != NULL, ("key_freesp: null sp"));
+ mtx_lock(&sptree_lock);
SP_DELREF(sp);
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
@@ -1073,6 +1058,7 @@
*spp = NULL;
key_delsp(sp);
}
+ mtx_unlock(&sptree_lock);
}
/*
@@ -1174,9 +1160,10 @@
static void
key_delsp(struct secpolicy *sp)
{
- int s;
+ struct ipsecrequest *isr, *nextisr;
KASSERT(sp != NULL, ("key_delsp: null sp"));
+ mtx_assert(&sptree_lock, MA_OWNED);
sp->state = IPSEC_SPSTATE_DEAD;
@@ -1184,29 +1171,20 @@
("key_delsp: SP with references deleted (refcnt %u)",
sp->refcnt));
- s = splnet(); /*called from softclock()*/
/* remove from SP index */
if (__LIST_CHAINED(sp))
LIST_REMOVE(sp, chain);
- {
- struct ipsecrequest *isr = sp->req, *nextisr;
-
- while (isr != NULL) {
+ for (isr = sp->req; isr != NULL; isr = nextisr) {
if (isr->sav != NULL) {
KEY_FREESAV(&isr->sav);
isr->sav = NULL;
}
nextisr = isr->next;
- KFREE(isr);
- isr = nextisr;
+ ipsec_delisr(isr);
}
- }
-
- KFREE(sp);
-
- splx(s);
+ _key_delsp(sp);
}
/*
@@ -1221,16 +1199,18 @@
KASSERT(spidx != NULL, ("key_getsp: null spidx"));
+ mtx_lock(&sptree_lock);
LIST_FOREACH(sp, &sptree[spidx->dir], chain) {
if (sp->state == IPSEC_SPSTATE_DEAD)
continue;
if (key_cmpspidx_exactly(spidx, &sp->spidx)) {
SP_ADDREF(sp);
- return sp;
+ break;
}
}
+ mtx_unlock(&sptree_lock);
- return NULL;
+ return sp;
}
/*
@@ -1243,12 +1223,13 @@
{
struct secpolicy *sp;
+ mtx_lock(&sptree_lock);
LIST_FOREACH(sp, &sptree[IPSEC_DIR_INBOUND], chain) {
if (sp->state == IPSEC_SPSTATE_DEAD)
continue;
if (sp->id == id) {
SP_ADDREF(sp);
- return sp;
+ goto done;
}
}
@@ -1257,11 +1238,13 @@
continue;
if (sp->id == id) {
SP_ADDREF(sp);
- return sp;
+ goto done;
}
}
+done:
+ mtx_unlock(&sptree_lock);
- return NULL;
+ return sp;
}
struct secpolicy *
@@ -1270,8 +1253,9 @@
struct secpolicy *newsp = NULL;
newsp = (struct secpolicy *)
- malloc(sizeof(struct secpolicy), M_SECA, M_NOWAIT|M_ZERO);
+ malloc(sizeof(struct secpolicy), M_IPSEC_SP, M_NOWAIT|M_ZERO);
if (newsp) {
+ mtx_init(&newsp->lock, "ipsec policy", NULL, MTX_DEF);
newsp->refcnt = 1;
newsp->req = NULL;
}
@@ -1282,6 +1266,13 @@
return newsp;
}
+static void
+_key_delsp(struct secpolicy *sp)
+{
+ mtx_destroy(&sp->lock);
+ free(sp, M_IPSEC_SP);
+}
+
/*
* create secpolicy structure from sadb_x_policy structure.
* NOTE: `state', `secpolicyindex' in secpolicy structure are not set,
@@ -1352,7 +1343,8 @@
}
/* allocate request buffer */
- KMALLOC(*p_isr, struct ipsecrequest *, sizeof(**p_isr));
+ /* NB: data structure is zero'd */
+ *p_isr = ipsec_newisr();
if ((*p_isr) == NULL) {
ipseclog((LOG_DEBUG,
"key_msg2sp: No more memory.\n"));
@@ -1360,11 +1352,8 @@
*error = ENOBUFS;
return NULL;
}
- bzero(*p_isr, sizeof(**p_isr));
/* set values */
- (*p_isr)->next = NULL;
-
switch (xisr->sadb_x_ipsecrequest_proto) {
case IPPROTO_ESP:
case IPPROTO_AH:
@@ -1475,7 +1464,6 @@
paddr->sa_len);
}
- (*p_isr)->sav = NULL;
(*p_isr)->sp = newsp;
/* initialization for the next. */
@@ -1792,7 +1780,7 @@
}
if ((newsp->id = key_getnewspid()) == 0) {
- KFREE(newsp);
+ _key_delsp(newsp);
return key_senderror(so, m, ENOBUFS);
}
@@ -1808,12 +1796,12 @@
/* sanity check on addr pair */
if (((struct sockaddr *)(src0 + 1))->sa_family !=
((struct sockaddr *)(dst0+ 1))->sa_family) {
- KFREE(newsp);
+ _key_delsp(newsp);
return key_senderror(so, m, EINVAL);
}
if (((struct sockaddr *)(src0 + 1))->sa_len !=
((struct sockaddr *)(dst0+ 1))->sa_len) {
- KFREE(newsp);
+ _key_delsp(newsp);
return key_senderror(so, m, EINVAL);
}
#if 1
@@ -1821,7 +1809,7 @@
struct sockaddr *sa;
sa = (struct sockaddr *)(src0 + 1);
if (sa->sa_family != newsp->req->saidx.src.sa.sa_family) {
- KFREE(newsp);
+ _key_delsp(newsp);
return key_senderror(so, m, EINVAL);
}
}
@@ -1829,7 +1817,7 @@
struct sockaddr *sa;
sa = (struct sockaddr *)(dst0 + 1);
if (sa->sa_family != newsp->req->saidx.dst.sa.sa_family) {
- KFREE(newsp);
+ _key_delsp(newsp);
return key_senderror(so, m, EINVAL);
}
}
@@ -1846,11 +1834,12 @@
/* delete the entry in spacqtree */
if (mhp->msg->sadb_msg_type == SADB_X_SPDUPDATE) {
- struct secspacq *spacq;
- if ((spacq = key_getspacq(&spidx)) != NULL) {
+ struct secspacq *spacq = key_getspacq(&spidx);
+ if (spacq != NULL) {
/* reset counter in order to deletion by timehandler. */
spacq->created = time_second;
spacq->count = 0;
+ mtx_unlock(&spacq_lock);
}
}
@@ -2005,6 +1994,7 @@
xpl0->sadb_x_policy_id = sp->id;
sp->state = IPSEC_SPSTATE_DEAD;
+ mtx_destroy(&sp->lock);
KEY_FREESP(&sp);
{
@@ -2067,6 +2057,7 @@
}
sp->state = IPSEC_SPSTATE_DEAD;
+ mtx_destroy(&sp->lock);
KEY_FREESP(&sp);
{
@@ -2202,7 +2193,8 @@
panic("key_spdacquire: policy mismathed. IPsec is expected.\n");
/* Get an entry to check whether sent message or not. */
- if ((newspacq = key_getspacq(&sp->spidx)) != NULL) {
+ newspacq = key_getspacq(&sp->spidx);
+ if (newspacq != NULL) {
if (key_blockacq_count < newspacq->count) {
/* reset counter and do send message. */
newspacq->count = 0;
@@ -2211,13 +2203,12 @@
newspacq->count++;
return 0;
}
+ mtx_unlock(&spacq_lock);
} else {
/* make new entry for blocking to send SADB_ACQUIRE. */
- if ((newspacq = key_newspacq(&sp->spidx)) == NULL)
+ newspacq = key_newspacq(&sp->spidx);
+ if (newspacq == NULL)
return ENOBUFS;
-
- /* add to acqtree */
- LIST_INSERT_HEAD(&spacqtree, newspacq, chain);
}
/* create new sadb_msg to reply. */
@@ -2446,14 +2437,12 @@
key_spdexpire(sp)
struct secpolicy *sp;
{
- int s;
struct mbuf *result = NULL, *m;
int len;
int error = -1;
struct sadb_lifetime *lt;
/* XXX: Why do we lock ? */
- s = splnet(); /*called from softclock()*/
/* sanity check */
if (sp == NULL)
@@ -2546,7 +2535,6 @@
fail:
if (result)
m_freem(result);
- splx(s);
return error;
}
@@ -2564,8 +2552,7 @@
KASSERT(saidx != NULL, ("key_newsaidx: null saidx"));
- newsah = (struct secashead *)
- malloc(sizeof(struct secashead), M_SECA, M_NOWAIT|M_ZERO);
+ newsah = malloc(sizeof(struct secashead), M_IPSEC_SAH, M_NOWAIT|M_ZERO);
if (newsah != NULL) {
int i;
for (i = 0; i < sizeof(newsah->savtree)/sizeof(newsah->savtree[0]); i++)
@@ -2574,7 +2561,10 @@
/* add to saidxtree */
newsah->state = SADB_SASTATE_MATURE;
+
+ mtx_lock(&sahtree_lock);
LIST_INSERT_HEAD(&sahtree, newsah, chain);
+ mtx_unlock(&sahtree_lock);
}
return(newsah);
}
@@ -2588,14 +2578,11 @@
{
struct secasvar *sav, *nextsav;
u_int stateidx, state;
- int s;
int zombie = 0;
/* sanity check */
- if (sah == NULL)
- panic("key_delsah: NULL pointer is passed.\n");
-
- s = splnet(); /*called from softclock()*/
+ KASSERT(sah != NULL, ("key_delsah: NULL sah"));
+ mtx_assert(&sahtree_lock, MA_OWNED);
/* searching all SA registerd in the secindex. */
for (stateidx = 0;
@@ -2619,26 +2606,20 @@
}
}
}
+ /* remove from tree of SA index */
+ if (!zombie && __LIST_CHAINED(sah))
+ LIST_REMOVE(sah, chain);
/* don't delete sah only if there are savs. */
- if (zombie) {
- splx(s);
+ if (zombie)
return;
- }
if (sah->sa_route.ro_rt) {
RTFREE(sah->sa_route.ro_rt);
sah->sa_route.ro_rt = (struct rtentry *)NULL;
}
- /* remove from tree of SA index */
- if (__LIST_CHAINED(sah))
- LIST_REMOVE(sah, chain);
-
- KFREE(sah);
-
- splx(s);
- return;
+ free(sah, M_IPSEC_SAH);
}
/*
@@ -2669,13 +2650,12 @@
if (m == NULL || mhp == NULL || mhp->msg == NULL || sah == NULL)
panic("key_newsa: NULL pointer is passed.\n");
- KMALLOC(newsav, struct secasvar *, sizeof(struct secasvar));
+ newsav = malloc(sizeof(struct secasvar), M_IPSEC_SA, M_NOWAIT|M_ZERO);
if (newsav == NULL) {
ipseclog((LOG_DEBUG, "key_newsa: No more memory.\n"));
*errp = ENOBUFS;
goto done;
}
- bzero((caddr_t)newsav, sizeof(struct secasvar));
switch (mhp->msg->sadb_msg_type) {
case SADB_GETSPI:
@@ -2694,7 +2674,8 @@
case SADB_ADD:
/* sanity check */
if (mhp->ext[SADB_EXT_SA] == NULL) {
- KFREE(newsav), newsav = NULL;
+ free(newsav, M_IPSEC_SA);
+ newsav = NULL;
ipseclog((LOG_DEBUG, "key_newsa: invalid message is passed.\n"));
*errp = EINVAL;
goto done;
@@ -2704,20 +2685,25 @@
newsav->seq = mhp->msg->sadb_msg_seq;
break;
default:
- KFREE(newsav), newsav = NULL;
+ free(newsav, M_IPSEC_SA);
+ newsav = NULL;
*errp = EINVAL;
goto done;
}
+
/* copy sav values */
if (mhp->msg->sadb_msg_type != SADB_GETSPI) {
*errp = key_setsaval(newsav, m, mhp);
if (*errp) {
- KFREE(newsav), newsav = NULL;
+ free(newsav, M_IPSEC_SA);
+ newsav = NULL;
goto done;
}
}
+ mtx_init(&newsav->lock, "ipsec sa", NULL, MTX_DEF);
+
/* reset created */
newsav->created = time_second;
newsav->pid = mhp->msg->sadb_msg_pid;
@@ -2726,6 +2712,8 @@
newsav->sah = sah;
newsav->refcnt = 1;
newsav->state = SADB_SASTATE_LARVAL;
+
+ /* XXX locking??? */
LIST_INSERT_TAIL(&sah->savtree[SADB_SASTATE_LARVAL], newsav,
secasvar, chain);
done:
@@ -2740,17 +2728,8 @@
* free() SA variable entry.
*/
static void
-key_delsav(sav)
- struct secasvar *sav;
+key_cleansav(struct secasvar *sav)
{
- KASSERT(sav != NULL, ("key_delsav: null sav"));
- KASSERT(sav->refcnt == 0,
- ("key_delsav: reference count %u > 0", sav->refcnt));
-
- /* remove from SA header */
- if (__LIST_CHAINED(sav))
- LIST_REMOVE(sav, chain);
-
/*
* Cleanup xform state. Note that zeroize'ing causes the
* keys to be cleared; otherwise we must do it ourself.
@@ -2765,42 +2744,57 @@
bzero(_KEYBUF(sav->key_enc), _KEYLEN(sav->key_enc));
}
if (sav->key_auth != NULL) {
- KFREE(sav->key_auth);
+ free(sav->key_auth, M_IPSEC_MISC);
sav->key_auth = NULL;
}
if (sav->key_enc != NULL) {
- KFREE(sav->key_enc);
+ free(sav->key_enc, M_IPSEC_MISC);
sav->key_enc = NULL;
}
if (sav->sched) {
bzero(sav->sched, sav->schedlen);
- KFREE(sav->sched);
+ free(sav->sched, M_IPSEC_MISC);
sav->sched = NULL;
}
if (sav->replay != NULL) {
- KFREE(sav->replay);
+ free(sav->replay, M_IPSEC_MISC);
sav->replay = NULL;
}
if (sav->lft_c != NULL) {
- KFREE(sav->lft_c);
+ free(sav->lft_c, M_IPSEC_MISC);
sav->lft_c = NULL;
}
if (sav->lft_h != NULL) {
- KFREE(sav->lft_h);
+ free(sav->lft_h, M_IPSEC_MISC);
sav->lft_h = NULL;
}
if (sav->lft_s != NULL) {
- KFREE(sav->lft_s);
+ free(sav->lft_s, M_IPSEC_MISC);
sav->lft_s = NULL;
}
if (sav->iv != NULL) {
- KFREE(sav->iv);
+ free(sav->iv, M_IPSEC_MISC);
sav->iv = NULL;
}
+}
- KFREE(sav);
+/*
+ * free() SA variable entry.
+ */
+static void
+key_delsav(sav)
+ struct secasvar *sav;
>>> TRUNCATED FOR MAIL (1000 lines) <<<
More information about the p4-projects
mailing list