aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/networking/ip-sysctl.txt4
-rw-r--r--include/linux/ipv6.h2
-rw-r--r--net/ipv6/addrconf.c11
-rw-r--r--net/ipv6/ip6_input.c3
-rw-r--r--net/ipv6/ip6_output.c7
5 files changed, 26 insertions, 1 deletions
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index 71c7bea97160..dae980e8f1b9 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -1025,6 +1025,10 @@ max_addresses - INTEGER
1025 autoconfigured addresses. 1025 autoconfigured addresses.
1026 Default: 16 1026 Default: 16
1027 1027
1028disable_ipv6 - BOOLEAN
1029 Disable IPv6 operation.
1030 Default: FALSE (enable IPv6 operation)
1031
1028icmp/*: 1032icmp/*:
1029ratelimit - INTEGER 1033ratelimit - INTEGER
1030 Limit the maximal rates for sending ICMPv6 packets. 1034 Limit the maximal rates for sending ICMPv6 packets.
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index cde056e08181..d9d7f9b69eb4 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -163,6 +163,7 @@ struct ipv6_devconf {
163#ifdef CONFIG_IPV6_MROUTE 163#ifdef CONFIG_IPV6_MROUTE
164 __s32 mc_forwarding; 164 __s32 mc_forwarding;
165#endif 165#endif
166 __s32 disable_ipv6;
166 void *sysctl; 167 void *sysctl;
167}; 168};
168 169
@@ -194,6 +195,7 @@ enum {
194 DEVCONF_OPTIMISTIC_DAD, 195 DEVCONF_OPTIMISTIC_DAD,
195 DEVCONF_ACCEPT_SOURCE_ROUTE, 196 DEVCONF_ACCEPT_SOURCE_ROUTE,
196 DEVCONF_MC_FORWARDING, 197 DEVCONF_MC_FORWARDING,
198 DEVCONF_DISABLE_IPV6,
197 DEVCONF_MAX 199 DEVCONF_MAX
198}; 200};
199 201
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 8b6875f02039..8c5cff50bbed 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -183,6 +183,7 @@ struct ipv6_devconf ipv6_devconf __read_mostly = {
183#endif 183#endif
184 .proxy_ndp = 0, 184 .proxy_ndp = 0,
185 .accept_source_route = 0, /* we do not accept RH0 by default. */ 185 .accept_source_route = 0, /* we do not accept RH0 by default. */
186 .disable_ipv6 = 0,
186}; 187};
187 188
188static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = { 189static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
@@ -215,6 +216,7 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
215#endif 216#endif
216 .proxy_ndp = 0, 217 .proxy_ndp = 0,
217 .accept_source_route = 0, /* we do not accept RH0 by default. */ 218 .accept_source_route = 0, /* we do not accept RH0 by default. */
219 .disable_ipv6 = 0,
218}; 220};
219 221
220/* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */ 222/* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */
@@ -3657,6 +3659,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
3657#ifdef CONFIG_IPV6_MROUTE 3659#ifdef CONFIG_IPV6_MROUTE
3658 array[DEVCONF_MC_FORWARDING] = cnf->mc_forwarding; 3660 array[DEVCONF_MC_FORWARDING] = cnf->mc_forwarding;
3659#endif 3661#endif
3662 array[DEVCONF_DISABLE_IPV6] = cnf->disable_ipv6;
3660} 3663}
3661 3664
3662static inline size_t inet6_if_nlmsg_size(void) 3665static inline size_t inet6_if_nlmsg_size(void)
@@ -4216,6 +4219,14 @@ static struct addrconf_sysctl_table
4216 }, 4219 },
4217#endif 4220#endif
4218 { 4221 {
4222 .ctl_name = CTL_UNNUMBERED,
4223 .procname = "disable_ipv6",
4224 .data = &ipv6_devconf.disable_ipv6,
4225 .maxlen = sizeof(int),
4226 .mode = 0644,
4227 .proc_handler = &proc_dointvec,
4228 },
4229 {
4219 .ctl_name = 0, /* sentinel */ 4230 .ctl_name = 0, /* sentinel */
4220 } 4231 }
4221 }, 4232 },
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 34e5a96623ae..ea81c614dde2 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -71,7 +71,8 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
71 71
72 IP6_INC_STATS_BH(idev, IPSTATS_MIB_INRECEIVES); 72 IP6_INC_STATS_BH(idev, IPSTATS_MIB_INRECEIVES);
73 73
74 if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) { 74 if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL ||
75 !idev || unlikely(idev->cnf.disable_ipv6)) {
75 IP6_INC_STATS_BH(idev, IPSTATS_MIB_INDISCARDS); 76 IP6_INC_STATS_BH(idev, IPSTATS_MIB_INDISCARDS);
76 rcu_read_unlock(); 77 rcu_read_unlock();
77 goto out; 78 goto out;
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 871bdec09edb..0981c1ef3057 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -173,6 +173,13 @@ static inline int ip6_skb_dst_mtu(struct sk_buff *skb)
173 173
174int ip6_output(struct sk_buff *skb) 174int ip6_output(struct sk_buff *skb)
175{ 175{
176 struct inet6_dev *idev = ip6_dst_idev(skb->dst);
177 if (unlikely(idev->cnf.disable_ipv6)) {
178 IP6_INC_STATS(idev, IPSTATS_MIB_OUTDISCARDS);
179 kfree_skb(skb);
180 return 0;
181 }
182
176 if ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) || 183 if ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) ||
177 dst_allfrag(skb->dst)) 184 dst_allfrag(skb->dst))
178 return ip6_fragment(skb, ip6_output2); 185 return ip6_fragment(skb, ip6_output2);