diff options
| author | Bruce M Simpson <bms@FreeBSD.org> | 2004-02-11 04:26:04 +0000 | 
|---|---|---|
| committer | Bruce M Simpson <bms@FreeBSD.org> | 2004-02-11 04:26:04 +0000 | 
| commit | 1cfd4b5326854e594bfcd5f31dec0f2b52ccaa71 (patch) | |
| tree | 7a14054c69fb5681c86f54e9b66a9128c1e16003 /sys/netinet/tcp_timewait.c | |
| parent | 33febf93d6e69967393353136a9e3a0829e1bd10 (diff) | |
Notes
Diffstat (limited to 'sys/netinet/tcp_timewait.c')
| -rw-r--r-- | sys/netinet/tcp_timewait.c | 114 | 
1 files changed, 114 insertions, 0 deletions
diff --git a/sys/netinet/tcp_timewait.c b/sys/netinet/tcp_timewait.c index 4b56295f4bc4..689d0cdc48b5 100644 --- a/sys/netinet/tcp_timewait.c +++ b/sys/netinet/tcp_timewait.c @@ -35,6 +35,7 @@   */  #include "opt_compat.h" +#include "opt_inet.h"  #include "opt_inet6.h"  #include "opt_ipsec.h"  #include "opt_mac.h" @@ -101,9 +102,11 @@  #ifdef FAST_IPSEC  #include <netipsec/ipsec.h> +#include <netipsec/xform.h>  #ifdef INET6  #include <netipsec/ipsec6.h>  #endif +#include <netipsec/key.h>  #define	IPSEC  #endif /*FAST_IPSEC*/ @@ -1917,3 +1920,114 @@ tcp_xmit_bandwidth_limit(struct tcpcb *tp, tcp_seq ack_seq)  	tp->snd_bwnd = bwnd;  } +#ifdef TCP_SIGNATURE +/* + * Compute TCP-MD5 hash of a TCPv4 segment. (RFC2385) + * + * We do this over ip, tcphdr, segment data, and the key in the SADB. + * 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 + * search with the destination IP address, and a 'magic SPI' to be + * determined by the application. This is hardcoded elsewhere to 1179 + * right now. Another branch of this code exists which uses the SPD to + * specify per-application flows but it is unstable. + */ +int +tcpsignature_compute( +	struct mbuf *m,		/* mbuf chain */ +	int off0,		/* offset to TCP header */ +	int len,		/* length of TCP data */ +	int optlen,		/* length of TCP options */ +	u_char *buf,		/* storage for MD5 digest */ +	u_int direction)	/* direction of flow */ +{ +	union sockaddr_union dst; +	struct ippseudo ippseudo; +	MD5_CTX ctx; +	int doff; +	struct ip *ip; +	struct ipovly *ipovly; +	struct secasvar *sav; +	struct tcphdr *th; +	u_short savecsum; + +	KASSERT(m != NULL, ("passed NULL mbuf. Game over.")); +	KASSERT(buf != NULL, ("passed NULL storage pointer for MD5 signature")); +	/* +	 * 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; +	/* +	 * Look up an SADB entry which matches the address found in +	 * the segment. +	 */ +	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)); +		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. +	 * +	 * XXX The ippseudo header MUST be digested in network byte order, +	 * or else we'll fail the regression test. Assume all fields we've +	 * been doing arithmetic on have been in host byte order. +	 * 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)); +	/* +	 * Step 2: Update MD5 hash with TCP header, excluding options. +	 * The TCP checksum must be set to zero. +	 */ +	savecsum = th->th_sum; +	th->th_sum = 0; +	MD5Update(&ctx, (char *)th, sizeof(struct tcphdr)); +	th->th_sum = savecsum; +	/* +	 * Step 3: Update MD5 hash with TCP segment data. +	 *         Use m_apply() to avoid an early m_pullup(). +	 */ +	if (len > 0) +		m_apply(m, doff, len, tcpsignature_apply, &ctx); +	/* +	 * Step 4: Update MD5 hash with shared secret. +	 */ +	MD5Update(&ctx, _KEYBUF(sav->key_auth), _KEYLEN(sav->key_auth)); +	MD5Final(buf, &ctx); +	key_sa_recordxfer(sav, m); +	KEY_FREESAV(&sav); +	return (0); +} + +int +tcpsignature_apply(void *fstate, void *data, unsigned int len) +{ + +	MD5Update((MD5_CTX *)fstate, (unsigned char *)data, len); +	return (0); +} +#endif /* TCP_SIGNATURE */  | 
