diff options
-rw-r--r-- | Documentation/networking/ip-sysctl.txt | 5 | ||||
-rw-r--r-- | include/linux/snmp.h | 1 | ||||
-rw-r--r-- | include/net/tcp.h | 1 | ||||
-rw-r--r-- | net/ipv4/proc.c | 1 | ||||
-rw-r--r-- | net/ipv4/sysctl_net_ipv4.c | 7 | ||||
-rw-r--r-- | net/ipv4/tcp_input.c | 31 |
6 files changed, 45 insertions, 1 deletions
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index e20c17a7d34e..e1e021594cff 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt | |||
@@ -565,6 +565,11 @@ tcp_limit_output_bytes - INTEGER | |||
565 | reduce the size of individual GSO packet (64KB being the max) | 565 | reduce the size of individual GSO packet (64KB being the max) |
566 | Default: 131072 | 566 | Default: 131072 |
567 | 567 | ||
568 | tcp_challenge_ack_limit - INTEGER | ||
569 | Limits number of Challenge ACK sent per second, as recommended | ||
570 | in RFC 5961 (Improving TCP's Robustness to Blind In-Window Attacks) | ||
571 | Default: 100 | ||
572 | |||
568 | UDP variables: | 573 | UDP variables: |
569 | 574 | ||
570 | udp_mem - vector of 3 INTEGERs: min, pressure, max | 575 | udp_mem - vector of 3 INTEGERs: min, pressure, max |
diff --git a/include/linux/snmp.h b/include/linux/snmp.h index 6e4c51123828..673e0e928b2b 100644 --- a/include/linux/snmp.h +++ b/include/linux/snmp.h | |||
@@ -237,6 +237,7 @@ enum | |||
237 | LINUX_MIB_TCPOFOQUEUE, /* TCPOFOQueue */ | 237 | LINUX_MIB_TCPOFOQUEUE, /* TCPOFOQueue */ |
238 | LINUX_MIB_TCPOFODROP, /* TCPOFODrop */ | 238 | LINUX_MIB_TCPOFODROP, /* TCPOFODrop */ |
239 | LINUX_MIB_TCPOFOMERGE, /* TCPOFOMerge */ | 239 | LINUX_MIB_TCPOFOMERGE, /* TCPOFOMerge */ |
240 | LINUX_MIB_TCPCHALLENGEACK, /* TCPChallengeACK */ | ||
240 | __LINUX_MIB_MAX | 241 | __LINUX_MIB_MAX |
241 | }; | 242 | }; |
242 | 243 | ||
diff --git a/include/net/tcp.h b/include/net/tcp.h index 439984b9af49..85c5090bfe25 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h | |||
@@ -254,6 +254,7 @@ extern int sysctl_tcp_thin_linear_timeouts; | |||
254 | extern int sysctl_tcp_thin_dupack; | 254 | extern int sysctl_tcp_thin_dupack; |
255 | extern int sysctl_tcp_early_retrans; | 255 | extern int sysctl_tcp_early_retrans; |
256 | extern int sysctl_tcp_limit_output_bytes; | 256 | extern int sysctl_tcp_limit_output_bytes; |
257 | extern int sysctl_tcp_challenge_ack_limit; | ||
257 | 258 | ||
258 | extern atomic_long_t tcp_memory_allocated; | 259 | extern atomic_long_t tcp_memory_allocated; |
259 | extern struct percpu_counter tcp_sockets_allocated; | 260 | extern struct percpu_counter tcp_sockets_allocated; |
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index dae25e7622cf..3e8e78f12a38 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c | |||
@@ -261,6 +261,7 @@ static const struct snmp_mib snmp4_net_list[] = { | |||
261 | SNMP_MIB_ITEM("TCPOFOQueue", LINUX_MIB_TCPOFOQUEUE), | 261 | SNMP_MIB_ITEM("TCPOFOQueue", LINUX_MIB_TCPOFOQUEUE), |
262 | SNMP_MIB_ITEM("TCPOFODrop", LINUX_MIB_TCPOFODROP), | 262 | SNMP_MIB_ITEM("TCPOFODrop", LINUX_MIB_TCPOFODROP), |
263 | SNMP_MIB_ITEM("TCPOFOMerge", LINUX_MIB_TCPOFOMERGE), | 263 | SNMP_MIB_ITEM("TCPOFOMerge", LINUX_MIB_TCPOFOMERGE), |
264 | SNMP_MIB_ITEM("TCPChallengeACK", LINUX_MIB_TCPCHALLENGEACK), | ||
264 | SNMP_MIB_SENTINEL | 265 | SNMP_MIB_SENTINEL |
265 | }; | 266 | }; |
266 | 267 | ||
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 70730f7aeafe..3f6a1e762e9c 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c | |||
@@ -605,6 +605,13 @@ static struct ctl_table ipv4_table[] = { | |||
605 | .mode = 0644, | 605 | .mode = 0644, |
606 | .proc_handler = proc_dointvec | 606 | .proc_handler = proc_dointvec |
607 | }, | 607 | }, |
608 | { | ||
609 | .procname = "tcp_challenge_ack_limit", | ||
610 | .data = &sysctl_tcp_challenge_ack_limit, | ||
611 | .maxlen = sizeof(int), | ||
612 | .mode = 0644, | ||
613 | .proc_handler = proc_dointvec | ||
614 | }, | ||
608 | #ifdef CONFIG_NET_DMA | 615 | #ifdef CONFIG_NET_DMA |
609 | { | 616 | { |
610 | .procname = "tcp_dma_copybreak", | 617 | .procname = "tcp_dma_copybreak", |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index cc4e12f1f2f7..c841a8990377 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -88,6 +88,9 @@ int sysctl_tcp_app_win __read_mostly = 31; | |||
88 | int sysctl_tcp_adv_win_scale __read_mostly = 1; | 88 | int sysctl_tcp_adv_win_scale __read_mostly = 1; |
89 | EXPORT_SYMBOL(sysctl_tcp_adv_win_scale); | 89 | EXPORT_SYMBOL(sysctl_tcp_adv_win_scale); |
90 | 90 | ||
91 | /* rfc5961 challenge ack rate limiting */ | ||
92 | int sysctl_tcp_challenge_ack_limit = 100; | ||
93 | |||
91 | int sysctl_tcp_stdurg __read_mostly; | 94 | int sysctl_tcp_stdurg __read_mostly; |
92 | int sysctl_tcp_rfc1337 __read_mostly; | 95 | int sysctl_tcp_rfc1337 __read_mostly; |
93 | int sysctl_tcp_max_orphans __read_mostly = NR_FILE; | 96 | int sysctl_tcp_max_orphans __read_mostly = NR_FILE; |
@@ -5247,6 +5250,23 @@ out: | |||
5247 | } | 5250 | } |
5248 | #endif /* CONFIG_NET_DMA */ | 5251 | #endif /* CONFIG_NET_DMA */ |
5249 | 5252 | ||
5253 | static void tcp_send_challenge_ack(struct sock *sk) | ||
5254 | { | ||
5255 | /* unprotected vars, we dont care of overwrites */ | ||
5256 | static u32 challenge_timestamp; | ||
5257 | static unsigned int challenge_count; | ||
5258 | u32 now = jiffies / HZ; | ||
5259 | |||
5260 | if (now != challenge_timestamp) { | ||
5261 | challenge_timestamp = now; | ||
5262 | challenge_count = 0; | ||
5263 | } | ||
5264 | if (++challenge_count <= sysctl_tcp_challenge_ack_limit) { | ||
5265 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPCHALLENGEACK); | ||
5266 | tcp_send_ack(sk); | ||
5267 | } | ||
5268 | } | ||
5269 | |||
5250 | /* Does PAWS and seqno based validation of an incoming segment, flags will | 5270 | /* Does PAWS and seqno based validation of an incoming segment, flags will |
5251 | * play significant role here. | 5271 | * play significant role here. |
5252 | */ | 5272 | */ |
@@ -5283,7 +5303,16 @@ static int tcp_validate_incoming(struct sock *sk, struct sk_buff *skb, | |||
5283 | 5303 | ||
5284 | /* Step 2: check RST bit */ | 5304 | /* Step 2: check RST bit */ |
5285 | if (th->rst) { | 5305 | if (th->rst) { |
5286 | tcp_reset(sk); | 5306 | /* RFC 5961 3.2 : |
5307 | * If sequence number exactly matches RCV.NXT, then | ||
5308 | * RESET the connection | ||
5309 | * else | ||
5310 | * Send a challenge ACK | ||
5311 | */ | ||
5312 | if (TCP_SKB_CB(skb)->seq == tp->rcv_nxt) | ||
5313 | tcp_reset(sk); | ||
5314 | else | ||
5315 | tcp_send_challenge_ack(sk); | ||
5287 | goto discard; | 5316 | goto discard; |
5288 | } | 5317 | } |
5289 | 5318 | ||