Only add the IPcomp header if crypto reported success and we have a lower

payload size.  Before we had always added the header, no matter if we
actually send out compressed data or not.

With this, after the opencrypto/deflate changes, IPcomp starts to work
apart from edge cases.  Leave it disabled by default until those are
fixed as well.

PR:		kern/123587
MFC after:	5 days
This commit is contained in:
Bjoern A. Zeeb 2009-11-29 10:53:34 +00:00
parent f14ad5fa40
commit afa47e51aa
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=199899

View File

@ -330,13 +330,10 @@ ipcomp_output(
{
struct secasvar *sav;
struct comp_algo *ipcompx;
int error, ralen, hlen, maxpacketsize, roff;
u_int8_t prot;
int error, ralen, maxpacketsize;
struct cryptodesc *crdc;
struct cryptop *crp;
struct tdb_crypto *tc;
struct mbuf *mo;
struct ipcomp *ipcomp;
sav = isr->sav;
IPSEC_ASSERT(sav != NULL, ("null SA"));
@ -355,8 +352,6 @@ ipcomp_output(
}
ralen = m->m_pkthdr.len - skip; /* Raw payload length before comp. */
hlen = IPCOMP_HLENGTH;
V_ipcompstat.ipcomps_output++;
/* Check for maximum packet size violations. */
@ -381,13 +376,13 @@ ipcomp_output(
error = EPFNOSUPPORT;
goto bad;
}
if (skip + hlen + ralen > maxpacketsize) {
if (ralen + skip + IPCOMP_HLENGTH > maxpacketsize) {
V_ipcompstat.ipcomps_toobig++;
DPRINTF(("%s: packet in IPCA %s/%08lx got too big "
"(len %u, max len %u)\n", __func__,
ipsec_address(&sav->sah->saidx.dst),
(u_long) ntohl(sav->spi),
skip + hlen + ralen, maxpacketsize));
ralen + skip + IPCOMP_HLENGTH, maxpacketsize));
error = EMSGSIZE;
goto bad;
}
@ -405,40 +400,7 @@ ipcomp_output(
goto bad;
}
/* Inject IPCOMP header */
mo = m_makespace(m, skip, hlen, &roff);
if (mo == NULL) {
V_ipcompstat.ipcomps_wrap++;
DPRINTF(("%s: IPCOMP header inject failed for IPCA %s/%08lx\n",
__func__, ipsec_address(&sav->sah->saidx.dst),
(u_long) ntohl(sav->spi)));
error = ENOBUFS;
goto bad;
}
ipcomp = (struct ipcomp *)(mtod(mo, caddr_t) + roff);
/* Initialize the IPCOMP header */
/* XXX alignment always correct? */
switch (sav->sah->saidx.dst.sa.sa_family) {
#ifdef INET
case AF_INET:
ipcomp->comp_nxt = mtod(m, struct ip *)->ip_p;
break;
#endif /* INET */
#ifdef INET6
case AF_INET6:
ipcomp->comp_nxt = mtod(m, struct ip6_hdr *)->ip6_nxt;
break;
#endif
}
ipcomp->comp_flags = 0;
ipcomp->comp_cpi = htons((u_int16_t) ntohl(sav->spi));
/* Fix Next Protocol in IPv4/IPv6 header */
prot = IPPROTO_IPCOMP;
m_copyback(m, protoff, sizeof(u_int8_t), (u_char *) &prot);
/* Ok now, we can pass to the crypto processing */
/* Ok now, we can pass to the crypto processing. */
/* Get crypto descriptors */
crp = crypto_getreq(1);
@ -451,10 +413,10 @@ ipcomp_output(
crdc = crp->crp_desc;
/* Compression descriptor */
crdc->crd_skip = skip + hlen;
crdc->crd_len = m->m_pkthdr.len - (skip + hlen);
crdc->crd_skip = skip;
crdc->crd_len = ralen;
crdc->crd_flags = CRD_F_COMP;
crdc->crd_inject = skip + hlen;
crdc->crd_inject = skip;
/* Compression operation */
crdc->crd_alg = ipcompx->type;
@ -474,7 +436,8 @@ ipcomp_output(
tc->tc_spi = sav->spi;
tc->tc_dst = sav->sah->saidx.dst;
tc->tc_proto = sav->sah->saidx.proto;
tc->tc_skip = skip + hlen;
tc->tc_protoff = protoff;
tc->tc_skip = skip;
/* Crypto operation descriptor */
crp->crp_ilen = m->m_pkthdr.len; /* Total input length */
@ -501,13 +464,12 @@ ipcomp_output_cb(struct cryptop *crp)
struct ipsecrequest *isr;
struct secasvar *sav;
struct mbuf *m;
int error, skip, rlen;
int error, skip;
tc = (struct tdb_crypto *) crp->crp_opaque;
IPSEC_ASSERT(tc != NULL, ("null opaque data area!"));
m = (struct mbuf *) crp->crp_buf;
skip = tc->tc_skip;
rlen = crp->crp_ilen - skip;
isr = tc->tc_isr;
IPSECREQUEST_LOCK(isr);
@ -529,8 +491,7 @@ ipcomp_output_cb(struct cryptop *crp)
if (crp->crp_etype == EAGAIN) {
KEY_FREESAV(&sav);
IPSECREQUEST_UNLOCK(isr);
error = crypto_dispatch(crp);
return error;
return crypto_dispatch(crp);
}
V_ipcompstat.ipcomps_noxform++;
DPRINTF(("%s: crypto error %d\n", __func__, crp->crp_etype));
@ -546,7 +507,46 @@ ipcomp_output_cb(struct cryptop *crp)
}
V_ipcompstat.ipcomps_hist[sav->alg_comp]++;
if (rlen > crp->crp_olen) {
if (crp->crp_ilen - skip > crp->crp_olen) {
struct mbuf *mo;
struct ipcomp *ipcomp;
int roff;
uint8_t prot;
/* Compression helped, inject IPCOMP header. */
mo = m_makespace(m, skip, IPCOMP_HLENGTH, &roff);
if (mo == NULL) {
V_ipcompstat.ipcomps_wrap++;
DPRINTF(("%s: IPCOMP header inject failed for IPCA %s/%08lx\n",
__func__, ipsec_address(&sav->sah->saidx.dst),
(u_long) ntohl(sav->spi)));
error = ENOBUFS;
goto bad;
}
ipcomp = (struct ipcomp *)(mtod(mo, caddr_t) + roff);
/* Initialize the IPCOMP header */
/* XXX alignment always correct? */
switch (sav->sah->saidx.dst.sa.sa_family) {
#ifdef INET
case AF_INET:
ipcomp->comp_nxt = mtod(m, struct ip *)->ip_p;
break;
#endif /* INET */
#ifdef INET6
case AF_INET6:
ipcomp->comp_nxt = mtod(m, struct ip6_hdr *)->ip6_nxt;
break;
#endif
}
ipcomp->comp_flags = 0;
ipcomp->comp_cpi = htons((u_int16_t) ntohl(sav->spi));
/* Fix Next Protocol in IPv4/IPv6 header */
prot = IPPROTO_IPCOMP;
m_copyback(m, tc->tc_protoff, sizeof(u_int8_t),
(u_char *)&prot);
/* Adjust the length in the IP header */
switch (sav->sah->saidx.dst.sa.sa_family) {
#ifdef INET
@ -573,6 +573,8 @@ ipcomp_output_cb(struct cryptop *crp)
} else {
/* compression was useless, we have lost time */
/* XXX add statistic */
/* XXX remember state to not compress the next couple
* of packets, RFC 3173, 2.2. Non-Expansion Policy */
}
/* Release the crypto descriptor */