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