diff options
Diffstat (limited to 'net/ipv4/tcp_input.c')
| -rw-r--r-- | net/ipv4/tcp_input.c | 66 |
1 files changed, 41 insertions, 25 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 2c2b13a999ea..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 | */ |
| @@ -5313,11 +5320,6 @@ static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb, | |||
| 5313 | goto discard; | 5320 | goto discard; |
| 5314 | } | 5321 | } |
| 5315 | 5322 | ||
| 5316 | /* ts_recent update must be made after we are sure that the packet | ||
| 5317 | * is in window. | ||
| 5318 | */ | ||
| 5319 | tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq); | ||
| 5320 | |||
| 5321 | /* step 3: check security and precedence [ignored] */ | 5323 | /* step 3: check security and precedence [ignored] */ |
| 5322 | 5324 | ||
| 5323 | /* step 4: Check for a SYN | 5325 | /* step 4: Check for a SYN |
| @@ -5552,6 +5554,11 @@ step5: | |||
| 5552 | if (th->ack && tcp_ack(sk, skb, FLAG_SLOWPATH) < 0) | 5554 | if (th->ack && tcp_ack(sk, skb, FLAG_SLOWPATH) < 0) |
| 5553 | goto discard; | 5555 | goto discard; |
| 5554 | 5556 | ||
| 5557 | /* ts_recent update must be made after we are sure that the packet | ||
| 5558 | * is in window. | ||
| 5559 | */ | ||
| 5560 | tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq); | ||
| 5561 | |||
| 5555 | tcp_rcv_rtt_measure_ts(sk, skb); | 5562 | tcp_rcv_rtt_measure_ts(sk, skb); |
| 5556 | 5563 | ||
| 5557 | /* Process urgent data. */ | 5564 | /* Process urgent data. */ |
| @@ -5645,7 +5652,11 @@ static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack, | |||
| 5645 | tcp_fastopen_cache_set(sk, mss, cookie, syn_drop); | 5652 | tcp_fastopen_cache_set(sk, mss, cookie, syn_drop); |
| 5646 | 5653 | ||
| 5647 | if (data) { /* Retransmit unacked data in SYN */ | 5654 | if (data) { /* Retransmit unacked data in SYN */ |
| 5648 | tcp_retransmit_skb(sk, data); | 5655 | tcp_for_write_queue_from(data, sk) { |
| 5656 | if (data == tcp_send_head(sk) || | ||
| 5657 | __tcp_retransmit_skb(sk, data)) | ||
| 5658 | break; | ||
| 5659 | } | ||
| 5649 | tcp_rearm_rto(sk); | 5660 | tcp_rearm_rto(sk); |
| 5650 | return true; | 5661 | return true; |
| 5651 | } | 5662 | } |
| @@ -5988,7 +5999,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
| 5988 | */ | 5999 | */ |
| 5989 | if (req) { | 6000 | if (req) { |
| 5990 | tcp_synack_rtt_meas(sk, req); | 6001 | tcp_synack_rtt_meas(sk, req); |
| 5991 | tp->total_retrans = req->retrans; | 6002 | tp->total_retrans = req->num_retrans; |
| 5992 | 6003 | ||
| 5993 | reqsk_fastopen_remove(sk, req, false); | 6004 | reqsk_fastopen_remove(sk, req, false); |
| 5994 | } else { | 6005 | } else { |
| @@ -6130,6 +6141,11 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
| 6130 | } else | 6141 | } else |
| 6131 | goto discard; | 6142 | goto discard; |
| 6132 | 6143 | ||
| 6144 | /* ts_recent update must be made after we are sure that the packet | ||
| 6145 | * is in window. | ||
| 6146 | */ | ||
| 6147 | tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq); | ||
| 6148 | |||
| 6133 | /* step 6: check the URG bit */ | 6149 | /* step 6: check the URG bit */ |
| 6134 | tcp_urg(sk, skb, th); | 6150 | tcp_urg(sk, skb, th); |
| 6135 | 6151 | ||
