Skip to content

Commit

Permalink
ipv6: introduce secret_stable to ipv6_devconf
Browse files Browse the repository at this point in the history
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: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Hannes Frederic Sowa authored and David S. Miller committed Mar 24, 2015
1 parent ab2bb32 commit 3d1bec9
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 0 deletions.
4 changes: 4 additions & 0 deletions include/linux/ipv6.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ struct ipv6_devconf {
__s32 ndisc_notify;
__s32 suppress_frag_ndisc;
__s32 accept_ra_mtu;
struct ipv6_stable_secret {
bool initialized;
struct in6_addr secret;
} stable_secret;
void *sysctl;
};

Expand Down
1 change: 1 addition & 0 deletions include/uapi/linux/ipv6.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ enum {
DEVCONF_ACCEPT_RA_FROM_LOCAL,
DEVCONF_USE_OPTIMISTIC,
DEVCONF_ACCEPT_RA_MTU,
DEVCONF_STABLE_SECRET,
DEVCONF_MAX
};

Expand Down
68 changes: 68 additions & 0 deletions net/ipv6/addrconf.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
#include <linux/socket.h>
#include <linux/sockios.h>
#include <linux/net.h>
#include <linux/inet.h>
#include <linux/in6.h>
#include <linux/netdevice.h>
#include <linux/if_addr.h>
Expand Down Expand Up @@ -102,6 +103,9 @@

#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)
{
return (cstamp - INITIAL_JIFFIES) * 100UL / HZ;
Expand Down Expand Up @@ -202,6 +206,9 @@ static struct ipv6_devconf ipv6_devconf __read_mostly = {
.accept_dad = 1,
.suppress_frag_ndisc = 1,
.accept_ra_mtu = 1,
.stable_secret = {
.initialized = false,
}
};

static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
Expand Down Expand Up @@ -240,6 +247,9 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
.accept_dad = 1,
.suppress_frag_ndisc = 1,
.accept_ra_mtu = 1,
.stable_secret = {
.initialized = false,
},
};

/* Check if a valid qdisc is available */
Expand Down Expand Up @@ -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_ACCEPT_RA_FROM_LOCAL] = cnf->accept_ra_from_local;
array[DEVCONF_ACCEPT_RA_MTU] = cnf->accept_ra_mtu;
/* we omit DEVCONF_STABLE_SECRET for now */
}

static inline size_t inet6_ifla6_size(void)
Expand Down Expand Up @@ -5074,6 +5085,53 @@ int addrconf_sysctl_proxy_ndp(struct ctl_table *ctl, int write,
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
{
Expand Down Expand Up @@ -5346,6 +5404,13 @@ static struct addrconf_sysctl_table
.mode = 0644,
.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 */
}
Expand Down Expand Up @@ -5442,6 +5507,9 @@ static int __net_init addrconf_init_net(struct net *net)
dflt->autoconf = ipv6_defaults.autoconf;
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_dflt = dflt;

Expand Down

0 comments on commit 3d1bec9

Please sign in to comment.