Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 29 Nov 2009 10:53:34 +0000 (UTC)
From:      "Bjoern A. Zeeb" <bz@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r199899 - head/sys/netipsec
Message-ID:  <200911291053.nATArYrV086240@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200911291053.nATArYrV086240>