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>