diff options
author | 2007-06-15 18:23:06 +0000 | |
---|---|---|
committer | 2007-06-15 18:23:06 +0000 | |
commit | 16193b2ba7bc3e2cbde4514c36576e5ba91dccb4 (patch) | |
tree | 20189f285844778846aabcbd6a91edf14522d5ef /sys/netinet/tcp_input.c | |
parent | In power_match(), make sure oa_irq is correctly initialized. (diff) | |
download | wireguard-openbsd-16193b2ba7bc3e2cbde4514c36576e5ba91dccb4.tar.xz wireguard-openbsd-16193b2ba7bc3e2cbde4514c36576e5ba91dccb4.zip |
Drop the current random timestamps and the current ISN generation
code and replace both with a RFC1948 based method, so TCP clients
now have monotonic ISN/timestamps. The server side uses completely
random ISN/timestamps and does time-wait recycling (on port reuse).
ok djm@, mcbride@; thanks to lots of testers
Diffstat (limited to 'sys/netinet/tcp_input.c')
-rw-r--r-- | sys/netinet/tcp_input.c | 46 |
1 files changed, 28 insertions, 18 deletions
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index 32a322220bc..b2a9a3bb20a 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_input.c,v 1.206 2007/06/11 11:29:35 henning Exp $ */ +/* $OpenBSD: tcp_input.c,v 1.207 2007/06/15 18:23:06 markus Exp $ */ /* $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $ */ /* @@ -378,7 +378,7 @@ tcp_input(struct mbuf *m, ...) int todrop, acked, ourfinisacked, needoutput = 0; int hdroptlen = 0; short ostate = 0; - int iss = 0; + tcp_seq iss, *reuse = NULL; u_long tiwin; struct tcp_opt_info opti; int iphlen; @@ -846,7 +846,7 @@ findpcb: */ if (so->so_qlen <= so->so_qlimit && syn_cache_add(&src.sa, &dst.sa, th, iphlen, - so, m, optp, optlen, &opti)) + so, m, optp, optlen, &opti, reuse)) m = NULL; } goto drop; @@ -1268,6 +1268,28 @@ trimthenstep6: tp->snd_wl1 = th->th_seq - 1; tp->rcv_up = th->th_seq; goto step6; + /* + * If a new connection request is received while in TIME_WAIT, + * drop the old connection and start over if the if the + * timestamp or the sequence numbers are above the previous + * ones. + */ + case TCPS_TIME_WAIT: + if (((tiflags & (TH_SYN|TH_ACK)) == TH_SYN) && + ((opti.ts_present && + TSTMP_LT(tp->ts_recent, opti.ts_val)) || + SEQ_GT(th->th_seq, tp->rcv_nxt))) { + /* + * Advance the iss by at least 32768, but + * clear the msb in order to make sure + * that SEG_LT(snd_nxt, iss). + */ + iss = tp->snd_nxt + + ((arc4random() & 0x7fffffff) | 0x8000); + reuse = &iss; + tp = tcp_close(tp); + goto findpcb; + } } /* @@ -1367,19 +1389,6 @@ trimthenstep6: if (todrop >= tlen) { tcpstat.tcps_rcvbyteafterwin += tlen; /* - * If a new connection request is received - * while in TIME_WAIT, drop the old connection - * and start over if the sequence numbers - * are above the previous ones. - */ - if (tiflags & TH_SYN && - tp->t_state == TCPS_TIME_WAIT && - SEQ_GT(th->th_seq, tp->rcv_nxt)) { - iss = tp->snd_nxt + TCP_ISSINCR; - tp = tcp_close(tp); - goto findpcb; - } - /* * If window is closed can only take segments at * window edge, and have to drop data and PUSH from * incoming segments. Continue processing, but @@ -3950,7 +3959,7 @@ syn_cache_unreach(src, dst, th) */ int -syn_cache_add(src, dst, th, iphlen, so, m, optp, optlen, oi) +syn_cache_add(src, dst, th, iphlen, so, m, optp, optlen, oi, issp) struct sockaddr *src; struct sockaddr *dst; struct tcphdr *th; @@ -3960,6 +3969,7 @@ syn_cache_add(src, dst, th, iphlen, so, m, optp, optlen, oi) u_char *optp; int optlen; struct tcp_opt_info *oi; + tcp_seq *issp; { struct tcpcb tb, *tp; long win; @@ -4062,7 +4072,7 @@ syn_cache_add(src, dst, th, iphlen, so, m, optp, optlen, oi) tcp_iss += TCP_ISSINCR/2; sc->sc_iss = tcp_iss; #else - sc->sc_iss = tcp_rndiss_next(); + sc->sc_iss = issp ? *issp : arc4random(); #endif sc->sc_peermaxseg = oi->maxseg; sc->sc_ourmaxseg = tcp_mss_adv(m->m_flags & M_PKTHDR ? |