aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/tcp.h1
-rw-r--r--net/ipv4/tcp_input.c29
-rw-r--r--net/ipv4/tcp_minisocks.c1
3 files changed, 24 insertions, 7 deletions
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index bcc828d3b9b9..66d85a80a1ec 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -153,6 +153,7 @@ struct tcp_sock {
153 u32 snd_sml; /* Last byte of the most recently transmitted small packet */ 153 u32 snd_sml; /* Last byte of the most recently transmitted small packet */
154 u32 rcv_tstamp; /* timestamp of last received ACK (for keepalives) */ 154 u32 rcv_tstamp; /* timestamp of last received ACK (for keepalives) */
155 u32 lsndtime; /* timestamp of last sent data packet (for restart window) */ 155 u32 lsndtime; /* timestamp of last sent data packet (for restart window) */
156 u32 last_oow_ack_time; /* timestamp of last out-of-window ACK */
156 157
157 u32 tsoffset; /* timestamp offset */ 158 u32 tsoffset; /* timestamp offset */
158 159
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 9401aa43b814..8fdd27b17306 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -3322,13 +3322,22 @@ static int tcp_ack_update_window(struct sock *sk, const struct sk_buff *skb, u32
3322} 3322}
3323 3323
3324/* RFC 5961 7 [ACK Throttling] */ 3324/* RFC 5961 7 [ACK Throttling] */
3325static void tcp_send_challenge_ack(struct sock *sk) 3325static void tcp_send_challenge_ack(struct sock *sk, const struct sk_buff *skb)
3326{ 3326{
3327 /* unprotected vars, we dont care of overwrites */ 3327 /* unprotected vars, we dont care of overwrites */
3328 static u32 challenge_timestamp; 3328 static u32 challenge_timestamp;
3329 static unsigned int challenge_count; 3329 static unsigned int challenge_count;
3330 u32 now = jiffies / HZ; 3330 struct tcp_sock *tp = tcp_sk(sk);
3331 u32 now;
3332
3333 /* First check our per-socket dupack rate limit. */
3334 if (tcp_oow_rate_limited(sock_net(sk), skb,
3335 LINUX_MIB_TCPACKSKIPPEDCHALLENGE,
3336 &tp->last_oow_ack_time))
3337 return;
3331 3338
3339 /* Then check the check host-wide RFC 5961 rate limit. */
3340 now = jiffies / HZ;
3332 if (now != challenge_timestamp) { 3341 if (now != challenge_timestamp) {
3333 challenge_timestamp = now; 3342 challenge_timestamp = now;
3334 challenge_count = 0; 3343 challenge_count = 0;
@@ -3424,7 +3433,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
3424 if (before(ack, prior_snd_una)) { 3433 if (before(ack, prior_snd_una)) {
3425 /* RFC 5961 5.2 [Blind Data Injection Attack].[Mitigation] */ 3434 /* RFC 5961 5.2 [Blind Data Injection Attack].[Mitigation] */
3426 if (before(ack, prior_snd_una - tp->max_window)) { 3435 if (before(ack, prior_snd_una - tp->max_window)) {
3427 tcp_send_challenge_ack(sk); 3436 tcp_send_challenge_ack(sk, skb);
3428 return -1; 3437 return -1;
3429 } 3438 }
3430 goto old_ack; 3439 goto old_ack;
@@ -4993,7 +5002,10 @@ static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb,
4993 tcp_paws_discard(sk, skb)) { 5002 tcp_paws_discard(sk, skb)) {
4994 if (!th->rst) { 5003 if (!th->rst) {
4995 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSESTABREJECTED); 5004 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSESTABREJECTED);
4996 tcp_send_dupack(sk, skb); 5005 if (!tcp_oow_rate_limited(sock_net(sk), skb,
5006 LINUX_MIB_TCPACKSKIPPEDPAWS,
5007 &tp->last_oow_ack_time))
5008 tcp_send_dupack(sk, skb);
4997 goto discard; 5009 goto discard;
4998 } 5010 }
4999 /* Reset is accepted even if it did not pass PAWS. */ 5011 /* Reset is accepted even if it did not pass PAWS. */
@@ -5010,7 +5022,10 @@ static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb,
5010 if (!th->rst) { 5022 if (!th->rst) {
5011 if (th->syn) 5023 if (th->syn)
5012 goto syn_challenge; 5024 goto syn_challenge;
5013 tcp_send_dupack(sk, skb); 5025 if (!tcp_oow_rate_limited(sock_net(sk), skb,
5026 LINUX_MIB_TCPACKSKIPPEDSEQ,
5027 &tp->last_oow_ack_time))
5028 tcp_send_dupack(sk, skb);
5014 } 5029 }
5015 goto discard; 5030 goto discard;
5016 } 5031 }
@@ -5026,7 +5041,7 @@ static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb,
5026 if (TCP_SKB_CB(skb)->seq == tp->rcv_nxt) 5041 if (TCP_SKB_CB(skb)->seq == tp->rcv_nxt)
5027 tcp_reset(sk); 5042 tcp_reset(sk);
5028 else 5043 else
5029 tcp_send_challenge_ack(sk); 5044 tcp_send_challenge_ack(sk, skb);
5030 goto discard; 5045 goto discard;
5031 } 5046 }
5032 5047
@@ -5040,7 +5055,7 @@ syn_challenge:
5040 if (syn_inerr) 5055 if (syn_inerr)
5041 TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS); 5056 TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS);
5042 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPSYNCHALLENGE); 5057 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPSYNCHALLENGE);
5043 tcp_send_challenge_ack(sk); 5058 tcp_send_challenge_ack(sk, skb);
5044 goto discard; 5059 goto discard;
5045 } 5060 }
5046 5061
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index 131aa4950d1c..98a840561ec8 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -467,6 +467,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req,
467 tcp_enable_early_retrans(newtp); 467 tcp_enable_early_retrans(newtp);
468 newtp->tlp_high_seq = 0; 468 newtp->tlp_high_seq = 0;
469 newtp->lsndtime = treq->snt_synack; 469 newtp->lsndtime = treq->snt_synack;
470 newtp->last_oow_ack_time = 0;
470 newtp->total_retrans = req->num_retrans; 471 newtp->total_retrans = req->num_retrans;
471 472
472 /* So many TCP implementations out there (incorrectly) count the 473 /* So many TCP implementations out there (incorrectly) count the