From owner-svn-src-head@FreeBSD.ORG Sun Nov 29 10:53:34 2009 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 9CC85106566B; Sun, 29 Nov 2009 10:53:34 +0000 (UTC) (envelope-from bz@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 826048FC13; Sun, 29 Nov 2009 10:53:34 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id nATArYxE086241; Sun, 29 Nov 2009 10:53:34 GMT (envelope-from bz@svn.freebsd.org) Received: (from bz@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id nATArYrV086240; Sun, 29 Nov 2009 10:53:34 GMT (envelope-from bz@svn.freebsd.org) Message-Id: <200911291053.nATArYrV086240@svn.freebsd.org> From: "Bjoern A. Zeeb" Date: Sun, 29 Nov 2009 10:53:34 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r199899 - head/sys/netipsec X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 29 Nov 2009 10:53:34 -0000 Author: bz Date: Sun Nov 29 10:53:34 2009 New Revision: 199899 URL: http://svn.freebsd.org/changeset/base/199899 Log: 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 Modified: head/sys/netipsec/xform_ipcomp.c Modified: head/sys/netipsec/xform_ipcomp.c ============================================================================== --- head/sys/netipsec/xform_ipcomp.c Sat Nov 28 23:50:48 2009 (r199898) +++ head/sys/netipsec/xform_ipcomp.c Sun Nov 29 10:53:34 2009 (r199899) @@ -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 */