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