0002-Implement-IPv6-support-for-TCP-MD5-Signature-Option-.patch

david, 09/03/2010 07:19 PM

Download (8.02 KB)

View differences:

sys/netinet/tcp_output.c
602 602
		tcp_sack_fill_report(tp, opt, &optlen);
603 603

  
604 604
#ifdef TCP_SIGNATURE
605
	if (!isipv6)
606
		if (tp->t_flags & TF_SIGNATURE) {
607
			int i;
608
			u_char *bp;
609
			/*
610
			 * Initialize TCP-MD5 option (RFC2385)
611
			 */
612
			bp = (u_char *)opt + optlen;
613
			*bp++ = TCPOPT_SIGNATURE;
614
			*bp++ = TCPOLEN_SIGNATURE;
615
			sigoff = optlen + 2;
616
			for (i = 0; i < TCP_SIGLEN; i++)
617
				*bp++ = 0;
618
			optlen += TCPOLEN_SIGNATURE;
619
			/*
620
			 * Terminate options list and maintain 32-bit alignment.
621
			 */
622
			*bp++ = TCPOPT_NOP;
623
			*bp++ = TCPOPT_EOL;
624
			optlen += 2;
625
		}
605
	if (tp->t_flags & TF_SIGNATURE) {
606
		int i;
607
		u_char *bp;
608
		/*
609
		 * Initialize TCP-MD5 option (RFC2385)
610
		 */
611
		bp = (u_char *)opt + optlen;
612
		*bp++ = TCPOPT_SIGNATURE;
613
		*bp++ = TCPOLEN_SIGNATURE;
614
		sigoff = optlen + 2;
615
		for (i = 0; i < TCP_SIGLEN; i++)
616
			*bp++ = 0;
617
		optlen += TCPOLEN_SIGNATURE;
618
		/*
619
		 * Terminate options list and maintain 32-bit alignment.
620
		 */
621
		*bp++ = TCPOPT_NOP;
622
		*bp++ = TCPOPT_EOL;
623
		optlen += 2;
624
	}
626 625
#endif /* TCP_SIGNATURE */
627 626
	KASSERT(optlen <= TCP_MAXOLEN, ("too many TCP options"));
628 627
	hdrlen += optlen;
......
844 843
	}
845 844

  
846 845
#ifdef TCP_SIGNATURE
847
	if (!isipv6)
848
		if (tp->t_flags & TF_SIGNATURE)
849
			tcpsignature_compute(m, sizeof(struct ip), len, optlen,
850
					(u_char *)(th + 1) + sigoff, IPSEC_DIR_OUTBOUND);
846
	if (tp->t_flags & TF_SIGNATURE)
847
		tcpsignature_compute(m, len, optlen,
848
				(u_char *)(th + 1) + sigoff, IPSEC_DIR_OUTBOUND);
851 849
#endif /* TCP_SIGNATURE */
852 850

  
853 851
	/*
sys/netinet/tcp_subr.c
1984 1984

  
1985 1985
#ifdef TCP_SIGNATURE
1986 1986
/*
1987
 * Compute TCP-MD5 hash of a TCPv4 segment. (RFC2385)
1987
 * Compute TCP-MD5 hash of a TCP segment. (RFC2385)
1988 1988
 *
1989 1989
 * We do this over ip, tcphdr, segment data, and the key in the SADB.
1990 1990
 * When called from tcp_input(), we can be sure that th_sum has been
1991 1991
 * zeroed out and verified already.
1992 1992
 *
1993
 * This function is for IPv4 use only. Calling this function with an
1994
 * IPv6 packet in the mbuf chain will yield undefined results.
1995
 *
1996 1993
 * Return 0 if successful, otherwise return -1.
1997 1994
 *
1998 1995
 * XXX The key is retrieved from the system's PF_KEY SADB, by keying a
......
2004 2001
int
2005 2002
tcpsignature_compute(
2006 2003
	struct mbuf *m,		/* mbuf chain */
2007
	int off0,		/* offset to TCP header */
2008 2004
	int len,		/* length of TCP data */
2009 2005
	int optlen,		/* length of TCP options */
2010 2006
	u_char *buf,		/* storage for MD5 digest */
......
2017 2013
	struct ipovly *ipovly;
2018 2014
	struct secasvar *sav;
2019 2015
	struct tcphdr *th;
2016
#ifdef INET6
2017
	struct ip6_hdr *ip6;
2018
	struct in6_addr in6;
2019
	uint32_t plen;
2020
	uint16_t nhdr;
2021
#endif /* INET6 */
2020 2022
	u_short savecsum;
2021 2023

  
2022 2024
	KASSERT(m != NULL, ("passed NULL mbuf. Game over."));
......
2025 2027
	 * Extract the destination from the IP header in the mbuf.
2026 2028
	 */
2027 2029
	ip = mtod(m, struct ip *);
2030
#ifdef INET6
2031
	ip6 = NULL;     /* Make the compiler happy. */
2032
#endif /* INET6 */
2028 2033
	/*
2029 2034
	 * Look up an SADB entry which matches the address found in
2030 2035
	 * the segment.
2031 2036
	 */
2032
	sav = key_allocsa(AF_INET, (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst,
2033
			IPPROTO_TCP, htonl(TCP_SIG_SPI));
2037
	switch (IP_VHL_V(ip->ip_vhl)) {
2038
	case IPVERSION:
2039
		sav = key_allocsa(AF_INET, (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst,
2040
				IPPROTO_TCP, htonl(TCP_SIG_SPI));
2041
		break;
2042
#ifdef INET6
2043
	case (IPV6_VERSION >> 4):
2044
		ip6 = mtod(m, struct ip6_hdr *);
2045
		sav = key_allocsa(AF_INET6, (caddr_t)&ip6->ip6_src, (caddr_t)&ip6->ip6_dst,
2046
				IPPROTO_TCP, htonl(TCP_SIG_SPI));
2047
		break;
2048
#endif /* INET6 */
2049
	default:
2050
		return (EINVAL);
2051
		/* NOTREACHED */
2052
		break;
2053
	}
2034 2054
	if (sav == NULL) {
2035 2055
		kprintf("%s: SADB lookup failed\n", __func__);
2036 2056
		return (EINVAL);
2037 2057
	}
2038 2058
	MD5Init(&ctx);
2039 2059

  
2040
	ipovly = (struct ipovly *)ip;
2041
	th = (struct tcphdr *)((u_char *)ip + off0);
2042
	doff = off0 + sizeof(struct tcphdr) + optlen;
2043 2060
	/*
2044 2061
	 * Step 1: Update MD5 hash with IP pseudo-header.
2045 2062
	 *
......
2049 2066
	 * XXX One cannot depend on ipovly->ih_len here. When called from
2050 2067
	 * tcp_output(), the underlying ip_len member has not yet been set.
2051 2068
	 */
2052
	ippseudo.ippseudo_src = ipovly->ih_src;
2053
	ippseudo.ippseudo_dst = ipovly->ih_dst;
2054
	ippseudo.ippseudo_pad = 0;
2055
	ippseudo.ippseudo_p = IPPROTO_TCP;
2056
	ippseudo.ippseudo_len = htons(len + sizeof(struct tcphdr) + optlen);
2057
	MD5Update(&ctx, (char *)&ippseudo, sizeof(struct ippseudo));
2069
	switch (IP_VHL_V(ip->ip_vhl)) {
2070
	case IPVERSION:
2071
		ipovly = (struct ipovly *)ip;
2072
		ippseudo.ippseudo_src = ipovly->ih_src;
2073
		ippseudo.ippseudo_dst = ipovly->ih_dst;
2074
		ippseudo.ippseudo_pad = 0;
2075
		ippseudo.ippseudo_p = IPPROTO_TCP;
2076
		ippseudo.ippseudo_len = htons(len + sizeof(struct tcphdr) + optlen);
2077
		MD5Update(&ctx, (char *)&ippseudo, sizeof(struct ippseudo));
2078
		th = (struct tcphdr *)((u_char *)ip + sizeof(struct ip));
2079
		doff = sizeof(struct ip) + sizeof(struct tcphdr) + optlen;
2080
		break;
2081
#ifdef INET6
2082
	/*
2083
	 * RFC 2385, 2.0  Proposal
2084
	 * For IPv6, the pseudo-header is as described in RFC 2460, namely the
2085
	 * 128-bit source IPv6 address, 128-bit destination IPv6 address, zero-
2086
	 * extended next header value (to form 32 bits), and 32-bit segment
2087
	 * length.
2088
	 * Note: Upper-Layer Packet Length comes before Next Header.
2089
	 */
2090
	case (IPV6_VERSION >> 4):
2091
		in6 = ip6->ip6_src;
2092
		in6_clearscope(&in6);
2093
		MD5Update(&ctx, (char *)&in6, sizeof(struct in6_addr));
2094
		in6 = ip6->ip6_dst;
2095
		in6_clearscope(&in6);
2096
		MD5Update(&ctx, (char *)&in6, sizeof(struct in6_addr));
2097
		plen = htonl(len + sizeof(struct tcphdr) + optlen);
2098
		MD5Update(&ctx, (char *)&plen, sizeof(uint32_t));
2099
		nhdr = 0;
2100
		MD5Update(&ctx, (char *)&nhdr, sizeof(uint8_t));
2101
		MD5Update(&ctx, (char *)&nhdr, sizeof(uint8_t));
2102
		MD5Update(&ctx, (char *)&nhdr, sizeof(uint8_t));
2103
		nhdr = IPPROTO_TCP;
2104
		MD5Update(&ctx, (char *)&nhdr, sizeof(uint8_t));
2105
		th = (struct tcphdr *)((u_char *)ip6 + sizeof(struct ip6_hdr));
2106
		doff = sizeof(struct ip6_hdr) + sizeof(struct tcphdr) + optlen;
2107
		break;
2108
#endif /* INET6 */
2109
	default:
2110
		return (EINVAL);
2111
		/* NOTREACHED */
2112
		break;
2113
	}
2058 2114
	/*
2059 2115
	 * Step 2: Update MD5 hash with TCP header, excluding options.
2060 2116
	 * The TCP checksum must be set to zero.
sys/netinet/tcp_syncache.c
1271 1271
		*bp++ = TCPOLEN_SIGNATURE;
1272 1272
		for (i = 0; i < TCP_SIGLEN; i++)
1273 1273
			*bp++ = 0;
1274
		tcpsignature_compute(m, sizeof(struct ip), 0, optlen,
1274
		tcpsignature_compute(m, 0, optlen,
1275 1275
				optp + 2, IPSEC_DIR_OUTBOUND);
1276 1276
		*bp++ = TCPOPT_NOP;
1277 1277
		*bp++ = TCPOPT_EOL;
sys/netinet/tcp_var.h
647 647

  
648 648
#ifdef TCP_SIGNATURE
649 649
int tcpsignature_apply(void *fstate, void *data, unsigned int len);
650
int tcpsignature_compute(struct mbuf *m, int off0, int len, int tcpoptlen,
650
int tcpsignature_compute(struct mbuf *m, int len, int tcpoptlen,
651 651
		u_char *buf, u_int direction);
652 652
#endif /* TCP_SIGNATURE */
653 653

  
654
-