Date: Sun, 20 Nov 2016 10:54:18 +0000 (UTC) From: "Andrey V. Elsukov" <ae@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r308879 - projects/ipsec/sys/netipsec Message-ID: <201611201054.uAKAsIrL018334@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: ae Date: Sun Nov 20 10:54:18 2016 New Revision: 308879 URL: https://svnweb.freebsd.org/changeset/base/308879 Log: Add SPDB generation id 'sp_genid' variable and key_getspgen() function to read its value. This variable incremented when security policy added or deleted from SPDB. Modify key_insertsp(), key_unlink() and key_spdflush() to modify generation id. Change condition in key_unlink(). Now we have many different SP states, but only SPs with IPSEC_SPSTATE_ALIVE state are linked into the SPDB. If SP has different state, do not try to unlink it. Also remove SP from idhash when it becomes unlinked. Change key_insertsp(), now it should be called with acquired SPTREE_LOCK. Also add new SP into idhash when it linked into SPDB. In key_spdflush() remove all flushed SPs from idhash. Modified: projects/ipsec/sys/netipsec/key.c projects/ipsec/sys/netipsec/key.h Modified: projects/ipsec/sys/netipsec/key.c ============================================================================== --- projects/ipsec/sys/netipsec/key.c Sun Nov 20 10:23:05 2016 (r308878) +++ projects/ipsec/sys/netipsec/key.c Sun Nov 20 10:54:18 2016 (r308879) @@ -141,6 +141,9 @@ static VNET_DEFINE(int, key_preferred_ol static VNET_DEFINE(u_int32_t, acq_seq) = 0; #define V_acq_seq VNET(acq_seq) +static VNET_DEFINE(uint32_t, sp_genid) = 0; +#define V_sp_genid VNET(sp_genid) + /* SPD */ TAILQ_HEAD(secpolicy_queue, secpolicy); LIST_HEAD(secpolicy_list, secpolicy); @@ -626,6 +629,16 @@ key_havesp(u_int dir) /* %%% IPsec policy management */ /* + * Return current SPDB generation. + */ +uint32_t +key_getspgen(void) +{ + + return (V_sp_genid); +} + +/* * allocating a SP for OUTBOUND or INBOUND packet. * Must call key_freesp() later. * OUT: NULL: not found @@ -1271,21 +1284,25 @@ static void key_unlink(struct secpolicy *sp) { - IPSEC_ASSERT(sp != NULL, ("null sp")); IPSEC_ASSERT(sp->spidx.dir == IPSEC_DIR_INBOUND || sp->spidx.dir == IPSEC_DIR_OUTBOUND, ("invalid direction %u", sp->spidx.dir)); SPTREE_UNLOCK_ASSERT(); + KEYDBG(KEY_STAMP, + printf("%s: SP(%p)\n", __func__, sp)); SPTREE_WLOCK(); - if (sp->state == IPSEC_SPSTATE_DEAD) { + if (sp->state != IPSEC_SPSTATE_ALIVE) { + /* SP is already unlinked */ SPTREE_WUNLOCK(); return; } sp->state = IPSEC_SPSTATE_DEAD; TAILQ_REMOVE(&V_sptree[sp->spidx.dir], sp, chain); + LIST_REMOVE(sp, idhash); + V_sp_genid++; SPTREE_WUNLOCK(); - KEY_FREESP(&sp); + key_freesp(&sp); } /* @@ -1296,7 +1313,7 @@ key_insertsp(struct secpolicy *newsp) { struct secpolicy *sp; - SPTREE_WLOCK(); + SPTREE_WLOCK_ASSERT(); TAILQ_FOREACH(sp, &V_sptree[newsp->spidx.dir], chain) { if (newsp->priority < sp->priority) { TAILQ_INSERT_BEFORE(sp, newsp, chain); @@ -1307,8 +1324,9 @@ key_insertsp(struct secpolicy *newsp) TAILQ_INSERT_TAIL(&V_sptree[newsp->spidx.dir], newsp, chain); done: + LIST_INSERT_HEAD(SPHASH_HASH(newsp->id), newsp, idhash); newsp->state = IPSEC_SPSTATE_ALIVE; - SPTREE_WUNLOCK(); + V_sp_genid++; } /* @@ -2427,7 +2445,7 @@ key_spdacquire(struct secpolicy *sp) static int key_spdflush(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp) { - TAILQ_HEAD(, secpolicy) drainq; + struct secpolicy_queue drainq; struct sadb_msg *newmsg; struct secpolicy *sp, *nextsp; u_int dir; @@ -2448,9 +2466,13 @@ key_spdflush(struct socket *so, struct m /* * We need to set state to DEAD for each policy to be sure, * that another thread won't try to unlink it. + * Also remove SP from sphash. */ - TAILQ_FOREACH(sp, &drainq, chain) + TAILQ_FOREACH(sp, &drainq, chain) { sp->state = IPSEC_SPSTATE_DEAD; + LIST_REMOVE(sp, idhash); + } + V_sp_genid++; SPTREE_WUNLOCK(); sp = TAILQ_FIRST(&drainq); while (sp != NULL) { Modified: projects/ipsec/sys/netipsec/key.h ============================================================================== --- projects/ipsec/sys/netipsec/key.h Sun Nov 20 10:23:05 2016 (r308878) +++ projects/ipsec/sys/netipsec/key.h Sun Nov 20 10:54:18 2016 (r308879) @@ -46,6 +46,8 @@ struct sadb_x_policy; struct secasindex; union sockaddr_union; +uint32_t key_getspgen(void); + extern void key_addref(struct secpolicy *sp); extern int key_havesp(u_int dir); extern struct secpolicy *key_allocsp(struct secpolicyindex *, u_int,
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201611201054.uAKAsIrL018334>