Skip site navigation (1)Skip section navigation (2)
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>