aboutsummaryrefslogtreecommitdiffstats
path: root/net/8021q/vlan.c
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2007-06-13 15:05:22 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-07-11 01:14:38 -0400
commitc17d8874f9959070552fddf1b4e1d73c0c144c0f (patch)
treeea5a61e37f71218f8cb69033293a55631511b470 /net/8021q/vlan.c
parent9ba2cd656021e7f70038ba9d551224e04d0bfcef (diff)
[VLAN]: Convert name-based configuration functions to struct netdevice *
Move the device lookup and checks to the ioctl handler under the RTNL and change all name-based interfaces to take a struct net_device * instead. This allows to use them from a netlink interface, which identifies devices based on ifindex not name. It also avoids races between the ioctl interface and the (upcoming) netlink interface since now all changes happen under the RTNL. As a nice side effect this greatly simplifies error handling in the helper functions and fixes a number of incorrect error codes like -EINVAL for device not found. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
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