summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/netipsec/key.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/sys/netipsec/key.c')
-rw-r--r--freebsd/sys/netipsec/key.c73
1 files changed, 40 insertions, 33 deletions
diff --git a/freebsd/sys/netipsec/key.c b/freebsd/sys/netipsec/key.c
index b6fb97a0..0252730f 100644
--- a/freebsd/sys/netipsec/key.c
+++ b/freebsd/sys/netipsec/key.c
@@ -811,6 +811,7 @@ key_checkrequest(struct ipsecrequest *isr, const struct secasindex *saidx)
{
u_int level;
int error;
+ struct secasvar *sav;
IPSEC_ASSERT(isr != NULL, ("null isr"));
IPSEC_ASSERT(saidx != NULL, ("null saidx"));
@@ -828,45 +829,31 @@ key_checkrequest(struct ipsecrequest *isr, const struct secasindex *saidx)
/* get current level */
level = ipsec_get_reqlevel(isr);
-#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.
- */
- if (isr->sav != NULL) {
- if (isr->sav->sah == NULL)
- panic("%s: sah is null.\n", __func__);
- if (isr->sav == (struct secasvar *)LIST_FIRST(
- &isr->sav->sah->savtree[SADB_SASTATE_DEAD])) {
- KEY_FREESAV(&isr->sav);
- isr->sav = NULL;
- }
- }
-#else
+
/*
- * we free any SA stashed in the IPsec request because a different
+ * We check new SA in the IPsec request because a different
* SA may be involved each time this request is checked, either
* because new SAs are being configured, or this request is
* associated with an unconnected datagram socket, or this request
* is associated with a system default policy.
*
- * The operation may have negative impact to performance. We may
- * want to check cached SA carefully, rather than picking new SA
- * every time.
- */
- if (isr->sav != NULL) {
- KEY_FREESAV(&isr->sav);
- isr->sav = NULL;
- }
-#endif
-
- /*
- * new SA allocation if no SA found.
* key_allocsa_policy should allocate the oldest SA available.
* See key_do_allocsa_policy(), and draft-jenkins-ipsec-rekeying-03.txt.
*/
- if (isr->sav == NULL)
- isr->sav = key_allocsa_policy(saidx);
+ sav = key_allocsa_policy(saidx);
+ if (sav != isr->sav) {
+ /* SA need to be updated. */
+ if (!IPSECREQUEST_UPGRADE(isr)) {
+ /* Kick everyone off. */
+ IPSECREQUEST_UNLOCK(isr);
+ IPSECREQUEST_WLOCK(isr);
+ }
+ if (isr->sav != NULL)
+ KEY_FREESAV(&isr->sav);
+ isr->sav = sav;
+ IPSECREQUEST_DOWNGRADE(isr);
+ } else if (sav != NULL)
+ KEY_FREESAV(&sav);
/* When there is SA. */
if (isr->sav != NULL) {
@@ -1241,6 +1228,16 @@ key_freesp_so(struct secpolicy **sp)
KEY_FREESP(sp);
}
+void
+key_addrefsa(struct secasvar *sav, const char* where, int tag)
+{
+
+ IPSEC_ASSERT(sav != NULL, ("null sav"));
+ IPSEC_ASSERT(sav->refcnt > 0, ("refcount must exist"));
+
+ sa_addref(sav);
+}
+
/*
* Must be called after calling key_allocsa().
* This function is called by key_freesp() to free some SA allocated
@@ -1768,6 +1765,7 @@ key_gather_mbuf(m, mhp, ndeep, nitem, va_alist)
fail:
m_freem(result);
+ va_end(ap);
return NULL;
}
@@ -2297,6 +2295,7 @@ key_spdget(so, m, mhp)
}
n = key_setdumpsp(sp, SADB_X_SPDGET, 0, mhp->msg->sadb_msg_pid);
+ KEY_FREESP(&sp);
if (n != NULL) {
m_freem(m);
return key_sendup_mbuf(so, n, KEY_SENDUP_ONE);
@@ -2870,9 +2869,10 @@ key_newsav(m, mhp, sah, errp, where, tag)
sa_initref(newsav);
newsav->state = SADB_SASTATE_LARVAL;
- /* XXX locking??? */
+ SAHTREE_LOCK();
LIST_INSERT_TAIL(&sah->savtree[SADB_SASTATE_LARVAL], newsav,
secasvar, chain);
+ SAHTREE_UNLOCK();
done:
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
printf("DP %s from %s:%u return SP:%p\n", __func__,
@@ -5716,8 +5716,8 @@ key_delete(so, m, mhp)
}
key_sa_chgstate(sav, SADB_SASTATE_DEAD);
- SAHTREE_UNLOCK();
KEY_FREESAV(&sav);
+ SAHTREE_UNLOCK();
{
struct mbuf *n;
@@ -6105,6 +6105,9 @@ key_getsizes_ah(
case SADB_X_AALG_MD5: *min = *max = 16; break;
case SADB_X_AALG_SHA: *min = *max = 20; break;
case SADB_X_AALG_NULL: *min = 1; *max = 256; break;
+ case SADB_X_AALG_SHA2_256: *min = *max = 32; break;
+ case SADB_X_AALG_SHA2_384: *min = *max = 48; break;
+ case SADB_X_AALG_SHA2_512: *min = *max = 64; break;
default:
DPRINTF(("%s: unknown AH algorithm %u\n",
__func__, alg));
@@ -6130,7 +6133,11 @@ key_getcomb_ah()
for (i = 1; i <= SADB_AALG_MAX; i++) {
#if 1
/* we prefer HMAC algorithms, not old algorithms */
- if (i != SADB_AALG_SHA1HMAC && i != SADB_AALG_MD5HMAC)
+ if (i != SADB_AALG_SHA1HMAC &&
+ i != SADB_AALG_MD5HMAC &&
+ i != SADB_X_AALG_SHA2_256 &&
+ i != SADB_X_AALG_SHA2_384 &&
+ i != SADB_X_AALG_SHA2_512)
continue;
#endif
algo = ah_algorithm_lookup(i);