aboutsummaryrefslogtreecommitdiff
path: root/net/core
diff options
context:
space:
mode:
Diffstat (limited to 'net/core')
-rw-r--r--net/core/datagram.c3
-rw-r--r--net/core/dev.c176
-rw-r--r--net/core/dev_mcast.c26
-rw-r--r--net/core/ethtool.c65
-rw-r--r--net/core/flow.c2
-rw-r--r--net/core/gen_estimator.c81
-rw-r--r--net/core/neighbour.c5
-rw-r--r--net/core/pktgen.c124
-rw-r--r--net/core/rtnetlink.c4
-rw-r--r--net/core/skbuff.c4
-rw-r--r--net/core/sock.c138
-rw-r--r--net/core/utils.c1
12 files changed, 378 insertions, 251 deletions
diff --git a/net/core/datagram.c b/net/core/datagram.c
index cb056f47612..029b93e246b 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -450,6 +450,9 @@ int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb,
__wsum csum;
int chunk = skb->len - hlen;
+ if (!chunk)
+ return 0;
+
/* Skip filled elements.
* Pretty silly, look at memcpy_toiovec, though 8)
*/
diff --git a/net/core/dev.c b/net/core/dev.c
index 13a0d9f6da5..a76021c7120 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -817,7 +817,9 @@ int dev_alloc_name(struct net_device *dev, const char *name)
*/
int dev_change_name(struct net_device *dev, char *newname)
{
+ char oldname[IFNAMSIZ];
int err = 0;
+ int ret;
ASSERT_RTNL();
@@ -827,6 +829,8 @@ int dev_change_name(struct net_device *dev, char *newname)
if (!dev_valid_name(newname))
return -EINVAL;
+ memcpy(oldname, dev->name, IFNAMSIZ);
+
if (strchr(newname, '%')) {
err = dev_alloc_name(dev, newname);
if (err < 0)
@@ -838,10 +842,28 @@ int dev_change_name(struct net_device *dev, char *newname)
else
strlcpy(dev->name, newname, IFNAMSIZ);
+rollback:
device_rename(&dev->dev, dev->name);
+
+ write_lock_bh(&dev_base_lock);
hlist_del(&dev->name_hlist);
hlist_add_head(&dev->name_hlist, dev_name_hash(dev->name));
- raw_notifier_call_chain(&netdev_chain, NETDEV_CHANGENAME, dev);
+ write_unlock_bh(&dev_base_lock);
+
+ ret = raw_notifier_call_chain(&netdev_chain, NETDEV_CHANGENAME, dev);
+ ret = notifier_to_errno(ret);
+
+ if (ret) {
+ if (err) {
+ printk(KERN_ERR
+ "%s: name change rollback failed: %d.\n",
+ dev->name, ret);
+ } else {
+ err = ret;
+ memcpy(dev->name, oldname, IFNAMSIZ);
+ goto rollback;
+ }
+ }
return err;
}
@@ -1054,20 +1076,43 @@ int dev_close(struct net_device *dev)
int register_netdevice_notifier(struct notifier_block *nb)
{
struct net_device *dev;
+ struct net_device *last;
int err;
rtnl_lock();
err = raw_notifier_chain_register(&netdev_chain, nb);
- if (!err) {
- for_each_netdev(dev) {
- nb->notifier_call(nb, NETDEV_REGISTER, dev);
+ if (err)
+ goto unlock;
- if (dev->flags & IFF_UP)
- nb->notifier_call(nb, NETDEV_UP, dev);
- }
+ for_each_netdev(dev) {
+ err = nb->notifier_call(nb, NETDEV_REGISTER, dev);
+ err = notifier_to_errno(err);
+ if (err)
+ goto rollback;
+
+ if (!(dev->flags & IFF_UP))
+ continue;
+
+ nb->notifier_call(nb, NETDEV_UP, dev);
}
+
+unlock:
rtnl_unlock();
return err;
+
+rollback:
+ last = dev;
+ for_each_netdev(dev) {
+ if (dev == last)
+ break;
+
+ if (dev->flags & IFF_UP) {
+ nb->notifier_call(nb, NETDEV_GOING_DOWN, dev);
+ nb->notifier_call(nb, NETDEV_DOWN, dev);
+ }
+ nb->notifier_call(nb, NETDEV_UNREGISTER, dev);
+ }
+ goto unlock;
}
/**
@@ -2629,7 +2674,7 @@ void __dev_set_rx_mode(struct net_device *dev)
return;
if (!netif_device_present(dev))
- return;
+ return;
if (dev->set_rx_mode)
dev->set_rx_mode(dev);
@@ -2715,26 +2760,14 @@ int __dev_addr_add(struct dev_addr_list **list, int *count,
return 0;
}
-void __dev_addr_discard(struct dev_addr_list **list)
-{
- struct dev_addr_list *tmp;
-
- while (*list != NULL) {
- tmp = *list;
- *list = tmp->next;
- if (tmp->da_users > tmp->da_gusers)
- printk("__dev_addr_discard: address leakage! "
- "da_users=%d\n", tmp->da_users);
- kfree(tmp);
- }
-}
-
/**
* dev_unicast_delete - Release secondary unicast address.
* @dev: device
+ * @addr: address to delete
+ * @alen: length of @addr
*
* Release reference to a secondary unicast address and remove it
- * from the device if the reference count drop to zero.
+ * from the device if the reference count drops to zero.
*
* The caller must hold the rtnl_mutex.
*/
@@ -2756,6 +2789,8 @@ EXPORT_SYMBOL(dev_unicast_delete);
/**
* dev_unicast_add - add a secondary unicast address
* @dev: device
+ * @addr: address to delete
+ * @alen: length of @addr
*
* Add a secondary unicast address to the device or increase
* the reference count if it already exists.
@@ -2777,11 +2812,30 @@ int dev_unicast_add(struct net_device *dev, void *addr, int alen)
}
EXPORT_SYMBOL(dev_unicast_add);
-static void dev_unicast_discard(struct net_device *dev)
+static void __dev_addr_discard(struct dev_addr_list **list)
+{
+ struct dev_addr_list *tmp;
+
+ while (*list != NULL) {
+ tmp = *list;
+ *list = tmp->next;
+ if (tmp->da_users > tmp->da_gusers)
+ printk("__dev_addr_discard: address leakage! "
+ "da_users=%d\n", tmp->da_users);
+ kfree(tmp);
+ }
+}
+
+static void dev_addr_discard(struct net_device *dev)
{
netif_tx_lock_bh(dev);
+
__dev_addr_discard(&dev->uc_list);
dev->uc_count = 0;
+
+ __dev_addr_discard(&dev->mc_list);
+ dev->mc_count = 0;
+
netif_tx_unlock_bh(dev);
}
@@ -3328,7 +3382,7 @@ int register_netdevice(struct net_device *dev)
if (!dev_valid_name(dev->name)) {
ret = -EINVAL;
- goto out;
+ goto err_uninit;
}
dev->ifindex = dev_new_index();
@@ -3342,7 +3396,7 @@ int register_netdevice(struct net_device *dev)
= hlist_entry(p, struct net_device, name_hlist);
if (!strncmp(d->name, dev->name, IFNAMSIZ)) {
ret = -EEXIST;
- goto out;
+ goto err_uninit;
}
}
@@ -3402,7 +3456,7 @@ int register_netdevice(struct net_device *dev)
ret = netdev_register_sysfs(dev);
if (ret)
- goto out;
+ goto err_uninit;
dev->reg_state = NETREG_REGISTERED;
/*
@@ -3421,12 +3475,18 @@ int register_netdevice(struct net_device *dev)
write_unlock_bh(&dev_base_lock);
/* Notify protocols, that a new device appeared. */
- raw_notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev);
-
- ret = 0;
+ ret = raw_notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev);
+ ret = notifier_to_errno(ret);
+ if (ret)
+ unregister_netdevice(dev);
out:
return ret;
+
+err_uninit:
+ if (dev->uninit)
+ dev->uninit(dev);
+ goto out;
}
/**
@@ -3619,7 +3679,7 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
/* ensure 32-byte alignment of both the device and private area */
alloc_size = (sizeof(*dev) + NETDEV_ALIGN_CONST +
- (sizeof(struct net_device_subqueue) * queue_count)) &
+ (sizeof(struct net_device_subqueue) * (queue_count - 1))) &
~NETDEV_ALIGN_CONST;
alloc_size += sizeof_priv + NETDEV_ALIGN_CONST;
@@ -3637,7 +3697,7 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
dev->priv = ((char *)dev +
((sizeof(struct net_device) +
(sizeof(struct net_device_subqueue) *
- queue_count) + NETDEV_ALIGN_CONST)
+ (queue_count - 1)) + NETDEV_ALIGN_CONST)
& ~NETDEV_ALIGN_CONST));
}
@@ -3739,8 +3799,7 @@ void unregister_netdevice(struct net_device *dev)
/*
* Flush the unicast and multicast chains
*/
- dev_unicast_discard(dev);
- dev_mc_discard(dev);
+ dev_addr_discard(dev);
if (dev->uninit)
dev->uninit(dev);
@@ -3826,9 +3885,11 @@ static int dev_cpu_callback(struct notifier_block *nfb,
#ifdef CONFIG_NET_DMA
/**
- * net_dma_rebalance -
- * This is called when the number of channels allocated to the net_dma_client
- * changes. The net_dma_client tries to have one DMA channel per CPU.
+ * net_dma_rebalance - try to maintain one DMA channel per CPU
+ * @net_dma: DMA client and associated data (lock, channels, channel_mask)
+ *
+ * This is called when the number of channels allocated to the net_dma client
+ * changes. The net_dma client tries to have one DMA channel per CPU.
*/
static void net_dma_rebalance(struct net_dma *net_dma)
@@ -3865,7 +3926,7 @@ static void net_dma_rebalance(struct net_dma *net_dma)
* netdev_dma_event - event callback for the net_dma_client
* @client: should always be net_dma_client
* @chan: DMA channel for the event
- * @event: event type
+ * @state: DMA state to be handled
*/
static enum dma_state_client
netdev_dma_event(struct dma_client *client, struct dma_chan *chan,
@@ -3932,6 +3993,45 @@ static int __init netdev_dma_register(void)
static int __init netdev_dma_register(void) { return -ENODEV; }
#endif /* CONFIG_NET_DMA */
+/**
+ * netdev_compute_feature - compute conjunction of two feature sets
+ * @all: first feature set
+ * @one: second feature set
+ *
+ * Computes a new feature set after adding a device with feature set
+ * @one to the master device with current feature set @all. Returns
+ * the new feature set.
+ */
+int netdev_compute_features(unsigned long all, unsigned long one)
+{
+ /* if device needs checksumming, downgrade to hw checksumming */
+ if (all & NETIF_F_NO_CSUM && !(one & NETIF_F_NO_CSUM))
+ all ^= NETIF_F_NO_CSUM | NETIF_F_HW_CSUM;
+
+ /* if device can't do all checksum, downgrade to ipv4/ipv6 */
+ if (all & NETIF_F_HW_CSUM && !(one & NETIF_F_HW_CSUM))
+ all ^= NETIF_F_HW_CSUM
+ | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+
+ if (one & NETIF_F_GSO)
+ one |= NETIF_F_GSO_SOFTWARE;
+ one |= NETIF_F_GSO;
+
+ /* If even one device supports robust GSO, enable it for all. */
+ if (one & NETIF_F_GSO_ROBUST)
+ all |= NETIF_F_GSO_ROBUST;
+
+ all &= one | NETIF_F_LLTX;
+
+ if (!(all & NETIF_F_ALL_CSUM))
+ all &= ~NETIF_F_SG;
+ if (!(all & NETIF_F_SG))
+ all &= ~NETIF_F_GSO_MASK;
+
+ return all;
+}
+EXPORT_SYMBOL(netdev_compute_features);
+
/*
* Initialize the DEV module. At boot time this walks the device list and
* unhooks any devices that fail to initialise (normally hardware not
diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c
index 235a2a8a0d0..20330c57261 100644
--- a/net/core/dev_mcast.c
+++ b/net/core/dev_mcast.c
@@ -116,11 +116,13 @@ int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl)
*/
int dev_mc_sync(struct net_device *to, struct net_device *from)
{
- struct dev_addr_list *da;
+ struct dev_addr_list *da, *next;
int err = 0;
netif_tx_lock_bh(to);
- for (da = from->mc_list; da != NULL; da = da->next) {
+ da = from->mc_list;
+ while (da != NULL) {
+ next = da->next;
if (!da->da_synced) {
err = __dev_addr_add(&to->mc_list, &to->mc_count,
da->da_addr, da->da_addrlen, 0);
@@ -134,6 +136,7 @@ int dev_mc_sync(struct net_device *to, struct net_device *from)
__dev_addr_delete(&from->mc_list, &from->mc_count,
da->da_addr, da->da_addrlen, 0);
}
+ da = next;
}
if (!err)
__dev_set_rx_mode(to);
@@ -156,12 +159,14 @@ EXPORT_SYMBOL(dev_mc_sync);
*/
void dev_mc_unsync(struct net_device *to, struct net_device *from)
{
- struct dev_addr_list *da;
+ struct dev_addr_list *da, *next;
netif_tx_lock_bh(from);
netif_tx_lock_bh(to);
- for (da = from->mc_list; da != NULL; da = da->next) {
+ da = from->mc_list;
+ while (da != NULL) {
+ next = da->next;
if (!da->da_synced)
continue;
__dev_addr_delete(&to->mc_list, &to->mc_count,
@@ -169,6 +174,7 @@ void dev_mc_unsync(struct net_device *to, struct net_device *from)
da->da_synced = 0;
__dev_addr_delete(&from->mc_list, &from->mc_count,
da->da_addr, da->da_addrlen, 0);
+ da = next;
}
__dev_set_rx_mode(to);
@@ -177,18 +183,6 @@ void dev_mc_unsync(struct net_device *to, struct net_device *from)
}
EXPORT_SYMBOL(dev_mc_unsync);
-/*
- * Discard multicast list when a device is downed
- */
-
-void dev_mc_discard(struct net_device *dev)
-{
- netif_tx_lock_bh(dev);
- __dev_addr_discard(&dev->mc_list);
- dev->mc_count = 0;
- netif_tx_unlock_bh(dev);
-}
-
#ifdef CONFIG_PROC_FS
static void *dev_mc_seq_start(struct seq_file *seq, loff_t *pos)
{
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 0b531e98ec3..c5e059352d4 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -3,10 +3,12 @@
* Copyright (c) 2003 Matthew Wilcox <matthew@wil.cx>
*
* This file is where we call all the ethtool_ops commands to get
- * the information ethtool needs. We fall back to calling do_ioctl()
- * for drivers which haven't been converted to ethtool_ops yet.
+ * the information ethtool needs.
*
- * It's GPL, stupid.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
*/
#include <linux/module.h>
@@ -93,18 +95,6 @@ int ethtool_op_set_tso(struct net_device *dev, u32 data)
return 0;
}
-int ethtool_op_get_perm_addr(struct net_device *dev, struct ethtool_perm_addr *addr, u8 *data)
-{
- unsigned char len = dev->addr_len;
- if ( addr->size < len )
- return -ETOOSMALL;
-
- addr->size = len;
- memcpy(data, dev->perm_addr, len);
- return 0;
-}
-
-
u32 ethtool_op_get_ufo(struct net_device *dev)
{
return (dev->features & NETIF_F_UFO) != 0;
@@ -777,34 +767,20 @@ static int ethtool_get_stats(struct net_device *dev, void __user *useraddr)
static int ethtool_get_perm_addr(struct net_device *dev, void __user *useraddr)
{
struct ethtool_perm_addr epaddr;
- u8 *data;
- int ret;
-
- if (!dev->ethtool_ops->get_perm_addr)
- return -EOPNOTSUPP;
- if (copy_from_user(&epaddr,useraddr,sizeof(epaddr)))
+ if (copy_from_user(&epaddr, useraddr, sizeof(epaddr)))
return -EFAULT;
- data = kmalloc(epaddr.size, GFP_USER);
- if (!data)
- return -ENOMEM;
-
- ret = dev->ethtool_ops->get_perm_addr(dev,&epaddr,data);
- if (ret)
- return ret;
+ if (epaddr.size < dev->addr_len)
+ return -ETOOSMALL;
+ epaddr.size = dev->addr_len;
- ret = -EFAULT;
if (copy_to_user(useraddr, &epaddr, sizeof(epaddr)))
- goto out;
+ return -EFAULT;
useraddr += sizeof(epaddr);
- if (copy_to_user(useraddr, data, epaddr.size))
- goto out;
- ret = 0;
-
- out:
- kfree(data);
- return ret;
+ if (copy_to_user(useraddr, dev->perm_addr, epaddr.size))
+ return -EFAULT;
+ return 0;
}
/* The main entry point in this file. Called from net/core/dev.c */
@@ -821,7 +797,7 @@ int dev_ethtool(struct ifreq *ifr)
return -ENODEV;
if (!dev->ethtool_ops)
- goto ioctl;
+ return -EOPNOTSUPP;
if (copy_from_user(&ethcmd, useraddr, sizeof (ethcmd)))
return -EFAULT;
@@ -960,7 +936,7 @@ int dev_ethtool(struct ifreq *ifr)
rc = ethtool_set_gso(dev, useraddr);
break;
default:
- rc = -EOPNOTSUPP;
+ rc = -EOPNOTSUPP;
}
if (dev->ethtool_ops->complete)
@@ -970,20 +946,9 @@ int dev_ethtool(struct ifreq *ifr)
netdev_features_change(dev);
return rc;
-
- ioctl:
- /* Keep existing behaviour for the moment. */
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
-
- if (dev->do_ioctl)
- return dev->do_ioctl(dev, ifr, SIOCETHTOOL);
- return -EOPNOTSUPP;
}
-EXPORT_SYMBOL(dev_ethtool);
EXPORT_SYMBOL(ethtool_op_get_link);
-EXPORT_SYMBOL_GPL(ethtool_op_get_perm_addr);
EXPORT_SYMBOL(ethtool_op_get_sg);
EXPORT_SYMBOL(ethtool_op_get_tso);
EXPORT_SYMBOL(ethtool_op_get_tx_csum);
diff --git a/net/core/flow.c b/net/core/flow.c
index 051430545a0..0ab5234b17d 100644
--- a/net/core/flow.c
+++ b/net/core/flow.c
@@ -350,7 +350,7 @@ static int __init flow_cache_init(void)
flow_cachep = kmem_cache_create("flow_cache",
sizeof(struct flow_cache_entry),
0, SLAB_HWCACHE_ALIGN|SLAB_PANIC,
- NULL, NULL);
+ NULL);
flow_hash_shift = 10;
flow_lwm = 2 * flow_hash_size;
flow_hwm = 4 * flow_hash_size;
diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c
index cc84d8d8a3c..590a767b029 100644
--- a/net/core/gen_estimator.c
+++ b/net/core/gen_estimator.c
@@ -79,27 +79,27 @@
struct gen_estimator
{
- struct gen_estimator *next;
+ struct list_head list;
struct gnet_stats_basic *bstats;
struct gnet_stats_rate_est *rate_est;
spinlock_t *stats_lock;
- unsigned interval;
int ewma_log;
u64 last_bytes;
u32 last_packets;
u32 avpps;
u32 avbps;
+ struct rcu_head e_rcu;
};
struct gen_estimator_head
{
struct timer_list timer;
- struct gen_estimator *list;
+ struct list_head list;
};
static struct gen_estimator_head elist[EST_MAX_INTERVAL+1];
-/* Estimator array lock */
+/* Protects against NULL dereference */
static DEFINE_RWLOCK(est_lock);
static void est_timer(unsigned long arg)
@@ -107,13 +107,17 @@ static void est_timer(unsigned long arg)
int idx = (int)arg;
struct gen_estimator *e;
- read_lock(&est_lock);
- for (e = elist[idx].list; e; e = e->next) {
+ rcu_read_lock();
+ list_for_each_entry_rcu(e, &elist[idx].list, list) {
u64 nbytes;
u32 npackets;
u32 rate;
spin_lock(e->stats_lock);
+ read_lock(&est_lock);
+ if (e->bstats == NULL)
+ goto skip;
+
nbytes = e->bstats->bytes;
npackets = e->bstats->packets;
rate = (nbytes - e->last_bytes)<<(7 - idx);
@@ -125,12 +129,14 @@ static void est_timer(unsigned long arg)
e->last_packets = npackets;
e->avpps += ((long)rate - (long)e->avpps) >> e->ewma_log;
e->rate_est->pps = (e->avpps+0x1FF)>>10;
+skip:
+ read_unlock(&est_lock);
spin_unlock(e->stats_lock);
}
- if (elist[idx].list != NULL)
+ if (!list_empty(&elist[idx].list))
mod_timer(&elist[idx].timer, jiffies + ((HZ<<idx)/4));
- read_unlock(&est_lock);
+ rcu_read_unlock();
}
/**
@@ -147,12 +153,17 @@ static void est_timer(unsigned long arg)
* &rate_est with the statistics lock grabed during this period.
*
* Returns 0 on success or a negative error code.
+ *
+ * NOTE: Called under rtnl_mutex
*/
int gen_new_estimator(struct gnet_stats_basic *bstats,
- struct gnet_stats_rate_est *rate_est, spinlock_t *stats_lock, struct rtattr *opt)
+ struct gnet_stats_rate_est *rate_est,
+ spinlock_t *stats_lock,
+ struct rtattr *opt)
{
struct gen_estimator *est;
struct gnet_estimator *parm = RTA_DATA(opt);
+ int idx;
if (RTA_PAYLOAD(opt) < sizeof(*parm))
return -EINVAL;
@@ -164,7 +175,7 @@ int gen_new_estimator(struct gnet_stats_basic *bstats,
if (est == NULL)
return -ENOBUFS;
- est->interval = parm->interval + 2;
+ idx = parm->interval + 2;
est->bstats = bstats;
est->rate_est = rate_est;
est->stats_lock = stats_lock;
@@ -174,20 +185,25 @@ int gen_new_estimator(struct gnet_stats_basic *bstats,
est->last_packets = bstats->packets;
est->avpps = rate_est->pps<<10;
- est->next = elist[est->interval].list;
- if (est->next == NULL) {
- init_timer(&elist[est->interval].timer);
- elist[est->interval].timer.data = est->interval;
- elist[est->interval].timer.expires = jiffies + ((HZ<<est->interval)/4);
- elist[est->interval].timer.function = est_timer;
- add_timer(&elist[est->interval].timer);
+ if (!elist[idx].timer.function) {
+ INIT_LIST_HEAD(&elist[idx].list);
+ setup_timer(&elist[idx].timer, est_timer, idx);
}
- write_lock_bh(&est_lock);
- elist[est->interval].list = est;
- write_unlock_bh(&est_lock);
+
+ if (list_empty(&elist[idx].list))
+ mod_timer(&elist[idx].timer, jiffies + ((HZ<<idx)/4));
+
+ list_add_rcu(&est->list, &elist[idx].list);
return 0;
}
+static void __gen_kill_estimator(struct rcu_head *head)
+{
+ struct gen_estimator *e = container_of(head,
+ struct gen_estimator, e_rcu);
+ kfree(e);
+}
+
/**
* gen_kill_estimator - remove a rate estimator
* @bstats: basic statistics
@@ -195,31 +211,32 @@ int gen_new_estimator(struct gnet_stats_basic *bstats,
*
* Removes the rate estimator specified by &bstats and &rate_est
* and deletes the timer.
+ *
+ * NOTE: Called under rtnl_mutex
*/
void gen_kill_estimator(struct gnet_stats_basic *bstats,
struct gnet_stats_rate_est *rate_est)
{
int idx;
- struct gen_estimator *est, **pest;
+ struct gen_estimator *e, *n;
for (idx=0; idx <= EST_MAX_INTERVAL; idx++) {
- int killed = 0;
- pest = &elist[idx].list;
- while ((est=*pest) != NULL) {
- if (est->rate_est != rate_est || est->bstats != bstats) {
- pest = &est->next;
+
+ /* Skip non initialized indexes */
+ if (!elist[idx].timer.function)
+ continue;
+
+ list_for_each_entry_safe(e, n, &elist[idx].list, list) {
+ if (e->rate_est != rate_est || e->bstats != bstats)
continue;
- }
write_lock_bh(&est_lock);
- *pest = est->next;
+ e->bstats = NULL;
write_unlock_bh(&est_lock);
- kfree(est);
- killed++;
+ list_del_rcu(&e->list);
+ call_rcu(&e->e_rcu, __gen_kill_estimator);
}
- if (killed && elist[idx].list == NULL)
- del_timer(&elist[idx].timer);
}
}
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 9df26a07f06..f7de8f24d8d 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -33,6 +33,7 @@
#include <linux/rtnetlink.h>
#include <linux/random.h>
#include <linux/string.h>
+#include <linux/log2.h>
#define NEIGH_DEBUG 1
@@ -311,7 +312,7 @@ static void neigh_hash_grow(struct neigh_table *tbl, unsigned long new_entries)
NEIGH_CACHE_STAT_INC(tbl, hash_grows);
- BUG_ON(new_entries & (new_entries - 1));
+ BUG_ON(!is_power_of_2(new_entries));
new_hash = neigh_hash_alloc(new_entries);
if (!new_hash)
return;
@@ -1347,7 +1348,7 @@ void neigh_table_init_no_netlink(struct neigh_table *tbl)
tbl->kmem_cachep =
kmem_cache_create(tbl->id, tbl->entry_size, 0,
SLAB_HWCACHE_ALIGN|SLAB_PANIC,
- NULL, NULL);
+ NULL);
tbl->stats = alloc_percpu(struct neigh_statistics);
if (!tbl->stats)
panic("cannot create neighbour cache statistics");
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index bca787fdbc5..803d0c8826a 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -111,6 +111,9 @@
*
* 802.1Q/Q-in-Q support by Francesco Fondelli (FF) <francesco.fondelli@gmail.com>
*
+ * Fixed src_mac command to set source mac of packet to value specified in
+ * command by Adit Ranadive <adit.262@gmail.com>
+ *
*/
#include <linux/sys.h>
#include <linux/types.h>
@@ -380,7 +383,6 @@ struct pktgen_thread {
/* Field for thread to receive "posted" events terminate, stop ifs etc. */
u32 control;
- int pid;
int cpu;
wait_queue_head_t queue;
@@ -567,7 +569,7 @@ static ssize_t pgctrl_write(struct file *file, const char __user * buf,
pktgen_run_all_threads();
else
- printk("pktgen: Unknown command: %s\n", data);
+ printk(KERN_WARNING "pktgen: Unknown command: %s\n", data);
err = count;
@@ -908,14 +910,14 @@ static ssize_t pktgen_if_write(struct file *file,
pg_result = &(pkt_dev->result[0]);
if (count < 1) {
- printk("pktgen: wrong command format\n");
+ printk(KERN_WARNING "pktgen: wrong command format\n");
return -EINVAL;
}
max = count - i;
tmp = count_trail_chars(&user_buffer[i], max);
if (tmp < 0) {
- printk("pktgen: illegal format\n");
+ printk(KERN_WARNING "pktgen: illegal format\n");
return tmp;
}
i += tmp;
@@ -943,7 +945,7 @@ static ssize_t pktgen_if_write(struct file *file,
if (copy_from_user(tb, user_buffer, count))
return -EFAULT;
tb[count] = 0;
- printk("pktgen: %s,%lu buffer -:%s:-\n", name,
+ printk(KERN_DEBUG "pktgen: %s,%lu buffer -:%s:-\n", name,
(unsigned long)count, tb);
}
@@ -1248,7 +1250,7 @@ static ssize_t pktgen_if_write(struct file *file,
pkt_dev->cur_daddr = pkt_dev->daddr_min;
}
if (debug)
- printk("pktgen: dst_min set to: %s\n",
+ printk(KERN_DEBUG "pktgen: dst_min set to: %s\n",
pkt_dev->dst_min);
i += len;
sprintf(pg_result, "OK: dst_min=%s", pkt_dev->dst_min);
@@ -1271,7 +1273,7 @@ static ssize_t pktgen_if_write(struct file *file,
pkt_dev->cur_daddr = pkt_dev->daddr_max;
}
if (debug)
- printk("pktgen: dst_max set to: %s\n",
+ printk(KERN_DEBUG "pktgen: dst_max set to: %s\n",
pkt_dev->dst_max);
i += len;
sprintf(pg_result, "OK: dst_max=%s", pkt_dev->dst_max);
@@ -1294,7 +1296,7 @@ static ssize_t pktgen_if_write(struct file *file,
ipv6_addr_copy(&pkt_dev->cur_in6_daddr, &pkt_dev->in6_daddr);
if (debug)
- printk("pktgen: dst6 set to: %s\n", buf);
+ printk(KERN_DEBUG "pktgen: dst6 set to: %s\n", buf);
i += len;
sprintf(pg_result, "OK: dst6=%s", buf);
@@ -1317,7 +1319,7 @@ static ssize_t pktgen_if_write(struct file *file,
ipv6_addr_copy(&pkt_dev->cur_in6_daddr,
&pkt_dev->min_in6_daddr);
if (debug)
- printk("pktgen: dst6_min set to: %s\n", buf);
+ printk(KERN_DEBUG "pktgen: dst6_min set to: %s\n", buf);
i += len;
sprintf(pg_result, "OK: dst6_min=%s", buf);
@@ -1338,7 +1340,7 @@ static ssize_t pktgen_if_write(struct file *file,
fmt_ip6(buf, pkt_dev->max_in6_daddr.s6_addr);
if (debug)
- printk("pktgen: dst6_max set to: %s\n", buf);
+ printk(KERN_DEBUG "pktgen: dst6_max set to: %s\n", buf);
i += len;
sprintf(pg_result, "OK: dst6_max=%s", buf);
@@ -1361,7 +1363,7 @@ static ssize_t pktgen_if_write(struct file *file,
ipv6_addr_copy(&pkt_dev->cur_in6_saddr, &pkt_dev->in6_saddr);
if (debug)
- printk("pktgen: src6 set to: %s\n", buf);
+ printk(KERN_DEBUG "pktgen: src6 set to: %s\n", buf);
i += len;
sprintf(pg_result, "OK: src6=%s", buf);
@@ -1382,7 +1384,7 @@ static ssize_t pktgen_if_write(struct file *file,
pkt_dev->cur_saddr = pkt_dev->saddr_min;
}
if (debug)
- printk("pktgen: src_min set to: %s\n",
+ printk(KERN_DEBUG "pktgen: src_min set to: %s\n",
pkt_dev->src_min);
i += len;
sprintf(pg_result, "OK: src_min=%s", pkt_dev->src_min);
@@ -1403,7 +1405,7 @@ static ssize_t pktgen_if_write(struct file *file,
pkt_dev->cur_saddr = pkt_dev->saddr_max;
}
if (debug)
- printk("pktgen: src_max set to: %s\n",
+ printk(KERN_DEBUG "pktgen: src_max set to: %s\n",
pkt_dev->src_max);
i += len;
sprintf(pg_result, "OK: src_max=%s", pkt_dev->src_max);
@@ -1452,8 +1454,11 @@ static ssize_t pktgen_if_write(struct file *file,
}
if (!strcmp(name, "src_mac")) {
char *v = valstr;
+ unsigned char old_smac[ETH_ALEN];
unsigned char *m = pkt_dev->src_mac;
+ memcpy(old_smac, pkt_dev->src_mac, ETH_ALEN);
+
len = strn_len(&user_buffer[i], sizeof(valstr) - 1);
if (len < 0) {
return len;
@@ -1482,6 +1487,10 @@ static ssize_t pktgen_if_write(struct file *file,
}
}
+ /* Set up Src MAC */
+ if (compare_ether_addr(old_smac, pkt_dev->src_mac))
+ memcpy(&(pkt_dev->hh[6]), pkt_dev->src_mac, ETH_ALEN);
+
sprintf(pg_result, "OK: srcmac");
return count;
}
@@ -1533,7 +1542,7 @@ static ssize_t pktgen_if_write(struct file *file,
pkt_dev->svlan_id = 0xffff;
if (debug)
- printk("pktgen: VLAN/SVLAN auto turned off\n");
+ printk(KERN_DEBUG "pktgen: VLAN/SVLAN auto turned off\n");
}
return count;
}
@@ -1548,10 +1557,10 @@ static ssize_t pktgen_if_write(struct file *file,
pkt_dev->vlan_id = value; /* turn on VLAN */
if (debug)
- printk("pktgen: VLAN turned on\n");
+ printk(KERN_DEBUG "pktgen: VLAN turned on\n");
if (debug && pkt_dev->nr_labels)
- printk("pktgen: MPLS auto turned off\n");
+ printk(KERN_DEBUG "pktgen: MPLS auto turned off\n");
pkt_dev->nr_labels = 0; /* turn off MPLS */
sprintf(pg_result, "OK: vlan_id=%u", pkt_dev->vlan_id);
@@ -1560,7 +1569,7 @@ static ssize_t pktgen_if_write(struct file *file,
pkt_dev->svlan_id = 0xffff;
if (debug)
- printk("pktgen: VLAN/SVLAN turned off\n");
+ printk(KERN_DEBUG "pktgen: VLAN/SVLAN turned off\n");
}
return count;
}
@@ -1605,10 +1614,10 @@ static ssize_t pktgen_if_write(struct file *file,
pkt_dev->svlan_id = value; /* turn on SVLAN */
if (debug)
- printk("pktgen: SVLAN turned on\n");
+ printk(KERN_DEBUG "pktgen: SVLAN turned on\n");
if (debug && pkt_dev->nr_labels)
- printk("pktgen: MPLS auto turned off\n");
+ printk(KERN_DEBUG "pktgen: MPLS auto turned off\n");
pkt_dev->nr_labels = 0; /* turn off MPLS */
sprintf(pg_result, "OK: svlan_id=%u", pkt_dev->svlan_id);
@@ -1617,7 +1626,7 @@ static ssize_t pktgen_if_write(struct file *file,
pkt_dev->svlan_id = 0xffff;
if (debug)
- printk("pktgen: VLAN/SVLAN turned off\n");
+ printk(KERN_DEBUG "pktgen: VLAN/SVLAN turned off\n");
}
return count;
}
@@ -1777,10 +1786,11 @@ static ssize_t pktgen_thread_write(struct file *file,
i += len;
if (debug)
- printk("pktgen: t=%s, count=%lu\n", name, (unsigned long)count);
+ printk(KERN_DEBUG "pktgen: t=%s, count=%lu\n",
+ name, (unsigned long)count);
if (!t) {
- printk("pktgen: ERROR: No thread\n");
+ printk(KERN_ERR "pktgen: ERROR: No thread\n");
ret = -EINVAL;
goto out;
}
@@ -1891,8 +1901,8 @@ static void pktgen_mark_device(const char *ifname)
mutex_lock(&pktgen_thread_lock);
if (++i >= max_tries) {
- printk("pktgen_mark_device: timed out after waiting "
- "%d msec for device %s to be removed\n",
+ printk(KERN_ERR "pktgen_mark_device: timed out after "
+ "waiting %d msec for device %s to be removed\n",
msec_per_try * i, ifname);
break;
}
@@ -1962,15 +1972,15 @@ static int pktgen_setup_dev(struct pktgen_dev *pkt_dev, const char *ifname)
odev = dev_get_by_name(ifname);
if (!odev) {
- printk("pktgen: no such netdevice: \"%s\"\n", ifname);
+ printk(KERN_ERR "pktgen: no such netdevice: \"%s\"\n", ifname);
return -ENODEV;
}
if (odev->type != ARPHRD_ETHER) {
- printk("pktgen: not an ethernet device: \"%s\"\n", ifname);
+ printk(KERN_ERR "pktgen: not an ethernet device: \"%s\"\n", ifname);
err = -EINVAL;
} else if (!netif_running(odev)) {
- printk("pktgen: device is down: \"%s\"\n", ifname);
+ printk(KERN_ERR "pktgen: device is down: \"%s\"\n", ifname);
err = -ENETDOWN;
} else {
pkt_dev->odev = odev;
@@ -1987,7 +1997,8 @@ static int pktgen_setup_dev(struct pktgen_dev *pkt_dev, const char *ifname)
static void pktgen_setup_inject(struct pktgen_dev *pkt_dev)
{
if (!pkt_dev->odev) {
- printk("pktgen: ERROR: pkt_dev->odev == NULL in setup_inject.\n");
+ printk(KERN_ERR "pktgen: ERROR: pkt_dev->odev == NULL in "
+ "setup_inject.\n");
sprintf(pkt_dev->result,
"ERROR: pkt_dev->odev == NULL in setup_inject.\n");
return;
@@ -2049,7 +2060,8 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev)
}
rcu_read_unlock();
if (err)
- printk("pktgen: ERROR: IPv6 link address not availble.\n");
+ printk(KERN_ERR "pktgen: ERROR: IPv6 link "
+ "address not availble.\n");
}
#endif
} else {
@@ -2156,8 +2168,7 @@ static inline int f_pick(struct pktgen_dev *pkt_dev)
/* If there was already an IPSEC SA, we keep it as is, else
* we go look for it ...
*/
-inline
-void get_ipsec_sa(struct pktgen_dev *pkt_dev, int flow)
+static void get_ipsec_sa(struct pktgen_dev *pkt_dev, int flow)
{
struct xfrm_state *x = pkt_dev->flows[flow].x;
if (!x) {
@@ -2441,7 +2452,8 @@ static inline int process_ipsec(struct pktgen_dev *pkt_dev,
if (nhead >0) {
ret = pskb_expand_head(skb, nhead, 0, GFP_ATOMIC);
if (ret < 0) {
- printk("Error expanding ipsec packet %d\n",ret);
+ printk(KERN_ERR "Error expanding "
+ "ipsec packet %d\n",ret);
return 0;
}
}
@@ -2450,7 +2462,8 @@ static inline int process_ipsec(struct pktgen_dev *pkt_dev,
skb_pull(skb, ETH_HLEN);
ret = pktgen_output_ipsec(skb, pkt_dev);
if (ret) {
- printk("Error creating ipsec packet %d\n",ret);
+ printk(KERN_ERR "Error creating ipsec "
+ "packet %d\n",ret);
kfree_skb(skb);
return 0;
}
@@ -3184,8 +3197,8 @@ static int pktgen_stop_device(struct pktgen_dev *pkt_dev)
int nr_frags = pkt_dev->skb ? skb_shinfo(pkt_dev->skb)->nr_frags : -1;
if (!pkt_dev->running) {
- printk("pktgen: interface: %s is already stopped\n",
- pkt_dev->odev->name);
+ printk(KERN_WARNING "pktgen: interface: %s is already "
+ "stopped\n", pkt_dev->odev->name);
return -EINVAL;
}
@@ -3327,8 +3340,9 @@ static __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev)
}
if ((netif_queue_stopped(odev) ||
- netif_subqueue_stopped(odev, pkt_dev->skb->queue_mapping)) ||
- need_resched()) {
+ (pkt_dev->skb &&
+ netif_subqueue_stopped(odev, pkt_dev->skb->queue_mapping))) ||
+ need_resched()) {
idle_start = getCurUs();
if (!netif_running(odev)) {
@@ -3360,7 +3374,8 @@ static __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev)
pkt_dev->skb = fill_packet(odev, pkt_dev);
if (pkt_dev->skb == NULL) {
- printk("pktgen: ERROR: couldn't allocate skb in fill_packet.\n");
+ printk(KERN_ERR "pktgen: ERROR: couldn't "
+ "allocate skb in fill_packet.\n");
schedule();
pkt_dev->clone_count--; /* back out increment, OOM */
goto out;
@@ -3457,8 +3472,6 @@ static int pktgen_thread_worker(void *arg)
init_waitqueue_head(&t->queue);
- t->pid = current->pid;
-
pr_debug("pktgen: starting pktgen/%d: pid=%d\n", cpu, current->pid);
max_before_softirq = t->max_before_softirq;
@@ -3565,7 +3578,8 @@ static int add_dev_to_thread(struct pktgen_thread *t,
if_lock(t);
if (pkt_dev->pg_thread) {
- printk("pktgen: ERROR: already assigned to a thread.\n");
+ printk(KERN_ERR "pktgen: ERROR: already assigned "
+ "to a thread.\n");
rv = -EBUSY;
goto out;
}
@@ -3590,7 +3604,7 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname)
pkt_dev = __pktgen_NN_threads(ifname, FIND);
if (pkt_dev) {
- printk("pktgen: ERROR: interface already used.\n");
+ printk(KERN_ERR "pktgen: ERROR: interface already used.\n");
return -EBUSY;
}
@@ -3632,7 +3646,7 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname)
pkt_dev->entry = create_proc_entry(ifname, 0600, pg_proc_dir);
if (!pkt_dev->entry) {
- printk("pktgen: cannot create %s/%s procfs entry.\n",
+ printk(KERN_ERR "pktgen: cannot create %s/%s procfs entry.\n",
PG_PROC_DIR, ifname);
err = -EINVAL;
goto out2;
@@ -3665,7 +3679,8 @@ static int __init pktgen_create_thread(int cpu)
t = kzalloc(sizeof(struct pktgen_thread), GFP_KERNEL);
if (!t) {
- printk("pktgen: ERROR: out of memory, can't create new thread.\n");
+ printk(KERN_ERR "pktgen: ERROR: out of memory, can't "
+ "create new thread.\n");
return -ENOMEM;
}
@@ -3678,7 +3693,8 @@ static int __init pktgen_create_thread(int cpu)
p = kthread_create(pktgen_thread_worker, t, "kpktgend_%d", cpu);
if (IS_ERR(p)) {
- printk("pktgen: kernel_thread() failed for cpu %d\n", t->cpu);
+ printk(KERN_ERR "pktgen: kernel_thread() failed "
+ "for cpu %d\n", t->cpu);
list_del(&t->th_list);
kfree(t);
return PTR_ERR(p);
@@ -3688,7 +3704,7 @@ static int __init pktgen_create_thread(int cpu)
pe = create_proc_entry(t->tsk->comm, 0600, pg_proc_dir);
if (!pe) {
- printk("pktgen: cannot create %s/%s procfs entry.\n",
+ printk(KERN_ERR "pktgen: cannot create %s/%s procfs entry.\n",
PG_PROC_DIR, t->tsk->comm);
kthread_stop(p);
list_del(&t->th_list);
@@ -3727,7 +3743,8 @@ static int pktgen_remove_device(struct pktgen_thread *t,
pr_debug("pktgen: remove_device pkt_dev=%p\n", pkt_dev);
if (pkt_dev->running) {
- printk("pktgen:WARNING: trying to remove a running interface, stopping it now.\n");
+ printk(KERN_WARNING "pktgen: WARNING: trying to remove a "
+ "running interface, stopping it now.\n");
pktgen_stop_device(pkt_dev);
}
@@ -3759,7 +3776,7 @@ static int __init pg_init(void)
int cpu;
struct proc_dir_entry *pe;
- printk(version);
+ printk(KERN_INFO "%s", version);
pg_proc_dir = proc_mkdir(PG_PROC_DIR, proc_net);
if (!pg_proc_dir)
@@ -3768,8 +3785,8 @@ static int __init pg_init(void)
pe = create_proc_entry(PGCTRL, 0600, pg_proc_dir);
if (pe == NULL) {
- printk("pktgen: ERROR: cannot create %s procfs entry.\n",
- PGCTRL);
+ printk(KERN_ERR "pktgen: ERROR: cannot create %s "
+ "procfs entry.\n", PGCTRL);
proc_net_remove(PG_PROC_DIR);
return -EINVAL;
}
@@ -3785,12 +3802,13 @@ static int __init pg_init(void)
err = pktgen_create_thread(cpu);
if (err)
- printk("pktgen: WARNING: Cannot create thread for cpu %d (%d)\n",
- cpu, err);
+ printk(KERN_WARNING "pktgen: WARNING: Cannot create "
+ "thread for cpu %d (%d)\n", cpu, err);
}
if (list_empty(&pktgen_threads)) {
- printk("pktgen: ERROR: Initialization failed for all threads\n");
+ printk(KERN_ERR "pktgen: ERROR: Initialization failed for "
+ "all threads\n");
unregister_netdevice_notifier(&pktgen_notifier_block);
remove_proc_entry(PGCTRL, pg_proc_dir);
proc_net_remove(PG_PROC_DIR);
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 864cbdf31ed..4756d5857ab 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -98,7 +98,7 @@ int rtattr_parse(struct rtattr *tb[], int maxattr, struct rtattr *rta, int len)
}
int __rtattr_parse_nested_compat(struct rtattr *tb[], int maxattr,
- struct rtattr *rta, int len)
+ struct rtattr *rta, int len)
{
if (RTA_PAYLOAD(rta) < len)
return -1;
@@ -952,7 +952,9 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
struct nlattr *linkinfo[IFLA_INFO_MAX+1];
int err;
+#ifdef CONFIG_KMOD
replay:
+#endif
err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy);
if (err < 0)
return err;
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 0583e8498f1..35021eb3ed0 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -2021,13 +2021,13 @@ void __init skb_init(void)
sizeof(struct sk_buff),
0,
SLAB_HWCACHE_ALIGN|SLAB_PANIC,
- NULL, NULL);
+ NULL);
skbuff_fclone_cache = kmem_cache_create("skbuff_fclone_cache",
(2*sizeof(struct sk_buff)) +
sizeof(atomic_t),
0,
SLAB_HWCACHE_ALIGN|SLAB_PANIC,
- NULL, NULL);
+ NULL);
}
/**
diff --git a/net/core/sock.c b/net/core/sock.c
index 091032a250c..190de61cd64 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -171,6 +171,20 @@ static const char *af_family_slock_key_strings[AF_MAX+1] = {
"slock-AF_TIPC" , "slock-AF_BLUETOOTH", "slock-AF_IUCV" ,
"slock-AF_RXRPC" , "slock-AF_MAX"
};
+static const char *af_family_clock_key_strings[AF_MAX+1] = {
+ "clock-AF_UNSPEC", "clock-AF_UNIX" , "clock-AF_INET" ,
+ "clock-AF_AX25" , "clock-AF_IPX" , "clock-AF_APPLETALK",
+ "clock-AF_NETROM", "clock-AF_BRIDGE" , "clock-AF_ATMPVC" ,
+ "clock-AF_X25" , "clock-AF_INET6" , "clock-AF_ROSE" ,
+ "clock-AF_DECnet", "clock-AF_NETBEUI" , "clock-AF_SECURITY" ,
+ "clock-AF_KEY" , "clock-AF_NETLINK" , "clock-AF_PACKET" ,
+ "clock-AF_ASH" , "clock-AF_ECONET" , "clock-AF_ATMSVC" ,
+ "clock-21" , "clock-AF_SNA" , "clock-AF_IRDA" ,
+ "clock-AF_PPPOX" , "clock-AF_WANPIPE" , "clock-AF_LLC" ,
+ "clock-27" , "clock-28" , "clock-29" ,
+ "clock-AF_TIPC" , "clock-AF_BLUETOOTH", "clock-AF_IUCV" ,
+ "clock-AF_RXRPC" , "clock-AF_MAX"
+};
#endif
/*
@@ -217,7 +231,7 @@ static int sock_set_timeout(long *timeo_p, char __user *optval, int optlen)
warned++;
printk(KERN_INFO "sock_set_timeout: `%s' (pid %d) "
"tries to set negative timeout\n",
- current->comm, current->pid);
+ current->comm, current->pid);
return 0;
}
*timeo_p = MAX_SCHEDULE_TIMEOUT;
@@ -348,6 +362,61 @@ struct dst_entry *sk_dst_check(struct sock *sk, u32 cookie)
}
EXPORT_SYMBOL(sk_dst_check);
+static int sock_bindtodevice(struct sock *sk, char __user *optval, int optlen)
+{
+ int ret = -ENOPROTOOPT;
+#ifdef CONFIG_NETDEVICES
+ char devname[IFNAMSIZ];
+ int index;
+
+ /* Sorry... */
+ ret = -EPERM;
+ if (!capable(CAP_NET_RAW))
+ goto out;
+
+ ret = -EINVAL;
+ if (optlen < 0)
+ goto out;
+
+ /* Bind this socket to a particular device like "eth0",
+ * as specified in the passed interface name. If the
+ * name is "" or the option length is zero the socket
+ * is not bound.
+ */
+ if (optlen > IFNAMSIZ - 1)
+ optlen = IFNAMSIZ - 1;
+ memset(devname, 0, sizeof(devname));
+
+ ret = -EFAULT;
+ if (copy_from_user(devname, optval, optlen))
+ goto out;
+
+ if (devname[0] == '\0') {
+ index = 0;
+ } else {
+ struct net_device *dev = dev_get_by_name(devname);
+
+ ret = -ENODEV;
+ if (!dev)
+ goto out;
+
+ index = dev->ifindex;
+ dev_put(dev);
+ }
+
+ lock_sock(sk);
+ sk->sk_bound_dev_if = index;
+ sk_dst_reset(sk);
+ release_sock(sk);
+
+ ret = 0;
+
+out:
+#endif
+
+ return ret;
+}
+
/*
* This is meant for all protocols to use and covers goings on
* at the socket level. Everything here is generic.
@@ -376,6 +445,9 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
}
#endif
+ if (optname == SO_BINDTODEVICE)
+ return sock_bindtodevice(sk, optval, optlen);
+
if (optlen < sizeof(int))
return -EINVAL;
@@ -564,54 +636,6 @@ set_rcvbuf:
ret = sock_set_timeout(&sk->sk_sndtimeo, optval, optlen);
break;
-#ifdef CONFIG_NETDEVICES
- case SO_BINDTODEVICE:
- {
- char devname[IFNAMSIZ];
-
- /* Sorry... */
- if (!capable(CAP_NET_RAW)) {
- ret = -EPERM;
- break;
- }
-
- /* Bind this socket to a particular device like "eth0",
- * as specified in the passed interface name. If the
- * name is "" or the option length is zero the socket
- * is not bound.
- */
-
- if (!valbool) {
- sk->sk_bound_dev_if = 0;
- } else {
- if (optlen > IFNAMSIZ - 1)
- optlen = IFNAMSIZ - 1;
- memset(devname, 0, sizeof(devname));
- if (copy_from_user(devname, optval, optlen)) {
- ret = -EFAULT;
- break;
- }
-
- /* Remove any cached route for this socket. */
- sk_dst_reset(sk);
-
- if (devname[0] == '\0') {
- sk->sk_bound_dev_if = 0;
- } else {
- struct net_device *dev = dev_get_by_name(devname);
- if (!dev) {
- ret = -ENODEV;
- break;
- }
- sk->sk_bound_dev_if = dev->ifindex;
- dev_put(dev);
- }
- }
- break;
- }
-#endif
-
-
case SO_ATTACH_FILTER:
ret = -EINVAL;
if (optlen == sizeof(struct sock_fprog)) {
@@ -941,8 +965,9 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority)
rwlock_init(&newsk->sk_dst_lock);
rwlock_init(&newsk->sk_callback_lock);
- lockdep_set_class(&newsk->sk_callback_lock,
- af_callback_keys + newsk->sk_family);
+ lockdep_set_class_and_name(&newsk->sk_callback_lock,
+ af_callback_keys + newsk->sk_family,
+ af_family_clock_key_strings[newsk->sk_family]);
newsk->sk_dst_cache = NULL;
newsk->sk_wmem_queued = 0;
@@ -1530,8 +1555,9 @@ void sock_init_data(struct socket *sock, struct sock *sk)
rwlock_init(&sk->sk_dst_lock);
rwlock_init(&sk->sk_callback_lock);
- lockdep_set_class(&sk->sk_callback_lock,
- af_callback_keys + sk->sk_family);
+ lockdep_set_class_and_name(&sk->sk_callback_lock,
+ af_callback_keys + sk->sk_family,
+ af_family_clock_key_strings[sk->sk_family]);
sk->sk_state_change = sock_def_wakeup;
sk->sk_data_ready = sock_def_readable;
@@ -1752,7 +1778,7 @@ int proto_register(struct proto *prot, int alloc_slab)
if (alloc_slab) {
prot->slab = kmem_cache_create(prot->name, prot->obj_size, 0,
- SLAB_HWCACHE_ALIGN, NULL, NULL);
+ SLAB_HWCACHE_ALIGN, NULL);
if (prot->slab == NULL) {
printk(KERN_CRIT "%s: Can't create sock SLAB cache!\n",
@@ -1770,7 +1796,7 @@ int proto_register(struct proto *prot, int alloc_slab)
sprintf(request_sock_slab_name, mask, prot->name);
prot->rsk_prot->slab = kmem_cache_create(request_sock_slab_name,
prot->rsk_prot->obj_size, 0,
- SLAB_HWCACHE_ALIGN, NULL, NULL);
+ SLAB_HWCACHE_ALIGN, NULL);
if (prot->rsk_prot->slab == NULL) {
printk(KERN_CRIT "%s: Can't create request sock SLAB cache!\n",
@@ -1792,7 +1818,7 @@ int proto_register(struct proto *prot, int alloc_slab)
kmem_cache_create(timewait_sock_slab_name,
prot->twsk_prot->twsk_obj_size,
0, SLAB_HWCACHE_ALIGN,
- NULL, NULL);
+ NULL);
if (prot->twsk_prot->twsk_slab == NULL)
goto out_free_timewait_sock_slab_name;
}
diff --git a/net/core/utils.c b/net/core/utils.c
index 2030bb8c2d3..0bf17da40d5 100644
--- a/net/core/utils.c
+++ b/net/core/utils.c
@@ -25,6 +25,7 @@
#include <linux/random.h>
#include <linux/percpu.h>
#include <linux/init.h>
+#include <net/sock.h>
#include <asm/byteorder.h>
#include <asm/system.h>