From owner-p4-projects@FreeBSD.ORG Tue Jul 22 18:40:05 2003 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 4157C37B404; Tue, 22 Jul 2003 18:40:05 -0700 (PDT) Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id E83AC37B401 for ; Tue, 22 Jul 2003 18:40:04 -0700 (PDT) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id EEEE143F3F for ; Tue, 22 Jul 2003 18:40:03 -0700 (PDT) (envelope-from sam@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.12.6/8.12.6) with ESMTP id h6N1e30U039769 for ; Tue, 22 Jul 2003 18:40:03 -0700 (PDT) (envelope-from sam@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.12.6/8.12.6/Submit) id h6N1e3p2039766 for perforce@freebsd.org; Tue, 22 Jul 2003 18:40:03 -0700 (PDT) Date: Tue, 22 Jul 2003 18:40:03 -0700 (PDT) Message-Id: <200307230140.h6N1e3p2039766@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to sam@freebsd.org using -f From: Sam Leffler To: Perforce Change Reviews Subject: PERFORCE change 34866 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 23 Jul 2003 01:40:06 -0000 http://perforce.freebsd.org/chv.cgi?CH=34866 Change 34866 by sam@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 #include #include +#include +#include #include #include #include @@ -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) <<<