diff options
Diffstat (limited to 'sys/netipsec/xform_ipcomp.c')
-rw-r--r-- | sys/netipsec/xform_ipcomp.c | 104 |
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 */ |