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