diff options
-rw-r--r-- | include/net/tcp.h | 32 | ||||
-rw-r--r-- | net/ipv4/tcp_input.c | 30 |
2 files changed, 32 insertions, 30 deletions
diff --git a/include/net/tcp.h b/include/net/tcp.h index 9fe1d535cd6c..5b29835b81d8 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h | |||
@@ -1216,36 +1216,8 @@ static inline bool tcp_paws_reject(const struct tcp_options_received *rx_opt, | |||
1216 | return true; | 1216 | return true; |
1217 | } | 1217 | } |
1218 | 1218 | ||
1219 | /* Return true if we're currently rate-limiting out-of-window ACKs and | 1219 | bool tcp_oow_rate_limited(struct net *net, const struct sk_buff *skb, |
1220 | * thus shouldn't send a dupack right now. We rate-limit dupacks in | 1220 | int mib_idx, u32 *last_oow_ack_time); |
1221 | * response to out-of-window SYNs or ACKs to mitigate ACK loops or DoS | ||
1222 | * attacks that send repeated SYNs or ACKs for the same connection. To | ||
1223 | * do this, we do not send a duplicate SYNACK or ACK if the remote | ||
1224 | * endpoint is sending out-of-window SYNs or pure ACKs at a high rate. | ||
1225 | */ | ||
1226 | static inline bool tcp_oow_rate_limited(struct net *net, | ||
1227 | const struct sk_buff *skb, | ||
1228 | int mib_idx, u32 *last_oow_ack_time) | ||
1229 | { | ||
1230 | /* Data packets without SYNs are not likely part of an ACK loop. */ | ||
1231 | if ((TCP_SKB_CB(skb)->seq != TCP_SKB_CB(skb)->end_seq) && | ||
1232 | !tcp_hdr(skb)->syn) | ||
1233 | goto not_rate_limited; | ||
1234 | |||
1235 | if (*last_oow_ack_time) { | ||
1236 | s32 elapsed = (s32)(tcp_time_stamp - *last_oow_ack_time); | ||
1237 | |||
1238 | if (0 <= elapsed && elapsed < sysctl_tcp_invalid_ratelimit) { | ||
1239 | NET_INC_STATS_BH(net, mib_idx); | ||
1240 | return true; /* rate-limited: don't send yet! */ | ||
1241 | } | ||
1242 | } | ||
1243 | |||
1244 | *last_oow_ack_time = tcp_time_stamp; | ||
1245 | |||
1246 | not_rate_limited: | ||
1247 | return false; /* not rate-limited: go ahead, send dupack now! */ | ||
1248 | } | ||
1249 | 1221 | ||
1250 | static inline void tcp_mib_init(struct net *net) | 1222 | static inline void tcp_mib_init(struct net *net) |
1251 | { | 1223 | { |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 10d6bd93f229..7257eb206c07 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -3321,6 +3321,36 @@ static int tcp_ack_update_window(struct sock *sk, const struct sk_buff *skb, u32 | |||
3321 | return flag; | 3321 | return flag; |
3322 | } | 3322 | } |
3323 | 3323 | ||
3324 | /* Return true if we're currently rate-limiting out-of-window ACKs and | ||
3325 | * thus shouldn't send a dupack right now. We rate-limit dupacks in | ||
3326 | * response to out-of-window SYNs or ACKs to mitigate ACK loops or DoS | ||
3327 | * attacks that send repeated SYNs or ACKs for the same connection. To | ||
3328 | * do this, we do not send a duplicate SYNACK or ACK if the remote | ||
3329 | * endpoint is sending out-of-window SYNs or pure ACKs at a high rate. | ||
3330 | */ | ||
3331 | bool tcp_oow_rate_limited(struct net *net, const struct sk_buff *skb, | ||
3332 | int mib_idx, u32 *last_oow_ack_time) | ||
3333 | { | ||
3334 | /* Data packets without SYNs are not likely part of an ACK loop. */ | ||
3335 | if ((TCP_SKB_CB(skb)->seq != TCP_SKB_CB(skb)->end_seq) && | ||
3336 | !tcp_hdr(skb)->syn) | ||
3337 | goto not_rate_limited; | ||
3338 | |||
3339 | if (*last_oow_ack_time) { | ||
3340 | s32 elapsed = (s32)(tcp_time_stamp - *last_oow_ack_time); | ||
3341 | |||
3342 | if (0 <= elapsed && elapsed < sysctl_tcp_invalid_ratelimit) { | ||
3343 | NET_INC_STATS_BH(net, mib_idx); | ||
3344 | return true; /* rate-limited: don't send yet! */ | ||
3345 | } | ||
3346 | } | ||
3347 | |||
3348 | *last_oow_ack_time = tcp_time_stamp; | ||
3349 | |||
3350 | not_rate_limited: | ||
3351 | return false; /* not rate-limited: go ahead, send dupack now! */ | ||
3352 | } | ||
3353 | |||
3324 | /* RFC 5961 7 [ACK Throttling] */ | 3354 | /* RFC 5961 7 [ACK Throttling] */ |
3325 | static void tcp_send_challenge_ack(struct sock *sk, const struct sk_buff *skb) | 3355 | static void tcp_send_challenge_ack(struct sock *sk, const struct sk_buff *skb) |
3326 | { | 3356 | { |