aboutsummaryrefslogtreecommitdiffstats
path: root/net/8021q/vlan.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/8021q/vlan.c')
-rw-r--r--net/8021q/vlan.c153
1 files changed, 64 insertions, 89 deletions
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index de78c9dd713b..3678f0719934 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -278,43 +278,16 @@ static int unregister_vlan_dev(struct net_device *real_dev,
278 return ret; 278 return ret;
279} 279}
280 280
281static int unregister_vlan_device(const char *vlan_IF_name) 281static int unregister_vlan_device(struct net_device *dev)
282{ 282{
283 struct net_device *dev = NULL;
284 int ret; 283 int ret;
285 284
285 ret = unregister_vlan_dev(VLAN_DEV_INFO(dev)->real_dev,
286 VLAN_DEV_INFO(dev)->vlan_id);
287 unregister_netdevice(dev);
286 288
287 dev = dev_get_by_name(vlan_IF_name); 289 if (ret == 1)
288 ret = -EINVAL; 290 ret = 0;
289 if (dev) {
290 if (dev->priv_flags & IFF_802_1Q_VLAN) {
291 rtnl_lock();
292
293 ret = unregister_vlan_dev(VLAN_DEV_INFO(dev)->real_dev,
294 VLAN_DEV_INFO(dev)->vlan_id);
295
296 dev_put(dev);
297 unregister_netdevice(dev);
298
299 rtnl_unlock();
300
301 if (ret == 1)
302 ret = 0;
303 } else {
304 printk(VLAN_ERR
305 "%s: ERROR: Tried to remove a non-vlan device "
306 "with VLAN code, name: %s priv_flags: %hX\n",
307 __FUNCTION__, dev->name, dev->priv_flags);
308 dev_put(dev);
309 ret = -EPERM;
310 }
311 } else {
312#ifdef VLAN_DEBUG
313 printk(VLAN_DBG "%s: WARNING: Could not find dev.\n", __FUNCTION__);
314#endif
315 ret = -EINVAL;
316 }
317
318 return ret; 291 return ret;
319} 292}
320 293
@@ -378,12 +351,11 @@ static struct lock_class_key vlan_netdev_xmit_lock_key;
378 * Returns the device that was created, or NULL if there was 351 * Returns the device that was created, or NULL if there was
379 * an error of some kind. 352 * an error of some kind.
380 */ 353 */
381static struct net_device *register_vlan_device(const char *eth_IF_name, 354static struct net_device *register_vlan_device(struct net_device *real_dev,
382 unsigned short VLAN_ID) 355 unsigned short VLAN_ID)
383{ 356{
384 struct vlan_group *grp; 357 struct vlan_group *grp;
385 struct net_device *new_dev; 358 struct net_device *new_dev;
386 struct net_device *real_dev; /* the ethernet device */
387 char name[IFNAMSIZ]; 359 char name[IFNAMSIZ];
388 int i; 360 int i;
389 361
@@ -395,46 +367,36 @@ static struct net_device *register_vlan_device(const char *eth_IF_name,
395 if (VLAN_ID >= VLAN_VID_MASK) 367 if (VLAN_ID >= VLAN_VID_MASK)
396 goto out_ret_null; 368 goto out_ret_null;
397 369
398 /* find the device relating to eth_IF_name. */
399 real_dev = dev_get_by_name(eth_IF_name);
400 if (!real_dev)
401 goto out_ret_null;
402
403 if (real_dev->features & NETIF_F_VLAN_CHALLENGED) { 370 if (real_dev->features & NETIF_F_VLAN_CHALLENGED) {
404 printk(VLAN_DBG "%s: VLANs not supported on %s.\n", 371 printk(VLAN_DBG "%s: VLANs not supported on %s.\n",
405 __FUNCTION__, real_dev->name); 372 __FUNCTION__, real_dev->name);
406 goto out_put_dev; 373 goto out_ret_null;
407 } 374 }
408 375
409 if ((real_dev->features & NETIF_F_HW_VLAN_RX) && 376 if ((real_dev->features & NETIF_F_HW_VLAN_RX) &&
410 !real_dev->vlan_rx_register) { 377 !real_dev->vlan_rx_register) {
411 printk(VLAN_DBG "%s: Device %s has buggy VLAN hw accel.\n", 378 printk(VLAN_DBG "%s: Device %s has buggy VLAN hw accel.\n",
412 __FUNCTION__, real_dev->name); 379 __FUNCTION__, real_dev->name);
413 goto out_put_dev; 380 goto out_ret_null;
414 } 381 }
415 382
416 if ((real_dev->features & NETIF_F_HW_VLAN_FILTER) && 383 if ((real_dev->features & NETIF_F_HW_VLAN_FILTER) &&
417 (!real_dev->vlan_rx_add_vid || !real_dev->vlan_rx_kill_vid)) { 384 (!real_dev->vlan_rx_add_vid || !real_dev->vlan_rx_kill_vid)) {
418 printk(VLAN_DBG "%s: Device %s has buggy VLAN hw accel.\n", 385 printk(VLAN_DBG "%s: Device %s has buggy VLAN hw accel.\n",
419 __FUNCTION__, real_dev->name); 386 __FUNCTION__, real_dev->name);
420 goto out_put_dev; 387 goto out_ret_null;
421 } 388 }
422 389
423 /* From this point on, all the data structures must remain
424 * consistent.
425 */
426 rtnl_lock();
427
428 /* The real device must be up and operating in order to 390 /* The real device must be up and operating in order to
429 * assosciate a VLAN device with it. 391 * assosciate a VLAN device with it.
430 */ 392 */
431 if (!(real_dev->flags & IFF_UP)) 393 if (!(real_dev->flags & IFF_UP))
432 goto out_unlock; 394 goto out_ret_null;
433 395
434 if (__find_vlan_dev(real_dev, VLAN_ID) != NULL) { 396 if (__find_vlan_dev(real_dev, VLAN_ID) != NULL) {
435 /* was already registered. */ 397 /* was already registered. */
436 printk(VLAN_DBG "%s: ALREADY had VLAN registered\n", __FUNCTION__); 398 printk(VLAN_DBG "%s: ALREADY had VLAN registered\n", __FUNCTION__);
437 goto out_unlock; 399 goto out_ret_null;
438 } 400 }
439 401
440 /* Gotta set up the fields for the device. */ 402 /* Gotta set up the fields for the device. */
@@ -471,7 +433,7 @@ static struct net_device *register_vlan_device(const char *eth_IF_name,
471 vlan_setup); 433 vlan_setup);
472 434
473 if (new_dev == NULL) 435 if (new_dev == NULL)
474 goto out_unlock; 436 goto out_ret_null;
475 437
476#ifdef VLAN_DEBUG 438#ifdef VLAN_DEBUG
477 printk(VLAN_DBG "Allocated new name -:%s:-\n", new_dev->name); 439 printk(VLAN_DBG "Allocated new name -:%s:-\n", new_dev->name);
@@ -577,9 +539,8 @@ static struct net_device *register_vlan_device(const char *eth_IF_name,
577 if (real_dev->features & NETIF_F_HW_VLAN_FILTER) 539 if (real_dev->features & NETIF_F_HW_VLAN_FILTER)
578 real_dev->vlan_rx_add_vid(real_dev, VLAN_ID); 540 real_dev->vlan_rx_add_vid(real_dev, VLAN_ID);
579 541
580 rtnl_unlock(); 542 /* Account for reference in struct vlan_dev_info */
581 543 dev_hold(real_dev);
582
583#ifdef VLAN_DEBUG 544#ifdef VLAN_DEBUG
584 printk(VLAN_DBG "Allocated new device successfully, returning.\n"); 545 printk(VLAN_DBG "Allocated new device successfully, returning.\n");
585#endif 546#endif
@@ -590,17 +551,11 @@ out_free_arrays:
590 551
591out_free_unregister: 552out_free_unregister:
592 unregister_netdev(new_dev); 553 unregister_netdev(new_dev);
593 goto out_unlock; 554 goto out_ret_null;
594 555
595out_free_newdev: 556out_free_newdev:
596 free_netdev(new_dev); 557 free_netdev(new_dev);
597 558
598out_unlock:
599 rtnl_unlock();
600
601out_put_dev:
602 dev_put(real_dev);
603
604out_ret_null: 559out_ret_null:
605 return NULL; 560 return NULL;
606} 561}
@@ -693,9 +648,10 @@ out:
693 */ 648 */
694static int vlan_ioctl_handler(void __user *arg) 649static int vlan_ioctl_handler(void __user *arg)
695{ 650{
696 int err = 0; 651 int err;
697 unsigned short vid = 0; 652 unsigned short vid = 0;
698 struct vlan_ioctl_args args; 653 struct vlan_ioctl_args args;
654 struct net_device *dev = NULL;
699 655
700 if (copy_from_user(&args, arg, sizeof(struct vlan_ioctl_args))) 656 if (copy_from_user(&args, arg, sizeof(struct vlan_ioctl_args)))
701 return -EFAULT; 657 return -EFAULT;
@@ -708,35 +664,61 @@ static int vlan_ioctl_handler(void __user *arg)
708 printk(VLAN_DBG "%s: args.cmd: %x\n", __FUNCTION__, args.cmd); 664 printk(VLAN_DBG "%s: args.cmd: %x\n", __FUNCTION__, args.cmd);
709#endif 665#endif
710 666
667 rtnl_lock();
668
711 switch (args.cmd) { 669 switch (args.cmd) {
712 case SET_VLAN_INGRESS_PRIORITY_CMD: 670 case SET_VLAN_INGRESS_PRIORITY_CMD:
671 case SET_VLAN_EGRESS_PRIORITY_CMD:
672 case SET_VLAN_FLAG_CMD:
673 case ADD_VLAN_CMD:
674 case DEL_VLAN_CMD:
675 case GET_VLAN_REALDEV_NAME_CMD:
676 case GET_VLAN_VID_CMD:
677 err = -ENODEV;
678 dev = __dev_get_by_name(args.device1);
679 if (!dev)
680 goto out;
681
682 err = -EINVAL;
683 if (args.cmd != ADD_VLAN_CMD &&
684 !(dev->priv_flags & IFF_802_1Q_VLAN))
685 goto out;
686 }
687
688 switch (args.cmd) {
689 case SET_VLAN_INGRESS_PRIORITY_CMD:
690 err = -EPERM;
713 if (!capable(CAP_NET_ADMIN)) 691 if (!capable(CAP_NET_ADMIN))
714 return -EPERM; 692 break;
715 err = vlan_dev_set_ingress_priority(args.device1, 693 vlan_dev_set_ingress_priority(dev,
716 args.u.skb_priority, 694 args.u.skb_priority,
717 args.vlan_qos); 695 args.vlan_qos);
718 break; 696 break;
719 697
720 case SET_VLAN_EGRESS_PRIORITY_CMD: 698 case SET_VLAN_EGRESS_PRIORITY_CMD:
699 err = -EPERM;
721 if (!capable(CAP_NET_ADMIN)) 700 if (!capable(CAP_NET_ADMIN))
722 return -EPERM; 701 break;
723 err = vlan_dev_set_egress_priority(args.device1, 702 err = vlan_dev_set_egress_priority(dev,
724 args.u.skb_priority, 703 args.u.skb_priority,
725 args.vlan_qos); 704 args.vlan_qos);
726 break; 705 break;
727 706
728 case SET_VLAN_FLAG_CMD: 707 case SET_VLAN_FLAG_CMD:
708 err = -EPERM;
729 if (!capable(CAP_NET_ADMIN)) 709 if (!capable(CAP_NET_ADMIN))
730 return -EPERM; 710 break;
731 err = vlan_dev_set_vlan_flag(args.device1, 711 err = vlan_dev_set_vlan_flag(dev,
732 args.u.flag, 712 args.u.flag,
733 args.vlan_qos); 713 args.vlan_qos);
734 break; 714 break;
735 715
736 case SET_VLAN_NAME_TYPE_CMD: 716 case SET_VLAN_NAME_TYPE_CMD:
717 err = -EPERM;
737 if (!capable(CAP_NET_ADMIN)) 718 if (!capable(CAP_NET_ADMIN))
738 return -EPERM; 719 return -EPERM;
739 if (args.u.name_type < VLAN_NAME_TYPE_HIGHEST) { 720 if ((args.u.name_type >= 0) &&
721 (args.u.name_type < VLAN_NAME_TYPE_HIGHEST)) {
740 vlan_name_type = args.u.name_type; 722 vlan_name_type = args.u.name_type;
741 err = 0; 723 err = 0;
742 } else { 724 } else {
@@ -745,13 +727,10 @@ static int vlan_ioctl_handler(void __user *arg)
745 break; 727 break;
746 728
747 case ADD_VLAN_CMD: 729 case ADD_VLAN_CMD:
730 err = -EPERM;
748 if (!capable(CAP_NET_ADMIN)) 731 if (!capable(CAP_NET_ADMIN))
749 return -EPERM; 732 break;
750 /* we have been given the name of the Ethernet Device we want to 733 if (register_vlan_device(dev, args.u.VID)) {
751 * talk to: args.dev1 We also have the
752 * VLAN ID: args.u.VID
753 */
754 if (register_vlan_device(args.device1, args.u.VID)) {
755 err = 0; 734 err = 0;
756 } else { 735 } else {
757 err = -EINVAL; 736 err = -EINVAL;
@@ -759,12 +738,10 @@ static int vlan_ioctl_handler(void __user *arg)
759 break; 738 break;
760 739
761 case DEL_VLAN_CMD: 740 case DEL_VLAN_CMD:
741 err = -EPERM;
762 if (!capable(CAP_NET_ADMIN)) 742 if (!capable(CAP_NET_ADMIN))
763 return -EPERM; 743 break;
764 /* Here, the args.dev1 is the actual VLAN we want 744 err = unregister_vlan_device(dev);
765 * to get rid of.
766 */
767 err = unregister_vlan_device(args.device1);
768 break; 745 break;
769 746
770 case GET_VLAN_INGRESS_PRIORITY_CMD: 747 case GET_VLAN_INGRESS_PRIORITY_CMD:
@@ -788,9 +765,7 @@ static int vlan_ioctl_handler(void __user *arg)
788 err = -EINVAL; 765 err = -EINVAL;
789 break; 766 break;
790 case GET_VLAN_REALDEV_NAME_CMD: 767 case GET_VLAN_REALDEV_NAME_CMD:
791 err = vlan_dev_get_realdev_name(args.device1, args.u.device2); 768 vlan_dev_get_realdev_name(dev, args.u.device2);
792 if (err)
793 goto out;
794 if (copy_to_user(arg, &args, 769 if (copy_to_user(arg, &args,
795 sizeof(struct vlan_ioctl_args))) { 770 sizeof(struct vlan_ioctl_args))) {
796 err = -EFAULT; 771 err = -EFAULT;
@@ -798,9 +773,7 @@ static int vlan_ioctl_handler(void __user *arg)
798 break; 773 break;
799 774
800 case GET_VLAN_VID_CMD: 775 case GET_VLAN_VID_CMD:
801 err = vlan_dev_get_vid(args.device1, &vid); 776 vlan_dev_get_vid(dev, &vid);
802 if (err)
803 goto out;
804 args.u.VID = vid; 777 args.u.VID = vid;
805 if (copy_to_user(arg, &args, 778 if (copy_to_user(arg, &args,
806 sizeof(struct vlan_ioctl_args))) { 779 sizeof(struct vlan_ioctl_args))) {
@@ -812,9 +785,11 @@ static int vlan_ioctl_handler(void __user *arg)
812 /* pass on to underlying device instead?? */ 785 /* pass on to underlying device instead?? */
813 printk(VLAN_DBG "%s: Unknown VLAN CMD: %x \n", 786 printk(VLAN_DBG "%s: Unknown VLAN CMD: %x \n",
814 __FUNCTION__, args.cmd); 787 __FUNCTION__, args.cmd);
815 return -EINVAL; 788 err = -EINVAL;
789 break;
816 } 790 }
817out: 791out:
792 rtnl_unlock();
818 return err; 793 return err;
819} 794}
820 795