aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/ipv6/addrconf.c68
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
105static inline u32 cstamp_delta(unsigned long cstamp) 109static 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
207static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = { 214static 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
4435static inline size_t inet6_ifla6_size(void) 4446static 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
5088static 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
5130out:
5131 rtnl_unlock();
5132
5133 return err;
5134}
5077 5135
5078static struct addrconf_sysctl_table 5136static 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