diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/netinet/tcp_input.c | 13 | ||||
-rw-r--r-- | sys/netinet/tcp_seq.h | 2 | ||||
-rw-r--r-- | sys/netinet/tcp_subr.c | 63 | ||||
-rw-r--r-- | sys/netinet/tcp_timer.c | 2 | ||||
-rw-r--r-- | sys/netinet/tcp_usrreq.c | 7 | ||||
-rw-r--r-- | sys/netinet/tcp_var.h | 4 |
6 files changed, 85 insertions, 6 deletions
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index 7dc4e538b590..d9e8d18dce1d 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -722,9 +722,14 @@ findpcb: tcp_dooptions(tp, optp, optlen, ti, &to); if (iss) tp->iss = iss; - else + else { +#ifdef TCP_COMPAT_42 + tcp_iss += TCP_ISSINCR/2; tp->iss = tcp_iss; - tcp_iss += TCP_ISSINCR/4; +#else + tp->iss = tcp_rndiss_next(); +#endif /* TCP_COMPAT_42 */ + } tp->irs = ti->ti_seq; tcp_sendseqinit(tp); tcp_rcvseqinit(tp); @@ -1222,7 +1227,11 @@ trimthenstep6: if (tiflags & TH_SYN && tp->t_state == TCPS_TIME_WAIT && SEQ_GT(ti->ti_seq, tp->rcv_nxt)) { +#ifdef TCP_COMPAT_42 iss = tp->snd_nxt + TCP_ISSINCR; +#else + iss = tcp_rndiss_next(); +#endif /* TCP_COMPAT_42 */ tp = tcp_close(tp); goto findpcb; } diff --git a/sys/netinet/tcp_seq.h b/sys/netinet/tcp_seq.h index 9392df7be6fc..b5cc7ff14e4b 100644 --- a/sys/netinet/tcp_seq.h +++ b/sys/netinet/tcp_seq.h @@ -81,6 +81,7 @@ #ifdef KERNEL extern tcp_cc tcp_ccgen; /* global connection count */ +#ifdef TCP_COMPAT_42 /* * Increment for tcp_iss each second. * This is designed to increment at the standard 250 KB/s, @@ -96,6 +97,7 @@ extern tcp_cc tcp_ccgen; /* global connection count */ #define TCP_ISSINCR (122*1024 + tcp_random18()) extern tcp_seq tcp_iss; /* tcp initial send seq # */ +#endif /* TCP_COMPAT_42 */ #else #define TCP_ISSINCR (250*1024) /* increment for tcp_iss each second */ #endif /* KERNEL */ diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index 430336de3663..2e1aad115c9b 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -47,9 +47,10 @@ #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/protosw.h> - #include <vm/vm_zone.h> +#include <i386/include/random.h> + #include <net/route.h> #include <net/if.h> @@ -130,7 +131,9 @@ tcp_init() { int hashsize; - tcp_iss = arc4random(); /* wrong, but better than a constant */ +#ifdef TCP_COMPAT_42 + tcp_iss = 1; /* wrong */ +#endif /* TCP_COMPAT_42 */ tcp_ccgen = 1; tcp_cleartaocache(); LIST_INIT(&tcb); @@ -665,6 +668,62 @@ tcp_ctlinput(cmd, sa, vip) in_pcbnotifyall(&tcb, sa, cmd, notify); } +#define TCP_RNDISS_ROUNDS 16 +#define TCP_RNDISS_OUT 7200 +#define TCP_RNDISS_MAX 30000 + +u_int8_t tcp_rndiss_sbox[128]; +u_int16_t tcp_rndiss_msb; +u_int16_t tcp_rndiss_cnt; +long tcp_rndiss_reseed; + +u_int16_t +tcp_rndiss_encrypt(val) + u_int16_t val; +{ + u_int16_t sum = 0, i; + + for (i = 0; i < TCP_RNDISS_ROUNDS; i++) { + sum += 0x79b9; + val ^= ((u_int16_t)tcp_rndiss_sbox[(val^sum) & 0x7f]) << 7; + val = ((val & 0xff) << 7) | (val >> 8); + } + + return val; +} + +void +tcp_rndiss_init() +{ + struct timeval time; + + getmicrotime(&time); + read_random_unlimited(tcp_rndiss_sbox, sizeof(tcp_rndiss_sbox)); + + tcp_rndiss_reseed = time.tv_sec + TCP_RNDISS_OUT; + tcp_rndiss_msb = tcp_rndiss_msb == 0x8000 ? 0 : 0x8000; + tcp_rndiss_cnt = 0; +} + +tcp_seq +tcp_rndiss_next() +{ + u_int32_t tmp; + struct timeval time; + + getmicrotime(&time); + + if (tcp_rndiss_cnt >= TCP_RNDISS_MAX || + time.tv_sec > tcp_rndiss_reseed) + tcp_rndiss_init(); + + tmp = arc4random(); + + /* (tmp & 0x7fff) ensures a 32768 byte gap between ISS */ + return ((tcp_rndiss_encrypt(tcp_rndiss_cnt++) | tcp_rndiss_msb) <<16) | + (tmp & 0x7fff); +} + /* * When a source quench is received, close congestion window * to one segment. We will gradually open it again as we proceed. diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c index 858c684f048e..2b941cb22540 100644 --- a/sys/netinet/tcp_timer.c +++ b/sys/netinet/tcp_timer.c @@ -167,8 +167,8 @@ tcp_slowtimo() tpgone: ; } - tcp_iss += TCP_ISSINCR/PR_SLOWHZ; /* increment iss */ #ifdef TCP_COMPAT_42 + tcp_iss += TCP_ISSINCR/PR_SLOWHZ; /* increment iss */ if ((int)tcp_iss < 0) tcp_iss = TCP_ISSINCR; /* XXX */ #endif diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index 060f84ac1e38..d6a4497a7bef 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -562,7 +562,12 @@ tcp_connect(tp, nam, p) tcpstat.tcps_connattempt++; tp->t_state = TCPS_SYN_SENT; tp->t_timer[TCPT_KEEP] = tcp_keepinit; - tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2; +#ifdef TCP_COMPAT_42 + tp->iss = tcp_iss; + tcp_iss += TCP_ISSINCR/2; +#else /* TCP_COMPAT_42 */ + tp->iss = tcp_rndiss_next(); +#endif /* !TCP_COMPAT_42 */ tcp_sendseqinit(tp); /* diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h index c2ff37d49b21..452d4a86fd51 100644 --- a/sys/netinet/tcp_var.h +++ b/sys/netinet/tcp_var.h @@ -365,6 +365,10 @@ void tcp_trace __P((int, int, struct tcpcb *, struct tcpiphdr *, int)); extern struct pr_usrreqs tcp_usrreqs; extern u_long tcp_sendspace; extern u_long tcp_recvspace; +void tcp_rndiss_init __P((void)); +tcp_seq tcp_rndiss_next __P((void)); +u_int16_t + tcp_rndiss_encrypt __P((u_int16_t)); #endif /* KERNEL */ |