Update to FreeBSD 8.4

This commit is contained in:
Sebastian Huber
2013-11-04 11:33:00 +01:00
parent 6779ce55bc
commit af5333e0a0
486 changed files with 66546 additions and 41281 deletions

View File

@@ -123,7 +123,7 @@ struct ipsecrequest {
struct secasvar *sav; /* place holder of SA for use */
struct secpolicy *sp; /* back pointer to SP */
struct mtx lock; /* to interlock updates */
struct rwlock lock; /* to interlock updates */
};
/*
@@ -132,11 +132,15 @@ struct ipsecrequest {
* hard it is to remove this...
*/
#define IPSECREQUEST_LOCK_INIT(_isr) \
mtx_init(&(_isr)->lock, "ipsec request", NULL, MTX_DEF | MTX_RECURSE)
#define IPSECREQUEST_LOCK(_isr) mtx_lock(&(_isr)->lock)
#define IPSECREQUEST_UNLOCK(_isr) mtx_unlock(&(_isr)->lock)
#define IPSECREQUEST_LOCK_DESTROY(_isr) mtx_destroy(&(_isr)->lock)
#define IPSECREQUEST_LOCK_ASSERT(_isr) mtx_assert(&(_isr)->lock, MA_OWNED)
rw_init_flags(&(_isr)->lock, "ipsec request", RW_RECURSE)
#define IPSECREQUEST_LOCK(_isr) rw_rlock(&(_isr)->lock)
#define IPSECREQUEST_UNLOCK(_isr) rw_runlock(&(_isr)->lock)
#define IPSECREQUEST_WLOCK(_isr) rw_wlock(&(_isr)->lock)
#define IPSECREQUEST_WUNLOCK(_isr) rw_wunlock(&(_isr)->lock)
#define IPSECREQUEST_UPGRADE(_isr) rw_try_upgrade(&(_isr)->lock)
#define IPSECREQUEST_DOWNGRADE(_isr) rw_downgrade(&(_isr)->lock)
#define IPSECREQUEST_LOCK_DESTROY(_isr) rw_destroy(&(_isr)->lock)
#define IPSECREQUEST_LOCK_ASSERT(_isr) rw_assert(&(_isr)->lock, RA_LOCKED)
/* security policy in PCB */
struct inpcbpolicy {

View File

@@ -249,7 +249,6 @@ ipsec_process_done(struct mbuf *m, struct ipsecrequest *isr)
panic("ipsec_process_done");
bad:
m_freem(m);
KEY_FREESAV(&sav);
return (error);
}
@@ -846,7 +845,7 @@ ipsec6_output_tunnel(struct ipsec_output_state *state, struct secpolicy *sp, int
dst6->sin6_family = AF_INET6;
dst6->sin6_len = sizeof(*dst6);
dst6->sin6_addr = ip6->ip6_dst;
rtalloc(state->ro);
rtalloc_ign_fib(state->ro, 0UL, M_GETFIB(m));
}
if (state->ro->ro_rt == NULL) {
V_ip6stat.ip6s_noroute++;

View File

@@ -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);

View File

@@ -76,10 +76,13 @@ extern void _key_freesp(struct secpolicy **, const char*, int);
extern struct secasvar *key_allocsa(union sockaddr_union *, u_int, u_int32_t,
const char*, int);
extern void key_addrefsa(struct secasvar *, const char*, int);
extern void key_freesav(struct secasvar **, const char*, int);
#define KEY_ALLOCSA(dst, proto, spi) \
key_allocsa(dst, proto, spi, __FILE__, __LINE__)
#define KEY_ADDREFSA(sav) \
key_addrefsa(sav, __FILE__, __LINE__)
#define KEY_FREESAV(psav) \
key_freesav(psav, __FILE__, __LINE__)

View File

@@ -46,6 +46,7 @@
#include <opencrypto/xform.h>
#define AH_HMAC_HASHLEN 12 /* 96 bits of authenticator */
#define AH_HMAC_MAXHASHLEN (SHA2_512_HASH_LEN/2) /* Keep this updated */
#define AH_HMAC_INITIAL_RPL 1 /* replay counter initial value */
/*
@@ -74,6 +75,7 @@ struct tdb_crypto {
int tc_protoff; /* current protocol offset */
int tc_skip; /* data offset */
caddr_t tc_ptr; /* associated crypto data */
struct secasvar *tc_sav; /* related SA */
};
struct secasvar;

View File

@@ -87,8 +87,7 @@
* to use a fixed 16-byte authenticator. The new algorithm use 12-byte
* authenticator.
*/
#define AUTHSIZE(sav) \
((sav->flags & SADB_X_EXT_OLD) ? 16 : AH_HMAC_HASHLEN)
#define AUTHSIZE(sav) ah_authsize(sav)
VNET_DEFINE(int, ah_enable) = 1; /* control flow of packets with AH */
VNET_DEFINE(int, ah_cleartos) = 1; /* clear ip_tos when doing AH calc */
@@ -107,6 +106,27 @@ static unsigned char ipseczeroes[256]; /* larger than an ip6 extension hdr */
static int ah_input_cb(struct cryptop*);
static int ah_output_cb(struct cryptop*);
static int
ah_authsize(struct secasvar *sav)
{
IPSEC_ASSERT(sav != NULL, ("%s: sav == NULL", __func__));
if (sav->flags & SADB_X_EXT_OLD)
return 16;
switch (sav->alg_auth) {
case SADB_X_AALG_SHA2_256:
return 16;
case SADB_X_AALG_SHA2_384:
return 24;
case SADB_X_AALG_SHA2_512:
return 32;
default:
return AH_HMAC_HASHLEN;
}
/* NOTREACHED */
}
/*
* NB: this is public for use by the PF_KEY support.
*/
@@ -697,6 +717,8 @@ ah_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
tc->tc_protoff = protoff;
tc->tc_skip = skip;
tc->tc_ptr = (caddr_t) mtag; /* Save the mtag we've identified. */
KEY_ADDREFSA(sav);
tc->tc_sav = sav;
if (mtag == NULL)
return crypto_dispatch(crp);
@@ -746,13 +768,8 @@ ah_input_cb(struct cryptop *crp)
mtag = (struct m_tag *) tc->tc_ptr;
m = (struct mbuf *) crp->crp_buf;
sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi);
if (sav == NULL) {
V_ahstat.ahs_notdb++;
DPRINTF(("%s: SA expired while in crypto\n", __func__));
error = ENOBUFS; /*XXX*/
goto bad;
}
sav = tc->tc_sav;
IPSEC_ASSERT(sav != NULL, ("null SA!"));
saidx = &sav->sah->saidx;
IPSEC_ASSERT(saidx->dst.sa.sa_family == AF_INET ||
@@ -1092,6 +1109,8 @@ ah_output(
/* These are passed as-is to the callback. */
tc->tc_isr = isr;
KEY_ADDREFSA(sav);
tc->tc_sav = sav;
tc->tc_spi = sav->spi;
tc->tc_dst = sav->sah->saidx.dst;
tc->tc_proto = sav->sah->saidx.proto;
@@ -1128,14 +1147,14 @@ ah_output_cb(struct cryptop *crp)
isr = tc->tc_isr;
IPSECREQUEST_LOCK(isr);
sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi);
if (sav == NULL) {
sav = tc->tc_sav;
/* With the isr lock released SA pointer can be updated. */
if (sav != isr->sav) {
V_ahstat.ahs_notdb++;
DPRINTF(("%s: SA expired while in crypto\n", __func__));
error = ENOBUFS; /*XXX*/
goto bad;
}
IPSEC_ASSERT(isr->sav == sav, ("SA changed\n"));
/* Check for crypto errors. */
if (crp->crp_etype) {
@@ -1143,7 +1162,6 @@ ah_output_cb(struct cryptop *crp)
sav->tdb_cryptoid = crp->crp_sid;
if (crp->crp_etype == EAGAIN) {
KEY_FREESAV(&sav);
IPSECREQUEST_UNLOCK(isr);
error = crypto_dispatch(crp);
return error;

View File

@@ -299,7 +299,19 @@ esp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
else
hlen = sizeof (struct newesp) + sav->ivlen;
/* Authenticator hash size */
alen = esph ? AH_HMAC_HASHLEN : 0;
if (esph != NULL) {
switch (esph->type) {
case CRYPTO_SHA2_256_HMAC:
case CRYPTO_SHA2_384_HMAC:
case CRYPTO_SHA2_512_HMAC:
alen = esph->hashsize/2;
break;
default:
alen = AH_HMAC_HASHLEN;
break;
}
}else
alen = 0;
/*
* Verify payload length is multiple of encryption algorithm
@@ -413,6 +425,8 @@ esp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
tc->tc_proto = sav->sah->saidx.proto;
tc->tc_protoff = protoff;
tc->tc_skip = skip;
KEY_ADDREFSA(sav);
tc->tc_sav = sav;
/* Decryption descriptor */
if (espx) {
@@ -452,8 +466,8 @@ esp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
static int
esp_input_cb(struct cryptop *crp)
{
u_int8_t lastthree[3], aalg[AH_HMAC_HASHLEN];
int hlen, skip, protoff, error;
u_int8_t lastthree[3], aalg[AH_HMAC_MAXHASHLEN];
int hlen, skip, protoff, error, alen;
struct mbuf *m;
struct cryptodesc *crd;
struct auth_hash *esph;
@@ -474,15 +488,8 @@ esp_input_cb(struct cryptop *crp)
mtag = (struct m_tag *) tc->tc_ptr;
m = (struct mbuf *) crp->crp_buf;
sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi);
if (sav == NULL) {
V_espstat.esps_notdb++;
DPRINTF(("%s: SA gone during crypto (SA %s/%08lx proto %u)\n",
__func__, ipsec_address(&tc->tc_dst),
(u_long) ntohl(tc->tc_spi), tc->tc_proto));
error = ENOBUFS; /*XXX*/
goto bad;
}
sav = tc->tc_sav;
IPSEC_ASSERT(sav != NULL, ("null SA!"));
saidx = &sav->sah->saidx;
IPSEC_ASSERT(saidx->dst.sa.sa_family == AF_INET ||
@@ -499,7 +506,6 @@ esp_input_cb(struct cryptop *crp)
sav->tdb_cryptoid = crp->crp_sid;
if (crp->crp_etype == EAGAIN) {
KEY_FREESAV(&sav);
error = crypto_dispatch(crp);
return error;
}
@@ -521,6 +527,16 @@ esp_input_cb(struct cryptop *crp)
/* If authentication was performed, check now. */
if (esph != NULL) {
switch (esph->type) {
case CRYPTO_SHA2_256_HMAC:
case CRYPTO_SHA2_384_HMAC:
case CRYPTO_SHA2_512_HMAC:
alen = esph->hashsize/2;
break;
default:
alen = AH_HMAC_HASHLEN;
break;
}
/*
* If we have a tag, it means an IPsec-aware NIC did
* the verification for us. Otherwise we need to
@@ -529,13 +545,13 @@ esp_input_cb(struct cryptop *crp)
V_ahstat.ahs_hist[sav->alg_auth]++;
if (mtag == NULL) {
/* Copy the authenticator from the packet */
m_copydata(m, m->m_pkthdr.len - AH_HMAC_HASHLEN,
AH_HMAC_HASHLEN, aalg);
m_copydata(m, m->m_pkthdr.len - alen,
alen, aalg);
ptr = (caddr_t) (tc + 1);
/* Verify authenticator */
if (bcmp(ptr, aalg, AH_HMAC_HASHLEN) != 0) {
if (bcmp(ptr, aalg, alen) != 0) {
DPRINTF(("%s: "
"authentication hash mismatch for packet in SA %s/%08lx\n",
__func__,
@@ -548,7 +564,7 @@ esp_input_cb(struct cryptop *crp)
}
/* Remove trailing authenticator */
m_adj(m, -AH_HMAC_HASHLEN);
m_adj(m, -alen);
}
/* Release the crypto descriptors */
@@ -692,7 +708,16 @@ esp_output(
plen = rlen + padding; /* Padded payload length. */
if (esph)
switch (esph->type) {
case CRYPTO_SHA2_256_HMAC:
case CRYPTO_SHA2_384_HMAC:
case CRYPTO_SHA2_512_HMAC:
alen = esph->hashsize/2;
break;
default:
alen = AH_HMAC_HASHLEN;
break;
}
else
alen = 0;
@@ -848,6 +873,8 @@ esp_output(
/* Callback parameters */
tc->tc_isr = isr;
KEY_ADDREFSA(sav);
tc->tc_sav = sav;
tc->tc_spi = sav->spi;
tc->tc_dst = saidx->dst;
tc->tc_proto = saidx->proto;
@@ -897,8 +924,9 @@ esp_output_cb(struct cryptop *crp)
isr = tc->tc_isr;
IPSECREQUEST_LOCK(isr);
sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi);
if (sav == NULL) {
sav = tc->tc_sav;
/* With the isr lock released SA pointer can be updated. */
if (sav != isr->sav) {
V_espstat.esps_notdb++;
DPRINTF(("%s: SA gone during crypto (SA %s/%08lx proto %u)\n",
__func__, ipsec_address(&tc->tc_dst),
@@ -906,8 +934,6 @@ esp_output_cb(struct cryptop *crp)
error = ENOBUFS; /*XXX*/
goto bad;
}
IPSEC_ASSERT(isr->sav == sav,
("SA changed was %p now %p\n", isr->sav, sav));
/* Check for crypto errors. */
if (crp->crp_etype) {
@@ -916,7 +942,6 @@ esp_output_cb(struct cryptop *crp)
sav->tdb_cryptoid = crp->crp_sid;
if (crp->crp_etype == EAGAIN) {
KEY_FREESAV(&sav);
IPSECREQUEST_UNLOCK(isr);
error = crypto_dispatch(crp);
return error;
@@ -946,7 +971,7 @@ esp_output_cb(struct cryptop *crp)
#ifdef REGRESSION
/* Emulate man-in-the-middle attack when ipsec_integrity is TRUE. */
if (V_ipsec_integrity) {
static unsigned char ipseczeroes[AH_HMAC_HASHLEN];
static unsigned char ipseczeroes[AH_HMAC_MAXHASHLEN];
struct auth_hash *esph;
/*
@@ -955,8 +980,20 @@ esp_output_cb(struct cryptop *crp)
*/
esph = sav->tdb_authalgxform;
if (esph != NULL) {
m_copyback(m, m->m_pkthdr.len - AH_HMAC_HASHLEN,
AH_HMAC_HASHLEN, ipseczeroes);
int alen;
switch (esph->type) {
case CRYPTO_SHA2_256_HMAC:
case CRYPTO_SHA2_384_HMAC:
case CRYPTO_SHA2_512_HMAC:
alen = esph->hashsize/2;
break;
default:
alen = AH_HMAC_HASHLEN;
break;
}
m_copyback(m, m->m_pkthdr.len - alen,
alen, ipseczeroes);
}
}
#endif

View File

@@ -39,6 +39,7 @@
#include <sys/mbuf.h>
#include <rtems/bsd/sys/lock.h>
#include <sys/mutex.h>
#include <sys/rwlock.h>
#include <sys/socket.h>
#include <sys/kernel.h>
#include <sys/protosw.h>
@@ -143,8 +144,29 @@ ipcomp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
struct tdb_crypto *tc;
struct cryptodesc *crdc;
struct cryptop *crp;
struct ipcomp *ipcomp;
caddr_t addr;
int hlen = IPCOMP_HLENGTH;
/*
* Check that the next header of the IPComp is not IPComp again, before
* doing any real work. Given it is not possible to do double
* compression it means someone is playing tricks on us.
*/
if (m->m_len < skip + hlen && (m = m_pullup(m, skip + hlen)) == NULL) {
V_ipcompstat.ipcomps_hdrops++; /*XXX*/
DPRINTF(("%s: m_pullup failed\n", __func__));
return (ENOBUFS);
}
addr = (caddr_t) mtod(m, struct ip *) + skip;
ipcomp = (struct ipcomp *)addr;
if (ipcomp->comp_nxt == IPPROTO_IPCOMP) {
m_freem(m);
V_ipcompstat.ipcomps_pdrops++; /* XXX have our own stats? */
DPRINTF(("%s: recursive compression detected\n", __func__));
return (EINVAL);
}
/* Get crypto descriptors */
crp = crypto_getreq(1);
if (crp == NULL) {
@@ -187,6 +209,8 @@ ipcomp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
tc->tc_proto = sav->sah->saidx.proto;
tc->tc_protoff = protoff;
tc->tc_skip = skip;
KEY_ADDREFSA(sav);
tc->tc_sav = sav;
return crypto_dispatch(crp);
}
@@ -230,13 +254,8 @@ ipcomp_input_cb(struct cryptop *crp)
mtag = (struct mtag *) tc->tc_ptr;
m = (struct mbuf *) crp->crp_buf;
sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi);
if (sav == NULL) {
V_ipcompstat.ipcomps_notdb++;
DPRINTF(("%s: SA expired while in crypto\n", __func__));
error = ENOBUFS; /*XXX*/
goto bad;
}
sav = tc->tc_sav;
IPSEC_ASSERT(sav != NULL, ("null SA!"));
saidx = &sav->sah->saidx;
IPSEC_ASSERT(saidx->dst.sa.sa_family == AF_INET ||
@@ -250,7 +269,6 @@ ipcomp_input_cb(struct cryptop *crp)
sav->tdb_cryptoid = crp->crp_sid;
if (crp->crp_etype == EAGAIN) {
KEY_FREESAV(&sav);
return crypto_dispatch(crp);
}
V_ipcompstat.ipcomps_noxform++;
@@ -433,6 +451,8 @@ ipcomp_output(
}
tc->tc_isr = isr;
KEY_ADDREFSA(sav);
tc->tc_sav = sav;
tc->tc_spi = sav->spi;
tc->tc_dst = sav->sah->saidx.dst;
tc->tc_proto = sav->sah->saidx.proto;
@@ -473,14 +493,14 @@ ipcomp_output_cb(struct cryptop *crp)
isr = tc->tc_isr;
IPSECREQUEST_LOCK(isr);
sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi);
if (sav == NULL) {
sav = tc->tc_sav;
/* With the isr lock released SA pointer can be updated. */
if (sav != isr->sav) {
V_ipcompstat.ipcomps_notdb++;
DPRINTF(("%s: SA expired while in crypto\n", __func__));
error = ENOBUFS; /*XXX*/
goto bad;
}
IPSEC_ASSERT(isr->sav == sav, ("SA changed\n"));
/* Check for crypto errors */
if (crp->crp_etype) {
@@ -489,7 +509,6 @@ ipcomp_output_cb(struct cryptop *crp)
sav->tdb_cryptoid = crp->crp_sid;
if (crp->crp_etype == EAGAIN) {
KEY_FREESAV(&sav);
IPSECREQUEST_UNLOCK(isr);
return crypto_dispatch(crp);
}