From ebe55280e4b6541e6b52d9f70a73b3f3e7aaaa7f Mon Sep 17 00:00:00 2001 From: Fedor Date: Mon, 31 Jan 2011 23:16:09 -0500 Subject: [PATCH] TCP: paws check and RFC1323 updates from upstream kernel.org commits fc1ad92dfc4e363a055053746552cdb445ba5c57 tcp: allow timestamps even if SYN packet has tsval=0 c887e6d2d9aee56ee7c9f2af4cec3a5efdcc4c72 tcp: consolidate paws check bc2ce894e113ed95b92541134b002fdc641e8080 tcp: relax tcp_paws_check() --- release/src-rt/linux/linux-2.6/include/net/tcp.h | 24 ++++++++++++++++++---- .../src-rt/linux/linux-2.6/net/ipv4/tcp_input.c | 12 +++++------ release/src-rt/linux/linux-2.6/net/ipv4/tcp_ipv4.c | 9 -------- .../linux/linux-2.6/net/ipv4/tcp_minisocks.c | 4 ++-- 4 files changed, 28 insertions(+), 21 deletions(-) diff --git a/release/src-rt/linux/linux-2.6/include/net/tcp.h b/release/src-rt/linux/linux-2.6/include/net/tcp.h index ad4553878b..444c5e4c97 100644 --- a/release/src-rt/linux/linux-2.6/include/net/tcp.h +++ b/release/src-rt/linux/linux-2.6/include/net/tcp.h @@ -997,11 +997,27 @@ static inline int tcp_fin_time(const struct sock *sk) return fin_timeout; } -static inline int tcp_paws_check(const struct tcp_options_received *rx_opt, int rst) +static inline int tcp_paws_check(const struct tcp_options_received *rx_opt, + int paws_win) { - if ((s32)(rx_opt->rcv_tsval - rx_opt->ts_recent) >= 0) - return 0; - if (get_seconds() >= rx_opt->ts_recent_stamp + TCP_PAWS_24DAYS) + if ((s32)(rx_opt->ts_recent - rx_opt->rcv_tsval) <= paws_win) + return 1; + if (unlikely(get_seconds() >= rx_opt->ts_recent_stamp + TCP_PAWS_24DAYS)) + return 1; + /* + * Some OSes send SYN and SYNACK messages with tsval=0 tsecr=0, + * then following tcp messages have valid values. Ignore 0 value, + * or else 'negative' tsval might forbid us to accept their packets. + */ + if (!rx_opt->ts_recent) + return 1; + return 0; +} + +static inline int tcp_paws_reject(const struct tcp_options_received *rx_opt, + int rst) +{ + if (tcp_paws_check(rx_opt, 0)) return 0; /* RST segments are not recommended to carry timestamp, diff --git a/release/src-rt/linux/linux-2.6/net/ipv4/tcp_input.c b/release/src-rt/linux/linux-2.6/net/ipv4/tcp_input.c index 955e005c16..c10f8d9845 100644 --- a/release/src-rt/linux/linux-2.6/net/ipv4/tcp_input.c +++ b/release/src-rt/linux/linux-2.6/net/ipv4/tcp_input.c @@ -3042,8 +3042,7 @@ static inline void tcp_replace_ts_recent(struct tcp_sock *tp, u32 seq) * Not only, also it occurs for expired timestamps. */ - if ((s32)(tp->rx_opt.rcv_tsval - tp->rx_opt.ts_recent) >= 0 || - get_seconds() >= tp->rx_opt.ts_recent_stamp + TCP_PAWS_24DAYS) + if (tcp_paws_check(&tp->rx_opt, 0)) tcp_store_ts_recent(tp); } } @@ -3094,9 +3093,9 @@ static int tcp_disordered_ack(const struct sock *sk, const struct sk_buff *skb) static inline int tcp_paws_discard(const struct sock *sk, const struct sk_buff *skb) { const struct tcp_sock *tp = tcp_sk(sk); - return ((s32)(tp->rx_opt.ts_recent - tp->rx_opt.rcv_tsval) > TCP_PAWS_WINDOW && - get_seconds() < tp->rx_opt.ts_recent_stamp + TCP_PAWS_24DAYS && - !tcp_disordered_ack(sk, skb)); + + return !tcp_paws_check(&tp->rx_opt, TCP_PAWS_WINDOW) && + !tcp_disordered_ack(sk, skb); } /* Check segment sequence number for validity. @@ -4622,7 +4621,8 @@ discard: } /* PAWS check. */ - if (tp->rx_opt.ts_recent_stamp && tp->rx_opt.saw_tstamp && tcp_paws_check(&tp->rx_opt, 0)) + if (tp->rx_opt.ts_recent_stamp && tp->rx_opt.saw_tstamp && + tcp_paws_reject(&tp->rx_opt, 0)) goto discard_and_undo; if (th->syn) { diff --git a/release/src-rt/linux/linux-2.6/net/ipv4/tcp_ipv4.c b/release/src-rt/linux/linux-2.6/net/ipv4/tcp_ipv4.c index e11ff644e4..9fa073f375 100644 --- a/release/src-rt/linux/linux-2.6/net/ipv4/tcp_ipv4.c +++ b/release/src-rt/linux/linux-2.6/net/ipv4/tcp_ipv4.c @@ -1313,15 +1313,6 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) tmp_opt.saw_tstamp = 0; } - if (tmp_opt.saw_tstamp && !tmp_opt.rcv_tsval) { - /* Some OSes (unknown ones, but I see them on web server, which - * contains information interesting only for windows' - * users) do not send their stamp in SYN. It is easy case. - * We simply do not advertise TS support. - */ - tmp_opt.saw_tstamp = 0; - tmp_opt.tstamp_ok = 0; - } tmp_opt.tstamp_ok = tmp_opt.saw_tstamp; tcp_openreq_init(req, &tmp_opt, skb); diff --git a/release/src-rt/linux/linux-2.6/net/ipv4/tcp_minisocks.c b/release/src-rt/linux/linux-2.6/net/ipv4/tcp_minisocks.c index a12b08fca5..da66e8736e 100644 --- a/release/src-rt/linux/linux-2.6/net/ipv4/tcp_minisocks.c +++ b/release/src-rt/linux/linux-2.6/net/ipv4/tcp_minisocks.c @@ -107,7 +107,7 @@ tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb, if (tmp_opt.saw_tstamp) { tmp_opt.ts_recent = tcptw->tw_ts_recent; tmp_opt.ts_recent_stamp = tcptw->tw_ts_recent_stamp; - paws_reject = tcp_paws_check(&tmp_opt, th->rst); + paws_reject = tcp_paws_reject(&tmp_opt, th->rst); } } @@ -506,7 +506,7 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb, * from another data. */ tmp_opt.ts_recent_stamp = get_seconds() - ((TCP_TIMEOUT_INIT/HZ)<retrans); - paws_reject = tcp_paws_check(&tmp_opt, th->rst); + paws_reject = tcp_paws_reject(&tmp_opt, th->rst); } } -- 2.11.4.GIT