udp_blackhole and tcp_blackhole sysctls for Linux. -Frank Denis . diff -ur orig/linux-source-3.2.0/include/net/netns/ipv6.h linux-source-3.2.0/linux-source-3.2.0/include/net/netns/ipv6.h --- orig/linux-source-3.2.0/include/net/netns/ipv6.h 2012-01-04 15:55:44.000000000 -0800 +++ linux-source-3.2.0/linux-source-3.2.0/include/net/netns/ipv6.h 2012-02-03 15:26:57.911212138 -0800 @@ -25,6 +25,8 @@ int ip6_rt_mtu_expires; int ip6_rt_min_advmss; int icmpv6_time; + int udp_blackhole; + int tcp_blackhole; }; struct netns_ipv6 { diff -ur orig/linux-source-3.2.0/include/net/tcp.h linux-source-3.2.0/linux-source-3.2.0/include/net/tcp.h --- orig/linux-source-3.2.0/include/net/tcp.h 2012-01-04 15:55:44.000000000 -0800 +++ linux-source-3.2.0/linux-source-3.2.0/include/net/tcp.h 2012-02-03 14:28:49.580448545 -0800 @@ -251,6 +251,7 @@ extern int sysctl_tcp_cookie_size; extern int sysctl_tcp_thin_linear_timeouts; extern int sysctl_tcp_thin_dupack; +extern int sysctl_tcp_blackhole; extern atomic_long_t tcp_memory_allocated; extern struct percpu_counter tcp_sockets_allocated; diff -ur orig/linux-source-3.2.0/include/net/udp.h linux-source-3.2.0/linux-source-3.2.0/include/net/udp.h --- orig/linux-source-3.2.0/include/net/udp.h 2012-01-04 15:55:44.000000000 -0800 +++ linux-source-3.2.0/linux-source-3.2.0/include/net/udp.h 2012-02-03 14:29:10.011831704 -0800 @@ -111,6 +111,7 @@ extern long sysctl_udp_mem[3]; extern int sysctl_udp_rmem_min; extern int sysctl_udp_wmem_min; +extern int sysctl_udp_blackhole; struct sk_buff; diff -ur orig/linux-source-3.2.0/net/ipv4/sysctl_net_ipv4.c linux-source-3.2.0/linux-source-3.2.0/net/ipv4/sysctl_net_ipv4.c --- orig/linux-source-3.2.0/net/ipv4/sysctl_net_ipv4.c 2012-01-04 15:55:44.000000000 -0800 +++ linux-source-3.2.0/linux-source-3.2.0/net/ipv4/sysctl_net_ipv4.c 2012-02-03 14:27:32.086803007 -0800 @@ -721,6 +721,20 @@ .mode = 0644, .proc_handler = ipv4_ping_group_range, }, + { + .procname = "udp_blackhole", + .data = &sysctl_udp_blackhole, + .maxlen = sizeof(sysctl_udp_blackhole), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { + .procname = "tcp_blackhole", + .data = &sysctl_tcp_blackhole, + .maxlen = sizeof(sysctl_tcp_blackhole), + .mode = 0644, + .proc_handler = proc_dointvec, + }, { } }; diff -ur orig/linux-source-3.2.0/net/ipv4/tcp_ipv4.c linux-source-3.2.0/linux-source-3.2.0/net/ipv4/tcp_ipv4.c --- orig/linux-source-3.2.0/net/ipv4/tcp_ipv4.c 2012-01-04 15:55:44.000000000 -0800 +++ linux-source-3.2.0/linux-source-3.2.0/net/ipv4/tcp_ipv4.c 2012-02-03 15:18:09.905888263 -0800 @@ -75,6 +75,7 @@ #include #include +#include #include #include #include @@ -87,6 +88,8 @@ int sysctl_tcp_low_latency __read_mostly; EXPORT_SYMBOL(sysctl_tcp_low_latency); +int sysctl_tcp_blackhole __read_mostly; +EXPORT_SYMBOL(sysctl_tcp_blackhole); #ifdef CONFIG_TCP_MD5SIG static struct tcp_md5sig_key *tcp_v4_md5_do_lookup(struct sock *sk, @@ -610,6 +613,9 @@ if (skb_rtable(skb)->rt_type != RTN_LOCAL) return; + if (sysctl_tcp_blackhole > 0) + return; + /* Swap the send and the receive. */ memset(&rep, 0, sizeof(rep)); rep.th.dest = th->source; diff -ur orig/linux-source-3.2.0/net/ipv4/udp.c linux-source-3.2.0/linux-source-3.2.0/net/ipv4/udp.c --- orig/linux-source-3.2.0/net/ipv4/udp.c 2012-01-04 15:55:44.000000000 -0800 +++ linux-source-3.2.0/linux-source-3.2.0/net/ipv4/udp.c 2012-02-03 15:17:53.149692232 -0800 @@ -120,6 +120,9 @@ int sysctl_udp_wmem_min __read_mostly; EXPORT_SYMBOL(sysctl_udp_wmem_min); +int sysctl_udp_blackhole __read_mostly; +EXPORT_SYMBOL(sysctl_udp_blackhole); + atomic_long_t udp_memory_allocated; EXPORT_SYMBOL(udp_memory_allocated); @@ -1675,7 +1678,8 @@ goto csum_error; UDP_INC_STATS_BH(net, UDP_MIB_NOPORTS, proto == IPPROTO_UDPLITE); - icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); + if (sysctl_udp_blackhole <= 0) + icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); /* * Hmm. We got an UDP packet to a port to which we diff -ur orig/linux-source-3.2.0/net/ipv6/sysctl_net_ipv6.c linux-source-3.2.0/linux-source-3.2.0/net/ipv6/sysctl_net_ipv6.c --- orig/linux-source-3.2.0/net/ipv6/sysctl_net_ipv6.c 2012-01-04 15:55:44.000000000 -0800 +++ linux-source-3.2.0/linux-source-3.2.0/net/ipv6/sysctl_net_ipv6.c 2012-02-03 15:24:48.756774624 -0800 @@ -48,6 +48,20 @@ .mode = 0644, .proc_handler = proc_dointvec }, + { + .procname = "udp_blackhole", + .data = &init_net.ipv6.sysctl.udp_blackhole, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, + { + .procname = "tcp_blackhole", + .data = &init_net.ipv6.sysctl.tcp_blackhole, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, { } }; diff -ur orig/linux-source-3.2.0/net/ipv6/tcp_ipv6.c linux-source-3.2.0/linux-source-3.2.0/net/ipv6/tcp_ipv6.c --- orig/linux-source-3.2.0/net/ipv6/tcp_ipv6.c 2012-01-04 15:55:44.000000000 -0800 +++ linux-source-3.2.0/linux-source-3.2.0/net/ipv6/tcp_ipv6.c 2012-02-03 16:19:30.342931290 -0800 @@ -1783,6 +1783,7 @@ bad_packet: TCP_INC_STATS_BH(net, TCP_MIB_INERRS); } else { + if (init_net.ipv6.sysctl.tcp_blackhole <= 0) tcp_v6_send_reset(NULL, skb); } diff -ur orig/linux-source-3.2.0/net/ipv6/udp.c linux-source-3.2.0/linux-source-3.2.0/net/ipv6/udp.c --- orig/linux-source-3.2.0/net/ipv6/udp.c 2012-01-04 15:55:44.000000000 -0800 +++ linux-source-3.2.0/linux-source-3.2.0/net/ipv6/udp.c 2012-02-03 16:15:54.526934850 -0800 @@ -779,8 +779,8 @@ goto discard; UDP6_INC_STATS_BH(net, UDP_MIB_NOPORTS, proto == IPPROTO_UDPLITE); - - icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0); + if (init_net.ipv6.sysctl.udp_blackhole <= 0) + icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0); kfree_skb(skb); return 0;