aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/sysctl.h1
-rw-r--r--include/net/ip.h3
-rw-r--r--kernel/sysctl_binary.c2
-rw-r--r--net/ipv4/ip_input.c22
-rw-r--r--net/ipv4/sysctl_net_ipv4.c7
5 files changed, 26 insertions, 9 deletions
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index c34b4c82b0dc..20825e5f433f 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -425,6 +425,7 @@ enum
425 NET_TCP_ALLOWED_CONG_CONTROL=123, 425 NET_TCP_ALLOWED_CONG_CONTROL=123,
426 NET_TCP_MAX_SSTHRESH=124, 426 NET_TCP_MAX_SSTHRESH=124,
427 NET_TCP_FRTO_RESPONSE=125, 427 NET_TCP_FRTO_RESPONSE=125,
428 NET_IPV4_EARLY_DEMUX=126,
428}; 429};
429 430
430enum { 431enum {
diff --git a/include/net/ip.h b/include/net/ip.h
index 83e0619f59d0..50841bd6f10e 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -210,6 +210,9 @@ extern int inet_peer_threshold;
210extern int inet_peer_minttl; 210extern int inet_peer_minttl;
211extern int inet_peer_maxttl; 211extern int inet_peer_maxttl;
212 212
213/* From ip_input.c */
214extern int sysctl_ip_early_demux;
215
213/* From ip_output.c */ 216/* From ip_output.c */
214extern int sysctl_ip_dynaddr; 217extern int sysctl_ip_dynaddr;
215 218
diff --git a/kernel/sysctl_binary.c b/kernel/sysctl_binary.c
index a650694883a1..6a3cf8253aae 100644
--- a/kernel/sysctl_binary.c
+++ b/kernel/sysctl_binary.c
@@ -415,6 +415,8 @@ static const struct bin_table bin_net_ipv4_table[] = {
415 { CTL_INT, NET_IPV4_IPFRAG_SECRET_INTERVAL, "ipfrag_secret_interval" }, 415 { CTL_INT, NET_IPV4_IPFRAG_SECRET_INTERVAL, "ipfrag_secret_interval" },
416 /* NET_IPV4_IPFRAG_MAX_DIST "ipfrag_max_dist" no longer used */ 416 /* NET_IPV4_IPFRAG_MAX_DIST "ipfrag_max_dist" no longer used */
417 417
418 { CTL_INT, NET_IPV4_EARLY_DEMUX, "ip_early_demux" },
419
418 { CTL_INT, 2088 /* NET_IPQ_QMAX */, "ip_queue_maxlen" }, 420 { CTL_INT, 2088 /* NET_IPQ_QMAX */, "ip_queue_maxlen" },
419 421
420 /* NET_TCP_DEFAULT_WIN_SCALE unused */ 422 /* NET_TCP_DEFAULT_WIN_SCALE unused */
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index 93b092c9a394..bca25179cdb9 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -313,6 +313,8 @@ drop:
313 return true; 313 return true;
314} 314}
315 315
316int sysctl_ip_early_demux __read_mostly = 1;
317
316static int ip_rcv_finish(struct sk_buff *skb) 318static int ip_rcv_finish(struct sk_buff *skb)
317{ 319{
318 const struct iphdr *iph = ip_hdr(skb); 320 const struct iphdr *iph = ip_hdr(skb);
@@ -323,16 +325,18 @@ static int ip_rcv_finish(struct sk_buff *skb)
323 * how the packet travels inside Linux networking. 325 * how the packet travels inside Linux networking.
324 */ 326 */
325 if (skb_dst(skb) == NULL) { 327 if (skb_dst(skb) == NULL) {
326 const struct net_protocol *ipprot; 328 int err = -ENOENT;
327 int protocol = iph->protocol;
328 int err;
329 329
330 rcu_read_lock(); 330 if (sysctl_ip_early_demux) {
331 ipprot = rcu_dereference(inet_protos[protocol]); 331 const struct net_protocol *ipprot;
332 err = -ENOENT; 332 int protocol = iph->protocol;
333 if (ipprot && ipprot->early_demux) 333
334 err = ipprot->early_demux(skb); 334 rcu_read_lock();
335 rcu_read_unlock(); 335 ipprot = rcu_dereference(inet_protos[protocol]);
336 if (ipprot && ipprot->early_demux)
337 err = ipprot->early_demux(skb);
338 rcu_read_unlock();
339 }
336 340
337 if (err) { 341 if (err) {
338 err = ip_route_input_noref(skb, iph->daddr, iph->saddr, 342 err = ip_route_input_noref(skb, iph->daddr, iph->saddr,
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index ef32956ed655..12aa0c5867c4 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -301,6 +301,13 @@ static struct ctl_table ipv4_table[] = {
301 .proc_handler = proc_dointvec 301 .proc_handler = proc_dointvec
302 }, 302 },
303 { 303 {
304 .procname = "ip_early_demux",
305 .data = &sysctl_ip_early_demux,
306 .maxlen = sizeof(int),
307 .mode = 0644,
308 .proc_handler = proc_dointvec
309 },
310 {
304 .procname = "ip_dynaddr", 311 .procname = "ip_dynaddr",
305 .data = &sysctl_ip_dynaddr, 312 .data = &sysctl_ip_dynaddr,
306 .maxlen = sizeof(int), 313 .maxlen = sizeof(int),