Merge branch 'audit.b3' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/audit...
[linux-2.6.git] / net / core / dev.c
index e9f84a6..8e1dc30 100644 (file)
@@ -81,6 +81,7 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
+#include <linux/mutex.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/socket.h>
 #include <linux/netpoll.h>
 #include <linux/rcupdate.h>
 #include <linux/delay.h>
-#ifdef CONFIG_NET_RADIO
-#include <linux/wireless.h>            /* Note : will define WIRELESS_EXT */
+#include <linux/wireless.h>
 #include <net/iw_handler.h>
-#endif /* CONFIG_NET_RADIO */
 #include <asm/current.h>
 #include <linux/audit.h>
 
@@ -979,7 +978,12 @@ int register_netdevice_notifier(struct notifier_block *nb)
 
 int unregister_netdevice_notifier(struct notifier_block *nb)
 {
-       return notifier_chain_unregister(&netdev_chain, nb);
+       int err;
+
+       rtnl_lock();
+       err = notifier_chain_unregister(&netdev_chain, nb);
+       rtnl_unlock();
+       return err;
 }
 
 /**
@@ -1449,8 +1453,29 @@ static inline struct net_device *skb_bond(struct sk_buff *skb)
 {
        struct net_device *dev = skb->dev;
 
-       if (dev->master)
+       if (dev->master) {
+               /*
+                * On bonding slaves other than the currently active
+                * slave, suppress duplicates except for 802.3ad
+                * ETH_P_SLOW and alb non-mcast/bcast.
+                */
+               if (dev->priv_flags & IFF_SLAVE_INACTIVE) {
+                       if (dev->master->priv_flags & IFF_MASTER_ALB) {
+                               if (skb->pkt_type != PACKET_BROADCAST &&
+                                   skb->pkt_type != PACKET_MULTICAST)
+                                       goto keep;
+                       }
+
+                       if (dev->master->priv_flags & IFF_MASTER_8023AD &&
+                           skb->protocol == __constant_htons(ETH_P_SLOW))
+                               goto keep;
+               
+                       kfree_skb(skb);
+                       return NULL;
+               }
+keep:
                skb->dev = dev->master;
+       }
 
        return dev;
 }
@@ -1594,6 +1619,9 @@ int netif_receive_skb(struct sk_buff *skb)
 
        orig_dev = skb_bond(skb);
 
+       if (!orig_dev)
+               return NET_RX_DROP;
+
        __get_cpu_var(netdev_rx_stat).total++;
 
        skb->h.raw = skb->nh.raw = skb->data;
@@ -1738,8 +1766,7 @@ static void net_rx_action(struct softirq_action *h)
                if (dev->quota <= 0 || dev->poll(dev, &budget)) {
                        netpoll_poll_unlock(have);
                        local_irq_disable();
-                       list_del(&dev->poll_list);
-                       list_add_tail(&dev->poll_list, &queue->poll_list);
+                       list_move_tail(&dev->poll_list, &queue->poll_list);
                        if (dev->quota < 0)
                                dev->quota += dev->weight;
                        else
@@ -2029,7 +2056,7 @@ static struct file_operations softnet_seq_fops = {
        .release = seq_release,
 };
 
-#ifdef WIRELESS_EXT
+#ifdef CONFIG_WIRELESS_EXT
 extern int wireless_proc_init(void);
 #else
 #define wireless_proc_init() 0
@@ -2159,12 +2186,20 @@ unsigned dev_get_flags(const struct net_device *dev)
 
        flags = (dev->flags & ~(IFF_PROMISC |
                                IFF_ALLMULTI |
-                               IFF_RUNNING)) | 
+                               IFF_RUNNING |
+                               IFF_LOWER_UP |
+                               IFF_DORMANT)) |
                (dev->gflags & (IFF_PROMISC |
                                IFF_ALLMULTI));
 
-       if (netif_running(dev) && netif_carrier_ok(dev))
-               flags |= IFF_RUNNING;
+       if (netif_running(dev)) {
+               if (netif_oper_up(dev))
+                       flags |= IFF_RUNNING;
+               if (netif_carrier_ok(dev))
+                       flags |= IFF_LOWER_UP;
+               if (netif_dormant(dev))
+                       flags |= IFF_DORMANT;
+       }
 
        return flags;
 }
@@ -2443,9 +2478,9 @@ int dev_ioctl(unsigned int cmd, void __user *arg)
         */
 
        if (cmd == SIOCGIFCONF) {
-               rtnl_shlock();
+               rtnl_lock();
                ret = dev_ifconf((char __user *) arg);
-               rtnl_shunlock();
+               rtnl_unlock();
                return ret;
        }
        if (cmd == SIOCGIFNAME)
@@ -2589,7 +2624,7 @@ int dev_ioctl(unsigned int cmd, void __user *arg)
                                        ret = -EFAULT;
                                return ret;
                        }
-#ifdef WIRELESS_EXT
+#ifdef CONFIG_WIRELESS_EXT
                        /* Take care of Wireless Extensions */
                        if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
                                /* If command is `set a parameter', or
@@ -2610,7 +2645,7 @@ int dev_ioctl(unsigned int cmd, void __user *arg)
                                        ret = -EFAULT;
                                return ret;
                        }
-#endif /* WIRELESS_EXT */
+#endif /* CONFIG_WIRELESS_EXT */
                        return -EINVAL;
        }
 }
@@ -2854,7 +2889,7 @@ static void netdev_wait_allrefs(struct net_device *dev)
        rebroadcast_time = warning_time = jiffies;
        while (atomic_read(&dev->refcnt) != 0) {
                if (time_after(jiffies, rebroadcast_time + 1 * HZ)) {
-                       rtnl_shlock();
+                       rtnl_lock();
 
                        /* Rebroadcast unregister notification */
                        notifier_call_chain(&netdev_chain,
@@ -2871,7 +2906,7 @@ static void netdev_wait_allrefs(struct net_device *dev)
                                linkwatch_run_queue();
                        }
 
-                       rtnl_shunlock();
+                       __rtnl_unlock();
 
                        rebroadcast_time = jiffies;
                }
@@ -2909,7 +2944,7 @@ static void netdev_wait_allrefs(struct net_device *dev)
  * 2) Since we run with the RTNL semaphore not held, we can sleep
  *    safely in order to wait for the netdev refcnt to drop to zero.
  */
-static DECLARE_MUTEX(net_todo_run_mutex);
+static DEFINE_MUTEX(net_todo_run_mutex);
 void netdev_run_todo(void)
 {
        struct list_head list = LIST_HEAD_INIT(list);
@@ -2917,7 +2952,7 @@ void netdev_run_todo(void)
 
 
        /* Need to guard against multiple cpu's getting out of order. */
-       down(&net_todo_run_mutex);
+       mutex_lock(&net_todo_run_mutex);
 
        /* Not safe to do outside the semaphore.  We must not return
         * until all unregister events invoked by the local processor
@@ -2974,7 +3009,7 @@ void netdev_run_todo(void)
        }
 
 out:
-       up(&net_todo_run_mutex);
+       mutex_unlock(&net_todo_run_mutex);
 }
 
 /**