diff options
Diffstat (limited to 'net/ipv4/tcp_input.c')
-rw-r--r-- | net/ipv4/tcp_input.c | 45 |
1 files changed, 26 insertions, 19 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 181fc8234a52..a13692560e63 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -3552,6 +3552,24 @@ static bool tcp_process_frto(struct sock *sk, int flag) | |||
3552 | return false; | 3552 | return false; |
3553 | } | 3553 | } |
3554 | 3554 | ||
3555 | /* RFC 5961 7 [ACK Throttling] */ | ||
3556 | static void tcp_send_challenge_ack(struct sock *sk) | ||
3557 | { | ||
3558 | /* unprotected vars, we dont care of overwrites */ | ||
3559 | static u32 challenge_timestamp; | ||
3560 | static unsigned int challenge_count; | ||
3561 | u32 now = jiffies / HZ; | ||
3562 | |||
3563 | if (now != challenge_timestamp) { | ||
3564 | challenge_timestamp = now; | ||
3565 | challenge_count = 0; | ||
3566 | } | ||
3567 | if (++challenge_count <= sysctl_tcp_challenge_ack_limit) { | ||
3568 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPCHALLENGEACK); | ||
3569 | tcp_send_ack(sk); | ||
3570 | } | ||
3571 | } | ||
3572 | |||
3555 | /* This routine deals with incoming acks, but not outgoing ones. */ | 3573 | /* This routine deals with incoming acks, but not outgoing ones. */ |
3556 | static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) | 3574 | static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) |
3557 | { | 3575 | { |
@@ -3571,8 +3589,14 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) | |||
3571 | /* If the ack is older than previous acks | 3589 | /* If the ack is older than previous acks |
3572 | * then we can probably ignore it. | 3590 | * then we can probably ignore it. |
3573 | */ | 3591 | */ |
3574 | if (before(ack, prior_snd_una)) | 3592 | if (before(ack, prior_snd_una)) { |
3593 | /* RFC 5961 5.2 [Blind Data Injection Attack].[Mitigation] */ | ||
3594 | if (before(ack, prior_snd_una - tp->max_window)) { | ||
3595 | tcp_send_challenge_ack(sk); | ||
3596 | return -1; | ||
3597 | } | ||
3575 | goto old_ack; | 3598 | goto old_ack; |
3599 | } | ||
3576 | 3600 | ||
3577 | /* If the ack includes data we haven't sent yet, discard | 3601 | /* If the ack includes data we haven't sent yet, discard |
3578 | * this segment (RFC793 Section 3.9). | 3602 | * this segment (RFC793 Section 3.9). |
@@ -5244,23 +5268,6 @@ out: | |||
5244 | } | 5268 | } |
5245 | #endif /* CONFIG_NET_DMA */ | 5269 | #endif /* CONFIG_NET_DMA */ |
5246 | 5270 | ||
5247 | static void tcp_send_challenge_ack(struct sock *sk) | ||
5248 | { | ||
5249 | /* unprotected vars, we dont care of overwrites */ | ||
5250 | static u32 challenge_timestamp; | ||
5251 | static unsigned int challenge_count; | ||
5252 | u32 now = jiffies / HZ; | ||
5253 | |||
5254 | if (now != challenge_timestamp) { | ||
5255 | challenge_timestamp = now; | ||
5256 | challenge_count = 0; | ||
5257 | } | ||
5258 | if (++challenge_count <= sysctl_tcp_challenge_ack_limit) { | ||
5259 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPCHALLENGEACK); | ||
5260 | tcp_send_ack(sk); | ||
5261 | } | ||
5262 | } | ||
5263 | |||
5264 | /* Does PAWS and seqno based validation of an incoming segment, flags will | 5271 | /* Does PAWS and seqno based validation of an incoming segment, flags will |
5265 | * play significant role here. | 5272 | * play significant role here. |
5266 | */ | 5273 | */ |
@@ -5992,7 +5999,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
5992 | */ | 5999 | */ |
5993 | if (req) { | 6000 | if (req) { |
5994 | tcp_synack_rtt_meas(sk, req); | 6001 | tcp_synack_rtt_meas(sk, req); |
5995 | tp->total_retrans = req->retrans; | 6002 | tp->total_retrans = req->num_retrans; |
5996 | 6003 | ||
5997 | reqsk_fastopen_remove(sk, req, false); | 6004 | reqsk_fastopen_remove(sk, req, false); |
5998 | } else { | 6005 | } else { |