diff options
-rw-r--r-- | include/linux/if_vlan.h | 1 | ||||
-rw-r--r-- | net/8021q/vlan.c | 9 | ||||
-rw-r--r-- | net/8021q/vlan_dev.c | 6 | ||||
-rw-r--r-- | net/8021q/vlan_netlink.c | 3 |
4 files changed, 14 insertions, 5 deletions
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index 153f6b9e722c..3d870fda8c4f 100644 --- a/include/linux/if_vlan.h +++ b/include/linux/if_vlan.h | |||
@@ -339,6 +339,7 @@ enum vlan_ioctl_cmds { | |||
339 | enum vlan_flags { | 339 | enum vlan_flags { |
340 | VLAN_FLAG_REORDER_HDR = 0x1, | 340 | VLAN_FLAG_REORDER_HDR = 0x1, |
341 | VLAN_FLAG_GVRP = 0x2, | 341 | VLAN_FLAG_GVRP = 0x2, |
342 | VLAN_FLAG_LOOSE_BINDING = 0x4, | ||
342 | }; | 343 | }; |
343 | 344 | ||
344 | enum vlan_name_types { | 345 | enum vlan_name_types { |
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 1483243edf14..225aa2fac0e3 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c | |||
@@ -431,6 +431,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, | |||
431 | struct vlan_group *grp; | 431 | struct vlan_group *grp; |
432 | int i, flgs; | 432 | int i, flgs; |
433 | struct net_device *vlandev; | 433 | struct net_device *vlandev; |
434 | struct vlan_dev_info *vlan; | ||
434 | LIST_HEAD(list); | 435 | LIST_HEAD(list); |
435 | 436 | ||
436 | if (is_vlan_dev(dev)) | 437 | if (is_vlan_dev(dev)) |
@@ -507,7 +508,9 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, | |||
507 | if (!(flgs & IFF_UP)) | 508 | if (!(flgs & IFF_UP)) |
508 | continue; | 509 | continue; |
509 | 510 | ||
510 | dev_change_flags(vlandev, flgs & ~IFF_UP); | 511 | vlan = vlan_dev_info(vlandev); |
512 | if (!(vlan->flags & VLAN_FLAG_LOOSE_BINDING)) | ||
513 | dev_change_flags(vlandev, flgs & ~IFF_UP); | ||
511 | vlan_transfer_operstate(dev, vlandev); | 514 | vlan_transfer_operstate(dev, vlandev); |
512 | } | 515 | } |
513 | break; | 516 | break; |
@@ -523,7 +526,9 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, | |||
523 | if (flgs & IFF_UP) | 526 | if (flgs & IFF_UP) |
524 | continue; | 527 | continue; |
525 | 528 | ||
526 | dev_change_flags(vlandev, flgs | IFF_UP); | 529 | vlan = vlan_dev_info(vlandev); |
530 | if (!(vlan->flags & VLAN_FLAG_LOOSE_BINDING)) | ||
531 | dev_change_flags(vlandev, flgs | IFF_UP); | ||
527 | vlan_transfer_operstate(dev, vlandev); | 532 | vlan_transfer_operstate(dev, vlandev); |
528 | } | 533 | } |
529 | break; | 534 | break; |
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index de0dc6bacbe8..b7889782047e 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c | |||
@@ -431,7 +431,8 @@ int vlan_dev_change_flags(const struct net_device *dev, u32 flags, u32 mask) | |||
431 | struct vlan_dev_info *vlan = vlan_dev_info(dev); | 431 | struct vlan_dev_info *vlan = vlan_dev_info(dev); |
432 | u32 old_flags = vlan->flags; | 432 | u32 old_flags = vlan->flags; |
433 | 433 | ||
434 | if (mask & ~(VLAN_FLAG_REORDER_HDR | VLAN_FLAG_GVRP)) | 434 | if (mask & ~(VLAN_FLAG_REORDER_HDR | VLAN_FLAG_GVRP | |
435 | VLAN_FLAG_LOOSE_BINDING)) | ||
435 | return -EINVAL; | 436 | return -EINVAL; |
436 | 437 | ||
437 | vlan->flags = (old_flags & ~mask) | (flags & mask); | 438 | vlan->flags = (old_flags & ~mask) | (flags & mask); |
@@ -456,7 +457,8 @@ static int vlan_dev_open(struct net_device *dev) | |||
456 | struct net_device *real_dev = vlan->real_dev; | 457 | struct net_device *real_dev = vlan->real_dev; |
457 | int err; | 458 | int err; |
458 | 459 | ||
459 | if (!(real_dev->flags & IFF_UP)) | 460 | if (!(real_dev->flags & IFF_UP) && |
461 | !(vlan->flags & VLAN_FLAG_LOOSE_BINDING)) | ||
460 | return -ENETDOWN; | 462 | return -ENETDOWN; |
461 | 463 | ||
462 | if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr)) { | 464 | if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr)) { |
diff --git a/net/8021q/vlan_netlink.c b/net/8021q/vlan_netlink.c index 3c9cf6a8e7fb..ddc105734af7 100644 --- a/net/8021q/vlan_netlink.c +++ b/net/8021q/vlan_netlink.c | |||
@@ -60,7 +60,8 @@ static int vlan_validate(struct nlattr *tb[], struct nlattr *data[]) | |||
60 | if (data[IFLA_VLAN_FLAGS]) { | 60 | if (data[IFLA_VLAN_FLAGS]) { |
61 | flags = nla_data(data[IFLA_VLAN_FLAGS]); | 61 | flags = nla_data(data[IFLA_VLAN_FLAGS]); |
62 | if ((flags->flags & flags->mask) & | 62 | if ((flags->flags & flags->mask) & |
63 | ~(VLAN_FLAG_REORDER_HDR | VLAN_FLAG_GVRP)) | 63 | ~(VLAN_FLAG_REORDER_HDR | VLAN_FLAG_GVRP | |
64 | VLAN_FLAG_LOOSE_BINDING)) | ||
64 | return -EINVAL; | 65 | return -EINVAL; |
65 | } | 66 | } |
66 | 67 | ||