summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/netinet/tcp_input.c13
-rw-r--r--sys/netinet/tcp_reass.c13
-rw-r--r--sys/netinet/tcp_seq.h2
-rw-r--r--sys/netinet/tcp_subr.c62
-rw-r--r--sys/netinet/tcp_timer.c2
-rw-r--r--sys/netinet/tcp_timewait.c62
-rw-r--r--sys/netinet/tcp_usrreq.c11
-rw-r--r--sys/netinet/tcp_var.h4
8 files changed, 161 insertions, 8 deletions
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index 6c7ae76..036f675 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -1110,9 +1110,14 @@ findpcb:
tcp_dooptions(tp, optp, optlen, th, &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 = th->th_seq;
tcp_sendseqinit(tp);
tcp_rcvseqinit(tp);
@@ -1643,7 +1648,11 @@ trimthenstep6:
if (thflags & TH_SYN &&
tp->t_state == TCPS_TIME_WAIT &&
SEQ_GT(th->th_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_reass.c b/sys/netinet/tcp_reass.c
index 6c7ae76..036f675 100644
--- a/sys/netinet/tcp_reass.c
+++ b/sys/netinet/tcp_reass.c
@@ -1110,9 +1110,14 @@ findpcb:
tcp_dooptions(tp, optp, optlen, th, &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 = th->th_seq;
tcp_sendseqinit(tp);
tcp_rcvseqinit(tp);
@@ -1643,7 +1648,11 @@ trimthenstep6:
if (thflags & TH_SYN &&
tp->t_state == TCPS_TIME_WAIT &&
SEQ_GT(th->th_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 49b714a..021f7aa 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 2afff53..64f4c06 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -53,6 +53,7 @@
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/protosw.h>
+#include <sys/random.h>
#include <vm/vm_zone.h>
@@ -181,7 +182,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();
@@ -1100,6 +1103,63 @@ tcp6_ctlinput(cmd, sa, d)
}
#endif /* INET6 */
+#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(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_int16_t tmp;
+ struct timeval time;
+
+ getmicrotime(&time);
+
+ if (tcp_rndiss_cnt >= TCP_RNDISS_MAX ||
+ time.tv_sec > tcp_rndiss_reseed)
+ tcp_rndiss_init();
+
+ read_random(&tmp, sizeof(tmp));
+
+ /* (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 0947295..2013c23 100644
--- a/sys/netinet/tcp_timer.c
+++ b/sys/netinet/tcp_timer.c
@@ -132,8 +132,8 @@ tcp_slowtimo()
tcp_maxidle = tcp_keepcnt * tcp_keepintvl;
- 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_timewait.c b/sys/netinet/tcp_timewait.c
index 2afff53..64f4c06 100644
--- a/sys/netinet/tcp_timewait.c
+++ b/sys/netinet/tcp_timewait.c
@@ -53,6 +53,7 @@
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/protosw.h>
+#include <sys/random.h>
#include <vm/vm_zone.h>
@@ -181,7 +182,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();
@@ -1100,6 +1103,63 @@ tcp6_ctlinput(cmd, sa, d)
}
#endif /* INET6 */
+#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(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_int16_t tmp;
+ struct timeval time;
+
+ getmicrotime(&time);
+
+ if (tcp_rndiss_cnt >= TCP_RNDISS_MAX ||
+ time.tv_sec > tcp_rndiss_reseed)
+ tcp_rndiss_init();
+
+ read_random(&tmp, sizeof(tmp));
+
+ /* (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_usrreq.c b/sys/netinet/tcp_usrreq.c
index ecd84a9..07e1b90 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -761,7 +761,12 @@ 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_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);
/*
@@ -853,7 +858,11 @@ 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);
+#ifdef TCP_COMPAT_42
tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2;
+#else
+ 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 e361caf..ecac451 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -409,6 +409,10 @@ void tcp_trace __P((int, int, struct tcpcb *, void *, struct tcphdr *,
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 */
OpenPOWER on IntegriCloud