Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 24 Jan 2017 05:06:52 +0000 (UTC)
From:      "Andrey V. Elsukov" <ae@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r312682 - in projects/ipsec: lib/libipsec sys/net sys/netipsec
Message-ID:  <201701240506.v0O56qCp020431@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ae
Date: Tue Jan 24 05:06:52 2017
New Revision: 312682
URL: https://svnweb.freebsd.org/changeset/base/312682

Log:
  Make it possible to change SA addresses via SADB_UPDATE.
  
  This is not allowed by RFC 2367, but it is useful feature for implementing
  MOBIKE protocol by IKEd (RFC 4555). We still support the old behavior of
  the SADB_UPDATE, but two new extension headers are added:
  SADB_X_EXT_NEW_ADDRESS_SRC and SADB_X_EXT_NEW_ADDRESS_DST. IKEd can use
  them to specify new addresses for MATURE SA. When kernel has discovered
  these headers, it allocates new SA, copies the content of old SA into new,
  then unlinks old SA from the SADB. The same actions will be done, when
  IKEd wants to change NAT-T configuration.
  
  This is similar to making SADB_DELETE and SADB_ADD, but it keeps the
  state of SA unchanged, that is impossible to make with SADB_DELETE
  and SADB_ADD.
  
  To implement this the lock filed of secasvar was changed to be a pointer.
  Also all fields that could not be copied moved to the end of structure.
  Now secasvar lock can be shared between old and new SA, this needed to
  avoid modification of SA content (e.g. replay window) during migration.
  
  Discussed with:	Tobias Brunner <tobias at strongswan org>

Modified:
  projects/ipsec/lib/libipsec/pfkey.c
  projects/ipsec/sys/net/pfkeyv2.h
  projects/ipsec/sys/netipsec/key.c
  projects/ipsec/sys/netipsec/keydb.h

Modified: projects/ipsec/lib/libipsec/pfkey.c
==============================================================================
--- projects/ipsec/lib/libipsec/pfkey.c	Tue Jan 24 03:00:22 2017	(r312681)
+++ projects/ipsec/lib/libipsec/pfkey.c	Tue Jan 24 05:06:52 2017	(r312682)
@@ -1783,6 +1783,8 @@ pfkey_align(msg, mhp)
 		case SADB_X_EXT_NAT_T_OAR:
 		case SADB_X_EXT_NAT_T_FRAG:
 		case SADB_X_EXT_SA_REPLAY:
+		case SADB_X_EXT_NEW_ADDRESS_SRC:
+		case SADB_X_EXT_NEW_ADDRESS_DST:
 			mhp[ext->sadb_ext_type] = (caddr_t)ext;
 			break;
 		default:

Modified: projects/ipsec/sys/net/pfkeyv2.h
==============================================================================
--- projects/ipsec/sys/net/pfkeyv2.h	Tue Jan 24 03:00:22 2017	(r312681)
+++ projects/ipsec/sys/net/pfkeyv2.h	Tue Jan 24 05:06:52 2017	(r312682)
@@ -320,7 +320,9 @@ _Static_assert(sizeof(struct sadb_x_sa_r
 #define SADB_X_EXT_NAT_T_OAR          24	/* Peer's NAT_OA for dst of SA. */
 #define SADB_X_EXT_NAT_T_FRAG         25	/* Manual MTU override. */
 #define SADB_X_EXT_SA_REPLAY          26	/* Replay window override. */
-#define SADB_EXT_MAX                  26
+#define	SADB_X_EXT_NEW_ADDRESS_SRC    27
+#define	SADB_X_EXT_NEW_ADDRESS_DST    28
+#define	SADB_EXT_MAX                  28
 
 #define SADB_SATYPE_UNSPEC	0
 #define SADB_SATYPE_AH		2

Modified: projects/ipsec/sys/netipsec/key.c
==============================================================================
--- projects/ipsec/sys/netipsec/key.c	Tue Jan 24 03:00:22 2017	(r312681)
+++ projects/ipsec/sys/netipsec/key.c	Tue Jan 24 05:06:52 2017	(r312682)
@@ -336,6 +336,8 @@ static const int minsize[] = {
 	sizeof(struct sadb_address),	/* SADB_X_EXT_NAT_T_OAR */
 	sizeof(struct sadb_x_nat_t_frag),/* SADB_X_EXT_NAT_T_FRAG */
 	sizeof(struct sadb_x_sa_replay), /* SADB_X_EXT_SA_REPLAY */
+	sizeof(struct sadb_address),	/* SADB_X_EXT_NEW_ADDRESS_SRC */
+	sizeof(struct sadb_address),	/* SADB_X_EXT_NEW_ADDRESS_DST */
 };
 _Static_assert(sizeof(minsize)/sizeof(int) == SADB_EXT_MAX + 1, "minsize size mismatch");
 
@@ -367,9 +369,18 @@ static const int maxsize[] = {
 	0,				/* SADB_X_EXT_NAT_T_OAR */
 	sizeof(struct sadb_x_nat_t_frag),/* SADB_X_EXT_NAT_T_FRAG */
 	sizeof(struct sadb_x_sa_replay), /* SADB_X_EXT_SA_REPLAY */
+	0,				/* SADB_X_EXT_NEW_ADDRESS_SRC */
+	0,				/* SADB_X_EXT_NEW_ADDRESS_DST */
 };
 _Static_assert(sizeof(maxsize)/sizeof(int) == SADB_EXT_MAX + 1, "minsize size mismatch");
 
+/*
+ * Internal values for SA flags:
+ * SADB_X_EXT_F_CLONED means that SA was cloned by key_updateaddresses,
+ *	thus we will not free the most of SA content in key_delsav().
+ */
+#define	SADB_X_EXT_F_CLONED	0x80000000
+
 #define	SADB_CHECKLEN(_mhp, _ext)			\
     ((_mhp)->extlen[(_ext)] < minsize[(_ext)] || (maxsize[(_ext)] != 0 && \
 	((_mhp)->extlen[(_ext)] > maxsize[(_ext)])))
@@ -596,6 +607,9 @@ static struct secasvar *key_getsavbyspi(
 static int key_setnatt(struct secasvar *, const struct sadb_msghdr *);
 static int key_setsaval(struct secasvar *, const struct sadb_msghdr *);
 static int key_updatelifetimes(struct secasvar *, const struct sadb_msghdr *);
+static int key_updateaddresses(struct socket *, struct mbuf *,
+    const struct sadb_msghdr *, struct secasvar *, struct secasindex *);
+
 static struct mbuf *key_setdumpsa(struct secasvar *, u_int8_t,
 	u_int8_t, u_int32_t, u_int32_t);
 static struct mbuf *key_setsadbmsg(u_int8_t, u_int16_t, u_int8_t,
@@ -2748,16 +2762,18 @@ key_newsav(const struct sadb_msghdr *mhp
 
 	sav = malloc(sizeof(struct secasvar), M_IPSEC_SA, M_NOWAIT | M_ZERO);
 	if (sav == NULL) {
-		PFKEYSTAT_INC(in_nomem);
-		ipseclog((LOG_DEBUG, "%s: No more memory.\n", __func__));
 		*errp = ENOBUFS;
 		goto done;
 	}
+	sav->lock = malloc(sizeof(struct mtx), M_IPSEC_MISC,
+	    M_NOWAIT | M_ZERO);
+	if (sav->lock == NULL) {
+		*errp = ENOBUFS;
+		goto done;
+	}
+	mtx_init(sav->lock, "ipsec association", NULL, MTX_DEF);
 	sav->lft_c = uma_zalloc(V_key_lft_zone, M_NOWAIT);
 	if (sav->lft_c == NULL) {
-		PFKEYSTAT_INC(in_nomem);
-		ipseclog((LOG_DEBUG, "%s: No more memory.\n", __func__));
-		free(sav, M_IPSEC_SA), sav = NULL;
 		*errp = ENOBUFS;
 		goto done;
 	}
@@ -2769,7 +2785,6 @@ key_newsav(const struct sadb_msghdr *mhp
 	sav->state = SADB_SASTATE_LARVAL;
 	sav->pid = (pid_t)mhp->msg->sadb_msg_pid;
 	SAV_INITREF(sav);
-	SECASVAR_LOCK_INIT(sav);
 again:
 	sah = key_getsah(saidx);
 	if (sah == NULL) {
@@ -2844,12 +2859,21 @@ again:
 done:
 	if (*errp != 0) {
 		if (sav != NULL) {
-			SECASVAR_LOCK_DESTROY(sav);
-			uma_zfree(V_key_lft_zone, sav->lft_c);
+			if (sav->lock != NULL) {
+				mtx_destroy(sav->lock);
+				free(sav->lock, M_IPSEC_MISC);
+			}
+			if (sav->lft_c != NULL)
+				uma_zfree(V_key_lft_zone, sav->lft_c);
 			free(sav, M_IPSEC_SA), sav = NULL;
 		}
 		if (sah != NULL)
 			key_freesah(&sah);
+		if (*errp == ENOBUFS) {
+			ipseclog((LOG_DEBUG, "%s: No more memory.\n",
+			    __func__));
+			PFKEYSTAT_INC(in_nomem);
+		}
 	}
 	return (sav);
 }
@@ -2861,6 +2885,12 @@ static void
 key_cleansav(struct secasvar *sav)
 {
 
+	if (sav->natt != NULL) {
+		free(sav->natt, M_IPSEC_MISC);
+		sav->natt = NULL;
+	}
+	if (sav->flags & SADB_X_EXT_F_CLONED)
+		return;
 	/*
 	 * Cleanup xform state.  Note that zeroize'ing causes the
 	 * keys to be cleared; otherwise we must do it ourself.
@@ -2886,10 +2916,6 @@ key_cleansav(struct secasvar *sav)
 		free(sav->key_enc, M_IPSEC_MISC);
 		sav->key_enc = NULL;
 	}
-	if (sav->natt != NULL) {
-		free(sav->natt, M_IPSEC_MISC);
-		sav->natt = NULL;
-	}
 	if (sav->replay != NULL) {
 		if (sav->replay->bitmap != NULL)
 			free(sav->replay->bitmap, M_IPSEC_MISC);
@@ -2918,10 +2944,17 @@ key_delsav(struct secasvar *sav)
 	IPSEC_ASSERT(sav->refcnt == 0, ("reference count %u > 0",
 	    sav->refcnt));
 
-	/* SA must be unlinked from the chain and hashtbl */
+	/*
+	 * SA must be unlinked from the chain and hashtbl.
+	 * If SA was cloned, we leave all fields untouched,
+	 * except NAT-T config.
+	 */
 	key_cleansav(sav);
-	SECASVAR_LOCK_DESTROY(sav);
-	uma_zfree(V_key_lft_zone, sav->lft_c);
+	if ((sav->flags & SADB_X_EXT_F_CLONED) == 0) {
+		mtx_destroy(sav->lock);
+		free(sav->lock, M_IPSEC_MISC);
+		uma_zfree(V_key_lft_zone, sav->lft_c);
+	}
 	free(sav, M_IPSEC_SA);
 }
 
@@ -3012,7 +3045,6 @@ key_updatelifetimes(struct secasvar *sav
 		}
 		return (0);
 	}
-	/* XXXAE: what should we do with CURRENT lifetime? */
 	/* Both HARD and SOFT extensions must present */
 	if ((SADB_CHECKHDR(mhp, SADB_EXT_LIFETIME_HARD) &&
 	    !SADB_CHECKHDR(mhp, SADB_EXT_LIFETIME_SOFT)) ||
@@ -4939,6 +4971,177 @@ key_getsav_tcpmd5(struct secasindex *sai
 	return (NULL);
 }
 
+static int
+key_updateaddresses(struct socket *so, struct mbuf *m,
+    const struct sadb_msghdr *mhp, struct secasvar *sav,
+    struct secasindex *saidx)
+{
+	struct sockaddr *newaddr;
+	struct secashead *sah;
+	struct secasvar *newsav, *tmp;
+	struct mbuf *n;
+	int error, isnew;
+
+	/* Check that we need to change SAH */
+	if (!SADB_CHECKHDR(mhp, SADB_X_EXT_NEW_ADDRESS_SRC)) {
+		newaddr = (struct sockaddr *)(
+		    ((struct sadb_address *)
+		    mhp->ext[SADB_X_EXT_NEW_ADDRESS_SRC]) + 1);
+		bcopy(newaddr, &saidx->src, newaddr->sa_len);
+		key_porttosaddr(&saidx->src.sa, 0);
+	}
+	if (!SADB_CHECKHDR(mhp, SADB_X_EXT_NEW_ADDRESS_DST)) {
+		newaddr = (struct sockaddr *)(
+		    ((struct sadb_address *)
+		    mhp->ext[SADB_X_EXT_NEW_ADDRESS_DST]) + 1);
+		bcopy(newaddr, &saidx->dst, newaddr->sa_len);
+		key_porttosaddr(&saidx->dst.sa, 0);
+	}
+	if (!SADB_CHECKHDR(mhp, SADB_X_EXT_NEW_ADDRESS_SRC) ||
+	    !SADB_CHECKHDR(mhp, SADB_X_EXT_NEW_ADDRESS_DST)) {
+		error = key_checksockaddrs(&saidx->src.sa, &saidx->dst.sa);
+		if (error != 0) {
+			ipseclog((LOG_DEBUG, "%s: invalid new sockaddr.\n",
+			    __func__));
+			return (error);
+		}
+
+		sah = key_getsah(saidx);
+		if (sah == NULL) {
+			/* create a new SA index */
+			sah = key_newsah(saidx);
+			if (sah == NULL) {
+				ipseclog((LOG_DEBUG,
+				    "%s: No more memory.\n", __func__));
+				return (ENOBUFS);
+			}
+			isnew = 2; /* SAH is new */
+		} else
+			isnew = 1; /* existing SAH is referenced */
+	} else {
+		/*
+		 * src and dst addresses are still the same.
+		 * Do we want to change NAT-T config?
+		 */
+		if (sav->sah->saidx.proto != IPPROTO_ESP ||
+		    SADB_CHECKHDR(mhp, SADB_X_EXT_NAT_T_TYPE) ||
+		    SADB_CHECKHDR(mhp, SADB_X_EXT_NAT_T_SPORT) ||
+		    SADB_CHECKHDR(mhp, SADB_X_EXT_NAT_T_DPORT)) {
+			ipseclog((LOG_DEBUG,
+			    "%s: invalid message: missing required header.\n",
+			    __func__));
+			return (EINVAL);
+		}
+		/* We hold reference to SA, thus SAH will be referenced too. */
+		sah = sav->sah;
+		isnew = 0;
+	}
+
+	newsav = malloc(sizeof(struct secasvar), M_IPSEC_SA,
+	    M_NOWAIT | M_ZERO);
+	if (newsav == NULL) {
+		ipseclog((LOG_DEBUG, "%s: No more memory.\n", __func__));
+		error = ENOBUFS;
+		goto fail;
+	}
+
+	/* Clone SA's content into newsav */
+	SAV_INITREF(newsav);
+	bcopy(sav, newsav, offsetof(struct secasvar, chain));
+	/*
+	 * We create new NAT-T config if it is needed.
+	 * Old NAT-T config will be freed by key_cleansav() when
+	 * last reference to SA will be released.
+	 */
+	newsav->natt = NULL;
+	newsav->sah = sah;
+	newsav->state = SADB_SASTATE_MATURE;
+	error = key_setnatt(sav, mhp);
+	if (error != 0)
+		goto fail;
+
+	SAHTREE_WLOCK();
+	/* Check that SA is still alive */
+	if (sav->state == SADB_SASTATE_DEAD) {
+		/* SA was unlinked */
+		SAHTREE_WUNLOCK();
+		error = ESRCH;
+		goto fail;
+	}
+
+	/* Unlink SA from SAH and SPI hash */
+	IPSEC_ASSERT((sav->flags & SADB_X_EXT_F_CLONED) == 0,
+	    ("SA is already cloned"));
+	IPSEC_ASSERT(sav->state == SADB_SASTATE_MATURE ||
+	    sav->state == SADB_SASTATE_DYING,
+	    ("Wrong SA state %u\n", sav->state));
+	TAILQ_REMOVE(&sav->sah->savtree_alive, sav, chain);
+	LIST_REMOVE(sav, spihash);
+	sav->state = SADB_SASTATE_DEAD;
+
+	/*
+	 * Link new SA with SAH. Keep SAs ordered by
+	 * create time (newer are first).
+	 */
+	TAILQ_FOREACH(tmp, &sah->savtree_alive, chain) {
+		if (newsav->created > tmp->created) {
+			TAILQ_INSERT_BEFORE(tmp, newsav, chain);
+			break;
+		}
+	}
+	if (tmp == NULL)
+		TAILQ_INSERT_TAIL(&sah->savtree_alive, newsav, chain);
+
+	/* Add new SA into SPI hash. */
+	LIST_INSERT_HEAD(SAVHASH_HASH(newsav->spi), newsav, spihash);
+
+	/* Add new SAH into SADB. */
+	if (isnew == 2) {
+		TAILQ_INSERT_HEAD(&V_sahtree, sah, chain);
+		LIST_INSERT_HEAD(SAHADDRHASH_HASH(saidx), sah, addrhash);
+		sah->state = SADB_SASTATE_MATURE;
+		SAH_ADDREF(sah); /* newsav references new SAH */
+	}
+	/*
+	 * isnew == 1 -> @sah was referenced by key_getsah().
+	 * isnew == 0 -> we use the same @sah, that was used by @sav,
+	 *	and we use its reference for @newsav.
+	 */
+	SECASVAR_LOCK(sav);
+	/* XXX: replace cntr with pointer? */
+	newsav->cntr = sav->cntr;
+	sav->flags |= SADB_X_EXT_F_CLONED;
+	SECASVAR_UNLOCK(sav);
+
+	SAHTREE_WUNLOCK();
+
+	KEYDBG(KEY_STAMP,
+	    printf("%s: SA(%p) cloned into SA(%p)\n",
+	    __func__, sav, newsav));
+	KEYDBG(KEY_DATA, kdebug_secasv(newsav));
+
+	key_freesav(&sav); /* release last reference */
+
+	/* set msg buf from mhp */
+	n = key_getmsgbuf_x1(m, mhp);
+	if (n == NULL) {
+		ipseclog((LOG_DEBUG, "%s: No more memory.\n", __func__));
+		return (ENOBUFS);
+	}
+	m_freem(m);
+	key_sendup_mbuf(so, n, KEY_SENDUP_ALL);
+	return (0);
+fail:
+	if (isnew != 0)
+		key_freesah(&sah);
+	if (newsav != NULL) {
+		if (newsav->natt != NULL)
+			free(newsav->natt, M_IPSEC_MISC);
+		free(newsav, M_IPSEC_SA);
+	}
+	return (error);
+}
+
 /*
  * SADB_UPDATE processing
  * receive
@@ -5109,6 +5312,24 @@ key_update(struct socket *so, struct mbu
 			key_freesav(&sav);
 			return (key_senderror(so, m, error));
 		}
+		/*
+		 * This is FreeBSD extension to RFC2367.
+		 * IKEd can specify SADB_X_EXT_NEW_ADDRESS_SRC and/or
+		 * SADB_X_EXT_NEW_ADDRESS_DST when it wants to change
+		 * SA addresses (for example to implement MOBIKE protocol
+		 * as described in RFC4555). Also we allow to change
+		 * NAT-T config.
+		 */
+		if (!SADB_CHECKHDR(mhp, SADB_X_EXT_NEW_ADDRESS_SRC) ||
+		    !SADB_CHECKHDR(mhp, SADB_X_EXT_NEW_ADDRESS_DST) ||
+		    !SADB_CHECKHDR(mhp, SADB_X_EXT_NAT_T_TYPE) ||
+		    sav->natt != NULL) {
+			error = key_updateaddresses(so, m, mhp, sav, &saidx);
+			key_freesav(&sav);
+			if (error != 0)
+				return (key_senderror(so, m, error));
+			return (0);
+		}
 		/* Check that SA is still alive */
 		SAHTREE_WLOCK();
 		if (sav->state == SADB_SASTATE_DEAD) {
@@ -5558,14 +5779,15 @@ key_getmsgbuf_x1(struct mbuf *m, const s
 	IPSEC_ASSERT(mhp->msg != NULL, ("null msg"));
 
 	/* create new sadb_msg to reply. */
-	n = key_gather_mbuf(m, mhp, 1, 14, SADB_EXT_RESERVED,
+	n = key_gather_mbuf(m, mhp, 1, 16, SADB_EXT_RESERVED,
 	    SADB_EXT_SA, SADB_X_EXT_SA2,
 	    SADB_EXT_ADDRESS_SRC, SADB_EXT_ADDRESS_DST,
 	    SADB_EXT_LIFETIME_HARD, SADB_EXT_LIFETIME_SOFT,
 	    SADB_EXT_IDENTITY_SRC, SADB_EXT_IDENTITY_DST,
 	    SADB_X_EXT_NAT_T_TYPE, SADB_X_EXT_NAT_T_SPORT,
 	    SADB_X_EXT_NAT_T_DPORT, SADB_X_EXT_NAT_T_OAI,
-	    SADB_X_EXT_NAT_T_OAR);
+	    SADB_X_EXT_NAT_T_OAR, SADB_X_EXT_NEW_ADDRESS_SRC,
+	    SADB_X_EXT_NEW_ADDRESS_DST);
 	if (!n)
 		return NULL;
 
@@ -7675,6 +7897,8 @@ key_align(struct mbuf *m, struct sadb_ms
 		case SADB_X_EXT_NAT_T_OAR:
 		case SADB_X_EXT_NAT_T_FRAG:
 		case SADB_X_EXT_SA_REPLAY:
+		case SADB_X_EXT_NEW_ADDRESS_SRC:
+		case SADB_X_EXT_NEW_ADDRESS_DST:
 			/* duplicate check */
 			/*
 			 * XXX Are there duplication payloads of either
@@ -7750,6 +7974,10 @@ key_validate_ext(const struct sadb_ext *
 	case SADB_EXT_ADDRESS_SRC:
 	case SADB_EXT_ADDRESS_DST:
 	case SADB_EXT_ADDRESS_PROXY:
+	case SADB_X_EXT_NAT_T_OAI:
+	case SADB_X_EXT_NAT_T_OAR:
+	case SADB_X_EXT_NEW_ADDRESS_SRC:
+	case SADB_X_EXT_NEW_ADDRESS_DST:
 		baselen = PFKEY_ALIGN8(sizeof(struct sadb_address));
 		checktype = ADDR;
 		break;

Modified: projects/ipsec/sys/netipsec/keydb.h
==============================================================================
--- projects/ipsec/sys/netipsec/keydb.h	Tue Jan 24 03:00:22 2017	(r312681)
+++ projects/ipsec/sys/netipsec/keydb.h	Tue Jan 24 05:06:52 2017	(r312682)
@@ -133,61 +133,60 @@ struct comp_algo;
  * to search better candidate. The newer SA (by created time) are placed
  * in the beginning of the savtree list. There is no preference between
  * DYING and MATURE.
+ *
+ * NB: Fields with a tdb_ prefix are part of the "glue" used
+ *     to interface to the OpenBSD crypto support.  This was done
+ *     to distinguish this code from the mainline KAME code.
+ * NB: Fields are sorted on the basis of the frequency of changes, i.e.
+ *     constants and unchangeable fields are going first.
+ * NB: if you want to change this structure, check that this will not break
+ *     key_updateaddresses().
  */
 struct secasvar {
-	TAILQ_ENTRY(secasvar) chain;
-	LIST_ENTRY(secasvar) spihash;
-	LIST_ENTRY(secasvar) drainq;	/* used ONLY by flush callout */
-
 	uint32_t spi;			/* SPI Value, network byte order */
 	uint32_t flags;			/* holder for SADB_KEY_FLAGS */
-
 	uint32_t seq;			/* sequence number */
 	pid_t pid;			/* message's pid */
-
-	uint8_t state;			/* Status of this SA (pfkeyv2.h) */
-	uint8_t alg_auth;		/* Authentication Algorithm Identifier*/
-	uint8_t alg_enc;		/* Cipher Algorithm Identifier */
-	uint8_t alg_comp;		/* Compression Algorithm Identifier */
+	u_int ivlen;			/* length of IV */
 
 	struct secashead *sah;		/* back pointer to the secashead */
 	struct seckey *key_auth;	/* Key for Authentication */
 	struct seckey *key_enc;	        /* Key for Encryption */
 	struct secreplay *replay;	/* replay prevention */
 	struct secnatt *natt;		/* NAT-T config */
-	uint64_t cntr;			/* counter for GCM and CTR */
-	u_int ivlen;			/* length of IV */
+	struct mtx *lock;		/* update/access lock */
 
-	volatile u_int refcnt;		/* reference count */
+	const struct xformsw *tdb_xform;	/* transform */
+	const struct enc_xform *tdb_encalgxform;/* encoding algorithm */
+	const struct auth_hash *tdb_authalgxform;/* authentication algorithm */
+	const struct comp_algo *tdb_compalgxform;/* compression algorithm */
+	uint64_t tdb_cryptoid;		/* crypto session id */
+
+	uint8_t alg_auth;		/* Authentication Algorithm Identifier*/
+	uint8_t alg_enc;		/* Cipher Algorithm Identifier */
+	uint8_t alg_comp;		/* Compression Algorithm Identifier */
+	uint8_t state;			/* Status of this SA (pfkeyv2.h) */
 
-	uint64_t created;		/* time when SA was created */
-	uint64_t firstused;		/* time when SA was first used */
 	counter_u64_t lft_c;		/* CURRENT lifetime */
 #define	lft_c_allocations	lft_c
 #define	lft_c_bytes		lft_c + 1
 	struct seclifetime *lft_h;	/* HARD lifetime */
 	struct seclifetime *lft_s;	/* SOFT lifetime */
 
-	/*
-	 * NB: Fields with a tdb_ prefix are part of the "glue" used
-	 *     to interface to the OpenBSD crypto support.  This was done
-	 *     to distinguish this code from the mainline KAME code.
-	 */
-	const struct xformsw *tdb_xform;	/* transform */
-	const struct enc_xform *tdb_encalgxform;/* encoding algorithm */
-	const struct auth_hash *tdb_authalgxform;/* authentication algorithm */
-	const struct comp_algo *tdb_compalgxform;/* compression algorithm */
-	uint64_t tdb_cryptoid;		/* crypto session id */
+	uint64_t created;		/* time when SA was created */
+	uint64_t firstused;		/* time when SA was first used */
 
-	struct mtx lock;		/* update/access lock */
+	TAILQ_ENTRY(secasvar) chain;
+	LIST_ENTRY(secasvar) spihash;
+	LIST_ENTRY(secasvar) drainq;	/* used ONLY by flush callout */
+
+	uint64_t cntr;			/* counter for GCM and CTR */
+	volatile u_int refcnt;		/* reference count */
 };
 
-#define	SECASVAR_LOCK_INIT(_sav) \
-	mtx_init(&(_sav)->lock, "ipsec association", NULL, MTX_DEF)
-#define	SECASVAR_LOCK(_sav)		mtx_lock(&(_sav)->lock)
-#define	SECASVAR_UNLOCK(_sav)		mtx_unlock(&(_sav)->lock)
-#define	SECASVAR_LOCK_DESTROY(_sav)	mtx_destroy(&(_sav)->lock)
-#define	SECASVAR_LOCK_ASSERT(_sav)	mtx_assert(&(_sav)->lock, MA_OWNED)
+#define	SECASVAR_LOCK(_sav)		mtx_lock((_sav)->lock)
+#define	SECASVAR_UNLOCK(_sav)		mtx_unlock((_sav)->lock)
+#define	SECASVAR_LOCK_ASSERT(_sav)	mtx_assert((_sav)->lock, MA_OWNED)
 #define	SAV_ISGCM(_sav)							\
 			((_sav)->alg_enc == SADB_X_EALG_AESGCM8 ||	\
 			(_sav)->alg_enc == SADB_X_EALG_AESGCM12 ||	\



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201701240506.v0O56qCp020431>