Commit 3d1bec99 authored by Hannes Frederic Sowa's avatar Hannes Frederic Sowa Committed by David S. Miller

ipv6: introduce secret_stable to ipv6_devconf

This patch implements the procfs logic for the stable_address knob:
The secret is formatted as an ipv6 address and will be stored per
interface and per namespace. We track initialized flag and return EIO
errors until the secret is set.

We don't inherit the secret to newly created namespaces.

Cc: Erik Kline <ek@google.com>
Cc: Fernando Gont <fgont@si6networks.com>
Cc: Lorenzo Colitti <lorenzo@google.com>
Cc: YOSHIFUJI Hideaki/吉藤英明 <hideaki.yoshifuji@miraclelinux.com>
Signed-off-by: default avatarHannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ab2bb324
...@@ -53,6 +53,10 @@ struct ipv6_devconf { ...@@ -53,6 +53,10 @@ struct ipv6_devconf {
__s32 ndisc_notify; __s32 ndisc_notify;
__s32 suppress_frag_ndisc; __s32 suppress_frag_ndisc;
__s32 accept_ra_mtu; __s32 accept_ra_mtu;
struct ipv6_stable_secret {
bool initialized;
struct in6_addr secret;
} stable_secret;
void *sysctl; void *sysctl;
}; };
......
...@@ -170,6 +170,7 @@ enum { ...@@ -170,6 +170,7 @@ enum {
DEVCONF_ACCEPT_RA_FROM_LOCAL, DEVCONF_ACCEPT_RA_FROM_LOCAL,
DEVCONF_USE_OPTIMISTIC, DEVCONF_USE_OPTIMISTIC,
DEVCONF_ACCEPT_RA_MTU, DEVCONF_ACCEPT_RA_MTU,
DEVCONF_STABLE_SECRET,
DEVCONF_MAX DEVCONF_MAX
}; };
......
...@@ -46,6 +46,7 @@ ...@@ -46,6 +46,7 @@
#include <linux/socket.h> #include <linux/socket.h>
#include <linux/sockios.h> #include <linux/sockios.h>
#include <linux/net.h> #include <linux/net.h>
#include <linux/inet.h>
#include <linux/in6.h> #include <linux/in6.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/if_addr.h> #include <linux/if_addr.h>
...@@ -102,6 +103,9 @@ ...@@ -102,6 +103,9 @@
#define INFINITY_LIFE_TIME 0xFFFFFFFF #define INFINITY_LIFE_TIME 0xFFFFFFFF
#define IPV6_MAX_STRLEN \
sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")
static inline u32 cstamp_delta(unsigned long cstamp) static inline u32 cstamp_delta(unsigned long cstamp)
{ {
return (cstamp - INITIAL_JIFFIES) * 100UL / HZ; return (cstamp - INITIAL_JIFFIES) * 100UL / HZ;
...@@ -202,6 +206,9 @@ static struct ipv6_devconf ipv6_devconf __read_mostly = { ...@@ -202,6 +206,9 @@ static struct ipv6_devconf ipv6_devconf __read_mostly = {
.accept_dad = 1, .accept_dad = 1,
.suppress_frag_ndisc = 1, .suppress_frag_ndisc = 1,
.accept_ra_mtu = 1, .accept_ra_mtu = 1,
.stable_secret = {
.initialized = false,
}
}; };
static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = { static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
...@@ -240,6 +247,9 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = { ...@@ -240,6 +247,9 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
.accept_dad = 1, .accept_dad = 1,
.suppress_frag_ndisc = 1, .suppress_frag_ndisc = 1,
.accept_ra_mtu = 1, .accept_ra_mtu = 1,
.stable_secret = {
.initialized = false,
},
}; };
/* Check if a valid qdisc is available */ /* Check if a valid qdisc is available */
...@@ -4430,6 +4440,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf, ...@@ -4430,6 +4440,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
array[DEVCONF_SUPPRESS_FRAG_NDISC] = cnf->suppress_frag_ndisc; array[DEVCONF_SUPPRESS_FRAG_NDISC] = cnf->suppress_frag_ndisc;
array[DEVCONF_ACCEPT_RA_FROM_LOCAL] = cnf->accept_ra_from_local; array[DEVCONF_ACCEPT_RA_FROM_LOCAL] = cnf->accept_ra_from_local;
array[DEVCONF_ACCEPT_RA_MTU] = cnf->accept_ra_mtu; array[DEVCONF_ACCEPT_RA_MTU] = cnf->accept_ra_mtu;
/* we omit DEVCONF_STABLE_SECRET for now */
} }
static inline size_t inet6_ifla6_size(void) static inline size_t inet6_ifla6_size(void)
...@@ -5074,6 +5085,53 @@ int addrconf_sysctl_proxy_ndp(struct ctl_table *ctl, int write, ...@@ -5074,6 +5085,53 @@ int addrconf_sysctl_proxy_ndp(struct ctl_table *ctl, int write,
return ret; return ret;
} }
static int addrconf_sysctl_stable_secret(struct ctl_table *ctl, int write,
void __user *buffer, size_t *lenp,
loff_t *ppos)
{
int err;
struct in6_addr addr;
char str[IPV6_MAX_STRLEN];
struct ctl_table lctl = *ctl;
struct ipv6_stable_secret *secret = ctl->data;
lctl.maxlen = IPV6_MAX_STRLEN;
lctl.data = str;
if (!rtnl_trylock())
return restart_syscall();
if (!write && !secret->initialized) {
err = -EIO;
goto out;
}
if (!write) {
err = snprintf(str, sizeof(str), "%pI6",
&secret->secret);
if (err >= sizeof(str)) {
err = -EIO;
goto out;
}
}
err = proc_dostring(&lctl, write, buffer, lenp, ppos);
if (err || !write)
goto out;
if (in6_pton(str, -1, addr.in6_u.u6_addr8, -1, NULL) != 1) {
err = -EIO;
goto out;
}
secret->initialized = true;
secret->secret = addr;
out:
rtnl_unlock();
return err;
}
static struct addrconf_sysctl_table static struct addrconf_sysctl_table
{ {
...@@ -5346,6 +5404,13 @@ static struct addrconf_sysctl_table ...@@ -5346,6 +5404,13 @@ static struct addrconf_sysctl_table
.mode = 0644, .mode = 0644,
.proc_handler = proc_dointvec, .proc_handler = proc_dointvec,
}, },
{
.procname = "stable_secret",
.data = &ipv6_devconf.stable_secret,
.maxlen = IPV6_MAX_STRLEN,
.mode = 0600,
.proc_handler = addrconf_sysctl_stable_secret,
},
{ {
/* sentinel */ /* sentinel */
} }
...@@ -5442,6 +5507,9 @@ static int __net_init addrconf_init_net(struct net *net) ...@@ -5442,6 +5507,9 @@ static int __net_init addrconf_init_net(struct net *net)
dflt->autoconf = ipv6_defaults.autoconf; dflt->autoconf = ipv6_defaults.autoconf;
dflt->disable_ipv6 = ipv6_defaults.disable_ipv6; dflt->disable_ipv6 = ipv6_defaults.disable_ipv6;
dflt->stable_secret.initialized = false;
all->stable_secret.initialized = false;
net->ipv6.devconf_all = all; net->ipv6.devconf_all = all;
net->ipv6.devconf_dflt = dflt; net->ipv6.devconf_dflt = dflt;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment