Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 17 Mar 2009 20:59:45 +0000 (UTC)
From:      "Bjoern A. Zeeb" <bz@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org
Subject:   svn commit: r189938 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb netinet
Message-ID:  <200903172059.n2HKxjMf006194@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: bz
Date: Tue Mar 17 20:59:45 2009
New Revision: 189938
URL: http://svn.freebsd.org/changeset/base/189938

Log:
  MFC r183001:
    Implement IPv6 support for TCP MD5 Signature Option (RFC 2385)
    the same way it has been implemented for IPv4.

Modified:
  stable/7/sys/   (props changed)
  stable/7/sys/contrib/pf/   (props changed)
  stable/7/sys/dev/ath/ath_hal/   (props changed)
  stable/7/sys/dev/cxgb/   (props changed)
  stable/7/sys/netinet/tcp_output.c
  stable/7/sys/netinet/tcp_subr.c
  stable/7/sys/netinet/tcp_syncache.c

Modified: stable/7/sys/netinet/tcp_output.c
==============================================================================
--- stable/7/sys/netinet/tcp_output.c	Tue Mar 17 19:57:11 2009	(r189937)
+++ stable/7/sys/netinet/tcp_output.c	Tue Mar 17 20:59:45 2009	(r189938)
@@ -681,11 +681,7 @@ send:
 		}
 #ifdef TCP_SIGNATURE
 		/* TCP-MD5 (RFC2385). */
-#ifdef INET6
-		if (!isipv6 && (tp->t_flags & TF_SIGNATURE))
-#else
 		if (tp->t_flags & TF_SIGNATURE)
-#endif /* INET6 */
 			to.to_flags |= TOF_SIGNATURE;
 #endif /* TCP_SIGNATURE */
 
@@ -954,12 +950,9 @@ send:
 		tp->snd_up = tp->snd_una;		/* drag it along */
 
 #ifdef TCP_SIGNATURE
-#ifdef INET6
-	if (!isipv6)
-#endif
 	if (tp->t_flags & TF_SIGNATURE) {
 		int sigoff = to.to_signature - opt;
-		tcp_signature_compute(m, sizeof(struct ip), len, optlen,
+		tcp_signature_compute(m, 0, len, optlen,
 		    (u_char *)(th + 1) + sigoff, IPSEC_DIR_OUTBOUND);
 	}
 #endif

Modified: stable/7/sys/netinet/tcp_subr.c
==============================================================================
--- stable/7/sys/netinet/tcp_subr.c	Tue Mar 17 19:57:11 2009	(r189937)
+++ stable/7/sys/netinet/tcp_subr.c	Tue Mar 17 20:59:45 2009	(r189938)
@@ -102,6 +102,7 @@ __FBSDID("$FreeBSD$");
 #include <netipsec/ipsec6.h>
 #endif
 #include <netipsec/key.h>
+#include <sys/syslog.h>
 #endif /*IPSEC*/
 
 #include <machine/in_cksum.h>
@@ -1852,11 +1853,11 @@ tcp_signature_apply(void *fstate, void *
 }
 
 /*
- * Compute TCP-MD5 hash of a TCPv4 segment. (RFC2385)
+ * Compute TCP-MD5 hash of a TCP segment. (RFC2385)
  *
  * Parameters:
  * m		pointer to head of mbuf chain
- * off0		offset to TCP header within the mbuf chain
+ * _unused	
  * len		length of TCP segment data, excluding options
  * optlen	length of TCP segment options
  * buf		pointer to storage for computed MD5 digest
@@ -1866,9 +1867,6 @@ tcp_signature_apply(void *fstate, void *
  * When called from tcp_input(), we can be sure that th_sum has been
  * zeroed out and verified already.
  *
- * This function is for IPv4 use only. Calling this function with an
- * IPv6 packet in the mbuf chain will yield undefined results.
- *
  * Return 0 if successful, otherwise return -1.
  *
  * XXX The key is retrieved from the system's PF_KEY SADB, by keying a
@@ -1878,7 +1876,7 @@ tcp_signature_apply(void *fstate, void *
  * specify per-application flows but it is unstable.
  */
 int
-tcp_signature_compute(struct mbuf *m, int off0, int len, int optlen,
+tcp_signature_compute(struct mbuf *m, int _unused, int len, int optlen,
     u_char *buf, u_int direction)
 {
 	union sockaddr_union dst;
@@ -1889,34 +1887,62 @@ tcp_signature_compute(struct mbuf *m, in
 	struct ipovly *ipovly;
 	struct secasvar *sav;
 	struct tcphdr *th;
+#ifdef INET6
+	struct ip6_hdr *ip6;
+	struct in6_addr in6;
+	char ip6buf[INET6_ADDRSTRLEN];
+	uint32_t plen;
+	uint16_t nhdr;
+#endif
 	u_short savecsum;
 
 	KASSERT(m != NULL, ("NULL mbuf chain"));
 	KASSERT(buf != NULL, ("NULL signature pointer"));
 
 	/* Extract the destination from the IP header in the mbuf. */
-	ip = mtod(m, struct ip *);
 	bzero(&dst, sizeof(union sockaddr_union));
-	dst.sa.sa_len = sizeof(struct sockaddr_in);
-	dst.sa.sa_family = AF_INET;
-	dst.sin.sin_addr = (direction == IPSEC_DIR_INBOUND) ?
-	    ip->ip_src : ip->ip_dst;
+	ip = mtod(m, struct ip *);
+#ifdef INET6
+	ip6 = NULL;	/* Make the compiler happy. */
+#endif
+	switch (ip->ip_v) {
+	case IPVERSION:
+		dst.sa.sa_len = sizeof(struct sockaddr_in);
+		dst.sa.sa_family = AF_INET;
+		dst.sin.sin_addr = (direction == IPSEC_DIR_INBOUND) ?
+		    ip->ip_src : ip->ip_dst;
+		break;
+#ifdef INET6
+	case (IPV6_VERSION >> 4):
+		ip6 = mtod(m, struct ip6_hdr *);
+		dst.sa.sa_len = sizeof(struct sockaddr_in6);
+		dst.sa.sa_family = AF_INET6;
+		dst.sin6.sin6_addr = (direction == IPSEC_DIR_INBOUND) ?
+		    ip6->ip6_src : ip6->ip6_dst;
+		break;
+#endif
+	default:
+		return (EINVAL);
+		/* NOTREACHED */
+		break;
+	}
 
 	/* Look up an SADB entry which matches the address of the peer. */
 	sav = KEY_ALLOCSA(&dst, IPPROTO_TCP, htonl(TCP_SIG_SPI));
 	if (sav == NULL) {
-		printf("%s: SADB lookup failed for %s\n", __func__,
-		    inet_ntoa(dst.sin.sin_addr));
+		ipseclog((LOG_ERR, "%s: SADB lookup failed for %s\n", __func__,
+		    (ip->ip_v == IPVERSION) ? inet_ntoa(dst.sin.sin_addr) :
+#ifdef INET6
+			(ip->ip_v == (IPV6_VERSION >> 4)) ?
+			    ip6_sprintf(ip6buf, &dst.sin6.sin6_addr) :
+#endif
+			"(unsupported)"));
 		return (EINVAL);
 	}
 
 	MD5Init(&ctx);
-	ipovly = (struct ipovly *)ip;
-	th = (struct tcphdr *)((u_char *)ip + off0);
-	doff = off0 + sizeof(struct tcphdr) + optlen;
-
 	/*
-	 * Step 1: Update MD5 hash with IP pseudo-header.
+	 * Step 1: Update MD5 hash with IP(v6) pseudo-header.
 	 *
 	 * XXX The ippseudo header MUST be digested in network byte order,
 	 * or else we'll fail the regression test. Assume all fields we've
@@ -1924,12 +1950,55 @@ tcp_signature_compute(struct mbuf *m, in
 	 * XXX One cannot depend on ipovly->ih_len here. When called from
 	 * tcp_output(), the underlying ip_len member has not yet been set.
 	 */
-	ippseudo.ippseudo_src = ipovly->ih_src;
-	ippseudo.ippseudo_dst = ipovly->ih_dst;
-	ippseudo.ippseudo_pad = 0;
-	ippseudo.ippseudo_p = IPPROTO_TCP;
-	ippseudo.ippseudo_len = htons(len + sizeof(struct tcphdr) + optlen);
-	MD5Update(&ctx, (char *)&ippseudo, sizeof(struct ippseudo));
+	switch (ip->ip_v) {
+	case IPVERSION:
+		ipovly = (struct ipovly *)ip;
+		ippseudo.ippseudo_src = ipovly->ih_src;
+		ippseudo.ippseudo_dst = ipovly->ih_dst;
+		ippseudo.ippseudo_pad = 0;
+		ippseudo.ippseudo_p = IPPROTO_TCP;
+		ippseudo.ippseudo_len = htons(len + sizeof(struct tcphdr) +
+		    optlen);
+		MD5Update(&ctx, (char *)&ippseudo, sizeof(struct ippseudo));
+
+		th = (struct tcphdr *)((u_char *)ip + sizeof(struct ip));
+		doff = sizeof(struct ip) + sizeof(struct tcphdr) + optlen;
+		break;
+#ifdef INET6
+	/*
+	 * RFC 2385, 2.0  Proposal
+	 * For IPv6, the pseudo-header is as described in RFC 2460, namely the
+	 * 128-bit source IPv6 address, 128-bit destination IPv6 address, zero-
+	 * extended next header value (to form 32 bits), and 32-bit segment
+	 * length.
+	 * Note: Upper-Layer Packet Length comes before Next Header.
+	 */
+	case (IPV6_VERSION >> 4):
+		in6 = ip6->ip6_src;
+		in6_clearscope(&in6);
+		MD5Update(&ctx, (char *)&in6, sizeof(struct in6_addr));
+		in6 = ip6->ip6_dst;
+		in6_clearscope(&in6);
+		MD5Update(&ctx, (char *)&in6, sizeof(struct in6_addr));
+		plen = htonl(len + sizeof(struct tcphdr) + optlen);
+		MD5Update(&ctx, (char *)&plen, sizeof(uint32_t));
+		nhdr = 0;
+		MD5Update(&ctx, (char *)&nhdr, sizeof(uint8_t));
+		MD5Update(&ctx, (char *)&nhdr, sizeof(uint8_t));
+		MD5Update(&ctx, (char *)&nhdr, sizeof(uint8_t));
+		nhdr = IPPROTO_TCP;
+		MD5Update(&ctx, (char *)&nhdr, sizeof(uint8_t));
+
+		th = (struct tcphdr *)((u_char *)ip6 + sizeof(struct ip6_hdr));
+		doff = sizeof(struct ip6_hdr) + sizeof(struct tcphdr) + optlen;
+		break;
+#endif
+	default:
+		return (EINVAL);
+		/* NOTREACHED */
+		break;
+	}
+
 
 	/*
 	 * Step 2: Update MD5 hash with TCP header, excluding options.

Modified: stable/7/sys/netinet/tcp_syncache.c
==============================================================================
--- stable/7/sys/netinet/tcp_syncache.c	Tue Mar 17 19:57:11 2009	(r189937)
+++ stable/7/sys/netinet/tcp_syncache.c	Tue Mar 17 20:59:45 2009	(r189938)
@@ -1425,7 +1425,7 @@ syncache_respond(struct syncache *sc)
 
 #ifdef TCP_SIGNATURE
 		if (sc->sc_flags & SCF_SIGNATURE)
-			tcp_signature_compute(m, sizeof(struct ip), 0, optlen,
+			tcp_signature_compute(m, 0, 0, optlen,
 			    to.to_signature, IPSEC_DIR_OUTBOUND);
 #endif
 #ifdef INET6



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