svn commit: r281692 - in head/sys: conf netipsec

Andrey V. Elsukov ae at FreeBSD.org
Sat Apr 18 16:38:47 UTC 2015


Author: ae
Date: Sat Apr 18 16:38:45 2015
New Revision: 281692
URL: https://svnweb.freebsd.org/changeset/base/281692

Log:
  Remove xform_ipip.c and code related to XF_IP4.
  
  The only thing is used from this code is ipip_output() function, that does
  IPIP encapsulation. Other parts of XF_IP4 code were removed in r275133.
  Also it isn't possible to configure the use of XF_IP4, nor from userland
  via setkey(8), nor from the kernel.
  
  Simplify the ipip_output() function and rename it to ipsec_encap().
  * move IP_DF handling from ipsec4_process_packet() into ipsec_encap();
  * since ipsec_encap() called from ipsec[64]_process_packet(), it
    is safe to assume that mbuf is contiguous at least to IP header
    for used IP version. Remove all unneeded m_pullup(), m_copydata
    and related checks.
  * use V_ip_defttl and V_ip6_defhlim for outer headers;
  * use V_ip4_ipsec_ecn and V_ip6_ipsec_ecn for outer headers;
  * move all diagnostic messages to the ipsec_encap() callers;
  * simplify handling of ipsec_encap() results: if it returns non zero
    value, print diagnostic message and free mbuf.
  * some style(9) fixes.
  
  Differential Revision:	https://reviews.freebsd.org/D2303
  Reviewed by:	glebius
  Sponsored by:	Yandex LLC

Deleted:
  head/sys/netipsec/xform_ipip.c
Modified:
  head/sys/conf/files
  head/sys/netipsec/ipsec_output.c
  head/sys/netipsec/xform.h

Modified: head/sys/conf/files
==============================================================================
--- head/sys/conf/files	Sat Apr 18 16:08:06 2015	(r281691)
+++ head/sys/conf/files	Sat Apr 18 16:38:45 2015	(r281692)
@@ -3565,7 +3565,6 @@ netipsec/keysock.c		optional ipsec inet 
 netipsec/xform_ah.c		optional ipsec inet | ipsec inet6
 netipsec/xform_esp.c		optional ipsec inet | ipsec inet6
 netipsec/xform_ipcomp.c		optional ipsec inet | ipsec inet6
-netipsec/xform_ipip.c		optional ipsec inet | ipsec inet6
 netipsec/xform_tcp.c		optional ipsec inet tcp_signature | \
 					 ipsec inet6 tcp_signature
 netnatm/natm.c			optional natm

Modified: head/sys/netipsec/ipsec_output.c
==============================================================================
--- head/sys/netipsec/ipsec_output.c	Sat Apr 18 16:08:06 2015	(r281691)
+++ head/sys/netipsec/ipsec_output.c	Sat Apr 18 16:38:45 2015	(r281692)
@@ -61,6 +61,7 @@
 #include <netinet/ip6.h>
 #ifdef INET6
 #include <netinet6/ip6_var.h>
+#include <netinet6/scope6_var.h>
 #endif
 #include <netinet/in_pcb.h>
 #ifdef INET6
@@ -419,6 +420,101 @@ bad:
 #undef IPSEC_OSTAT
 }
 
+static int
+ipsec_encap(struct mbuf **mp, struct secasindex *saidx)
+{
+#ifdef INET6
+	struct ip6_hdr *ip6;
+#endif
+	struct ip *ip;
+	int setdf;
+	uint8_t itos, proto;
+
+	ip = mtod(*mp, struct ip *);
+	switch (ip->ip_v) {
+#ifdef INET
+	case IPVERSION:
+		proto = IPPROTO_IPIP;
+		/*
+		 * Collect IP_DF state from the inner header
+		 * and honor system-wide control of how to handle it.
+		 */
+		switch (V_ip4_ipsec_dfbit) {
+		case 0:	/* clear in outer header */
+		case 1:	/* set in outer header */
+			setdf = V_ip4_ipsec_dfbit;
+			break;
+		default:/* propagate to outer header */
+			setdf = (ip->ip_off & ntohs(IP_DF)) != 0;
+		}
+		itos = ip->ip_tos;
+		break;
+#endif
+#ifdef INET6
+	case (IPV6_VERSION >> 4):
+		proto = IPPROTO_IPV6;
+		ip6 = mtod(*mp, struct ip6_hdr *);
+		itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
+		setdf = V_ip4_ipsec_dfbit ? 1: 0;
+		/* scoped address handling */
+		in6_clearscope(&ip6->ip6_src);
+		in6_clearscope(&ip6->ip6_dst);
+		break;
+#endif
+	default:
+		return (EAFNOSUPPORT);
+	}
+	switch (saidx->dst.sa.sa_family) {
+#ifdef INET
+	case AF_INET:
+		if (saidx->src.sa.sa_family != AF_INET ||
+		    saidx->src.sin.sin_addr.s_addr == INADDR_ANY ||
+		    saidx->dst.sin.sin_addr.s_addr == INADDR_ANY)
+			return (EINVAL);
+		M_PREPEND(*mp, sizeof(struct ip), M_NOWAIT);
+		if (*mp == NULL)
+			return (ENOBUFS);
+		ip = mtod(*mp, struct ip *);
+		ip->ip_v = IPVERSION;
+		ip->ip_hl = sizeof(struct ip) >> 2;
+		ip->ip_p = proto;
+		ip->ip_len = htons((*mp)->m_pkthdr.len);
+		ip->ip_ttl = V_ip_defttl;
+		ip->ip_sum = 0;
+		ip->ip_off = setdf ? htons(IP_DF): 0;
+		ip->ip_src = saidx->src.sin.sin_addr;
+		ip->ip_dst = saidx->dst.sin.sin_addr;
+		ip_ecn_ingress(V_ip4_ipsec_ecn, &ip->ip_tos, &itos);
+		ip_fillid(ip);
+		break;
+#endif /* INET */
+#ifdef INET6
+	case AF_INET6:
+		if (saidx->src.sa.sa_family != AF_INET6 ||
+		    IN6_IS_ADDR_UNSPECIFIED(&saidx->src.sin6.sin6_addr) ||
+		    IN6_IS_ADDR_UNSPECIFIED(&saidx->dst.sin6.sin6_addr))
+			return (EINVAL);
+		M_PREPEND(*mp, sizeof(struct ip6_hdr), M_NOWAIT);
+		if (*mp == NULL)
+			return (ENOBUFS);
+		ip6 = mtod(*mp, struct ip6_hdr *);
+		ip6->ip6_flow = 0;
+		ip6->ip6_vfc = IPV6_VERSION;
+		ip6->ip6_hlim = V_ip6_defhlim;
+		ip6->ip6_nxt = proto;
+		ip6->ip6_dst = saidx->dst.sin6.sin6_addr;
+		ip6->ip6_src = saidx->src.sin6.sin6_addr;
+		ip6->ip6_plen = htons((*mp)->m_pkthdr.len - sizeof(*ip6));
+		ip_ecn_ingress(V_ip6_ipsec_ecn, &proto, &itos);
+		ip6->ip6_flow |= htonl((uint32_t)proto << 20);
+		break;
+#endif /* INET6 */
+	default:
+		return (EAFNOSUPPORT);
+	}
+	return (0);
+}
+
 #ifdef INET
 /*
  * IPsec output logic for IPv4.
@@ -430,7 +526,7 @@ ipsec4_process_packet(struct mbuf *m, st
 	struct secasindex saidx;
 	struct secasvar *sav;
 	struct ip *ip;
-	int error, i, off, setdf;
+	int error, i, off;
 
 	IPSEC_ASSERT(m != NULL, ("null mbuf"));
 	IPSEC_ASSERT(isr != NULL, ("null isr"));
@@ -465,53 +561,23 @@ ipsec4_process_packet(struct mbuf *m, st
 	/* Do the appropriate encapsulation, if necessary */
 	if (isr->saidx.mode == IPSEC_MODE_TUNNEL || /* Tunnel requ'd */
 	    dst->sa.sa_family != AF_INET ||	    /* PF mismatch */
-#if 0
-		    (sav->flags & SADB_X_SAFLAGS_TUNNEL) || /* Tunnel requ'd */
-		    sav->tdb_xform->xf_type == XF_IP4 ||    /* ditto */
-#endif
 	    (dst->sa.sa_family == AF_INET &&	    /* Proxy */
 	     dst->sin.sin_addr.s_addr != INADDR_ANY &&
 	     dst->sin.sin_addr.s_addr != ip->ip_dst.s_addr)) {
-		struct mbuf *mp;
-
 		/* Fix IPv4 header checksum and length */
 		ip->ip_len = htons(m->m_pkthdr.len);
 		ip->ip_sum = 0;
 		ip->ip_sum = in_cksum(m, ip->ip_hl << 2);
-		/*
-		 * Collect IP_DF state from the outer header
-		 * and honor system-wide control of how to handle it.
-		 */
-		switch (V_ip4_ipsec_dfbit) {
-		case 0:			/* clear in outer header */
-		case 1:			/* set in outer header */
-			setdf = V_ip4_ipsec_dfbit;
-			break;
-		default:		/* propagate to outer header */
-			setdf = ntohs(ip->ip_off & IP_DF);
-		}
-		/* Encapsulate the packet */
-		error = ipip_output(m, isr, &mp, 0, 0);
+		error = ipsec_encap(&m, &sav->sah->saidx);
 		if (error != 0) {
-			m = NULL; /* ipip_output() already freed it */
+			DPRINTF(("%s: encapsulation for SA %s->%s "
+			    "SPI 0x%08x failed with error %d\n", __func__,
+			    ipsec_address(&sav->sah->saidx.src),
+			    ipsec_address(&sav->sah->saidx.dst),
+			    ntohl(sav->spi), error));
 			goto bad;
 		}
-		m = mp;
-		/*
-		 * ipip_output clears IP_DF in the new header.  If
-		 * we need to propagate IP_DF from the outer header,
-		 * then we have to do it here.
-		 *
-		 * XXX shouldn't assume what ipip_output does.
-		 */
-		if (dst->sa.sa_family == AF_INET && setdf) {
-			ip = mtod(m, struct ip *);
-			ip->ip_off = ntohs(ip->ip_off);
-			ip->ip_off |= IP_DF;
-			ip->ip_off = htons(ip->ip_off);
-		}
 	}
-
 #ifdef DEV_ENC
 	/* pass the mbuf to enc0 for bpf processing */
 	ipsec_bpf(m, sav, sav->sah->saidx.dst.sa.sa_family, ENC_OUT|ENC_AFTER);
@@ -523,40 +589,33 @@ ipsec4_process_packet(struct mbuf *m, st
 	/*
 	 * Dispatch to the appropriate IPsec transform logic.  The
 	 * packet will be returned for transmission after crypto
-	 * processing, etc. are completed.  For encapsulation we
-	 * bypass this call because of the explicit call done above
-	 * (necessary to deal with IP_DF handling for IPv4).
+	 * processing, etc. are completed.
 	 *
 	 * NB: m & sav are ``passed to caller'' who's reponsible for
 	 *     for reclaiming their resources.
 	 */
-	if (sav->tdb_xform->xf_type != XF_IP4) {
-		union sockaddr_union *dst = &sav->sah->saidx.dst;
-		switch(dst->sa.sa_family) {
-		case AF_INET:
-			ip = mtod(m, struct ip *);
-			i = ip->ip_hl << 2;
-			off = offsetof(struct ip, ip_p);
-			break;
+	switch(dst->sa.sa_family) {
+	case AF_INET:
+		ip = mtod(m, struct ip *);
+		i = ip->ip_hl << 2;
+		off = offsetof(struct ip, ip_p);
+		break;
 #ifdef INET6
-		case AF_INET6:
-			i = sizeof(struct ip6_hdr);
-			off = offsetof(struct ip6_hdr, ip6_nxt);
-			break;
+	case AF_INET6:
+		i = sizeof(struct ip6_hdr);
+		off = offsetof(struct ip6_hdr, ip6_nxt);
+		break;
 #endif /* INET6 */
-		default:
+	default:
 		DPRINTF(("%s: unsupported protocol family %u\n",
-				 __func__, dst->sa.sa_family));
-			error = EPFNOSUPPORT;
-			IPSECSTAT_INC(ips_out_inval);
-			goto bad;
-		}
-		error = (*sav->tdb_xform->xf_output)(m, isr, NULL, i, off);
-	} else {
-		error = ipsec_process_done(m, isr);
+		    __func__, dst->sa.sa_family));
+		error = EPFNOSUPPORT;
+		IPSECSTAT_INC(ips_out_inval);
+		goto bad;
 	}
+	error = (*sav->tdb_xform->xf_output)(m, isr, NULL, i, off);
 	IPSECREQUEST_UNLOCK(isr);
-	return error;
+	return (error);
 bad:
 	if (isr)
 		IPSECREQUEST_UNLOCK(isr);
@@ -606,7 +665,6 @@ ipsec6_process_packet(
 			goto bad;
 		return EJUSTRETURN;
 	}
-
 	sav = isr->sav;
 	dst = &sav->sah->saidx.dst;
 
@@ -630,42 +688,20 @@ ipsec6_process_packet(
 	     (!IN6_IS_ADDR_UNSPECIFIED(&dst->sin6.sin6_addr)) &&
 	     (!in6_sa_equal_addrwithscope(&dst->sin6,
 				  &ip6->ip6_dst)))) {
-		struct mbuf *mp;
-
-		/* Fix IPv6 header payload length. */
-		if (m->m_len < sizeof(struct ip6_hdr))
-			if ((m = m_pullup(m,sizeof(struct ip6_hdr))) == NULL) {
-				error = ENOBUFS;
-				goto bad;
-			}
-
 		if (m->m_pkthdr.len - sizeof(*ip6) > IPV6_MAXPACKET) {
 			/* No jumbogram support. */
 			error = ENXIO;   /*XXX*/
 			goto bad;
 		}
-
-		/* Encapsulate the packet */
-		error = ipip_output(m, isr, &mp, 0, 0);
-		if (mp == NULL && !error) {
-			/* Should never happen. */
-			DPRINTF(("ipsec6_process_packet: ipip_output "
-				 "returns no mbuf and no error!"));
-			error = EFAULT;
-			goto bad;
-		}
-
-		if (error) {
-			if (mp) {
-				/* XXX: Should never happen! */
-				m_freem(mp);
-			}
-			m = NULL; /* ipip_output() already freed it */
+		error = ipsec_encap(&m, &sav->sah->saidx);
+		if (error != 0) {
+			DPRINTF(("%s: encapsulation for SA %s->%s "
+			    "SPI 0x%08x failed with error %d\n", __func__,
+			    ipsec_address(&sav->sah->saidx.src),
+			    ipsec_address(&sav->sah->saidx.dst),
+			    ntohl(sav->spi), error));
 			goto bad;
 		}
-
-		m = mp;
-		mp = NULL;
 	}
 
 #ifdef DEV_ENC

Modified: head/sys/netipsec/xform.h
==============================================================================
--- head/sys/netipsec/xform.h	Sat Apr 18 16:08:06 2015	(r281691)
+++ head/sys/netipsec/xform.h	Sat Apr 18 16:38:45 2015	(r281692)
@@ -83,7 +83,7 @@ struct ipescrequest;
 
 struct xformsw {
 	u_short	xf_type;		/* xform ID */
-#define	XF_IP4		1	/* IP inside IP */
+#define	XF_IP4		1	/* unused */
 #define	XF_AH		2	/* AH */
 #define	XF_ESP		3	/* ESP */
 #define	XF_TCPSIGNATURE	5	/* TCP MD5 Signature option, RFC 2358 */
@@ -108,10 +108,6 @@ extern int xform_init(struct secasvar *s
 
 struct cryptoini;
 
-/* XF_IP4 */
-extern	int ipip_output(struct mbuf *, struct ipsecrequest *,
-			struct mbuf **, int, int);
-
 /* XF_AH */
 extern int ah_init0(struct secasvar *, struct xformsw *, struct cryptoini *);
 extern int ah_zeroize(struct secasvar *sav);


More information about the svn-src-all mailing list