1/*
2 * Copyright (c) 2003-2013 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28/*
29 * Copyright 1998 Massachusetts Institute of Technology
30 *
31 * Permission to use, copy, modify, and distribute this software and
32 * its documentation for any purpose and without fee is hereby
33 * granted, provided that both the above copyright notice and this
34 * permission notice appear in all copies, that both the above
35 * copyright notice and this permission notice appear in all
36 * supporting documentation, and that the name of M.I.T. not be used
37 * in advertising or publicity pertaining to distribution of the
38 * software without specific, written prior permission.  M.I.T. makes
39 * no representations about the suitability of this software for any
40 * purpose.  It is provided "as is" without express or implied
41 * warranty.
42 *
43 * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''.  M.I.T. DISCLAIMS
44 * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
45 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
46 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
47 * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
48 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
49 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
50 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
51 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
52 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
53 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
54 * SUCH DAMAGE.
55 *
56 * $FreeBSD: src/sys/net/if_vlan.c,v 1.54 2003/10/31 18:32:08 brooks Exp $
57 */
58
59/*
60 * if_vlan.c - pseudo-device driver for IEEE 802.1Q virtual LANs.
61 * Might be extended some day to also handle IEEE 802.1p priority
62 * tagging.  This is sort of sneaky in the implementation, since
63 * we need to pretend to be enough of an Ethernet implementation
64 * to make arp work.  The way we do this is by telling everyone
65 * that we are an Ethernet, and then catch the packets that
66 * ether_output() left on our output queue when it calls
67 * if_start(), rewrite them for use by the real outgoing interface,
68 * and ask it to send them.
69 */
70
71
72#include <sys/param.h>
73#include <sys/kernel.h>
74#include <sys/malloc.h>
75#include <sys/mbuf.h>
76#include <sys/queue.h>
77#include <sys/socket.h>
78#include <sys/sockio.h>
79#include <sys/sysctl.h>
80#include <sys/systm.h>
81#include <sys/kern_event.h>
82#include <sys/mcache.h>
83
84#include <net/bpf.h>
85#include <net/ethernet.h>
86#include <net/if.h>
87#include <net/if_arp.h>
88#include <net/if_dl.h>
89#include <net/if_ether.h>
90#include <net/if_types.h>
91#include <net/if_vlan_var.h>
92#include <libkern/OSAtomic.h>
93
94#include <net/dlil.h>
95
96#include <net/kpi_interface.h>
97#include <net/kpi_protocol.h>
98
99#include <kern/locks.h>
100
101#ifdef INET
102#include <netinet/in.h>
103#include <netinet/if_ether.h>
104#endif
105
106#include <net/if_media.h>
107#include <net/multicast_list.h>
108#include <net/ether_if_module.h>
109
110#define VLANNAME	"vlan"
111
112typedef int (bpf_callback_func)(struct ifnet *, struct mbuf *);
113typedef int (if_set_bpf_tap_func)(struct ifnet *ifp, int mode, bpf_callback_func * func);
114
115/**
116 ** vlan locks
117 **/
118static __inline__ lck_grp_t *
119my_lck_grp_alloc_init(const char * grp_name)
120{
121    lck_grp_t *		grp;
122    lck_grp_attr_t *	grp_attrs;
123
124    grp_attrs = lck_grp_attr_alloc_init();
125    grp = lck_grp_alloc_init(grp_name, grp_attrs);
126    lck_grp_attr_free(grp_attrs);
127    return (grp);
128}
129
130static __inline__ lck_mtx_t *
131my_lck_mtx_alloc_init(lck_grp_t * lck_grp)
132{
133    lck_attr_t * 	lck_attrs;
134    lck_mtx_t *		lck_mtx;
135
136    lck_attrs = lck_attr_alloc_init();
137    lck_mtx = lck_mtx_alloc_init(lck_grp, lck_attrs);
138    lck_attr_free(lck_attrs);
139    return (lck_mtx);
140}
141
142static lck_mtx_t * 	vlan_lck_mtx;
143
144static __inline__ void
145vlan_lock_init(void)
146{
147    lck_grp_t *		vlan_lck_grp;
148
149    vlan_lck_grp = my_lck_grp_alloc_init("if_vlan");
150    vlan_lck_mtx = my_lck_mtx_alloc_init(vlan_lck_grp);
151}
152
153static __inline__ void
154vlan_assert_lock_held(void)
155{
156    lck_mtx_assert(vlan_lck_mtx, LCK_MTX_ASSERT_OWNED);
157    return;
158}
159
160static __inline__ void
161vlan_assert_lock_not_held(void)
162{
163    lck_mtx_assert(vlan_lck_mtx, LCK_MTX_ASSERT_NOTOWNED);
164    return;
165}
166
167static __inline__ void
168vlan_lock(void)
169{
170    lck_mtx_lock(vlan_lck_mtx);
171    return;
172}
173
174static __inline__ void
175vlan_unlock(void)
176{
177    lck_mtx_unlock(vlan_lck_mtx);
178    return;
179}
180
181/**
182 ** vlan structures, types
183 **/
184struct vlan_parent;
185LIST_HEAD(vlan_parent_list, vlan_parent);
186struct ifvlan;
187LIST_HEAD(ifvlan_list, ifvlan);
188
189typedef LIST_ENTRY(vlan_parent)
190vlan_parent_entry;
191typedef LIST_ENTRY(ifvlan)
192ifvlan_entry;
193
194#define VLP_SIGNATURE		0xfaceface
195typedef struct vlan_parent {
196    vlan_parent_entry		vlp_parent_list;/* list of parents */
197    struct ifnet *		vlp_ifp;	/* interface */
198    struct ifvlan_list		vlp_vlan_list;	/* list of VLAN's */
199#define VLPF_SUPPORTS_VLAN_MTU	0x1
200#define VLPF_CHANGE_IN_PROGRESS	0x2
201#define VLPF_DETACHING		0x4
202    u_int32_t			vlp_flags;
203    struct ifdevmtu		vlp_devmtu;
204    SInt32			vlp_retain_count;
205    UInt32			vlp_signature;	/* VLP_SIGNATURE */
206} vlan_parent, * vlan_parent_ref;
207
208#define IFV_SIGNATURE		0xbeefbeef
209struct ifvlan {
210    ifvlan_entry 		ifv_vlan_list;
211    char			ifv_name[IFNAMSIZ]; /* our unique id */
212    struct ifnet *		ifv_ifp;	/* our interface */
213    vlan_parent_ref		ifv_vlp;	/* parent information */
214    struct	ifv_linkmib {
215	u_int16_t ifvm_encaplen;/* encapsulation length */
216	u_int16_t ifvm_mtufudge;/* MTU fudged by this much */
217	u_int16_t ifvm_proto;	/* encapsulation ethertype */
218	u_int16_t ifvm_tag; 	/* tag to apply on packets leaving if */
219    }	ifv_mib;
220    struct multicast_list 	ifv_multicast;
221#define	IFVF_PROMISC		0x1		/* promiscuous mode enabled */
222#define IFVF_DETACHING		0x2		/* interface is detaching */
223#define IFVF_READY		0x4		/* interface is ready */
224    u_int32_t			ifv_flags;
225    bpf_packet_func		ifv_bpf_input;
226    bpf_packet_func		ifv_bpf_output;
227    SInt32			ifv_retain_count;
228    UInt32			ifv_signature;	/* IFV_SIGNATURE */
229};
230
231typedef struct ifvlan * ifvlan_ref;
232
233typedef struct vlan_globals_s {
234    struct vlan_parent_list	parent_list;
235    int				verbose;
236} * vlan_globals_ref;
237
238static vlan_globals_ref	g_vlan;
239
240#define	ifv_tag		ifv_mib.ifvm_tag
241#define	ifv_encaplen	ifv_mib.ifvm_encaplen
242#define	ifv_mtufudge	ifv_mib.ifvm_mtufudge
243
244static void
245vlan_parent_retain(vlan_parent_ref vlp);
246
247static void
248vlan_parent_release(vlan_parent_ref vlp);
249
250/**
251 ** vlan_parent_ref vlp_flags in-lines
252 **/
253static __inline__ int
254vlan_parent_flags_supports_vlan_mtu(vlan_parent_ref vlp)
255{
256    return ((vlp->vlp_flags & VLPF_SUPPORTS_VLAN_MTU) != 0);
257}
258
259static __inline__ void
260vlan_parent_flags_set_supports_vlan_mtu(vlan_parent_ref vlp)
261{
262    vlp->vlp_flags |= VLPF_SUPPORTS_VLAN_MTU;
263    return;
264}
265
266static __inline__ void
267vlan_parent_flags_clear_supports_vlan_mtu(vlan_parent_ref vlp)
268{
269    vlp->vlp_flags &= ~VLPF_SUPPORTS_VLAN_MTU;
270    return;
271}
272
273static __inline__ int
274vlan_parent_flags_change_in_progress(vlan_parent_ref vlp)
275{
276    return ((vlp->vlp_flags & VLPF_CHANGE_IN_PROGRESS) != 0);
277}
278
279static __inline__ void
280vlan_parent_flags_set_change_in_progress(vlan_parent_ref vlp)
281{
282    vlp->vlp_flags |= VLPF_CHANGE_IN_PROGRESS;
283    return;
284}
285
286static __inline__ void
287vlan_parent_flags_clear_change_in_progress(vlan_parent_ref vlp)
288{
289    vlp->vlp_flags &= ~VLPF_CHANGE_IN_PROGRESS;
290    return;
291}
292
293static __inline__ int
294vlan_parent_flags_detaching(struct vlan_parent * vlp)
295{
296    return ((vlp->vlp_flags & VLPF_DETACHING) != 0);
297}
298
299static __inline__ void
300vlan_parent_flags_set_detaching(struct vlan_parent * vlp)
301{
302    vlp->vlp_flags |= VLPF_DETACHING;
303    return;
304}
305
306
307/**
308 ** ifvlan_flags in-lines routines
309 **/
310static __inline__ int
311ifvlan_flags_promisc(ifvlan_ref ifv)
312{
313    return ((ifv->ifv_flags & IFVF_PROMISC) != 0);
314}
315
316static __inline__ void
317ifvlan_flags_set_promisc(ifvlan_ref ifv)
318{
319    ifv->ifv_flags |= IFVF_PROMISC;
320    return;
321}
322
323static __inline__ void
324ifvlan_flags_clear_promisc(ifvlan_ref ifv)
325{
326    ifv->ifv_flags &= ~IFVF_PROMISC;
327    return;
328}
329
330static __inline__ int
331ifvlan_flags_ready(ifvlan_ref ifv)
332{
333    return ((ifv->ifv_flags & IFVF_READY) != 0);
334}
335
336static __inline__ void
337ifvlan_flags_set_ready(ifvlan_ref ifv)
338{
339    ifv->ifv_flags |= IFVF_READY;
340    return;
341}
342
343static __inline__ void
344ifvlan_flags_clear_ready(ifvlan_ref ifv)
345{
346    ifv->ifv_flags &= ~IFVF_READY;
347    return;
348}
349
350static __inline__ int
351ifvlan_flags_detaching(ifvlan_ref ifv)
352{
353    return ((ifv->ifv_flags & IFVF_DETACHING) != 0);
354}
355
356static __inline__ void
357ifvlan_flags_set_detaching(ifvlan_ref ifv)
358{
359    ifv->ifv_flags |= IFVF_DETACHING;
360    return;
361}
362
363#if 0
364SYSCTL_DECL(_net_link);
365SYSCTL_NODE(_net_link, IFT_L2VLAN, vlan, CTLFLAG_RW|CTLFLAG_LOCKED, 0, "IEEE 802.1Q VLAN");
366SYSCTL_NODE(_net_link_vlan, PF_LINK, link, CTLFLAG_RW|CTLFLAG_LOCKED, 0, "for consistency");
367#endif
368
369#define M_VLAN 		M_DEVBUF
370
371static	int vlan_clone_create(struct if_clone *, u_int32_t, void *);
372static	int vlan_clone_destroy(struct ifnet *);
373static	int vlan_input(ifnet_t ifp, protocol_family_t protocol,
374					   mbuf_t m, char *frame_header);
375static	int vlan_output(struct ifnet *ifp, struct mbuf *m);
376static	int vlan_ioctl(ifnet_t ifp, u_long cmd, void * addr);
377static  int vlan_set_bpf_tap(ifnet_t ifp, bpf_tap_mode mode,
378			     bpf_packet_func func);
379static 	int vlan_attach_protocol(struct ifnet *ifp);
380static	int vlan_detach_protocol(struct ifnet *ifp);
381static	int vlan_setmulti(struct ifnet *ifp);
382static	int vlan_unconfig(ifvlan_ref ifv, int need_to_wait);
383static 	int vlan_config(struct ifnet * ifp, struct ifnet * p, int tag);
384static	void vlan_if_free(struct ifnet * ifp);
385static 	int vlan_remove(ifvlan_ref ifv, int need_to_wait);
386
387static struct if_clone vlan_cloner = IF_CLONE_INITIALIZER(VLANNAME,
388							  vlan_clone_create,
389							  vlan_clone_destroy,
390							  0,
391							  IF_MAXUNIT);
392static	void interface_link_event(struct ifnet * ifp, u_int32_t event_code);
393static	void vlan_parent_link_event(struct ifnet * p,
394				    u_int32_t event_code);
395
396static 	int ifvlan_new_mtu(ifvlan_ref ifv, int mtu);
397
398/**
399 ** ifvlan_ref routines
400 **/
401static void
402ifvlan_retain(ifvlan_ref ifv)
403{
404    if (ifv->ifv_signature != IFV_SIGNATURE) {
405	panic("ifvlan_retain: bad signature\n");
406    }
407    if (ifv->ifv_retain_count == 0) {
408	panic("ifvlan_retain: retain count is 0\n");
409    }
410    OSIncrementAtomic(&ifv->ifv_retain_count);
411}
412
413static void
414ifvlan_release(ifvlan_ref ifv)
415{
416    UInt32		old_retain_count;
417
418    if (ifv->ifv_signature != IFV_SIGNATURE) {
419	panic("ifvlan_release: bad signature\n");
420    }
421    old_retain_count = OSDecrementAtomic(&ifv->ifv_retain_count);
422    switch (old_retain_count) {
423    case 0:
424	panic("ifvlan_release: retain count is 0\n");
425	break;
426    case 1:
427	if (g_vlan->verbose) {
428	    printf("ifvlan_release(%s)\n", ifv->ifv_name);
429	}
430	ifv->ifv_signature = 0;
431	FREE(ifv, M_VLAN);
432	break;
433    default:
434	break;
435    }
436    return;
437}
438
439static vlan_parent_ref
440ifvlan_get_vlan_parent_retained(ifvlan_ref ifv)
441{
442    vlan_parent_ref	vlp = ifv->ifv_vlp;
443
444    if (vlp == NULL || vlan_parent_flags_detaching(vlp)) {
445	return (NULL);
446    }
447    vlan_parent_retain(vlp);
448    return (vlp);
449}
450
451/**
452 ** ifnet_* routines
453 **/
454
455static ifvlan_ref
456ifnet_get_ifvlan(struct ifnet * ifp)
457{
458    ifvlan_ref		ifv;
459
460    ifv = (ifvlan_ref)ifnet_softc(ifp);
461    return (ifv);
462}
463
464static ifvlan_ref
465ifnet_get_ifvlan_retained(struct ifnet * ifp)
466{
467    ifvlan_ref		ifv;
468
469    ifv = ifnet_get_ifvlan(ifp);
470    if (ifv == NULL) {
471	return (NULL);
472    }
473    if (ifvlan_flags_detaching(ifv)) {
474	return (NULL);
475    }
476    ifvlan_retain(ifv);
477    return (ifv);
478}
479
480static int
481ifnet_ifvlan_vlan_parent_ok(struct ifnet * ifp, ifvlan_ref ifv,
482			    vlan_parent_ref vlp)
483{
484    ifvlan_ref		check_ifv;
485
486    check_ifv = ifnet_get_ifvlan(ifp);
487    if (check_ifv != ifv || ifvlan_flags_detaching(ifv)) {
488	/* ifvlan_ref no longer valid */
489	return (FALSE);
490    }
491    if (ifv->ifv_vlp != vlp) {
492	/* vlan_parent no longer valid */
493	return (FALSE);
494    }
495    if (vlan_parent_flags_detaching(vlp)) {
496	/* parent is detaching */
497	return (FALSE);
498    }
499    return (TRUE);
500}
501
502/**
503 ** vlan, etc. routines
504 **/
505
506static int
507vlan_globals_init(void)
508{
509    vlan_globals_ref	v;
510
511    vlan_assert_lock_not_held();
512
513    if (g_vlan != NULL) {
514	return (0);
515    }
516    v = _MALLOC(sizeof(*v), M_VLAN, M_WAITOK);
517    if (v != NULL) {
518	LIST_INIT(&v->parent_list);
519	v->verbose = 0;
520    }
521    vlan_lock();
522    if (g_vlan != NULL) {
523	vlan_unlock();
524	if (v != NULL) {
525	    _FREE(v, M_VLAN);
526	}
527	return (0);
528    }
529    g_vlan = v;
530    vlan_unlock();
531    if (v == NULL) {
532	return (ENOMEM);
533    }
534    return (0);
535}
536
537static int
538siocgifdevmtu(struct ifnet * ifp, struct ifdevmtu * ifdm_p)
539{
540    struct ifreq	ifr;
541    int 		error;
542
543    bzero(&ifr, sizeof(ifr));
544    error = ifnet_ioctl(ifp, 0,SIOCGIFDEVMTU, &ifr);
545    if (error == 0) {
546	*ifdm_p = ifr.ifr_devmtu;
547    }
548    return (error);
549}
550
551static int
552siocsifaltmtu(struct ifnet * ifp, int mtu)
553{
554    struct ifreq	ifr;
555
556    bzero(&ifr, sizeof(ifr));
557    ifr.ifr_mtu = mtu;
558    return (ifnet_ioctl(ifp, 0, SIOCSIFALTMTU, &ifr));
559}
560
561static __inline__ void
562vlan_bpf_output(struct ifnet * ifp, struct mbuf * m,
563		bpf_packet_func func)
564{
565    if (func != NULL) {
566	(*func)(ifp, m);
567    }
568    return;
569}
570
571static __inline__ void
572vlan_bpf_input(struct ifnet * ifp, struct mbuf * m,
573	       bpf_packet_func func, char * frame_header,
574	       int frame_header_len, int encap_len)
575{
576    if (func != NULL) {
577	if (encap_len > 0) {
578	    /* present the right header to bpf */
579	    bcopy(frame_header, frame_header + encap_len, frame_header_len);
580	}
581	m->m_data -= frame_header_len;
582	m->m_len += frame_header_len;
583	(*func)(ifp, m);
584	m->m_data += frame_header_len;
585	m->m_len -= frame_header_len;
586	if (encap_len > 0) {
587	    /* restore the header */
588	    bcopy(frame_header + encap_len, frame_header, frame_header_len);
589	}
590    }
591    return;
592}
593
594/**
595 ** vlan_parent synchronization routines
596 **/
597static void
598vlan_parent_retain(vlan_parent_ref vlp)
599{
600    if (vlp->vlp_signature != VLP_SIGNATURE) {
601	panic("vlan_parent_retain: signature is bad\n");
602    }
603    if (vlp->vlp_retain_count == 0) {
604	panic("vlan_parent_retain: retain count is 0\n");
605    }
606    OSIncrementAtomic(&vlp->vlp_retain_count);
607}
608
609static void
610vlan_parent_release(vlan_parent_ref vlp)
611{
612    UInt32		old_retain_count;
613
614    if (vlp->vlp_signature != VLP_SIGNATURE) {
615	panic("vlan_parent_release: signature is bad\n");
616    }
617    old_retain_count = OSDecrementAtomic(&vlp->vlp_retain_count);
618    switch (old_retain_count) {
619    case 0:
620	panic("vlan_parent_release: retain count is 0\n");
621	break;
622    case 1:
623	if (g_vlan->verbose) {
624	    struct ifnet * ifp = vlp->vlp_ifp;
625	    printf("vlan_parent_release(%s%d)\n", ifnet_name(ifp),
626		   ifnet_unit(ifp));
627	}
628	vlp->vlp_signature = 0;
629	FREE(vlp, M_VLAN);
630	break;
631    default:
632	break;
633    }
634    return;
635}
636
637/*
638 * Function: vlan_parent_wait
639 * Purpose:
640 *   Allows a single thread to gain exclusive access to the vlan_parent
641 *   data structure.  Some operations take a long time to complete,
642 *   and some have side-effects that we can't predict.  Holding the
643 *   vlan_lock() across such operations is not possible.
644 *
645 * Notes:
646 *   Before calling, you must be holding the vlan_lock and have taken
647 *   a reference on the vlan_parent_ref.
648 */
649static void
650vlan_parent_wait(vlan_parent_ref vlp, const char * msg)
651{
652    int		waited = 0;
653
654    /* other add/remove/multicast-change in progress */
655    while (vlan_parent_flags_change_in_progress(vlp)) {
656	if (g_vlan->verbose) {
657	    struct ifnet * ifp = vlp->vlp_ifp;
658
659	    printf("%s%d: %s msleep\n", ifnet_name(ifp), ifnet_unit(ifp), msg);
660	}
661	waited = 1;
662	(void)msleep(vlp, vlan_lck_mtx, PZERO, msg, 0);
663    }
664    /* prevent other vlan parent remove/add from taking place */
665    vlan_parent_flags_set_change_in_progress(vlp);
666    if (g_vlan->verbose && waited) {
667	struct ifnet * ifp = vlp->vlp_ifp;
668
669	printf("%s%d: %s woke up\n", ifnet_name(ifp), ifnet_unit(ifp), msg);
670    }
671    return;
672}
673
674/*
675 * Function: vlan_parent_signal
676 * Purpose:
677 *   Allows the thread that previously invoked vlan_parent_wait() to
678 *   give up exclusive access to the vlan_parent data structure, and wake up
679 *   any other threads waiting to access
680 * Notes:
681 *   Before calling, you must be holding the vlan_lock and have taken
682 *   a reference on the vlan_parent_ref.
683 */
684static void
685vlan_parent_signal(vlan_parent_ref vlp, const char * msg)
686{
687    vlan_parent_flags_clear_change_in_progress(vlp);
688    wakeup((caddr_t)vlp);
689    if (g_vlan->verbose) {
690	struct ifnet * ifp = vlp->vlp_ifp;
691
692	printf("%s%d: %s wakeup\n", ifnet_name(ifp), ifnet_unit(ifp), msg);
693    }
694    return;
695}
696
697/*
698 * Program our multicast filter. What we're actually doing is
699 * programming the multicast filter of the parent. This has the
700 * side effect of causing the parent interface to receive multicast
701 * traffic that it doesn't really want, which ends up being discarded
702 * later by the upper protocol layers. Unfortunately, there's no way
703 * to avoid this: there really is only one physical interface.
704 */
705static int
706vlan_setmulti(struct ifnet * ifp)
707{
708    int			error = 0;
709    ifvlan_ref 		ifv;
710    struct ifnet *	p;
711    vlan_parent_ref	vlp = NULL;
712
713    vlan_lock();
714    ifv = ifnet_get_ifvlan_retained(ifp);
715    if (ifv == NULL) {
716	goto unlock_done;
717    }
718    vlp = ifvlan_get_vlan_parent_retained(ifv);
719    if (vlp == NULL) {
720	/* no parent, no need to program the multicast filter */
721	goto unlock_done;
722    }
723    vlan_parent_wait(vlp, "vlan_setmulti");
724
725    /* check again, things could have changed */
726    if (ifnet_ifvlan_vlan_parent_ok(ifp, ifv, vlp) == FALSE) {
727	goto signal_done;
728    }
729    p = vlp->vlp_ifp;
730    vlan_unlock();
731
732    /* update parent interface with our multicast addresses */
733    error = multicast_list_program(&ifv->ifv_multicast, ifp, p);
734
735    vlan_lock();
736
737 signal_done:
738    vlan_parent_signal(vlp, "vlan_setmulti");
739
740 unlock_done:
741    vlan_unlock();
742    if (ifv != NULL) {
743	ifvlan_release(ifv);
744    }
745    if (vlp != NULL) {
746	vlan_parent_release(vlp);
747    }
748    return (error);
749}
750
751/**
752 ** vlan_parent list manipulation/lookup routines
753 **/
754static vlan_parent_ref
755parent_list_lookup(struct ifnet * p)
756{
757    vlan_parent_ref	vlp;
758
759    LIST_FOREACH(vlp, &g_vlan->parent_list, vlp_parent_list) {
760	if (vlp->vlp_ifp == p) {
761	    return (vlp);
762	}
763    }
764    return (NULL);
765}
766
767static ifvlan_ref
768vlan_parent_lookup_tag(vlan_parent_ref vlp, int tag)
769{
770    ifvlan_ref		ifv;
771
772    LIST_FOREACH(ifv, &vlp->vlp_vlan_list, ifv_vlan_list) {
773	if (tag == ifv->ifv_tag) {
774	    return (ifv);
775	}
776    }
777    return (NULL);
778}
779
780static ifvlan_ref
781vlan_lookup_parent_and_tag(struct ifnet * p, int tag)
782{
783    vlan_parent_ref	vlp;
784
785    vlp = parent_list_lookup(p);
786    if (vlp != NULL) {
787	return (vlan_parent_lookup_tag(vlp, tag));
788    }
789    return (NULL);
790}
791
792static int
793vlan_parent_find_max_mtu(vlan_parent_ref vlp, ifvlan_ref exclude_ifv)
794{
795    int			max_mtu = 0;
796    ifvlan_ref		ifv;
797
798    LIST_FOREACH(ifv, &vlp->vlp_vlan_list, ifv_vlan_list) {
799	int	req_mtu;
800
801	if (exclude_ifv == ifv) {
802	    continue;
803	}
804	req_mtu = ifnet_mtu(ifv->ifv_ifp) + ifv->ifv_mtufudge;
805	if (req_mtu > max_mtu) {
806	    max_mtu = req_mtu;
807	}
808    }
809    return (max_mtu);
810}
811
812/*
813 * Function: vlan_parent_create
814 * Purpose:
815 *   Create a vlan_parent structure to hold the VLAN's for the given
816 *   interface.  Add it to the list of VLAN parents.
817 */
818static int
819vlan_parent_create(struct ifnet * p, vlan_parent_ref * ret_vlp)
820{
821    int			error;
822    vlan_parent_ref	vlp;
823
824    *ret_vlp = NULL;
825    vlp = _MALLOC(sizeof(*vlp), M_VLAN, M_WAITOK);
826    if (vlp == NULL) {
827	return (ENOMEM);
828    }
829    bzero(vlp, sizeof(*vlp));
830    error = siocgifdevmtu(p, &vlp->vlp_devmtu);
831    if (error != 0) {
832	printf("vlan_parent_create (%s%d): siocgifdevmtu failed, %d\n",
833	       ifnet_name(p), ifnet_unit(p), error);
834	FREE(vlp, M_VLAN);
835	return (error);
836    }
837    LIST_INIT(&vlp->vlp_vlan_list);
838    vlp->vlp_ifp = p;
839    vlp->vlp_retain_count = 1;
840    vlp->vlp_signature = VLP_SIGNATURE;
841    if (ifnet_offload(p)
842	& (IF_HWASSIST_VLAN_MTU | IF_HWASSIST_VLAN_TAGGING)) {
843	vlan_parent_flags_set_supports_vlan_mtu(vlp);
844    }
845    *ret_vlp = vlp;
846    return (0);
847}
848
849static void
850vlan_parent_remove_all_vlans(struct ifnet * p)
851{
852    ifvlan_ref 		ifv;
853    int			need_vlp_release = 0;
854    ifvlan_ref		next;
855    vlan_parent_ref	vlp;
856
857    vlan_lock();
858    vlp = parent_list_lookup(p);
859    if (vlp == NULL || vlan_parent_flags_detaching(vlp)) {
860	/* no VLAN's */
861	vlan_unlock();
862	return;
863    }
864    vlan_parent_flags_set_detaching(vlp);
865    vlan_parent_retain(vlp);
866    vlan_parent_wait(vlp, "vlan_parent_remove_all_vlans");
867    need_vlp_release++;
868    vlp = parent_list_lookup(p);
869    /* check again */
870    if (vlp == NULL) {
871	goto signal_done;
872    }
873
874    for (ifv = LIST_FIRST(&vlp->vlp_vlan_list); ifv != NULL; ifv = next) {
875	struct ifnet *	ifp = ifv->ifv_ifp;
876	int		removed;
877
878	next = LIST_NEXT(ifv, ifv_vlan_list);
879	removed = vlan_remove(ifv, FALSE);
880	if (removed) {
881	    vlan_unlock();
882	    ifnet_detach(ifp);
883	    vlan_lock();
884	}
885    }
886
887    /* the vlan parent has no more VLAN's */
888    ifnet_set_eflags(p, 0, IFEF_VLAN); /* clear IFEF_VLAN */
889
890    LIST_REMOVE(vlp, vlp_parent_list);
891    need_vlp_release++;	/* one for being in the list */
892    need_vlp_release++; /* final reference */
893
894 signal_done:
895    vlan_parent_signal(vlp, "vlan_parent_remove_all_vlans");
896    vlan_unlock();
897
898    while (need_vlp_release--) {
899	vlan_parent_release(vlp);
900    }
901    return;
902}
903
904static __inline__ int
905vlan_parent_no_vlans(vlan_parent_ref vlp)
906{
907    return (LIST_EMPTY(&vlp->vlp_vlan_list));
908}
909
910static void
911vlan_parent_add_vlan(vlan_parent_ref vlp, ifvlan_ref ifv, int tag)
912{
913    LIST_INSERT_HEAD(&vlp->vlp_vlan_list, ifv, ifv_vlan_list);
914    ifv->ifv_vlp = vlp;
915    ifv->ifv_tag = tag;
916    return;
917}
918
919static void
920vlan_parent_remove_vlan(__unused vlan_parent_ref vlp, ifvlan_ref ifv)
921{
922    ifv->ifv_vlp = NULL;
923    LIST_REMOVE(ifv, ifv_vlan_list);
924    return;
925}
926
927static int
928vlan_clone_attach(void)
929{
930    int error;
931
932    error = if_clone_attach(&vlan_cloner);
933    if (error != 0)
934        return error;
935    vlan_lock_init();
936    return 0;
937}
938
939static int
940vlan_clone_create(struct if_clone *ifc, u_int32_t unit, __unused void *params)
941{
942	int							error;
943	ifvlan_ref					ifv;
944	ifnet_t						ifp;
945	struct ifnet_init_eparams	vlan_init;
946
947	error = vlan_globals_init();
948	if (error != 0) {
949		return (error);
950	}
951	ifv = _MALLOC(sizeof(struct ifvlan), M_VLAN, M_WAITOK);
952	if (ifv == NULL)
953		return ENOBUFS;
954	bzero(ifv, sizeof(struct ifvlan));
955	ifv->ifv_retain_count = 1;
956	ifv->ifv_signature = IFV_SIGNATURE;
957	multicast_list_init(&ifv->ifv_multicast);
958
959	/* use the interface name as the unique id for ifp recycle */
960	if ((unsigned int)
961	    snprintf(ifv->ifv_name, sizeof(ifv->ifv_name), "%s%d",
962		     ifc->ifc_name, unit) >= sizeof(ifv->ifv_name)) {
963	    ifvlan_release(ifv);
964	    return (EINVAL);
965	}
966
967	bzero(&vlan_init, sizeof(vlan_init));
968	vlan_init.ver = IFNET_INIT_CURRENT_VERSION;
969	vlan_init.len = sizeof (vlan_init);
970	vlan_init.flags = IFNET_INIT_LEGACY;
971	vlan_init.uniqueid = ifv->ifv_name;
972	vlan_init.uniqueid_len = strlen(ifv->ifv_name);
973	vlan_init.name = ifc->ifc_name;
974	vlan_init.unit = unit;
975	vlan_init.family = IFNET_FAMILY_VLAN;
976	vlan_init.type = IFT_L2VLAN;
977	vlan_init.output = vlan_output;
978	vlan_init.demux = ether_demux;
979	vlan_init.add_proto = ether_add_proto;
980	vlan_init.del_proto = ether_del_proto;
981	vlan_init.check_multi = ether_check_multi;
982	vlan_init.framer_extended = ether_frameout_extended;
983	vlan_init.softc = ifv;
984	vlan_init.ioctl = vlan_ioctl;
985	vlan_init.set_bpf_tap = vlan_set_bpf_tap;
986	vlan_init.detach = vlan_if_free;
987	vlan_init.broadcast_addr = etherbroadcastaddr;
988	vlan_init.broadcast_len = ETHER_ADDR_LEN;
989	error = ifnet_allocate_extended(&vlan_init, &ifp);
990
991	if (error) {
992	    ifvlan_release(ifv);
993	    return (error);
994	}
995
996	ifnet_set_offload(ifp, 0);
997	ifnet_set_addrlen(ifp, ETHER_ADDR_LEN); /* XXX ethernet specific */
998	ifnet_set_baudrate(ifp, 0);
999	ifnet_set_hdrlen(ifp, ETHER_VLAN_ENCAP_LEN);
1000
1001	error = ifnet_attach(ifp, NULL);
1002	if (error) {
1003	    ifnet_release(ifp);
1004	    ifvlan_release(ifv);
1005	    return (error);
1006	}
1007	ifv->ifv_ifp = ifp;
1008
1009	/* attach as ethernet */
1010	bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header));
1011	return (0);
1012}
1013
1014static int
1015vlan_remove(ifvlan_ref ifv, int need_to_wait)
1016{
1017    vlan_assert_lock_held();
1018    if (ifvlan_flags_detaching(ifv)) {
1019	return (0);
1020    }
1021    ifvlan_flags_set_detaching(ifv);
1022    vlan_unconfig(ifv, need_to_wait);
1023    return (1);
1024}
1025
1026
1027static int
1028vlan_clone_destroy(struct ifnet *ifp)
1029{
1030    ifvlan_ref ifv;
1031
1032    vlan_lock();
1033    ifv = ifnet_get_ifvlan_retained(ifp);
1034    if (ifv == NULL) {
1035	vlan_unlock();
1036	return 0;
1037    }
1038    if (vlan_remove(ifv, TRUE) == 0) {
1039	vlan_unlock();
1040	ifvlan_release(ifv);
1041	return 0;
1042    }
1043    vlan_unlock();
1044    ifvlan_release(ifv);
1045    ifnet_detach(ifp);
1046
1047    return 0;
1048}
1049
1050static int
1051vlan_set_bpf_tap(ifnet_t ifp, bpf_tap_mode mode, bpf_packet_func func)
1052{
1053    ifvlan_ref	ifv;
1054
1055    vlan_lock();
1056    ifv = ifnet_get_ifvlan_retained(ifp);
1057    if (ifv == NULL) {
1058	vlan_unlock();
1059	return (ENODEV);
1060    }
1061    switch (mode) {
1062        case BPF_TAP_DISABLE:
1063            ifv->ifv_bpf_input = ifv->ifv_bpf_output = NULL;
1064            break;
1065
1066        case BPF_TAP_INPUT:
1067            ifv->ifv_bpf_input = func;
1068            break;
1069
1070        case BPF_TAP_OUTPUT:
1071	    ifv->ifv_bpf_output = func;
1072            break;
1073
1074        case BPF_TAP_INPUT_OUTPUT:
1075            ifv->ifv_bpf_input = ifv->ifv_bpf_output = func;
1076            break;
1077        default:
1078            break;
1079    }
1080    vlan_unlock();
1081    ifvlan_release(ifv);
1082    return 0;
1083}
1084
1085static int
1086vlan_output(struct ifnet * ifp, struct mbuf * m)
1087{
1088    bpf_packet_func 		bpf_func;
1089    struct ether_vlan_header *	evl;
1090    int				encaplen;
1091    ifvlan_ref			ifv;
1092    struct ifnet *		p;
1093    int 			soft_vlan;
1094    u_short			tag;
1095    vlan_parent_ref		vlp = NULL;
1096    int				err;
1097    struct flowadv		adv = { FADV_SUCCESS };
1098
1099    if (m == 0) {
1100	return (0);
1101    }
1102    if ((m->m_flags & M_PKTHDR) == 0) {
1103	m_freem_list(m);
1104	return (0);
1105    }
1106    vlan_lock();
1107    ifv = ifnet_get_ifvlan_retained(ifp);
1108    if (ifv == NULL || ifvlan_flags_ready(ifv) == 0) {
1109	goto unlock_done;
1110    }
1111    vlp = ifvlan_get_vlan_parent_retained(ifv);
1112    if (vlp == NULL) {
1113	goto unlock_done;
1114    }
1115    p = vlp->vlp_ifp;
1116    (void)ifnet_stat_increment_out(ifp, 1, m->m_pkthdr.len, 0);
1117    soft_vlan = (ifnet_offload(p) & IF_HWASSIST_VLAN_TAGGING) == 0;
1118    bpf_func = ifv->ifv_bpf_output;
1119    tag = ifv->ifv_tag;
1120    encaplen = ifv->ifv_encaplen;
1121    vlan_unlock();
1122
1123    ifvlan_release(ifv);
1124    vlan_parent_release(vlp);
1125
1126    vlan_bpf_output(ifp, m, bpf_func);
1127
1128    /* do not run parent's if_output() if the parent is not up */
1129    if ((ifnet_flags(p) & (IFF_UP | IFF_RUNNING)) != (IFF_UP | IFF_RUNNING)) {
1130	m_freem(m);
1131	atomic_add_64(&ifp->if_collisions, 1);
1132	return (0);
1133    }
1134    /*
1135     * If underlying interface can do VLAN tag insertion itself,
1136     * just pass the packet along. However, we need some way to
1137     * tell the interface where the packet came from so that it
1138     * knows how to find the VLAN tag to use.  We use a field in
1139     * the mbuf header to store the VLAN tag, and a bit in the
1140     * csum_flags field to mark the field as valid.
1141     */
1142    if (soft_vlan == 0) {
1143	m->m_pkthdr.csum_flags |= CSUM_VLAN_TAG_VALID;
1144	m->m_pkthdr.vlan_tag = tag;
1145    } else {
1146	M_PREPEND(m, encaplen, M_DONTWAIT);
1147	if (m == NULL) {
1148	    printf("%s%d: unable to prepend VLAN header\n", ifnet_name(ifp),
1149		   ifnet_unit(ifp));
1150	    atomic_add_64(&ifp->if_oerrors, 1);
1151	    return (0);
1152	}
1153	/* M_PREPEND takes care of m_len, m_pkthdr.len for us */
1154	if (m->m_len < (int)sizeof(*evl)) {
1155	    m = m_pullup(m, sizeof(*evl));
1156	    if (m == NULL) {
1157		printf("%s%d: unable to pullup VLAN header\n", ifnet_name(ifp),
1158		       ifnet_unit(ifp));
1159		atomic_add_64(&ifp->if_oerrors, 1);
1160		return (0);
1161	    }
1162	}
1163
1164	/*
1165	 * Transform the Ethernet header into an Ethernet header
1166	 * with 802.1Q encapsulation.
1167	 */
1168	bcopy(mtod(m, char *) + encaplen,
1169	      mtod(m, char *), ETHER_HDR_LEN);
1170	evl = mtod(m, struct ether_vlan_header *);
1171	evl->evl_proto = evl->evl_encap_proto;
1172	evl->evl_encap_proto = htons(ETHERTYPE_VLAN);
1173	evl->evl_tag = htons(tag);
1174    }
1175
1176    err = dlil_output(p, PF_VLAN, m, NULL, NULL, 1, &adv);
1177
1178    if (err == 0) {
1179	if (adv.code == FADV_FLOW_CONTROLLED) {
1180	    err = EQFULL;
1181	} else if (adv.code == FADV_SUSPENDED) {
1182	    err = EQSUSPENDED;
1183	}
1184    }
1185
1186    return (err);
1187
1188 unlock_done:
1189    vlan_unlock();
1190    if (ifv != NULL) {
1191	ifvlan_release(ifv);
1192    }
1193    if (vlp != NULL) {
1194	vlan_parent_release(vlp);
1195    }
1196    m_freem_list(m);
1197    return (0);
1198
1199}
1200
1201static int
1202vlan_input(ifnet_t p, __unused protocol_family_t protocol,
1203					   mbuf_t m, char *frame_header)
1204{
1205    bpf_packet_func 		bpf_func = NULL;
1206    struct ether_vlan_header *	evl;
1207    struct ifnet *		ifp = NULL;
1208    int 			soft_vlan = 0;
1209    u_int 			tag = 0;
1210
1211    if (m->m_pkthdr.csum_flags & CSUM_VLAN_TAG_VALID) {
1212	/*
1213	 * Packet is tagged, m contains a normal
1214	 * Ethernet frame; the tag is stored out-of-band.
1215	 */
1216	m->m_pkthdr.csum_flags &= ~CSUM_VLAN_TAG_VALID;
1217	tag = EVL_VLANOFTAG(m->m_pkthdr.vlan_tag);
1218	m->m_pkthdr.vlan_tag = 0;
1219    } else {
1220	soft_vlan = 1;
1221	switch (ifnet_type(p)) {
1222	case IFT_ETHER:
1223	    if (m->m_len < ETHER_VLAN_ENCAP_LEN) {
1224		m_freem(m);
1225		return 0;
1226	    }
1227	    evl = (struct ether_vlan_header *)(void *)frame_header;
1228	    if (ntohs(evl->evl_proto) == ETHERTYPE_VLAN) {
1229		/* don't allow VLAN within VLAN */
1230		m_freem(m);
1231		return (0);
1232	    }
1233	    tag = EVL_VLANOFTAG(ntohs(evl->evl_tag));
1234
1235	    /*
1236	     * Restore the original ethertype.  We'll remove
1237	     * the encapsulation after we've found the vlan
1238	     * interface corresponding to the tag.
1239	     */
1240	    evl->evl_encap_proto = evl->evl_proto;
1241	    break;
1242	default:
1243	    printf("vlan_demux: unsupported if type %u",
1244		   ifnet_type(p));
1245	    m_freem(m);
1246	    return 0;
1247	    break;
1248	}
1249    }
1250    if (tag != 0) {
1251	ifvlan_ref		ifv;
1252
1253	if ((ifnet_eflags(p) & IFEF_VLAN) == 0) {
1254	    /* don't bother looking through the VLAN list */
1255	    m_freem(m);
1256	    return 0;
1257	}
1258	vlan_lock();
1259	ifv = vlan_lookup_parent_and_tag(p, tag);
1260	if (ifv != NULL) {
1261	    ifp = ifv->ifv_ifp;
1262	}
1263	if (ifv == NULL
1264	    || ifvlan_flags_ready(ifv) == 0
1265	    || (ifnet_flags(ifp) & IFF_UP) == 0) {
1266	    vlan_unlock();
1267	    m_freem(m);
1268	    return 0;
1269	}
1270	bpf_func = ifv->ifv_bpf_input;
1271	vlan_unlock();
1272    }
1273    if (soft_vlan) {
1274	/*
1275	 * Packet had an in-line encapsulation header;
1276	 * remove it.  The original header has already
1277	 * been fixed up above.
1278	 */
1279	m->m_len -= ETHER_VLAN_ENCAP_LEN;
1280	m->m_data += ETHER_VLAN_ENCAP_LEN;
1281	m->m_pkthdr.len -= ETHER_VLAN_ENCAP_LEN;
1282	m->m_pkthdr.csum_flags = 0; /* can't trust hardware checksum */
1283    }
1284    if (tag != 0) {
1285	m->m_pkthdr.rcvif = ifp;
1286	m->m_pkthdr.pkt_hdr = frame_header;
1287	(void)ifnet_stat_increment_in(ifp, 1,
1288				      m->m_pkthdr.len + ETHER_HDR_LEN, 0);
1289	vlan_bpf_input(ifp, m, bpf_func, frame_header, ETHER_HDR_LEN,
1290		       soft_vlan ? ETHER_VLAN_ENCAP_LEN : 0);
1291	/* We found a vlan interface, inject on that interface. */
1292	dlil_input_packet_list(ifp, m);
1293    } else {
1294	m->m_pkthdr.pkt_hdr = frame_header;
1295	/* Send priority-tagged packet up through the parent */
1296	dlil_input_packet_list(p, m);
1297    }
1298    return 0;
1299}
1300
1301static int
1302vlan_config(struct ifnet * ifp, struct ifnet * p, int tag)
1303{
1304    int			error;
1305    int			first_vlan = FALSE;
1306    ifvlan_ref 		ifv = NULL;
1307    int			ifv_added = FALSE;
1308    int			need_vlp_release = 0;
1309    vlan_parent_ref	new_vlp = NULL;
1310    ifnet_offload_t	offload;
1311    u_int16_t		parent_flags;
1312    vlan_parent_ref	vlp = NULL;
1313
1314    /* pre-allocate space for vlan_parent, in case we're first */
1315    error = vlan_parent_create(p, &new_vlp);
1316    if (error != 0) {
1317	return (error);
1318    }
1319
1320    vlan_lock();
1321    ifv = ifnet_get_ifvlan_retained(ifp);
1322    if (ifv == NULL || ifv->ifv_vlp != NULL) {
1323	vlan_unlock();
1324	if (ifv != NULL) {
1325	    ifvlan_release(ifv);
1326	}
1327	vlan_parent_release(new_vlp);
1328	return (EBUSY);
1329    }
1330    vlp = parent_list_lookup(p);
1331    if (vlp != NULL) {
1332	vlan_parent_retain(vlp);
1333	need_vlp_release++;
1334	if (vlan_parent_lookup_tag(vlp, tag) != NULL) {
1335	    /* already a VLAN with that tag on this interface */
1336	    error = EADDRINUSE;
1337	    goto unlock_done;
1338	}
1339    }
1340    else {
1341	/* one for being in the list */
1342	vlan_parent_retain(new_vlp);
1343
1344	/* we're the first VLAN on this interface */
1345	LIST_INSERT_HEAD(&g_vlan->parent_list, new_vlp, vlp_parent_list);
1346	vlp = new_vlp;
1347
1348	vlan_parent_retain(vlp);
1349	need_vlp_release++;
1350    }
1351
1352    /* need to wait to ensure no one else is trying to add/remove */
1353    vlan_parent_wait(vlp, "vlan_config");
1354
1355    if (ifnet_get_ifvlan(ifp) != ifv) {
1356	error = EINVAL;
1357	goto signal_done;
1358    }
1359
1360    /* check again because someone might have gotten in */
1361    if (parent_list_lookup(p) != vlp) {
1362	error = EBUSY;
1363	goto signal_done;
1364    }
1365
1366    if (vlan_parent_flags_detaching(vlp)
1367	|| ifvlan_flags_detaching(ifv) || ifv->ifv_vlp != NULL) {
1368	error = EBUSY;
1369	goto signal_done;
1370    }
1371
1372    /* check again because someone might have gotten the tag */
1373    if (vlan_parent_lookup_tag(vlp, tag) != NULL) {
1374	/* already a VLAN with that tag on this interface */
1375	error = EADDRINUSE;
1376	goto signal_done;
1377    }
1378
1379    if (vlan_parent_no_vlans(vlp)) {
1380	first_vlan = TRUE;
1381    }
1382    vlan_parent_add_vlan(vlp, ifv, tag);
1383    ifvlan_retain(ifv);	/* parent references ifv */
1384    ifv_added = TRUE;
1385
1386    /* check whether bond interface is using parent interface */
1387    ifnet_lock_exclusive(p);
1388    if ((ifnet_eflags(p) & IFEF_BOND) != 0) {
1389	ifnet_lock_done(p);
1390	/* don't allow VLAN over interface that's already part of a bond */
1391	error = EBUSY;
1392	goto signal_done;
1393    }
1394    /* prevent BOND interface from using it */
1395    /* Can't use ifnet_set_eflags because that would take the lock */
1396    p->if_eflags |= IFEF_VLAN;
1397    ifnet_lock_done(p);
1398    vlan_unlock();
1399
1400    if (first_vlan) {
1401	/* attach our VLAN "protocol" to the interface */
1402	error = vlan_attach_protocol(p);
1403	if (error) {
1404	    vlan_lock();
1405	    goto signal_done;
1406	}
1407    }
1408
1409    /* configure parent to receive our multicast addresses */
1410    error = multicast_list_program(&ifv->ifv_multicast, ifp, p);
1411    if (error != 0) {
1412	if (first_vlan) {
1413	    (void)vlan_detach_protocol(p);
1414	}
1415	vlan_lock();
1416	goto signal_done;
1417    }
1418
1419    /* set our ethernet address to that of the parent */
1420    ifnet_set_lladdr_and_type(ifp, IF_LLADDR(p), ETHER_ADDR_LEN, IFT_ETHER);
1421
1422    /* no failures past this point */
1423    vlan_lock();
1424
1425    ifv->ifv_encaplen = ETHER_VLAN_ENCAP_LEN;
1426    ifv->ifv_flags = 0;
1427    if (vlan_parent_flags_supports_vlan_mtu(vlp)) {
1428	ifv->ifv_mtufudge = 0;
1429    } else {
1430	/*
1431	 * Fudge the MTU by the encapsulation size.  This
1432	 * makes us incompatible with strictly compliant
1433	 * 802.1Q implementations, but allows us to use
1434	 * the feature with other NetBSD implementations,
1435	 * which might still be useful.
1436	 */
1437	ifv->ifv_mtufudge = ifv->ifv_encaplen;
1438    }
1439    ifnet_set_mtu(ifp, ETHERMTU - ifv->ifv_mtufudge);
1440
1441    /*
1442     * Copy only a selected subset of flags from the parent.
1443     * Other flags are none of our business.
1444     */
1445    parent_flags = ifnet_flags(p)
1446	& (IFF_BROADCAST | IFF_MULTICAST | IFF_SIMPLEX);
1447    ifnet_set_flags(ifp, parent_flags,
1448		    IFF_BROADCAST | IFF_MULTICAST | IFF_SIMPLEX);
1449
1450    /* use hwassist bits from parent interface, but exclude VLAN bits */
1451    offload = ifnet_offload(p) & ~(IFNET_VLAN_TAGGING | IFNET_VLAN_MTU);
1452    ifnet_set_offload(ifp, offload);
1453
1454    ifnet_set_flags(ifp, IFF_RUNNING, IFF_RUNNING);
1455    ifvlan_flags_set_ready(ifv);
1456    vlan_parent_signal(vlp, "vlan_config");
1457    vlan_unlock();
1458    if (new_vlp != vlp) {
1459	/* throw it away, it wasn't needed */
1460	vlan_parent_release(new_vlp);
1461    }
1462    if (ifv != NULL) {
1463	ifvlan_release(ifv);
1464    }
1465    if (first_vlan) {
1466	/* mark the parent interface up */
1467	ifnet_set_flags(p, IFF_UP, IFF_UP);
1468	(void)ifnet_ioctl(p, 0, SIOCSIFFLAGS, (caddr_t)NULL);
1469    }
1470    return 0;
1471
1472 signal_done:
1473    vlan_assert_lock_held();
1474
1475    if (ifv_added) {
1476	vlan_parent_remove_vlan(vlp, ifv);
1477	if (!vlan_parent_flags_detaching(vlp) && vlan_parent_no_vlans(vlp)) {
1478	    /* the vlan parent has no more VLAN's */
1479	    ifnet_set_eflags(p, 0, IFEF_VLAN);
1480	    LIST_REMOVE(vlp, vlp_parent_list);
1481	    /* release outside of the lock below */
1482	    need_vlp_release++;
1483
1484	    /* one for being in the list */
1485	    need_vlp_release++;
1486	}
1487    }
1488    vlan_parent_signal(vlp, "vlan_config");
1489
1490 unlock_done:
1491    vlan_unlock();
1492
1493    while (need_vlp_release--) {
1494	vlan_parent_release(vlp);
1495    }
1496    if (new_vlp != vlp) {
1497	vlan_parent_release(new_vlp);
1498    }
1499    if (ifv != NULL) {
1500	if (ifv_added) {
1501	    ifvlan_release(ifv);
1502	}
1503	ifvlan_release(ifv);
1504    }
1505    return (error);
1506}
1507
1508static void
1509vlan_link_event(struct ifnet * ifp, struct ifnet * p)
1510{
1511    struct ifmediareq ifmr;
1512
1513    /* generate a link event based on the state of the underlying interface */
1514    bzero(&ifmr, sizeof(ifmr));
1515    snprintf(ifmr.ifm_name, sizeof(ifmr.ifm_name),
1516	     "%s%d", ifnet_name(p), ifnet_unit(p));
1517    if (ifnet_ioctl(p, 0, SIOCGIFMEDIA, &ifmr) == 0
1518	&& ifmr.ifm_count > 0 && ifmr.ifm_status & IFM_AVALID) {
1519	u_int32_t	event;
1520
1521	event = (ifmr.ifm_status & IFM_ACTIVE)
1522	    ? KEV_DL_LINK_ON : KEV_DL_LINK_OFF;
1523	interface_link_event(ifp, event);
1524    }
1525    return;
1526}
1527
1528static int
1529vlan_unconfig(ifvlan_ref ifv, int need_to_wait)
1530{
1531    struct ifnet *	ifp = ifv->ifv_ifp;
1532    int			last_vlan = FALSE;
1533    int			need_ifv_release = 0;
1534    int			need_vlp_release = 0;
1535    struct ifnet *	p;
1536    vlan_parent_ref	vlp;
1537
1538    vlan_assert_lock_held();
1539    vlp = ifv->ifv_vlp;
1540    if (vlp == NULL) {
1541	return (0);
1542    }
1543    if (need_to_wait) {
1544	need_vlp_release++;
1545	vlan_parent_retain(vlp);
1546	vlan_parent_wait(vlp, "vlan_unconfig");
1547
1548        /* check again because another thread could be in vlan_unconfig */
1549	if (ifv != ifnet_get_ifvlan(ifp)) {
1550	    goto signal_done;
1551	}
1552	if (ifv->ifv_vlp != vlp) {
1553	    /* vlan parent changed */
1554	    goto signal_done;
1555	}
1556    }
1557
1558    /* ifv has a reference on vlp, need to remove it */
1559    need_vlp_release++;
1560    p = vlp->vlp_ifp;
1561
1562    /* remember whether we're the last VLAN on the parent */
1563    if (LIST_NEXT(LIST_FIRST(&vlp->vlp_vlan_list), ifv_vlan_list) == NULL) {
1564	if (g_vlan->verbose) {
1565	    printf("vlan_unconfig: last vlan on %s%d\n",
1566		   ifnet_name(p), ifnet_unit(p));
1567	}
1568	last_vlan = TRUE;
1569    }
1570
1571    /* back-out any effect our mtu might have had on the parent */
1572    (void)ifvlan_new_mtu(ifv, ETHERMTU - ifv->ifv_mtufudge);
1573
1574    vlan_unlock();
1575
1576    /* un-join multicast on parent interface */
1577    (void)multicast_list_remove(&ifv->ifv_multicast);
1578
1579    /* Clear our MAC address. */
1580    ifnet_set_lladdr_and_type(ifp, NULL, 0, IFT_L2VLAN);
1581
1582    /* detach VLAN "protocol" */
1583    if (last_vlan) {
1584	(void)vlan_detach_protocol(p);
1585    }
1586
1587    vlan_lock();
1588
1589    /* return to the state we were in before SIFVLAN */
1590    ifnet_set_mtu(ifp, 0);
1591    ifnet_set_flags(ifp, 0,
1592		    IFF_BROADCAST | IFF_MULTICAST | IFF_SIMPLEX | IFF_RUNNING);
1593    ifnet_set_offload(ifp, 0);
1594    ifv->ifv_mtufudge = 0;
1595
1596    /* Disconnect from parent. */
1597    vlan_parent_remove_vlan(vlp, ifv);
1598    ifv->ifv_flags = 0;
1599
1600    /* vlan_parent has reference to ifv, remove it */
1601    need_ifv_release++;
1602
1603    /* from this point on, no more referencing ifv */
1604    if (last_vlan && !vlan_parent_flags_detaching(vlp)) {
1605	/* the vlan parent has no more VLAN's */
1606	ifnet_set_eflags(p, 0, IFEF_VLAN);
1607	LIST_REMOVE(vlp, vlp_parent_list);
1608
1609	/* one for being in the list */
1610	need_vlp_release++;
1611
1612	/* release outside of the lock below */
1613	need_vlp_release++;
1614    }
1615
1616 signal_done:
1617    if (need_to_wait) {
1618	vlan_parent_signal(vlp, "vlan_unconfig");
1619    }
1620    vlan_unlock();
1621    while (need_ifv_release--) {
1622	ifvlan_release(ifv);
1623    }
1624    while (need_vlp_release--) {	/* references to vlp */
1625	vlan_parent_release(vlp);
1626    }
1627    vlan_lock();
1628    return (0);
1629}
1630
1631static int
1632vlan_set_promisc(struct ifnet * ifp)
1633{
1634    int 			error = 0;
1635    ifvlan_ref			ifv;
1636    vlan_parent_ref		vlp;
1637
1638    vlan_lock();
1639    ifv = ifnet_get_ifvlan_retained(ifp);
1640    if (ifv == NULL) {
1641	error = EBUSY;
1642	goto done;
1643    }
1644
1645    vlp = ifv->ifv_vlp;
1646    if (vlp == NULL) {
1647	goto done;
1648    }
1649    if ((ifnet_flags(ifp) & IFF_PROMISC) != 0) {
1650	if (!ifvlan_flags_promisc(ifv)) {
1651	    error = ifnet_set_promiscuous(vlp->vlp_ifp, 1);
1652	    if (error == 0) {
1653		ifvlan_flags_set_promisc(ifv);
1654	    }
1655	}
1656    } else {
1657	if (ifvlan_flags_promisc(ifv)) {
1658	    error = ifnet_set_promiscuous(vlp->vlp_ifp, 0);
1659	    if (error == 0) {
1660		ifvlan_flags_clear_promisc(ifv);
1661	    }
1662	}
1663    }
1664 done:
1665    vlan_unlock();
1666    if (ifv != NULL) {
1667	ifvlan_release(ifv);
1668    }
1669    return (error);
1670}
1671
1672static int
1673ifvlan_new_mtu(ifvlan_ref ifv, int mtu)
1674{
1675    struct ifdevmtu *	devmtu_p;
1676    int			error = 0;
1677    struct ifnet * 	ifp = ifv->ifv_ifp;
1678    int			max_mtu;
1679    int			new_mtu = 0;
1680    int			req_mtu;
1681    vlan_parent_ref	vlp;
1682
1683    vlan_assert_lock_held();
1684    vlp = ifv->ifv_vlp;
1685    devmtu_p = &vlp->vlp_devmtu;
1686    req_mtu = mtu + ifv->ifv_mtufudge;
1687    if (req_mtu > devmtu_p->ifdm_max || req_mtu < devmtu_p->ifdm_min) {
1688	return (EINVAL);
1689    }
1690    max_mtu = vlan_parent_find_max_mtu(vlp, ifv);
1691    if (req_mtu > max_mtu) {
1692	new_mtu = req_mtu;
1693    }
1694    else if (max_mtu < devmtu_p->ifdm_current) {
1695	new_mtu = max_mtu;
1696    }
1697    if (new_mtu != 0) {
1698	struct ifnet * 	p = vlp->vlp_ifp;
1699	vlan_unlock();
1700	error = siocsifaltmtu(p, new_mtu);
1701	vlan_lock();
1702    }
1703    if (error == 0) {
1704	if (new_mtu != 0) {
1705	    devmtu_p->ifdm_current = new_mtu;
1706	}
1707	ifnet_set_mtu(ifp, mtu);
1708    }
1709    return (error);
1710}
1711
1712static int
1713vlan_set_mtu(struct ifnet * ifp, int mtu)
1714{
1715    int			error = 0;
1716    ifvlan_ref		ifv;
1717    vlan_parent_ref	vlp;
1718
1719    if (mtu < IF_MINMTU) {
1720	return (EINVAL);
1721    }
1722    vlan_lock();
1723    ifv = ifnet_get_ifvlan_retained(ifp);
1724    if (ifv == NULL) {
1725	vlan_unlock();
1726	return (EBUSY);
1727    }
1728    vlp = ifvlan_get_vlan_parent_retained(ifv);
1729    if (vlp == NULL) {
1730	vlan_unlock();
1731	ifvlan_release(ifv);
1732	if (mtu != 0) {
1733	    return (EINVAL);
1734	}
1735	return (0);
1736    }
1737    vlan_parent_wait(vlp, "vlan_set_mtu");
1738
1739    /* check again, something might have changed */
1740    if (ifnet_get_ifvlan(ifp) != ifv
1741	|| ifvlan_flags_detaching(ifv)) {
1742	error = EBUSY;
1743	goto signal_done;
1744    }
1745    if (ifv->ifv_vlp != vlp) {
1746	/* vlan parent changed */
1747	goto signal_done;
1748    }
1749    if (vlan_parent_flags_detaching(vlp)) {
1750	if (mtu != 0) {
1751	    error = EINVAL;
1752	}
1753	goto signal_done;
1754    }
1755    error = ifvlan_new_mtu(ifv, mtu);
1756
1757 signal_done:
1758    vlan_parent_signal(vlp, "vlan_set_mtu");
1759    vlan_unlock();
1760    vlan_parent_release(vlp);
1761    ifvlan_release(ifv);
1762
1763    return (error);
1764}
1765
1766static int
1767vlan_ioctl(ifnet_t ifp, u_long cmd, void * data)
1768{
1769    struct ifdevmtu *	devmtu_p;
1770    int 		error = 0;
1771    struct ifaddr *	ifa;
1772    struct ifmediareq	*ifmr;
1773    struct ifreq *	ifr;
1774    ifvlan_ref		ifv;
1775    struct ifnet *	p;
1776    u_short		tag;
1777    user_addr_t		user_addr;
1778    vlan_parent_ref	vlp;
1779    struct vlanreq 	vlr;
1780
1781    if (ifnet_type(ifp) != IFT_L2VLAN) {
1782	return (EOPNOTSUPP);
1783    }
1784    ifr = (struct ifreq *)data;
1785    ifa = (struct ifaddr *)data;
1786
1787    switch (cmd) {
1788    case SIOCSIFADDR:
1789    ifnet_set_flags(ifp, IFF_UP, IFF_UP);
1790	break;
1791
1792    case SIOCGIFMEDIA32:
1793    case SIOCGIFMEDIA64:
1794	vlan_lock();
1795	ifv = (ifvlan_ref)ifnet_softc(ifp);
1796	if (ifv == NULL || ifvlan_flags_detaching(ifv)) {
1797	    vlan_unlock();
1798	    return (ifv == NULL ? EOPNOTSUPP : EBUSY);
1799	}
1800	p = (ifv->ifv_vlp == NULL) ? NULL : ifv->ifv_vlp->vlp_ifp;
1801	vlan_unlock();
1802	ifmr = (struct ifmediareq *)data;
1803	user_addr =  (cmd == SIOCGIFMEDIA64) ?
1804	    ((struct ifmediareq64 *)ifmr)->ifmu_ulist :
1805	    CAST_USER_ADDR_T(((struct ifmediareq32 *)ifmr)->ifmu_ulist);
1806	if (p != NULL) {
1807	    struct ifmediareq p_ifmr;
1808
1809	    bzero(&p_ifmr, sizeof(p_ifmr));
1810	    error = ifnet_ioctl(p, 0, SIOCGIFMEDIA, &p_ifmr);
1811	    if (error == 0) {
1812		ifmr->ifm_active = p_ifmr.ifm_active;
1813		ifmr->ifm_current = p_ifmr.ifm_current;
1814		ifmr->ifm_mask = p_ifmr.ifm_mask;
1815		ifmr->ifm_status = p_ifmr.ifm_status;
1816		ifmr->ifm_count = p_ifmr.ifm_count;
1817		/* Limit the result to the parent's current config. */
1818		if (ifmr->ifm_count >= 1 && user_addr != USER_ADDR_NULL) {
1819		    ifmr->ifm_count = 1;
1820		    error = copyout(&ifmr->ifm_current, user_addr,
1821				    sizeof(int));
1822		}
1823	    }
1824	} else {
1825	    ifmr->ifm_active = ifmr->ifm_current = IFM_NONE;
1826	    ifmr->ifm_mask = 0;
1827	    ifmr->ifm_status = IFM_AVALID;
1828	    ifmr->ifm_count = 1;
1829	    if (user_addr != USER_ADDR_NULL) {
1830		error = copyout(&ifmr->ifm_current, user_addr, sizeof(int));
1831	    }
1832	}
1833	break;
1834
1835    case SIOCSIFMEDIA:
1836	error = EOPNOTSUPP;
1837	break;
1838
1839    case SIOCGIFDEVMTU:
1840	vlan_lock();
1841	ifv = (ifvlan_ref)ifnet_softc(ifp);
1842	if (ifv == NULL || ifvlan_flags_detaching(ifv)) {
1843	    vlan_unlock();
1844	    return (ifv == NULL ? EOPNOTSUPP : EBUSY);
1845	}
1846	vlp = ifv->ifv_vlp;
1847	if (vlp != NULL) {
1848	    int		min_mtu = vlp->vlp_devmtu.ifdm_min - ifv->ifv_mtufudge;
1849	    devmtu_p = &ifr->ifr_devmtu;
1850	    devmtu_p->ifdm_current = ifnet_mtu(ifp);
1851	    devmtu_p->ifdm_min = max(min_mtu, IF_MINMTU);
1852	    devmtu_p->ifdm_max = vlp->vlp_devmtu.ifdm_max - ifv->ifv_mtufudge;
1853	}
1854	else {
1855	    devmtu_p = &ifr->ifr_devmtu;
1856	    devmtu_p->ifdm_current = 0;
1857	    devmtu_p->ifdm_min = 0;
1858	    devmtu_p->ifdm_max = 0;
1859	}
1860	vlan_unlock();
1861	break;
1862
1863    case SIOCSIFMTU:
1864	error = vlan_set_mtu(ifp, ifr->ifr_mtu);
1865	break;
1866
1867    case SIOCSIFVLAN:
1868	user_addr = proc_is64bit(current_proc())
1869	    ? ifr->ifr_data64 : CAST_USER_ADDR_T(ifr->ifr_data);
1870	error = copyin(user_addr, &vlr, sizeof(vlr));
1871	if (error) {
1872	    break;
1873	}
1874	p = NULL;
1875	if (vlr.vlr_parent[0] != '\0') {
1876	    if (vlr.vlr_tag & ~EVL_VLID_MASK) {
1877		/*
1878		 * Don't let the caller set up a VLAN tag with
1879		 * anything except VLID bits.
1880		 */
1881		error = EINVAL;
1882		break;
1883	    }
1884	    p = ifunit(vlr.vlr_parent);
1885	    if (p == NULL) {
1886		error = ENXIO;
1887		break;
1888	    }
1889	    /* can't do VLAN over anything but ethernet or ethernet aggregate */
1890	    if (ifnet_type(p) != IFT_ETHER
1891		&& ifnet_type(p) != IFT_IEEE8023ADLAG) {
1892		error = EPROTONOSUPPORT;
1893		break;
1894	    }
1895	    error = vlan_config(ifp, p, vlr.vlr_tag);
1896	    if (error) {
1897		break;
1898	    }
1899
1900	    /* Update promiscuous mode, if necessary. */
1901	    (void)vlan_set_promisc(ifp);
1902
1903	    /* generate a link event based on the state of the parent */
1904	    vlan_link_event(ifp, p);
1905	}
1906	else {
1907	    int		need_link_event = FALSE;
1908
1909	    vlan_lock();
1910	    ifv = (ifvlan_ref)ifnet_softc(ifp);
1911	    if (ifv == NULL || ifvlan_flags_detaching(ifv)) {
1912		vlan_unlock();
1913		error = (ifv == NULL ? EOPNOTSUPP : EBUSY);
1914		break;
1915	    }
1916	    need_link_event = vlan_remove(ifv, TRUE);
1917	    vlan_unlock();
1918	    if (need_link_event) {
1919		interface_link_event(ifp, KEV_DL_LINK_OFF);
1920	    }
1921	}
1922	break;
1923
1924    case SIOCGIFVLAN:
1925	bzero(&vlr, sizeof vlr);
1926	vlan_lock();
1927	ifv = (ifvlan_ref)ifnet_softc(ifp);
1928	if (ifv == NULL || ifvlan_flags_detaching(ifv)) {
1929	    vlan_unlock();
1930	    return (ifv == NULL ? EOPNOTSUPP : EBUSY);
1931	}
1932	p = (ifv->ifv_vlp == NULL) ? NULL : ifv->ifv_vlp->vlp_ifp;
1933	tag = ifv->ifv_tag;
1934	vlan_unlock();
1935	if (p != NULL) {
1936	    snprintf(vlr.vlr_parent, sizeof(vlr.vlr_parent),
1937		     "%s%d", ifnet_name(p), ifnet_unit(p));
1938	    vlr.vlr_tag = tag;
1939	}
1940	user_addr = proc_is64bit(current_proc())
1941	    ? ifr->ifr_data64 : CAST_USER_ADDR_T(ifr->ifr_data);
1942	error = copyout(&vlr, user_addr, sizeof(vlr));
1943	break;
1944
1945    case SIOCSIFFLAGS:
1946	/*
1947	 * For promiscuous mode, we enable promiscuous mode on
1948	 * the parent if we need promiscuous on the VLAN interface.
1949	 */
1950	error = vlan_set_promisc(ifp);
1951	break;
1952
1953    case SIOCADDMULTI:
1954    case SIOCDELMULTI:
1955	error = vlan_setmulti(ifp);
1956	break;
1957    default:
1958	error = EOPNOTSUPP;
1959    }
1960    return error;
1961}
1962
1963static void
1964vlan_if_free(struct ifnet * ifp)
1965{
1966    ifvlan_ref	ifv;
1967
1968    if (ifp == NULL) {
1969	return;
1970    }
1971    ifv = (ifvlan_ref)ifnet_softc(ifp);
1972    if (ifv == NULL) {
1973	return;
1974    }
1975    ifvlan_release(ifv);
1976    ifnet_release(ifp);
1977    return;
1978}
1979
1980static void
1981vlan_event(struct ifnet	* p, __unused protocol_family_t protocol,
1982		   const struct kev_msg * event)
1983{
1984    int			event_code;
1985
1986    /* Check if the interface we are attached to is being detached */
1987    if (event->vendor_code != KEV_VENDOR_APPLE
1988	|| event->kev_class != KEV_NETWORK_CLASS
1989	|| event->kev_subclass != KEV_DL_SUBCLASS) {
1990	return;
1991    }
1992    event_code = event->event_code;
1993    switch (event_code) {
1994    case KEV_DL_LINK_OFF:
1995    case KEV_DL_LINK_ON:
1996	vlan_parent_link_event(p, event_code);
1997	break;
1998    default:
1999	return;
2000    }
2001    return;
2002}
2003
2004static errno_t
2005vlan_detached(ifnet_t p, __unused protocol_family_t protocol)
2006{
2007    if (ifnet_is_attached(p, 0) == 0) {
2008	/* if the parent isn't attached, remove all VLANs */
2009	vlan_parent_remove_all_vlans(p);
2010    }
2011    return (0);
2012}
2013
2014static void
2015interface_link_event(struct ifnet * ifp, u_int32_t event_code)
2016{
2017    struct {
2018	struct kern_event_msg	header;
2019	u_int32_t			unit;
2020	char			if_name[IFNAMSIZ];
2021    } event;
2022
2023    bzero(&event, sizeof(event));
2024    event.header.total_size    = sizeof(event);
2025    event.header.vendor_code   = KEV_VENDOR_APPLE;
2026    event.header.kev_class     = KEV_NETWORK_CLASS;
2027    event.header.kev_subclass  = KEV_DL_SUBCLASS;
2028    event.header.event_code    = event_code;
2029    event.header.event_data[0] = ifnet_family(ifp);
2030    event.unit                 = (u_int32_t) ifnet_unit(ifp);
2031    strncpy(event.if_name, ifnet_name(ifp), IFNAMSIZ);
2032    ifnet_event(ifp, &event.header);
2033    return;
2034}
2035
2036static void
2037vlan_parent_link_event(struct ifnet * p, u_int32_t event_code)
2038{
2039    ifvlan_ref 		ifv;
2040    vlan_parent_ref 	vlp;
2041
2042    vlan_lock();
2043    if ((ifnet_eflags(p) & IFEF_VLAN) == 0) {
2044	vlan_unlock();
2045	/* no VLAN's */
2046	return;
2047    }
2048    vlp = parent_list_lookup(p);
2049    if (vlp == NULL) {
2050	/* no VLAN's */
2051	vlan_unlock();
2052	return;
2053    }
2054
2055    vlan_parent_retain(vlp);
2056    vlan_parent_wait(vlp, "vlan_parent_link_event");
2057    if (vlan_parent_flags_detaching(vlp)) {
2058	goto signal_done;
2059    }
2060
2061    vlan_unlock();
2062
2063    /* vlan_parent_wait() gives us exclusive access to the list */
2064    LIST_FOREACH(ifv, &vlp->vlp_vlan_list, ifv_vlan_list) {
2065	struct ifnet *	ifp = ifv->ifv_ifp;
2066
2067	interface_link_event(ifp, event_code);
2068    }
2069
2070    vlan_lock();
2071
2072 signal_done:
2073    vlan_parent_signal(vlp, "vlan_parent_link_event");
2074    vlan_unlock();
2075    vlan_parent_release(vlp);
2076    return;
2077
2078}
2079
2080/*
2081 * Function: vlan_attach_protocol
2082 * Purpose:
2083 *   Attach a DLIL protocol to the interface, using the ETHERTYPE_VLAN
2084 *   demux ether type.
2085 *
2086 *	 The ethernet demux actually special cases VLAN to support hardware.
2087 *	 The demux here isn't used. The demux will return PF_VLAN for the
2088 *	 appropriate packets and our vlan_input function will be called.
2089 */
2090static int
2091vlan_attach_protocol(struct ifnet *ifp)
2092{
2093    int								error;
2094    struct ifnet_attach_proto_param	reg;
2095
2096    bzero(&reg, sizeof(reg));
2097    reg.input            = vlan_input;
2098    reg.event            = vlan_event;
2099    reg.detached         = vlan_detached;
2100    error = ifnet_attach_protocol(ifp, PF_VLAN, &reg);
2101    if (error) {
2102	printf("vlan_proto_attach(%s%d) ifnet_attach_protocol failed, %d\n",
2103	       ifnet_name(ifp), ifnet_unit(ifp), error);
2104    }
2105    return (error);
2106}
2107
2108/*
2109 * Function: vlan_detach_protocol
2110 * Purpose:
2111 *   Detach our DLIL protocol from an interface
2112 */
2113static int
2114vlan_detach_protocol(struct ifnet *ifp)
2115{
2116    int         error;
2117
2118    error = ifnet_detach_protocol(ifp, PF_VLAN);
2119    if (error) {
2120	printf("vlan_proto_detach(%s%d) ifnet_detach_protocol failed, %d\n",
2121	       ifnet_name(ifp), ifnet_unit(ifp), error);
2122    }
2123
2124    return (error);
2125}
2126
2127/*
2128 * DLIL interface family functions
2129 *   We use the ethernet plumb functions, since that's all we support.
2130 *   If we wanted to handle multiple LAN types (tokenring, etc.), we'd
2131 *   call the appropriate routines for that LAN type instead of hard-coding
2132 *   ethernet.
2133 */
2134static errno_t
2135vlan_attach_inet(struct ifnet *ifp, protocol_family_t protocol_family)
2136{
2137    return (ether_attach_inet(ifp, protocol_family));
2138}
2139
2140static void
2141vlan_detach_inet(struct ifnet *ifp, protocol_family_t protocol_family)
2142{
2143    ether_detach_inet(ifp, protocol_family);
2144}
2145
2146#if INET6
2147static errno_t
2148vlan_attach_inet6(struct ifnet *ifp, protocol_family_t protocol_family)
2149{
2150    return (ether_attach_inet6(ifp, protocol_family));
2151}
2152
2153static void
2154vlan_detach_inet6(struct ifnet *ifp, protocol_family_t protocol_family)
2155{
2156    ether_detach_inet6(ifp, protocol_family);
2157}
2158#endif /* INET6 */
2159
2160__private_extern__ int
2161vlan_family_init(void)
2162{
2163    int error=0;
2164
2165    error = proto_register_plumber(PF_INET, IFNET_FAMILY_VLAN,
2166				   vlan_attach_inet, vlan_detach_inet);
2167    if (error != 0) {
2168	printf("proto_register_plumber failed for AF_INET error=%d\n",
2169	       error);
2170	goto done;
2171    }
2172#if INET6
2173    error = proto_register_plumber(PF_INET6, IFNET_FAMILY_VLAN,
2174				   vlan_attach_inet6, vlan_detach_inet6);
2175    if (error != 0) {
2176	printf("proto_register_plumber failed for AF_INET6 error=%d\n",
2177	       error);
2178	goto done;
2179    }
2180#endif
2181    error = vlan_clone_attach();
2182    if (error != 0) {
2183        printf("proto_register_plumber failed vlan_clone_attach error=%d\n",
2184               error);
2185        goto done;
2186    }
2187
2188
2189 done:
2190    return (error);
2191}
2192