summaryrefslogtreecommitdiffstats
path: root/sys/netipsec
diff options
context:
space:
mode:
authorbz <bz@FreeBSD.org>2009-12-05 19:07:28 +0000
committerbz <bz@FreeBSD.org>2009-12-05 19:07:28 +0000
commit811dd632335755ea78a26e8bb310b2a84878d195 (patch)
treece6b788fbd16192c9b12f29d07ec74bf598c20fc /sys/netipsec
parent5c6b0feb321bc57d06046cc48a3e343fc16b7c91 (diff)
downloadFreeBSD-src-811dd632335755ea78a26e8bb310b2a84878d195.zip
FreeBSD-src-811dd632335755ea78a26e8bb310b2a84878d195.tar.gz
MFC r199899:
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
Diffstat (limited to 'sys/netipsec')
-rw-r--r--sys/netipsec/xform_ipcomp.c104
1 files changed, 53 insertions, 51 deletions
diff --git a/sys/netipsec/xform_ipcomp.c b/sys/netipsec/xform_ipcomp.c
index 9b4e475..5a5f018 100644
--- a/sys/netipsec/xform_ipcomp.c
+++ b/sys/netipsec/xform_ipcomp.c
@@ -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 */
OpenPOWER on IntegriCloud