aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/networking/ip-sysctl.txt5
-rw-r--r--include/linux/snmp.h1
-rw-r--r--include/net/tcp.h1
-rw-r--r--net/ipv4/proc.c1
-rw-r--r--net/ipv4/sysctl_net_ipv4.c7
-rw-r--r--net/ipv4/tcp_input.c31
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
568tcp_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
568UDP variables: 573UDP variables:
569 574
570udp_mem - vector of 3 INTEGERs: min, pressure, max 575udp_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;
254extern int sysctl_tcp_thin_dupack; 254extern int sysctl_tcp_thin_dupack;
255extern int sysctl_tcp_early_retrans; 255extern int sysctl_tcp_early_retrans;
256extern int sysctl_tcp_limit_output_bytes; 256extern int sysctl_tcp_limit_output_bytes;
257extern int sysctl_tcp_challenge_ack_limit;
257 258
258extern atomic_long_t tcp_memory_allocated; 259extern atomic_long_t tcp_memory_allocated;
259extern struct percpu_counter tcp_sockets_allocated; 260extern 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;
88int sysctl_tcp_adv_win_scale __read_mostly = 1; 88int sysctl_tcp_adv_win_scale __read_mostly = 1;
89EXPORT_SYMBOL(sysctl_tcp_adv_win_scale); 89EXPORT_SYMBOL(sysctl_tcp_adv_win_scale);
90 90
91/* rfc5961 challenge ack rate limiting */
92int sysctl_tcp_challenge_ack_limit = 100;
93
91int sysctl_tcp_stdurg __read_mostly; 94int sysctl_tcp_stdurg __read_mostly;
92int sysctl_tcp_rfc1337 __read_mostly; 95int sysctl_tcp_rfc1337 __read_mostly;
93int sysctl_tcp_max_orphans __read_mostly = NR_FILE; 96int 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
5253static 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