Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 57425
b: refs/heads/master
c: 31be308
h: refs/heads/master
i:
  57423: 2ca2766
v: v3
  • Loading branch information
Herbert Xu authored and David S. Miller committed Jun 7, 2007
1 parent ec9d730 commit 87ef6d5
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 36 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 42f811b8bcdf6695bf74de580b1daf53445e8949
refs/heads/master: 31be308541e990592a2d0a3e77e8e51bd0cea0e0
3 changes: 3 additions & 0 deletions trunk/include/linux/inetdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#ifdef __KERNEL__

#include <linux/bitmap.h>
#include <linux/if.h>
#include <linux/netdevice.h>
#include <linux/rcupdate.h>
Expand All @@ -12,6 +13,7 @@ struct ipv4_devconf
{
void *sysctl;
int data[__NET_IPV4_CONF_MAX - 1];
DECLARE_BITMAP(state, __NET_IPV4_CONF_MAX - 1);
};

extern struct ipv4_devconf ipv4_devconf;
Expand Down Expand Up @@ -53,6 +55,7 @@ static inline void ipv4_devconf_set(struct in_device *in_dev, int index,
int val)
{
index--;
set_bit(index, in_dev->cnf.state);
in_dev->cnf.data[index] = val;
}

Expand Down
133 changes: 98 additions & 35 deletions trunk/net/ipv4/devinet.c
Original file line number Diff line number Diff line change
Expand Up @@ -1244,6 +1244,91 @@ static void rtmsg_ifa(int event, struct in_ifaddr* ifa, struct nlmsghdr *nlh,

#ifdef CONFIG_SYSCTL

static void devinet_copy_dflt_conf(int i)
{
struct net_device *dev;

read_lock(&dev_base_lock);
for_each_netdev(dev) {
struct in_device *in_dev;
rcu_read_lock();
in_dev = __in_dev_get_rcu(dev);
if (in_dev && !test_bit(i, in_dev->cnf.state))
in_dev->cnf.data[i] = ipv4_devconf_dflt.data[i];
rcu_read_unlock();
}
read_unlock(&dev_base_lock);
}

static int devinet_conf_proc(ctl_table *ctl, int write,
struct file* filp, void __user *buffer,
size_t *lenp, loff_t *ppos)
{
int ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);

if (write) {
struct ipv4_devconf *cnf = ctl->extra1;
int i = (int *)ctl->data - cnf->data;

set_bit(i, cnf->state);

if (cnf == &ipv4_devconf_dflt)
devinet_copy_dflt_conf(i);
}

return ret;
}

static int devinet_conf_sysctl(ctl_table *table, int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
void __user *newval, size_t newlen)
{
struct ipv4_devconf *cnf;
int *valp = table->data;
int new;
int i;

if (!newval || !newlen)
return 0;

if (newlen != sizeof(int))
return -EINVAL;

if (get_user(new, (int __user *)newval))
return -EFAULT;

if (new == *valp)
return 0;

if (oldval && oldlenp) {
size_t len;

if (get_user(len, oldlenp))
return -EFAULT;

if (len) {
if (len > table->maxlen)
len = table->maxlen;
if (copy_to_user(oldval, valp, len))
return -EFAULT;
if (put_user(len, oldlenp))
return -EFAULT;
}
}

*valp = new;

cnf = table->extra1;
i = (int *)table->data - cnf->data;

set_bit(i, cnf->state);

if (cnf == &ipv4_devconf_dflt)
devinet_copy_dflt_conf(i);

return 1;
}

void inet_forward_change(void)
{
struct net_device *dev;
Expand Down Expand Up @@ -1302,40 +1387,13 @@ int ipv4_doint_and_flush_strategy(ctl_table *table, int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
void __user *newval, size_t newlen)
{
int *valp = table->data;
int new;

if (!newval || !newlen)
return 0;

if (newlen != sizeof(int))
return -EINVAL;
int ret = devinet_conf_sysctl(table, name, nlen, oldval, oldlenp,
newval, newlen);

if (get_user(new, (int __user *)newval))
return -EFAULT;

if (new == *valp)
return 0;

if (oldval && oldlenp) {
size_t len;

if (get_user(len, oldlenp))
return -EFAULT;

if (len) {
if (len > table->maxlen)
len = table->maxlen;
if (copy_to_user(oldval, valp, len))
return -EFAULT;
if (put_user(len, oldlenp))
return -EFAULT;
}
}
if (ret == 1)
rt_cache_flush(0);

*valp = new;
rt_cache_flush(0);
return 1;
return ret;
}


Expand All @@ -1349,13 +1407,16 @@ int ipv4_doint_and_flush_strategy(ctl_table *table, int __user *name, int nlen,
.mode = mval, \
.proc_handler = proc, \
.strategy = sysctl, \
.extra1 = &ipv4_devconf, \
}

#define DEVINET_SYSCTL_RW_ENTRY(attr, name) \
DEVINET_SYSCTL_ENTRY(attr, name, 0644, &proc_dointvec, NULL)
DEVINET_SYSCTL_ENTRY(attr, name, 0644, devinet_conf_proc, \
devinet_conf_sysctl)

#define DEVINET_SYSCTL_RO_ENTRY(attr, name) \
DEVINET_SYSCTL_ENTRY(attr, name, 0444, &proc_dointvec, NULL)
DEVINET_SYSCTL_ENTRY(attr, name, 0444, devinet_conf_proc, \
devinet_conf_sysctl)

#define DEVINET_SYSCTL_COMPLEX_ENTRY(attr, name, proc, sysctl) \
DEVINET_SYSCTL_ENTRY(attr, name, 0644, proc, sysctl)
Expand All @@ -1374,7 +1435,8 @@ static struct devinet_sysctl_table {
} devinet_sysctl = {
.devinet_vars = {
DEVINET_SYSCTL_COMPLEX_ENTRY(FORWARDING, "forwarding",
devinet_sysctl_forward, NULL),
devinet_sysctl_forward,
devinet_conf_sysctl),
DEVINET_SYSCTL_RO_ENTRY(MC_FORWARDING, "mc_forwarding"),

DEVINET_SYSCTL_RW_ENTRY(ACCEPT_REDIRECTS, "accept_redirects"),
Expand Down Expand Up @@ -1448,6 +1510,7 @@ static void devinet_sysctl_register(struct in_device *in_dev,
return;
for (i = 0; i < ARRAY_SIZE(t->devinet_vars) - 1; i++) {
t->devinet_vars[i].data += (char *)p - (char *)&ipv4_devconf;
t->devinet_vars[i].extra1 = p;
}

if (dev) {
Expand Down

0 comments on commit 87ef6d5

Please sign in to comment.