[VLAN]: Don't synchronize addresses while the vlan device is down
[cascardo/linux.git] / net / 8021q / vlan.c
index 2a54691..0fadbc6 100644 (file)
@@ -31,6 +31,7 @@
 #include <net/arp.h>
 #include <linux/rtnetlink.h>
 #include <linux/notifier.h>
+#include <net/net_namespace.h>
 
 #include <linux/if_vlan.h>
 #include "vlan.h"
@@ -50,7 +51,7 @@ static char vlan_copyright[] = "Ben Greear <greearb@candelatech.com>";
 static char vlan_buggyright[] = "David S. Miller <davem@redhat.com>";
 
 static int vlan_device_event(struct notifier_block *, unsigned long, void *);
-static int vlan_ioctl_handler(void __user *);
+static int vlan_ioctl_handler(struct net *net, void __user *);
 static int unregister_vlan_dev(struct net_device *, unsigned short );
 
 static struct notifier_block vlan_notifier_block = {
@@ -313,6 +314,12 @@ int unregister_vlan_device(struct net_device *dev)
  */
 static struct lock_class_key vlan_netdev_xmit_lock_key;
 
+static const struct header_ops vlan_header_ops = {
+       .create  = vlan_dev_hard_header,
+       .rebuild = vlan_dev_rebuild_header,
+       .parse   = eth_header_parse,
+};
+
 static int vlan_dev_init(struct net_device *dev)
 {
        struct net_device *real_dev = VLAN_DEV_INFO(dev)->real_dev;
@@ -324,24 +331,23 @@ static int vlan_dev_init(struct net_device *dev)
                                          (1<<__LINK_STATE_DORMANT))) |
                      (1<<__LINK_STATE_PRESENT);
 
+       /* ipv6 shared card related stuff */
+       dev->dev_id = real_dev->dev_id;
+
        if (is_zero_ether_addr(dev->dev_addr))
                memcpy(dev->dev_addr, real_dev->dev_addr, dev->addr_len);
        if (is_zero_ether_addr(dev->broadcast))
                memcpy(dev->broadcast, real_dev->broadcast, dev->addr_len);
 
        if (real_dev->features & NETIF_F_HW_VLAN_TX) {
-               dev->hard_header     = real_dev->hard_header;
+               dev->header_ops      = real_dev->header_ops;
                dev->hard_header_len = real_dev->hard_header_len;
                dev->hard_start_xmit = vlan_dev_hwaccel_hard_start_xmit;
-               dev->rebuild_header  = real_dev->rebuild_header;
        } else {
-               dev->hard_header     = vlan_dev_hard_header;
+               dev->header_ops      = &vlan_header_ops;
                dev->hard_header_len = real_dev->hard_header_len + VLAN_HLEN;
                dev->hard_start_xmit = vlan_dev_hard_start_xmit;
-               dev->rebuild_header  = vlan_dev_rebuild_header;
        }
-       dev->hard_header_parse = real_dev->hard_header_parse;
-       dev->hard_header_cache = NULL;
 
        lockdep_set_class(&dev->_xmit_lock, &vlan_netdev_xmit_lock_key);
        return 0;
@@ -349,8 +355,6 @@ static int vlan_dev_init(struct net_device *dev)
 
 void vlan_setup(struct net_device *new_dev)
 {
-       SET_MODULE_OWNER(new_dev);
-
        ether_setup(new_dev);
 
        /* new_dev->ifindex = 0;  it will be set when added to
@@ -603,6 +607,9 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
        int i, flgs;
        struct net_device *vlandev;
 
+       if (dev->nd_net != &init_net)
+               return NOTIFY_DONE;
+
        if (!grp)
                goto out;
 
@@ -629,6 +636,10 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
                        if (!vlandev)
                                continue;
 
+                       flgs = vlandev->flags;
+                       if (!(flgs & IFF_UP))
+                               continue;
+
                        vlan_sync_address(dev, vlandev);
                }
                break;
@@ -693,7 +704,7 @@ out:
  *     o execute requested action or pass command to the device driver
  *   arg is really a struct vlan_ioctl_args __user *.
  */
-static int vlan_ioctl_handler(void __user *arg)
+static int vlan_ioctl_handler(struct net *net, void __user *arg)
 {
        int err;
        unsigned short vid = 0;
@@ -722,7 +733,7 @@ static int vlan_ioctl_handler(void __user *arg)
        case GET_VLAN_REALDEV_NAME_CMD:
        case GET_VLAN_VID_CMD:
                err = -ENODEV;
-               dev = __dev_get_by_name(args.device1);
+               dev = __dev_get_by_name(&init_net, args.device1);
                if (!dev)
                        goto out;
 
@@ -740,6 +751,7 @@ static int vlan_ioctl_handler(void __user *arg)
                vlan_dev_set_ingress_priority(dev,
                                              args.u.skb_priority,
                                              args.vlan_qos);
+               err = 0;
                break;
 
        case SET_VLAN_EGRESS_PRIORITY_CMD: