diff options
| -rw-r--r-- | sys/netinet/tcp_input.c | 4 | ||||
| -rw-r--r-- | sys/netinet/tcp_reass.c | 4 | ||||
| -rw-r--r-- | sys/netinet/tcp_seq.h | 18 | ||||
| -rw-r--r-- | sys/netinet/tcp_subr.c | 25 | ||||
| -rw-r--r-- | sys/netinet/tcp_timer.c | 2 | ||||
| -rw-r--r-- | sys/netinet/tcp_timewait.c | 25 | ||||
| -rw-r--r-- | sys/netinet/tcp_usrreq.c | 4 | ||||
| -rw-r--r-- | sys/netinet/tcp_var.h | 1 |
8 files changed, 77 insertions, 6 deletions
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index babf03fd0ce5..37b649288e5d 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -1135,7 +1135,7 @@ findpcb: if (iss) tp->iss = iss; else { - tp->iss = tcp_rndiss_next(); + tp->iss = tcp_new_isn(); } tp->irs = th->th_seq; tcp_sendseqinit(tp); @@ -1667,7 +1667,7 @@ trimthenstep6: if (thflags & TH_SYN && tp->t_state == TCPS_TIME_WAIT && SEQ_GT(th->th_seq, tp->rcv_nxt)) { - iss = tcp_rndiss_next(); + iss = tcp_new_isn(); tp = tcp_close(tp); goto findpcb; } diff --git a/sys/netinet/tcp_reass.c b/sys/netinet/tcp_reass.c index babf03fd0ce5..37b649288e5d 100644 --- a/sys/netinet/tcp_reass.c +++ b/sys/netinet/tcp_reass.c @@ -1135,7 +1135,7 @@ findpcb: if (iss) tp->iss = iss; else { - tp->iss = tcp_rndiss_next(); + tp->iss = tcp_new_isn(); } tp->irs = th->th_seq; tcp_sendseqinit(tp); @@ -1667,7 +1667,7 @@ trimthenstep6: if (thflags & TH_SYN && tp->t_state == TCPS_TIME_WAIT && SEQ_GT(th->th_seq, tp->rcv_nxt)) { - iss = tcp_rndiss_next(); + iss = tcp_new_isn(); tp = tcp_close(tp); goto findpcb; } diff --git a/sys/netinet/tcp_seq.h b/sys/netinet/tcp_seq.h index 9d4adc8bf78f..930734758dd3 100644 --- a/sys/netinet/tcp_seq.h +++ b/sys/netinet/tcp_seq.h @@ -81,6 +81,24 @@ #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. + * + * The variable tcp_iss and tcp_random18() are only used + * by sequence number generation scheme 0. + */ +#ifndef tcp_random18 +#define tcp_random18() (arc4random() & 0x3ffff) +#endif +#define TCP_ISSINCR (122*1024 + tcp_random18()) + +extern tcp_seq tcp_iss; #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 221e54120a2d..b126cbd323b4 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -139,6 +139,10 @@ static int icmp_may_rst = 1; SYSCTL_INT(_net_inet_tcp, OID_AUTO, icmp_may_rst, CTLFLAG_RW, &icmp_may_rst, 0, "Certain ICMP unreachable messages may abort connections in SYN_SENT"); +static int tcp_seq_genscheme = 1; +SYSCTL_INT(_net_inet_tcp, OID_AUTO, tcp_seq_genscheme, CTLFLAG_RW, + &tcp_seq_genscheme, 0, "TCP ISN generation scheme"); + static void tcp_cleartaocache __P((void)); static void tcp_notify __P((struct inpcb *, int)); @@ -182,6 +186,7 @@ tcp_init() { int hashsize = TCBHASHSIZE; + tcp_iss = arc4random(); /* wrong, but better than a constant */ tcp_ccgen = 1; tcp_cleartaocache(); @@ -1107,6 +1112,26 @@ tcp6_ctlinput(cmd, sa, d) } #endif /* INET6 */ +tcp_seq +tcp_new_isn() +{ + if ((tcp_seq_genscheme > 1) || (tcp_seq_genscheme < 0)) + tcp_seq_genscheme = 1; + + switch (tcp_seq_genscheme) { + case 0: /* + * Random positive increments + */ + tcp_iss += TCP_ISSINCR/2; + return tcp_iss; + case 1: /* + * OpemBSD randomized scheme + */ + return tcp_rndiss_next(); + } + +} + #define TCP_RNDISS_ROUNDS 16 #define TCP_RNDISS_OUT 7200 #define TCP_RNDISS_MAX 30000 diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c index 488c293e6003..78919452b502 100644 --- a/sys/netinet/tcp_timer.c +++ b/sys/netinet/tcp_timer.c @@ -133,6 +133,8 @@ tcp_slowtimo() tcp_maxidle = tcp_keepcnt * tcp_keepintvl; + tcp_iss += TCP_ISSINCR/PR_SLOWHZ; + splx(s); } diff --git a/sys/netinet/tcp_timewait.c b/sys/netinet/tcp_timewait.c index 221e54120a2d..b126cbd323b4 100644 --- a/sys/netinet/tcp_timewait.c +++ b/sys/netinet/tcp_timewait.c @@ -139,6 +139,10 @@ static int icmp_may_rst = 1; SYSCTL_INT(_net_inet_tcp, OID_AUTO, icmp_may_rst, CTLFLAG_RW, &icmp_may_rst, 0, "Certain ICMP unreachable messages may abort connections in SYN_SENT"); +static int tcp_seq_genscheme = 1; +SYSCTL_INT(_net_inet_tcp, OID_AUTO, tcp_seq_genscheme, CTLFLAG_RW, + &tcp_seq_genscheme, 0, "TCP ISN generation scheme"); + static void tcp_cleartaocache __P((void)); static void tcp_notify __P((struct inpcb *, int)); @@ -182,6 +186,7 @@ tcp_init() { int hashsize = TCBHASHSIZE; + tcp_iss = arc4random(); /* wrong, but better than a constant */ tcp_ccgen = 1; tcp_cleartaocache(); @@ -1107,6 +1112,26 @@ tcp6_ctlinput(cmd, sa, d) } #endif /* INET6 */ +tcp_seq +tcp_new_isn() +{ + if ((tcp_seq_genscheme > 1) || (tcp_seq_genscheme < 0)) + tcp_seq_genscheme = 1; + + switch (tcp_seq_genscheme) { + case 0: /* + * Random positive increments + */ + tcp_iss += TCP_ISSINCR/2; + return tcp_iss; + case 1: /* + * OpemBSD randomized scheme + */ + return tcp_rndiss_next(); + } + +} + #define TCP_RNDISS_ROUNDS 16 #define TCP_RNDISS_OUT 7200 #define TCP_RNDISS_MAX 30000 diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index ddd7d9b84f79..de1aa65a28cb 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -758,7 +758,7 @@ tcp_connect(tp, nam, p) tcpstat.tcps_connattempt++; tp->t_state = TCPS_SYN_SENT; callout_reset(tp->tt_keep, tcp_keepinit, tcp_timer_keep, tp); - tp->iss = tcp_rndiss_next(); + tp->iss = tcp_new_isn(); tcp_sendseqinit(tp); /* @@ -844,7 +844,7 @@ tcp6_connect(tp, nam, p) tcpstat.tcps_connattempt++; tp->t_state = TCPS_SYN_SENT; callout_reset(tp->tt_keep, tcp_keepinit, tcp_timer_keep, tp); - tp->iss = tcp_rndiss_next(); + tp->iss = tcp_new_isn(); tcp_sendseqinit(tp); /* diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h index 294699ff8432..299968e8c6a3 100644 --- a/sys/netinet/tcp_var.h +++ b/sys/netinet/tcp_var.h @@ -414,6 +414,7 @@ void tcp_rndiss_init __P((void)); tcp_seq tcp_rndiss_next __P((void)); u_int16_t tcp_rndiss_encrypt __P((u_int16_t)); +tcp_seq tcp_new_isn __P((void)); #endif /* _KERNEL */ |
