Commit d934a707 authored by Stephen Hemminger's avatar Stephen Hemminger

[NET]: Cleanup net-sysfs show and change functions.

parent faf460c4
......@@ -3,10 +3,6 @@
*
* Copyright (c) 2003 Stephen Hemminber <shemminger@osdl.org>
*
*
* TODO:
* last_tx
* last_rx
*/
#include <linux/config.h>
......@@ -16,33 +12,61 @@
#include <net/sock.h>
#include <linux/rtnetlink.h>
#define to_net_dev(class) container_of((class), struct net_device, class_dev)
#define to_class_dev(obj) container_of(obj,struct class_device,kobj)
#define to_net_dev(class) container_of(class, struct net_device, class_dev)
/* use same locking rules as GIF* ioctl's */
static ssize_t netdev_show(const struct class_device *cd, char *buf,
ssize_t (*format)(const struct net_device *, char *))
{
struct net_device *net = to_net_dev(cd);
ssize_t ret = -EINVAL;
read_lock(&dev_base_lock);
if (!net->deadbeaf)
ret = (*format)(net, buf);
read_unlock(&dev_base_lock);
return ret;
}
/* generate a show function for simple field */
#define NETDEVICE_SHOW(field, format_string) \
static ssize_t show_##field(struct class_device *dev, char *buf) \
static ssize_t format_##field(const struct net_device *net, char *buf) \
{ \
return sprintf(buf, format_string, to_net_dev(dev)->field); \
return sprintf(buf, format_string, net->field); \
} \
static ssize_t show_##field(struct class_device *cd, char *buf) \
{ \
return netdev_show(cd, buf, format_##field); \
}
/* generate a store function for a field with locking */
#define NETDEVICE_STORE(field) \
static ssize_t \
store_##field(struct class_device *dev, const char *buf, size_t len) \
{ \
char *endp; \
long new = simple_strtol(buf, &endp, 16); \
\
if (endp == buf || new < 0) \
return -EINVAL; \
\
if (!capable(CAP_NET_ADMIN)) \
return -EPERM; \
\
rtnl_lock(); \
to_net_dev(dev)->field = new; \
rtnl_unlock(); \
return len; \
/* use same locking and permission rules as SIF* ioctl's */
static ssize_t netdev_store(struct class_device *dev,
const char *buf, size_t len,
int (*set)(struct net_device *, unsigned long))
{
struct net_device *net = to_net_dev(dev);
char *endp;
unsigned long new;
int ret = -EINVAL;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
new = simple_strtoul(buf, &endp, 0);
if (endp == buf)
goto err;
rtnl_lock();
if (!net->deadbeaf) {
if ((ret = (*set)(net, new)) == 0)
ret = len;
}
rtnl_unlock();
err:
return ret;
}
/* generate a read-only network device class attribute */
......@@ -56,6 +80,7 @@ NETDEVICE_ATTR(ifindex, "%d\n");
NETDEVICE_ATTR(features, "%#x\n");
NETDEVICE_ATTR(type, "%d\n");
/* use same locking rules as GIFHWADDR ioctl's */
static ssize_t format_addr(char *buf, const unsigned char *addr, int len)
{
int i;
......@@ -72,12 +97,16 @@ static ssize_t format_addr(char *buf, const unsigned char *addr, int len)
static ssize_t show_address(struct class_device *dev, char *buf)
{
struct net_device *net = to_net_dev(dev);
if (net->deadbeaf)
return -EINVAL;
return format_addr(buf, net->dev_addr, net->addr_len);
}
static ssize_t show_broadcast(struct class_device *dev, char *buf)
{
struct net_device *net = to_net_dev(dev);
if (net->deadbeaf)
return -EINVAL;
return format_addr(buf, net->broadcast, net->addr_len);
}
......@@ -87,54 +116,45 @@ static CLASS_DEVICE_ATTR(broadcast, S_IRUGO, show_broadcast, NULL);
/* read-write attributes */
NETDEVICE_SHOW(mtu, "%d\n");
static ssize_t store_mtu(struct class_device *dev, const char *buf, size_t len)
static int change_mtu(struct net_device *net, unsigned long new_mtu)
{
char *endp;
int new_mtu;
int err;
new_mtu = simple_strtoul(buf, &endp, 10);
if (endp == buf)
return -EINVAL;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
rtnl_lock();
err = dev_set_mtu(to_net_dev(dev), new_mtu);
rtnl_unlock();
return dev_set_mtu(net, (int) new_mtu);
}
return err == 0 ? len : err;
static ssize_t store_mtu(struct class_device *dev, const char *buf, size_t len)
{
return netdev_store(dev, buf, len, change_mtu);
}
static CLASS_DEVICE_ATTR(mtu, S_IRUGO | S_IWUSR, show_mtu, store_mtu);
NETDEVICE_SHOW(flags, "%#x\n");
static ssize_t store_flags(struct class_device *dev, const char *buf, size_t len)
static int change_flags(struct net_device *net, unsigned long new_flags)
{
unsigned long new_flags;
char *endp;
int err = 0;
return dev_change_flags(net, (unsigned) new_flags);
}
new_flags = simple_strtoul(buf, &endp, 16);
if (endp == buf)
return -EINVAL;
static ssize_t store_flags(struct class_device *dev, const char *buf, size_t len)
{
return netdev_store(dev, buf, len, change_flags);
}
if (!capable(CAP_NET_ADMIN))
return -EPERM;
static CLASS_DEVICE_ATTR(flags, S_IRUGO | S_IWUSR, show_flags, store_flags);
rtnl_lock();
err = dev_change_flags(to_net_dev(dev), new_flags);
rtnl_unlock();
NETDEVICE_SHOW(tx_queue_len, "%lu\n");
return err ? err : len;
static int change_tx_queue_len(struct net_device *net, unsigned long new_len)
{
net->tx_queue_len = new_len;
return 0;
}
static CLASS_DEVICE_ATTR(flags, S_IRUGO | S_IWUSR, show_flags, store_flags);
static ssize_t store_tx_queue_len(struct class_device *dev, const char *buf, size_t len)
{
return netdev_store(dev, buf,len, change_tx_queue_len);
}
NETDEVICE_SHOW(tx_queue_len, "%lu\n");
NETDEVICE_STORE(tx_queue_len);
static CLASS_DEVICE_ATTR(tx_queue_len, S_IRUGO | S_IWUSR, show_tx_queue_len,
store_tx_queue_len);
......@@ -237,16 +257,17 @@ netstat_attr_show(struct kobject *kobj, struct attribute *attr, char *buf)
{
struct netstat_fs_entry *entry
= container_of(attr, struct netstat_fs_entry, attr);
struct class_device *class_dev
= container_of(kobj->parent, struct class_device, kobj);
struct net_device *dev
= to_net_dev(class_dev);
struct net_device_stats *stats
= dev->get_stats ? dev->get_stats(dev) : NULL;
= to_net_dev(to_class_dev(kobj->parent));
struct net_device_stats *stats;
ssize_t ret = -EINVAL;
if (stats && entry->show)
return entry->show(stats, buf);
return -EINVAL;
read_lock(&dev_base_lock);
if (!dev->deadbeaf && entry->show && dev->get_stats &&
(stats = (*dev->get_stats)(dev)))
ret = entry->show(stats, buf);
read_unlock(&dev_base_lock);
return ret;
}
static struct sysfs_ops netstat_sysfs_ops = {
......
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