Эх сурвалжийг харах

ipv6: Add icmp_echo_ignore_all support for ICMPv6

Preventing the kernel from responding to ICMP Echo Requests messages
can be useful in several ways. The sysctl parameter
'icmp_echo_ignore_all' can be used to prevent the kernel from
responding to IPv4 ICMP echo requests. For IPv6 pings, such
a sysctl kernel parameter did not exist.

Add the ability to prevent the kernel from responding to IPv6
ICMP echo requests through the use of the following sysctl
parameter : /proc/sys/net/ipv6/icmp/echo_ignore_all.
Update the documentation to reflect this change.

Signed-off-by: Virgile Jarry <virgile@acceis.fr>
Signed-off-by: David S. Miller <davem@davemloft.net>
Virgile Jarry 7 жил өмнө
parent
commit
e6f86b0f7a

+ 5 - 0
Documentation/networking/ip-sysctl.txt

@@ -1882,6 +1882,11 @@ ratelimit - INTEGER
 	otherwise the minimal space between responses in milliseconds.
 	otherwise the minimal space between responses in milliseconds.
 	Default: 1000
 	Default: 1000
 
 
+echo_ignore_all - BOOLEAN
+	If set non-zero, then the kernel will ignore all ICMP ECHO
+	requests sent to it over the IPv6 protocol.
+	Default: 0
+
 xfrm6_gc_thresh - INTEGER
 xfrm6_gc_thresh - INTEGER
 	The threshold at which we will start garbage collecting for IPv6
 	The threshold at which we will start garbage collecting for IPv6
 	destination cache entries.  At twice this value the system will
 	destination cache entries.  At twice this value the system will

+ 1 - 0
include/net/netns/ipv6.h

@@ -32,6 +32,7 @@ struct netns_sysctl_ipv6 {
 	int flowlabel_consistency;
 	int flowlabel_consistency;
 	int auto_flowlabels;
 	int auto_flowlabels;
 	int icmpv6_time;
 	int icmpv6_time;
+	int icmpv6_echo_ignore_all;
 	int anycast_src_echo_reply;
 	int anycast_src_echo_reply;
 	int ip_nonlocal_bind;
 	int ip_nonlocal_bind;
 	int fwmark_reflect;
 	int fwmark_reflect;

+ 2 - 1
include/uapi/linux/sysctl.h

@@ -575,7 +575,8 @@ enum {
 
 
 /* /proc/sys/net/ipv6/icmp */
 /* /proc/sys/net/ipv6/icmp */
 enum {
 enum {
-	NET_IPV6_ICMP_RATELIMIT=1
+	NET_IPV6_ICMP_RATELIMIT = 1,
+	NET_IPV6_ICMP_ECHO_IGNORE_ALL = 2
 };
 };
 
 
 /* /proc/sys/net/<protocol>/neigh/<dev> */
 /* /proc/sys/net/<protocol>/neigh/<dev> */

+ 1 - 0
net/ipv6/af_inet6.c

@@ -832,6 +832,7 @@ static int __net_init inet6_net_init(struct net *net)
 
 
 	net->ipv6.sysctl.bindv6only = 0;
 	net->ipv6.sysctl.bindv6only = 0;
 	net->ipv6.sysctl.icmpv6_time = 1*HZ;
 	net->ipv6.sysctl.icmpv6_time = 1*HZ;
+	net->ipv6.sysctl.icmpv6_echo_ignore_all = 0;
 	net->ipv6.sysctl.flowlabel_consistency = 1;
 	net->ipv6.sysctl.flowlabel_consistency = 1;
 	net->ipv6.sysctl.auto_flowlabels = IP6_DEFAULT_AUTO_FLOW_LABELS;
 	net->ipv6.sysctl.auto_flowlabels = IP6_DEFAULT_AUTO_FLOW_LABELS;
 	net->ipv6.sysctl.idgen_retries = 3;
 	net->ipv6.sysctl.idgen_retries = 3;

+ 13 - 3
net/ipv6/icmp.c

@@ -794,6 +794,7 @@ out:
 
 
 static int icmpv6_rcv(struct sk_buff *skb)
 static int icmpv6_rcv(struct sk_buff *skb)
 {
 {
+	struct net *net = dev_net(skb->dev);
 	struct net_device *dev = skb->dev;
 	struct net_device *dev = skb->dev;
 	struct inet6_dev *idev = __in6_dev_get(dev);
 	struct inet6_dev *idev = __in6_dev_get(dev);
 	const struct in6_addr *saddr, *daddr;
 	const struct in6_addr *saddr, *daddr;
@@ -843,7 +844,8 @@ static int icmpv6_rcv(struct sk_buff *skb)
 
 
 	switch (type) {
 	switch (type) {
 	case ICMPV6_ECHO_REQUEST:
 	case ICMPV6_ECHO_REQUEST:
-		icmpv6_echo_reply(skb);
+		if (!net->ipv6.sysctl.icmpv6_echo_ignore_all)
+			icmpv6_echo_reply(skb);
 		break;
 		break;
 
 
 	case ICMPV6_ECHO_REPLY:
 	case ICMPV6_ECHO_REPLY:
@@ -1104,6 +1106,13 @@ static struct ctl_table ipv6_icmp_table_template[] = {
 		.mode		= 0644,
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_ms_jiffies,
 		.proc_handler	= proc_dointvec_ms_jiffies,
 	},
 	},
+	{
+		.procname	= "echo_ignore_all",
+		.data		= &init_net.ipv6.sysctl.icmpv6_echo_ignore_all,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler = proc_dointvec,
+	},
 	{ },
 	{ },
 };
 };
 
 
@@ -1115,9 +1124,10 @@ struct ctl_table * __net_init ipv6_icmp_sysctl_init(struct net *net)
 			sizeof(ipv6_icmp_table_template),
 			sizeof(ipv6_icmp_table_template),
 			GFP_KERNEL);
 			GFP_KERNEL);
 
 
-	if (table)
+	if (table) {
 		table[0].data = &net->ipv6.sysctl.icmpv6_time;
 		table[0].data = &net->ipv6.sysctl.icmpv6_time;
-
+		table[1].data = &net->ipv6.sysctl.icmpv6_echo_ignore_all;
+	}
 	return table;
 	return table;
 }
 }
 #endif
 #endif