diff -c -N netinet.orig/tcp_input.c netinet/tcp_input.c *** netinet.orig/tcp_input.c Mon Aug 30 23:17:06 1999 --- netinet/tcp_input.c Wed Sep 1 08:03:00 1999 *************** *** 49,56 **** #include #include - #include /* before tcp_seq.h, for tcp_random18() */ - #include #include --- 49,54 ---- *************** *** 743,750 **** if (iss) tp->iss = iss; else ! tp->iss = tcp_iss; ! tcp_iss += TCP_ISSINCR/4; tp->irs = ti->ti_seq; tcp_sendseqinit(tp); tcp_rcvseqinit(tp); --- 741,748 ---- if (iss) tp->iss = iss; else ! tp->iss = tcp_init_seq(ti->ti_src, ti->ti_dst, ! ti->ti_sport , ti->ti_dport); tp->irs = ti->ti_seq; tcp_sendseqinit(tp); tcp_rcvseqinit(tp); *************** *** 1255,1261 **** if (tiflags & TH_SYN && tp->t_state == TCPS_TIME_WAIT && SEQ_GT(ti->ti_seq, tp->rcv_nxt)) { ! iss = tp->snd_nxt + TCP_ISSINCR; tp = tcp_close(tp); goto findpcb; } --- 1253,1260 ---- if (tiflags & TH_SYN && tp->t_state == TCPS_TIME_WAIT && SEQ_GT(ti->ti_seq, tp->rcv_nxt)) { ! iss = tp->snd_nxt + tcp_seq_incr(ti->ti_src, ti->ti_dst, ! ti->ti_sport , ti->ti_dport); tp = tcp_close(tp); goto findpcb; } diff -c -N netinet.orig/tcp_seq.c netinet/tcp_seq.c *** netinet.orig/tcp_seq.c Thu Jan 1 02:00:00 1970 --- netinet/tcp_seq.c Wed Sep 1 08:30:41 1999 *************** *** 0 **** --- 1,297 ---- + /* + * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All + * rights reserved. + * + * Copyright (c) 1999 Geoffrey M. Rehmet + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software withough specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + + /* + * Derived from src/lib/libmd/md5c.c + * + * The copyright below applies to code derived from the above file: + */ + + /* + * MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm + * + * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All + * rights reserved. + * + * License to copy and use this software is granted provided that it + * is identified as the "RSA Data Security, Inc. MD5 Message-Digest + * Algorithm" in all material mentioning or referencing this software + * or this function. + * + * License is also granted to make and use derivative works provided + * that such works are identified as "derived from the RSA Data + * Security, Inc. MD5 Message-Digest Algorithm" in all material + * mentioning or referencing the derived work. + * + * RSA Data Security, Inc. makes no representations concerning either + * the merchantability of this software or the suitability of this + * software for any particular purpose. It is provided "as is" + * without express or implied warranty of any kind. + * + * These notices must be retained in any copies of any part of this + * documentation and/or software. + * + * $Old-Id: md5c.c,v 1.9 1998/03/27 10:22:01 phk Exp $ + * + * This code is the same as the code published by RSA Inc. It has been + * edited for clarity and style only. + */ + + /* + * $Id$ + */ + + + #include + #include + #include + #include + + #include + #include + #include + #include /* we get PR_SLOWHZ from here */ + + #include + #include + #include + #include + #include + #include + + #define RESEED_SECONDS 300 + #define RESEED_TOUT ( PR_SLOWHZ * RESEED_SECONDS ) + #define HASH_BITS 24 + #define TCP_ISS_HZ 250000 + #define ISS_GROWTH ( RESEED_SECONDS * TCP_ISS_HZ - ( 1 << HASH_BITS )) + + /* + * This is the average growth required every TCP slow timeout + */ + #define ISS_INCR ( ISS_GROWTH / RESEED_SECONDS ) / PR_SLOWHZ + + static tcp_seq tcp_iss; + static u_int32_t secret[12]; + + static u_int32_t partialMD5Transform __P((const u_int32_t [4], + const u_int32_t [8])); + + + + + /* F, G, H and I are basic MD5 functions. */ + #define F(x, y, z) (((x) & (y)) | ((~x) & (z))) + #define G(x, y, z) (((x) & (z)) | ((y) & (~z))) + #define H(x, y, z) ((x) ^ (y) ^ (z)) + #define I(x, y, z) ((y) ^ ((x) | (~z))) + + /* ROTATE_LEFT rotates x left n bits. */ + #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + + /* + * FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. + * Rotation is separate from addition to prevent recomputation. + */ + #define FF(a, b, c, d, x, s, ac) { \ + (a) += F ((b), (c), (d)) + (x) + (u_int32_t)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } + #define GG(a, b, c, d, x, s, ac) { \ + (a) += G ((b), (c), (d)) + (x) + (u_int32_t)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } + #define HH(a, b, c, d, x, s, ac) { \ + (a) += H ((b), (c), (d)) + (x) + (u_int32_t)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } + #define II(a, b, c, d, x, s, ac) { \ + (a) += I ((b), (c), (d)) + (x) + (u_int32_t)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } + + /* + * Cut down MD5 basic transformation. Transforms state based on block. + * Block has been cut in half, and round 4 removed. + */ + static u_int32_t + partialMD5Transform (state, block) + const u_int32_t state[4]; + const u_int32_t block[8]; + { + u_int32_t a = state[0], b = state[1], c = state[2], d = state[3]; + + /* Round 1 */ + #define S11 7 + #define S12 12 + #define S13 17 + #define S14 22 + FF (a, b, c, d, block[ 0], S11, 0xd76aa478); + FF (d, a, b, c, block[ 1], S12, 0xe8c7b756); + FF (c, d, a, b, block[ 2], S13, 0x242070db); + FF (b, c, d, a, block[ 3], S14, 0xc1bdceee); + FF (a, b, c, d, block[ 4], S11, 0xf57c0faf); + FF (d, a, b, c, block[ 5], S12, 0x4787c62a); + FF (c, d, a, b, block[ 6], S13, 0xa8304613); + FF (b, c, d, a, block[ 7], S14, 0xfd469501); + + /* Round 2 */ + #define S21 5 + #define S22 9 + #define S23 14 + #define S24 20 + GG (a, b, c, d, block[ 1], S21, 0xf61e2562); + GG (d, a, b, c, block[ 6], S22, 0xc040b340); + GG (c, d, a, b, block[ 3], S23, 0x265e5a51); + GG (b, c, d, a, block[ 0], S24, 0xe9b6c7aa); + GG (a, b, c, d, block[ 5], S21, 0xd62f105d); + GG (d, a, b, c, block[ 2], S22, 0x2441453); + GG (c, d, a, b, block[ 7], S23, 0xd8a1e681); + GG (b, c, d, a, block[ 4], S24, 0xe7d3fbc8); + + /* Round 3 */ + #define S31 4 + #define S32 11 + #define S33 16 + #define S34 23 + HH (a, b, c, d, block[ 5], S31, 0xfffa3942); + HH (d, a, b, c, block[ 0], S32, 0x8771f681); + HH (c, d, a, b, block[ 3], S33, 0x6d9d6122); + HH (b, c, d, a, block[ 6], S34, 0xfde5380c); + HH (a, b, c, d, block[ 1], S31, 0xa4beea44); + HH (d, a, b, c, block[ 4], S32, 0x4bdecfa9); + HH (c, d, a, b, block[ 7], S33, 0xf6bb4b60); + HH (b, c, d, a, block[ 2], S34, 0xbebfbc70); + + /* Skip Round 4 */ + + return ( state[1] + b ); + } + + + /* + * TCP sequence number increment + */ + tcp_seq + tcp_seq_incr(saddr, daddr, sprt, dprt) + struct in_addr saddr; + struct in_addr daddr; + u_short sprt; + u_short dprt; + { + u_int rndval; + + rndval = random(); + rndval &= ( (1 << (HASH_BITS - 8)) -1 ); + return(rndval); + } + + + + /* + * Generate an initial TCP sequence number + */ + tcp_seq + tcp_init_seq(saddr, daddr, sprt, dprt) + struct in_addr saddr; + struct in_addr daddr; + u_short sprt; + u_short dprt; + { + tcp_seq seq; + + secret[0] = saddr.s_addr; + secret[1] = daddr.s_addr; + secret[2] = (((u_int32_t) dprt) << 16) | ((u_int32_t) sprt) ; + + seq = partialMD5Transform(secret+8, secret) & ((1 << HASH_BITS) - 1); + + /* add a linear random component as well */ + tcp_iss += (random() & ((1 << (HASH_BITS - 8)) -1 )); + return (seq + tcp_iss); + } + + /* + * Initialise TCP initial send sequence + */ + void + tcp_seq_initialise(void) + { + struct timeval tv; + + /* + * XXX This should be more elegant + */ + microtime(&tv); + srandom(tv.tv_usec); + tcp_iss = random(); + + tcp_iss_incr(); /* start the process off */ + } + + + /* + * Regular increment of tcp_iss + * Also reseed the secret for the hash here + * This routine is normally called out of the TCP slow timeout + * We also reseed the random number generator, to try and get some + * entropy into the system. + * This needs to be rewritten to use the entropy pool. + */ + void + tcp_iss_incr(void) + { + static int counter = 0; + int i; + struct timeval tv; + + if (!counter || (counter > RESEED_TOUT)) { + /* + * XXX This should use the entropy pool! + */ + microtime(&tv); + srandom((tv.tv_usec ^ tcp_iss) + secret[2]); + for (i = 3 ; i < 12 ; secret[i++] = random()); + + tcp_iss += (( 1 << HASH_BITS ) -1); /* avoid collisions */ + + counter = 0; + } + + counter++; + + /* should be more elegant */ + tcp_iss += ISS_INCR - ( 1 << (HASH_BITS - 8)) + + (random() & ((1 << (HASH_BITS - 8)) - 1)) ; + } diff -c -N netinet.orig/tcp_seq.h netinet/tcp_seq.h *** netinet.orig/tcp_seq.h Mon Aug 30 23:17:06 1999 --- netinet/tcp_seq.h Wed Sep 1 08:03:00 1999 *************** *** 81,101 **** #ifdef KERNEL extern tcp_cc tcp_ccgen; /* global connection count */ ! /* ! * Increment for tcp_iss each second. ! * This is designed to increment at the standard 250 KB/s, ! * but with a random component averaging 128 KB. ! * We also increment tcp_iss by a quarter of this amount ! * each time we use the value for a new connection. ! * If defined, the tcp_random18() macro should produce a ! * number in the range [0-0x3ffff] that is hard to predict. ! */ ! #ifndef tcp_random18 ! #define tcp_random18() ((random() >> 14) & 0x3ffff) ! #endif ! #define TCP_ISSINCR (122*1024 + tcp_random18()) - extern tcp_seq tcp_iss; /* tcp initial send seq # */ #else #define TCP_ISSINCR (250*1024) /* increment for tcp_iss each second */ #endif /* KERNEL */ --- 81,94 ---- #ifdef KERNEL extern tcp_cc tcp_ccgen; /* global connection count */ ! extern u_int tcp_init_seq __P((struct in_addr, struct in_addr, ! u_short, u_short)); ! extern tcp_seq tcp_seq_incr __P((struct in_addr, struct in_addr, u_short, ! u_short)); ! extern void tcp_seq_initialise __P((void)); ! extern void tcp_iss_incr __P((void)); ! #else #define TCP_ISSINCR (250*1024) /* increment for tcp_iss each second */ #endif /* KERNEL */ diff -c -N netinet.orig/tcp_subr.c netinet/tcp_subr.c *** netinet.orig/tcp_subr.c Mon Aug 30 23:17:06 1999 --- netinet/tcp_subr.c Wed Sep 1 08:03:00 1999 *************** *** 139,147 **** { int hashsize; - tcp_iss = random(); /* wrong, but better than a constant */ tcp_ccgen = 1; tcp_cleartaocache(); tcp_delacktime = TCPTV_DELACK; tcp_keepinit = TCPTV_KEEP_INIT; --- 139,147 ---- { int hashsize; tcp_ccgen = 1; tcp_cleartaocache(); + tcp_seq_initialise(); tcp_delacktime = TCPTV_DELACK; tcp_keepinit = TCPTV_KEEP_INIT; diff -c -N netinet.orig/tcp_timer.c netinet/tcp_timer.c *** netinet.orig/tcp_timer.c Tue Aug 31 18:34:20 1999 --- netinet/tcp_timer.c Wed Sep 1 08:03:00 1999 *************** *** 45,51 **** #include #include - #include /* before tcp_seq.h, for tcp_random18() */ #include --- 45,50 ---- *************** *** 114,119 **** --- 113,119 ---- /* max idle time in persist */ int tcp_maxidle; + /* * Tcp protocol timeout routine called every 500 ms. * Updates timestamps used for TCP *************** *** 128,138 **** tcp_maxidle = tcp_keepcnt * tcp_keepintvl; ! tcp_iss += TCP_ISSINCR/PR_SLOWHZ; /* increment iss */ ! #ifdef TCP_COMPAT_42 ! if ((int)tcp_iss < 0) ! tcp_iss = TCP_ISSINCR; /* XXX */ ! #endif splx(s); } --- 128,135 ---- tcp_maxidle = tcp_keepcnt * tcp_keepintvl; ! tcp_iss_incr(); ! splx(s); } diff -c -N netinet.orig/tcp_usrreq.c netinet/tcp_usrreq.c *** netinet.orig/tcp_usrreq.c Mon Aug 30 23:17:07 1999 --- netinet/tcp_usrreq.c Wed Sep 1 08:03:00 1999 *************** *** 564,570 **** tcpstat.tcps_connattempt++; tp->t_state = TCPS_SYN_SENT; callout_reset(tp->tt_keep, tcp_keepinit, tcp_timer_keep, tp); ! tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2; tcp_sendseqinit(tp); /* --- 564,571 ---- tcpstat.tcps_connattempt++; tp->t_state = TCPS_SYN_SENT; callout_reset(tp->tt_keep, tcp_keepinit, tcp_timer_keep, tp); ! tp->iss = tcp_init_seq(inp->inp_laddr, inp->inp_faddr, ! inp->inp_lport, inp->inp_fport); tcp_sendseqinit(tp); /* diff -c conf.orig/files conf/files *** conf.orig/files Wed Sep 1 08:32:20 1999 --- conf/files Wed Sep 1 08:03:00 1999 *************** *** 565,570 **** --- 565,571 ---- netinet/tcp_debug.c optional tcpdebug netinet/tcp_input.c optional inet netinet/tcp_output.c optional inet + netinet/tcp_seq.c optional inet netinet/tcp_subr.c optional inet netinet/tcp_timer.c optional inet netinet/tcp_usrreq.c optional inet Only in conf: files.orig