diff options
Diffstat (limited to 'freebsd/sys/netipsec/key.c')
-rw-r--r-- | freebsd/sys/netipsec/key.c | 73 |
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); |