diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv6/addrconf.c | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 158378e73f0a..5b967c8a617a 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include <linux/socket.h> | 46 | #include <linux/socket.h> |
47 | #include <linux/sockios.h> | 47 | #include <linux/sockios.h> |
48 | #include <linux/net.h> | 48 | #include <linux/net.h> |
49 | #include <linux/inet.h> | ||
49 | #include <linux/in6.h> | 50 | #include <linux/in6.h> |
50 | #include <linux/netdevice.h> | 51 | #include <linux/netdevice.h> |
51 | #include <linux/if_addr.h> | 52 | #include <linux/if_addr.h> |
@@ -102,6 +103,9 @@ | |||
102 | 103 | ||
103 | #define INFINITY_LIFE_TIME 0xFFFFFFFF | 104 | #define INFINITY_LIFE_TIME 0xFFFFFFFF |
104 | 105 | ||
106 | #define IPV6_MAX_STRLEN \ | ||
107 | sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") | ||
108 | |||
105 | static inline u32 cstamp_delta(unsigned long cstamp) | 109 | static inline u32 cstamp_delta(unsigned long cstamp) |
106 | { | 110 | { |
107 | return (cstamp - INITIAL_JIFFIES) * 100UL / HZ; | 111 | return (cstamp - INITIAL_JIFFIES) * 100UL / HZ; |
@@ -202,6 +206,9 @@ static struct ipv6_devconf ipv6_devconf __read_mostly = { | |||
202 | .accept_dad = 1, | 206 | .accept_dad = 1, |
203 | .suppress_frag_ndisc = 1, | 207 | .suppress_frag_ndisc = 1, |
204 | .accept_ra_mtu = 1, | 208 | .accept_ra_mtu = 1, |
209 | .stable_secret = { | ||
210 | .initialized = false, | ||
211 | } | ||
205 | }; | 212 | }; |
206 | 213 | ||
207 | static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = { | 214 | static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = { |
@@ -240,6 +247,9 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = { | |||
240 | .accept_dad = 1, | 247 | .accept_dad = 1, |
241 | .suppress_frag_ndisc = 1, | 248 | .suppress_frag_ndisc = 1, |
242 | .accept_ra_mtu = 1, | 249 | .accept_ra_mtu = 1, |
250 | .stable_secret = { | ||
251 | .initialized = false, | ||
252 | }, | ||
243 | }; | 253 | }; |
244 | 254 | ||
245 | /* Check if a valid qdisc is available */ | 255 | /* Check if a valid qdisc is available */ |
@@ -4430,6 +4440,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf, | |||
4430 | array[DEVCONF_SUPPRESS_FRAG_NDISC] = cnf->suppress_frag_ndisc; | 4440 | array[DEVCONF_SUPPRESS_FRAG_NDISC] = cnf->suppress_frag_ndisc; |
4431 | array[DEVCONF_ACCEPT_RA_FROM_LOCAL] = cnf->accept_ra_from_local; | 4441 | array[DEVCONF_ACCEPT_RA_FROM_LOCAL] = cnf->accept_ra_from_local; |
4432 | array[DEVCONF_ACCEPT_RA_MTU] = cnf->accept_ra_mtu; | 4442 | array[DEVCONF_ACCEPT_RA_MTU] = cnf->accept_ra_mtu; |
4443 | /* we omit DEVCONF_STABLE_SECRET for now */ | ||
4433 | } | 4444 | } |
4434 | 4445 | ||
4435 | static inline size_t inet6_ifla6_size(void) | 4446 | static inline size_t inet6_ifla6_size(void) |
@@ -5074,6 +5085,53 @@ int addrconf_sysctl_proxy_ndp(struct ctl_table *ctl, int write, | |||
5074 | return ret; | 5085 | return ret; |
5075 | } | 5086 | } |
5076 | 5087 | ||
5088 | static int addrconf_sysctl_stable_secret(struct ctl_table *ctl, int write, | ||
5089 | void __user *buffer, size_t *lenp, | ||
5090 | loff_t *ppos) | ||
5091 | { | ||
5092 | int err; | ||
5093 | struct in6_addr addr; | ||
5094 | char str[IPV6_MAX_STRLEN]; | ||
5095 | struct ctl_table lctl = *ctl; | ||
5096 | struct ipv6_stable_secret *secret = ctl->data; | ||
5097 | |||
5098 | lctl.maxlen = IPV6_MAX_STRLEN; | ||
5099 | lctl.data = str; | ||
5100 | |||
5101 | if (!rtnl_trylock()) | ||
5102 | return restart_syscall(); | ||
5103 | |||
5104 | if (!write && !secret->initialized) { | ||
5105 | err = -EIO; | ||
5106 | goto out; | ||
5107 | } | ||
5108 | |||
5109 | if (!write) { | ||
5110 | err = snprintf(str, sizeof(str), "%pI6", | ||
5111 | &secret->secret); | ||
5112 | if (err >= sizeof(str)) { | ||
5113 | err = -EIO; | ||
5114 | goto out; | ||
5115 | } | ||
5116 | } | ||
5117 | |||
5118 | err = proc_dostring(&lctl, write, buffer, lenp, ppos); | ||
5119 | if (err || !write) | ||
5120 | goto out; | ||
5121 | |||
5122 | if (in6_pton(str, -1, addr.in6_u.u6_addr8, -1, NULL) != 1) { | ||
5123 | err = -EIO; | ||
5124 | goto out; | ||
5125 | } | ||
5126 | |||
5127 | secret->initialized = true; | ||
5128 | secret->secret = addr; | ||
5129 | |||
5130 | out: | ||
5131 | rtnl_unlock(); | ||
5132 | |||
5133 | return err; | ||
5134 | } | ||
5077 | 5135 | ||
5078 | static struct addrconf_sysctl_table | 5136 | static struct addrconf_sysctl_table |
5079 | { | 5137 | { |
@@ -5347,6 +5405,13 @@ static struct addrconf_sysctl_table | |||
5347 | .proc_handler = proc_dointvec, | 5405 | .proc_handler = proc_dointvec, |
5348 | }, | 5406 | }, |
5349 | { | 5407 | { |
5408 | .procname = "stable_secret", | ||
5409 | .data = &ipv6_devconf.stable_secret, | ||
5410 | .maxlen = IPV6_MAX_STRLEN, | ||
5411 | .mode = 0600, | ||
5412 | .proc_handler = addrconf_sysctl_stable_secret, | ||
5413 | }, | ||
5414 | { | ||
5350 | /* sentinel */ | 5415 | /* sentinel */ |
5351 | } | 5416 | } |
5352 | }, | 5417 | }, |
@@ -5442,6 +5507,9 @@ static int __net_init addrconf_init_net(struct net *net) | |||
5442 | dflt->autoconf = ipv6_defaults.autoconf; | 5507 | dflt->autoconf = ipv6_defaults.autoconf; |
5443 | dflt->disable_ipv6 = ipv6_defaults.disable_ipv6; | 5508 | dflt->disable_ipv6 = ipv6_defaults.disable_ipv6; |
5444 | 5509 | ||
5510 | dflt->stable_secret.initialized = false; | ||
5511 | all->stable_secret.initialized = false; | ||
5512 | |||
5445 | net->ipv6.devconf_all = all; | 5513 | net->ipv6.devconf_all = all; |
5446 | net->ipv6.devconf_dflt = dflt; | 5514 | net->ipv6.devconf_dflt = dflt; |
5447 | 5515 | ||