1/* 2 * INET 802.1Q VLAN 3 * Ethernet-type device handling. 4 * 5 * Authors: Ben Greear <greearb@candelatech.com> 6 * Please send support related email to: vlan@scry.wanfear.com 7 * VLAN Home Page: http://www.candelatech.com/~greear/vlan.html 8 * 9 * Fixes: 10 * Fix for packet capture - Nick Eggleston <nick@dccinc.com>; 11 * Add HW acceleration hooks - David S. Miller <davem@redhat.com>; 12 * Correct all the locking - David S. Miller <davem@redhat.com>; 13 * Use hash table for VLAN groups - David S. Miller <davem@redhat.com> 14 * 15 * This program is free software; you can redistribute it and/or 16 * modify it under the terms of the GNU General Public License 17 * as published by the Free Software Foundation; either version 18 * 2 of the License, or (at your option) any later version. 19 */ 20 21#include <asm/uaccess.h> /* for copy_from_user */ 22#include <linux/capability.h> 23#include <linux/module.h> 24#include <linux/netdevice.h> 25#include <linux/skbuff.h> 26#include <net/datalink.h> 27#include <linux/mm.h> 28#include <linux/in.h> 29#include <linux/init.h> 30#include <net/p8022.h> 31#include <net/arp.h> 32#include <linux/rtnetlink.h> 33#include <linux/notifier.h> 34 35#include <linux/if_vlan.h> 36#include "vlan.h" 37#include "vlanproc.h" 38#ifdef HNDCTF 39#include <ctf/hndctf.h> 40#endif /* HNDCTF */ 41 42#define DRV_VERSION "1.8" 43 44/* Global VLAN variables */ 45 46/* Our listing of VLAN group(s) */ 47static struct hlist_head vlan_group_hash[VLAN_GRP_HASH_SIZE]; 48#define vlan_grp_hashfn(IDX) ((((IDX) >> VLAN_GRP_HASH_SHIFT) ^ (IDX)) & VLAN_GRP_HASH_MASK) 49 50static char vlan_fullname[] = "802.1Q VLAN Support"; 51static char vlan_version[] = DRV_VERSION; 52static char vlan_copyright[] = "Ben Greear <greearb@candelatech.com>"; 53static char vlan_buggyright[] = "David S. Miller <davem@redhat.com>"; 54 55static int vlan_device_event(struct notifier_block *, unsigned long, void *); 56static int vlan_ioctl_handler(void __user *); 57static int unregister_vlan_dev(struct net_device *, unsigned short ); 58 59static struct notifier_block vlan_notifier_block = { 60 .notifier_call = vlan_device_event, 61}; 62 63/* These may be changed at run-time through IOCTLs */ 64 65/* Determines interface naming scheme. */ 66unsigned short vlan_name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD; 67 68static struct packet_type vlan_packet_type = { 69 .type = __constant_htons(ETH_P_8021Q), 70 .func = vlan_skb_recv, /* VLAN receive method */ 71}; 72 73/* End of global variables definitions. */ 74 75/* 76 * Function vlan_proto_init (pro) 77 * 78 * Initialize VLAN protocol layer, 79 * 80 */ 81static int __init vlan_proto_init(void) 82{ 83 int err; 84 85 printk(VLAN_INF "%s v%s %s\n", 86 vlan_fullname, vlan_version, vlan_copyright); 87 printk(VLAN_INF "All bugs added by %s\n", 88 vlan_buggyright); 89 90 /* proc file system initialization */ 91 err = vlan_proc_init(); 92 if (err < 0) { 93 printk(KERN_ERR 94 "%s %s: can't create entry in proc filesystem!\n", 95 __FUNCTION__, VLAN_NAME); 96 return err; 97 } 98 99 dev_add_pack(&vlan_packet_type); 100 101 /* Register us to receive netdevice events */ 102 err = register_netdevice_notifier(&vlan_notifier_block); 103 if (err < 0) { 104 dev_remove_pack(&vlan_packet_type); 105 vlan_proc_cleanup(); 106 return err; 107 } 108 109 vlan_ioctl_set(vlan_ioctl_handler); 110 111 return 0; 112} 113 114/* Cleanup all vlan devices 115 * Note: devices that have been registered that but not 116 * brought up will exist but have no module ref count. 117 */ 118static void __exit vlan_cleanup_devices(void) 119{ 120 struct net_device *dev, *nxt; 121 122 rtnl_lock(); 123 for_each_netdev_safe(dev, nxt) { 124 if (dev->priv_flags & IFF_802_1Q_VLAN) { 125 unregister_vlan_dev(VLAN_DEV_INFO(dev)->real_dev, 126 VLAN_DEV_INFO(dev)->vlan_id); 127 128 unregister_netdevice(dev); 129 } 130 } 131 rtnl_unlock(); 132} 133 134/* 135 * Module 'remove' entry point. 136 * o delete /proc/net/router directory and static entries. 137 */ 138static void __exit vlan_cleanup_module(void) 139{ 140 int i; 141 142 vlan_ioctl_set(NULL); 143 144 /* Un-register us from receiving netdevice events */ 145 unregister_netdevice_notifier(&vlan_notifier_block); 146 147 dev_remove_pack(&vlan_packet_type); 148 vlan_cleanup_devices(); 149 150 /* This table must be empty if there are no module 151 * references left. 152 */ 153 for (i = 0; i < VLAN_GRP_HASH_SIZE; i++) { 154 BUG_ON(!hlist_empty(&vlan_group_hash[i])); 155 } 156 vlan_proc_cleanup(); 157 158 synchronize_net(); 159} 160 161module_init(vlan_proto_init); 162module_exit(vlan_cleanup_module); 163 164/* Must be invoked with RCU read lock (no preempt) */ 165static struct vlan_group *__vlan_find_group(int real_dev_ifindex) 166{ 167 struct vlan_group *grp; 168 struct hlist_node *n; 169 int hash = vlan_grp_hashfn(real_dev_ifindex); 170 171 hlist_for_each_entry_rcu(grp, n, &vlan_group_hash[hash], hlist) { 172 if (grp->real_dev_ifindex == real_dev_ifindex) 173 return grp; 174 } 175 176 return NULL; 177} 178 179/* Find the protocol handler. Assumes VID < VLAN_VID_MASK. 180 * 181 * Must be invoked with RCU read lock (no preempt) 182 */ 183struct net_device *__find_vlan_dev(struct net_device *real_dev, 184 unsigned short VID) 185{ 186 struct vlan_group *grp = __vlan_find_group(real_dev->ifindex); 187 188 if (grp) 189 return vlan_group_get_device(grp, VID); 190 191 return NULL; 192} 193 194static void vlan_group_free(struct vlan_group *grp) 195{ 196 int i; 197 198 for (i=0; i < VLAN_GROUP_ARRAY_SPLIT_PARTS; i++) 199 kfree(grp->vlan_devices_arrays[i]); 200 kfree(grp); 201} 202 203static void vlan_rcu_free(struct rcu_head *rcu) 204{ 205 vlan_group_free(container_of(rcu, struct vlan_group, rcu)); 206} 207 208 209/* This returns 0 if everything went fine. 210 * It will return 1 if the group was killed as a result. 211 * A negative return indicates failure. 212 * 213 * The RTNL lock must be held. 214 */ 215static int unregister_vlan_dev(struct net_device *real_dev, 216 unsigned short vlan_id) 217{ 218 struct net_device *dev = NULL; 219 int real_dev_ifindex = real_dev->ifindex; 220 struct vlan_group *grp; 221 int i, ret; 222 223#ifdef VLAN_DEBUG 224 printk(VLAN_DBG "%s: VID: %i\n", __FUNCTION__, vlan_id); 225#endif 226 227 /* sanity check */ 228 if (vlan_id >= VLAN_VID_MASK) 229 return -EINVAL; 230 231 ASSERT_RTNL(); 232 grp = __vlan_find_group(real_dev_ifindex); 233 234 ret = 0; 235 236 if (grp) { 237 dev = vlan_group_get_device(grp, vlan_id); 238 if (dev) { 239 /* Remove proc entry */ 240 vlan_proc_rem_dev(dev); 241 242 /* Take it out of our own structures, but be sure to 243 * interlock with HW accelerating devices or SW vlan 244 * input packet processing. 245 */ 246 if (real_dev->features & NETIF_F_HW_VLAN_FILTER) 247 real_dev->vlan_rx_kill_vid(real_dev, vlan_id); 248 249 vlan_group_set_device(grp, vlan_id, NULL); 250 synchronize_net(); 251 252#ifdef HNDCTF 253 (void)ctf_dev_vlan_delete(kcih, real_dev, vlan_id); 254#endif /* HNDCTF */ 255 256 /* Caller unregisters (and if necessary, puts) 257 * VLAN device, but we get rid of the reference to 258 * real_dev here. 259 */ 260 dev_put(real_dev); 261 262 /* If the group is now empty, kill off the 263 * group. 264 */ 265 for (i = 0; i < VLAN_VID_MASK; i++) 266 if (vlan_group_get_device(grp, i)) 267 break; 268 269 if (i == VLAN_VID_MASK) { 270 if (real_dev->features & NETIF_F_HW_VLAN_RX) 271 real_dev->vlan_rx_register(real_dev, NULL); 272 273 hlist_del_rcu(&grp->hlist); 274 275 /* Free the group, after all cpu's are done. */ 276 call_rcu(&grp->rcu, vlan_rcu_free); 277 278 grp = NULL; 279 ret = 1; 280 } 281 } 282 } 283 284 return ret; 285} 286 287static int unregister_vlan_device(const char *vlan_IF_name) 288{ 289 struct net_device *dev = NULL; 290 int ret; 291 292 293 dev = dev_get_by_name(vlan_IF_name); 294 ret = -EINVAL; 295 if (dev) { 296 if (dev->priv_flags & IFF_802_1Q_VLAN) { 297 rtnl_lock(); 298 299 ret = unregister_vlan_dev(VLAN_DEV_INFO(dev)->real_dev, 300 VLAN_DEV_INFO(dev)->vlan_id); 301 302 dev_put(dev); 303 unregister_netdevice(dev); 304 305 rtnl_unlock(); 306 307 if (ret == 1) 308 ret = 0; 309 } else { 310 printk(VLAN_ERR 311 "%s: ERROR: Tried to remove a non-vlan device " 312 "with VLAN code, name: %s priv_flags: %hX\n", 313 __FUNCTION__, dev->name, dev->priv_flags); 314 dev_put(dev); 315 ret = -EPERM; 316 } 317 } else { 318#ifdef VLAN_DEBUG 319 printk(VLAN_DBG "%s: WARNING: Could not find dev.\n", __FUNCTION__); 320#endif 321 ret = -EINVAL; 322 } 323 324 return ret; 325} 326 327static void vlan_setup(struct net_device *new_dev) 328{ 329 SET_MODULE_OWNER(new_dev); 330 331 /* new_dev->ifindex = 0; it will be set when added to 332 * the global list. 333 * iflink is set as well. 334 */ 335 new_dev->get_stats = vlan_dev_get_stats; 336 337 /* Make this thing known as a VLAN device */ 338 new_dev->priv_flags |= IFF_802_1Q_VLAN; 339 340 /* Set us up to have no queue, as the underlying Hardware device 341 * can do all the queueing we could want. 342 */ 343 new_dev->tx_queue_len = 0; 344 345 /* set up method calls */ 346 new_dev->change_mtu = vlan_dev_change_mtu; 347 new_dev->open = vlan_dev_open; 348 new_dev->stop = vlan_dev_stop; 349 new_dev->set_mac_address = vlan_dev_set_mac_address; 350 new_dev->set_multicast_list = vlan_dev_set_multicast_list; 351 new_dev->destructor = free_netdev; 352 new_dev->do_ioctl = vlan_dev_ioctl; 353} 354 355static void vlan_transfer_operstate(const struct net_device *dev, struct net_device *vlandev) 356{ 357 /* Have to respect userspace enforced dormant state 358 * of real device, also must allow supplicant running 359 * on VLAN device 360 */ 361 if (dev->operstate == IF_OPER_DORMANT) 362 netif_dormant_on(vlandev); 363 else 364 netif_dormant_off(vlandev); 365 366 if (netif_carrier_ok(dev)) { 367 if (!netif_carrier_ok(vlandev)) 368 netif_carrier_on(vlandev); 369 } else { 370 if (netif_carrier_ok(vlandev)) 371 netif_carrier_off(vlandev); 372 } 373} 374 375/* 376 * vlan network devices have devices nesting below it, and are a special 377 * "super class" of normal network devices; split their locks off into a 378 * separate class since they always nest. 379 */ 380static struct lock_class_key vlan_netdev_xmit_lock_key; 381 382 383/* Attach a VLAN device to a mac address (ie Ethernet Card). 384 * Returns the device that was created, or NULL if there was 385 * an error of some kind. 386 */ 387static struct net_device *register_vlan_device(const char *eth_IF_name, 388 unsigned short VLAN_ID) 389{ 390 struct vlan_group *grp; 391 struct net_device *new_dev; 392 struct net_device *real_dev; /* the ethernet device */ 393 char name[IFNAMSIZ]; 394 int i; 395 396#ifdef VLAN_DEBUG 397 printk(VLAN_DBG "%s: if_name -:%s:- vid: %i\n", 398 __FUNCTION__, eth_IF_name, VLAN_ID); 399#endif 400 401 if (VLAN_ID >= VLAN_VID_MASK) 402 goto out_ret_null; 403 404 /* find the device relating to eth_IF_name. */ 405 real_dev = dev_get_by_name(eth_IF_name); 406 if (!real_dev) 407 goto out_ret_null; 408 409 if (real_dev->features & NETIF_F_VLAN_CHALLENGED) { 410 printk(VLAN_DBG "%s: VLANs not supported on %s.\n", 411 __FUNCTION__, real_dev->name); 412 goto out_put_dev; 413 } 414 415 if ((real_dev->features & NETIF_F_HW_VLAN_RX) && 416 !real_dev->vlan_rx_register) { 417 printk(VLAN_DBG "%s: Device %s has buggy VLAN hw accel.\n", 418 __FUNCTION__, real_dev->name); 419 goto out_put_dev; 420 } 421 422 if ((real_dev->features & NETIF_F_HW_VLAN_FILTER) && 423 (!real_dev->vlan_rx_add_vid || !real_dev->vlan_rx_kill_vid)) { 424 printk(VLAN_DBG "%s: Device %s has buggy VLAN hw accel.\n", 425 __FUNCTION__, real_dev->name); 426 goto out_put_dev; 427 } 428 429 /* From this point on, all the data structures must remain 430 * consistent. 431 */ 432 rtnl_lock(); 433 434 /* The real device must be up and operating in order to 435 * assosciate a VLAN device with it. 436 */ 437 if (!(real_dev->flags & IFF_UP)) 438 goto out_unlock; 439 440 if (__find_vlan_dev(real_dev, VLAN_ID) != NULL) { 441 /* was already registered. */ 442 printk(VLAN_DBG "%s: ALREADY had VLAN registered\n", __FUNCTION__); 443 goto out_unlock; 444 } 445 446 /* Gotta set up the fields for the device. */ 447#ifdef VLAN_DEBUG 448 printk(VLAN_DBG "About to allocate name, vlan_name_type: %i\n", 449 vlan_name_type); 450#endif 451 switch (vlan_name_type) { 452 case VLAN_NAME_TYPE_RAW_PLUS_VID: 453 /* name will look like: eth1.0005 */ 454 snprintf(name, IFNAMSIZ, "%s.%.4i", real_dev->name, VLAN_ID); 455 break; 456 case VLAN_NAME_TYPE_PLUS_VID_NO_PAD: 457 /* Put our vlan.VID in the name. 458 * Name will look like: vlan5 459 */ 460 snprintf(name, IFNAMSIZ, "vlan%i", VLAN_ID); 461 break; 462 case VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD: 463 /* Put our vlan.VID in the name. 464 * Name will look like: eth0.5 465 */ 466 snprintf(name, IFNAMSIZ, "%s.%i", real_dev->name, VLAN_ID); 467 break; 468 case VLAN_NAME_TYPE_PLUS_VID: 469 /* Put our vlan.VID in the name. 470 * Name will look like: vlan0005 471 */ 472 default: 473 snprintf(name, IFNAMSIZ, "vlan%.4i", VLAN_ID); 474 } 475 476 new_dev = alloc_netdev(sizeof(struct vlan_dev_info), name, 477 vlan_setup); 478 479 if (new_dev == NULL) 480 goto out_unlock; 481 482#ifdef VLAN_DEBUG 483 printk(VLAN_DBG "Allocated new name -:%s:-\n", new_dev->name); 484#endif 485 /* IFF_BROADCAST|IFF_MULTICAST; ??? */ 486 new_dev->flags = real_dev->flags; 487 new_dev->flags &= ~IFF_UP; 488 489 new_dev->state = (real_dev->state & ((1<<__LINK_STATE_NOCARRIER) | 490 (1<<__LINK_STATE_DORMANT))) | 491 (1<<__LINK_STATE_PRESENT); 492 493 /* need 4 bytes for extra VLAN header info, 494 * hope the underlying device can handle it. 495 */ 496 new_dev->mtu = real_dev->mtu; 497 498 /* TODO: maybe just assign it to be ETHERNET? */ 499 new_dev->type = real_dev->type; 500 501 new_dev->hard_header_len = real_dev->hard_header_len; 502 if (!(real_dev->features & NETIF_F_HW_VLAN_TX)) { 503 /* Regular ethernet + 4 bytes (18 total). */ 504 new_dev->hard_header_len += VLAN_HLEN; 505 } 506 507 VLAN_MEM_DBG("new_dev->priv malloc, addr: %p size: %i\n", 508 new_dev->priv, 509 sizeof(struct vlan_dev_info)); 510 511 memcpy(new_dev->broadcast, real_dev->broadcast, real_dev->addr_len); 512 memcpy(new_dev->dev_addr, real_dev->dev_addr, real_dev->addr_len); 513 new_dev->addr_len = real_dev->addr_len; 514 515 if (real_dev->features & NETIF_F_HW_VLAN_TX) { 516 new_dev->hard_header = real_dev->hard_header; 517 new_dev->hard_start_xmit = vlan_dev_hwaccel_hard_start_xmit; 518 new_dev->rebuild_header = real_dev->rebuild_header; 519 } else { 520 new_dev->hard_header = vlan_dev_hard_header; 521 new_dev->hard_start_xmit = vlan_dev_hard_start_xmit; 522 new_dev->rebuild_header = vlan_dev_rebuild_header; 523 } 524 new_dev->hard_header_parse = real_dev->hard_header_parse; 525 526 VLAN_DEV_INFO(new_dev)->vlan_id = VLAN_ID; /* 1 through VLAN_VID_MASK */ 527 VLAN_DEV_INFO(new_dev)->real_dev = real_dev; 528 VLAN_DEV_INFO(new_dev)->dent = NULL; 529 VLAN_DEV_INFO(new_dev)->flags = 1; 530 531#ifdef VLAN_DEBUG 532 printk(VLAN_DBG "About to go find the group for idx: %i\n", 533 real_dev->ifindex); 534#endif 535 536 if (register_netdevice(new_dev)) 537 goto out_free_newdev; 538 539#ifdef HNDCTF 540 (void)ctf_dev_vlan_add(kcih, real_dev, VLAN_ID, new_dev); 541#endif /* HNDCTF */ 542 543 lockdep_set_class(&new_dev->_xmit_lock, &vlan_netdev_xmit_lock_key); 544 545 new_dev->iflink = real_dev->ifindex; 546 vlan_transfer_operstate(real_dev, new_dev); 547 linkwatch_fire_event(new_dev); /* _MUST_ call rfc2863_policy() */ 548 549 /* So, got the sucker initialized, now lets place 550 * it into our local structure. 551 */ 552 grp = __vlan_find_group(real_dev->ifindex); 553 554 /* Note, we are running under the RTNL semaphore 555 * so it cannot "appear" on us. 556 */ 557 if (!grp) { /* need to add a new group */ 558 grp = kzalloc(sizeof(struct vlan_group), GFP_KERNEL); 559 if (!grp) 560 goto out_free_unregister; 561 562 for (i=0; i < VLAN_GROUP_ARRAY_SPLIT_PARTS; i++) { 563 grp->vlan_devices_arrays[i] = kzalloc( 564 sizeof(struct net_device *)*VLAN_GROUP_ARRAY_PART_LEN, 565 GFP_KERNEL); 566 567 if (!grp->vlan_devices_arrays[i]) 568 goto out_free_arrays; 569 } 570 571 /* printk(KERN_ALERT "VLAN REGISTER: Allocated new group.\n"); */ 572 grp->real_dev_ifindex = real_dev->ifindex; 573 574 hlist_add_head_rcu(&grp->hlist, 575 &vlan_group_hash[vlan_grp_hashfn(real_dev->ifindex)]); 576 577 if (real_dev->features & NETIF_F_HW_VLAN_RX) 578 real_dev->vlan_rx_register(real_dev, grp); 579 } 580 581 vlan_group_set_device(grp, VLAN_ID, new_dev); 582 583 if (vlan_proc_add_dev(new_dev)<0)/* create it's proc entry */ 584 printk(KERN_WARNING "VLAN: failed to add proc entry for %s\n", 585 new_dev->name); 586 587 if (real_dev->features & NETIF_F_HW_VLAN_FILTER) 588 real_dev->vlan_rx_add_vid(real_dev, VLAN_ID); 589 590 rtnl_unlock(); 591 592 593#ifdef VLAN_DEBUG 594 printk(VLAN_DBG "Allocated new device successfully, returning.\n"); 595#endif 596 return new_dev; 597 598out_free_arrays: 599 vlan_group_free(grp); 600 601out_free_unregister: 602 unregister_netdev(new_dev); 603 goto out_unlock; 604 605out_free_newdev: 606 free_netdev(new_dev); 607 608out_unlock: 609 rtnl_unlock(); 610 611out_put_dev: 612 dev_put(real_dev); 613 614out_ret_null: 615 return NULL; 616} 617 618static int vlan_device_event(struct notifier_block *unused, unsigned long event, void *ptr) 619{ 620 struct net_device *dev = ptr; 621 struct vlan_group *grp = __vlan_find_group(dev->ifindex); 622 int i, flgs; 623 struct net_device *vlandev; 624 625 if (!grp) 626 goto out; 627 628 /* It is OK that we do not hold the group lock right now, 629 * as we run under the RTNL lock. 630 */ 631 632 switch (event) { 633 case NETDEV_CHANGE: 634 /* Propagate real device state to vlan devices */ 635 for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { 636 vlandev = vlan_group_get_device(grp, i); 637 if (!vlandev) 638 continue; 639 640 vlan_transfer_operstate(dev, vlandev); 641 } 642 break; 643 644 case NETDEV_DOWN: 645 /* Put all VLANs for this dev in the down state too. */ 646 for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { 647 vlandev = vlan_group_get_device(grp, i); 648 if (!vlandev) 649 continue; 650 651 flgs = vlandev->flags; 652 if (!(flgs & IFF_UP)) 653 continue; 654 655 dev_change_flags(vlandev, flgs & ~IFF_UP); 656 } 657 break; 658 659 case NETDEV_UP: 660 /* Put all VLANs for this dev in the up state too. */ 661 for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { 662 vlandev = vlan_group_get_device(grp, i); 663 if (!vlandev) 664 continue; 665 666 flgs = vlandev->flags; 667 if (flgs & IFF_UP) 668 continue; 669 670 dev_change_flags(vlandev, flgs | IFF_UP); 671 } 672 break; 673 674 case NETDEV_UNREGISTER: 675 /* Delete all VLANs for this dev. */ 676 for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { 677 int ret; 678 679 vlandev = vlan_group_get_device(grp, i); 680 if (!vlandev) 681 continue; 682 683 ret = unregister_vlan_dev(dev, 684 VLAN_DEV_INFO(vlandev)->vlan_id); 685 686 unregister_netdevice(vlandev); 687 688 /* Group was destroyed? */ 689 if (ret == 1) 690 break; 691 } 692 break; 693 } 694 695out: 696 return NOTIFY_DONE; 697} 698 699/* 700 * VLAN IOCTL handler. 701 * o execute requested action or pass command to the device driver 702 * arg is really a struct vlan_ioctl_args __user *. 703 */ 704static int vlan_ioctl_handler(void __user *arg) 705{ 706 int err = 0; 707 unsigned short vid = 0; 708 struct vlan_ioctl_args args; 709 710 if (copy_from_user(&args, arg, sizeof(struct vlan_ioctl_args))) 711 return -EFAULT; 712 713 /* Null terminate this sucker, just in case. */ 714 args.device1[23] = 0; 715 args.u.device2[23] = 0; 716 717#ifdef VLAN_DEBUG 718 printk(VLAN_DBG "%s: args.cmd: %x\n", __FUNCTION__, args.cmd); 719#endif 720 721 switch (args.cmd) { 722 case SET_VLAN_INGRESS_PRIORITY_CMD: 723 if (!capable(CAP_NET_ADMIN)) 724 return -EPERM; 725 err = vlan_dev_set_ingress_priority(args.device1, 726 args.u.skb_priority, 727 args.vlan_qos); 728 break; 729 730 case SET_VLAN_EGRESS_PRIORITY_CMD: 731 if (!capable(CAP_NET_ADMIN)) 732 return -EPERM; 733 err = vlan_dev_set_egress_priority(args.device1, 734 args.u.skb_priority, 735 args.vlan_qos); 736 break; 737 738 case SET_VLAN_FLAG_CMD: 739 if (!capable(CAP_NET_ADMIN)) 740 return -EPERM; 741 err = vlan_dev_set_vlan_flag(args.device1, 742 args.u.flag, 743 args.vlan_qos); 744 break; 745 746 case SET_VLAN_NAME_TYPE_CMD: 747 if (!capable(CAP_NET_ADMIN)) 748 return -EPERM; 749 if (args.u.name_type < VLAN_NAME_TYPE_HIGHEST) { 750 vlan_name_type = args.u.name_type; 751 err = 0; 752 } else { 753 err = -EINVAL; 754 } 755 break; 756 757 case ADD_VLAN_CMD: 758 if (!capable(CAP_NET_ADMIN)) 759 return -EPERM; 760 /* we have been given the name of the Ethernet Device we want to 761 * talk to: args.dev1 We also have the 762 * VLAN ID: args.u.VID 763 */ 764 if (register_vlan_device(args.device1, args.u.VID)) { 765 err = 0; 766 } else { 767 err = -EINVAL; 768 } 769 break; 770 771 case DEL_VLAN_CMD: 772 if (!capable(CAP_NET_ADMIN)) 773 return -EPERM; 774 /* Here, the args.dev1 is the actual VLAN we want 775 * to get rid of. 776 */ 777 err = unregister_vlan_device(args.device1); 778 break; 779 780 case GET_VLAN_INGRESS_PRIORITY_CMD: 781 /* TODO: Implement 782 err = vlan_dev_get_ingress_priority(args); 783 if (copy_to_user((void*)arg, &args, 784 sizeof(struct vlan_ioctl_args))) { 785 err = -EFAULT; 786 } 787 */ 788 err = -EINVAL; 789 break; 790 case GET_VLAN_EGRESS_PRIORITY_CMD: 791 /* TODO: Implement 792 err = vlan_dev_get_egress_priority(args.device1, &(args.args); 793 if (copy_to_user((void*)arg, &args, 794 sizeof(struct vlan_ioctl_args))) { 795 err = -EFAULT; 796 } 797 */ 798 err = -EINVAL; 799 break; 800 case GET_VLAN_REALDEV_NAME_CMD: 801 err = vlan_dev_get_realdev_name(args.device1, args.u.device2); 802 if (err) 803 goto out; 804 if (copy_to_user(arg, &args, 805 sizeof(struct vlan_ioctl_args))) { 806 err = -EFAULT; 807 } 808 break; 809 810 case GET_VLAN_VID_CMD: 811 err = vlan_dev_get_vid(args.device1, &vid); 812 if (err) 813 goto out; 814 args.u.VID = vid; 815 if (copy_to_user(arg, &args, 816 sizeof(struct vlan_ioctl_args))) { 817 err = -EFAULT; 818 } 819 break; 820 821 default: 822 /* pass on to underlying device instead?? */ 823 printk(VLAN_DBG "%s: Unknown VLAN CMD: %x \n", 824 __FUNCTION__, args.cmd); 825 return -EINVAL; 826 } 827out: 828 return err; 829} 830 831MODULE_LICENSE("GPL"); 832MODULE_VERSION(DRV_VERSION); 833