summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/netinet/tcp_input.c4
-rw-r--r--sys/netinet/tcp_reass.c4
-rw-r--r--sys/netinet/tcp_seq.h18
-rw-r--r--sys/netinet/tcp_subr.c25
-rw-r--r--sys/netinet/tcp_timer.c2
-rw-r--r--sys/netinet/tcp_timewait.c25
-rw-r--r--sys/netinet/tcp_usrreq.c4
-rw-r--r--sys/netinet/tcp_var.h1
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 */