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 (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_params	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.uniqueid = ifv->ifv_name;
969	vlan_init.uniqueid_len = strlen(ifv->ifv_name);
970	vlan_init.name = ifc->ifc_name;
971	vlan_init.unit = unit;
972	vlan_init.family = IFNET_FAMILY_VLAN;
973	vlan_init.type = IFT_L2VLAN;
974	vlan_init.output = vlan_output;
975	vlan_init.demux = ether_demux;
976	vlan_init.add_proto = ether_add_proto;
977	vlan_init.del_proto = ether_del_proto;
978	vlan_init.check_multi = ether_check_multi;
979	vlan_init.framer = ether_frameout;
980	vlan_init.softc = ifv;
981	vlan_init.ioctl = vlan_ioctl;
982	vlan_init.set_bpf_tap = vlan_set_bpf_tap;
983	vlan_init.detach = vlan_if_free;
984	vlan_init.broadcast_addr = etherbroadcastaddr;
985	vlan_init.broadcast_len = ETHER_ADDR_LEN;
986	error = ifnet_allocate(&vlan_init, &ifp);
987
988	if (error) {
989	    ifvlan_release(ifv);
990	    return (error);
991	}
992
993	ifnet_set_offload(ifp, 0);
994	ifnet_set_addrlen(ifp, ETHER_ADDR_LEN); /* XXX ethernet specific */
995	ifnet_set_baudrate(ifp, 0);
996	ifnet_set_hdrlen(ifp, ETHER_VLAN_ENCAP_LEN);
997
998	error = ifnet_attach(ifp, NULL);
999	if (error) {
1000	    ifnet_release(ifp);
1001	    ifvlan_release(ifv);
1002	    return (error);
1003	}
1004	ifv->ifv_ifp = ifp;
1005
1006	/* attach as ethernet */
1007	bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header));
1008	return (0);
1009}
1010
1011static int
1012vlan_remove(ifvlan_ref ifv, int need_to_wait)
1013{
1014    vlan_assert_lock_held();
1015    if (ifvlan_flags_detaching(ifv)) {
1016	return (0);
1017    }
1018    ifvlan_flags_set_detaching(ifv);
1019    vlan_unconfig(ifv, need_to_wait);
1020    return (1);
1021}
1022
1023
1024static int
1025vlan_clone_destroy(struct ifnet *ifp)
1026{
1027    ifvlan_ref ifv;
1028
1029    vlan_lock();
1030    ifv = ifnet_get_ifvlan_retained(ifp);
1031    if (ifv == NULL) {
1032	vlan_unlock();
1033	return 0;
1034    }
1035    if (vlan_remove(ifv, TRUE) == 0) {
1036	vlan_unlock();
1037	ifvlan_release(ifv);
1038	return 0;
1039    }
1040    vlan_unlock();
1041    ifvlan_release(ifv);
1042    ifnet_detach(ifp);
1043
1044    return 0;
1045}
1046
1047static int
1048vlan_set_bpf_tap(ifnet_t ifp, bpf_tap_mode mode, bpf_packet_func func)
1049{
1050    ifvlan_ref	ifv;
1051
1052    vlan_lock();
1053    ifv = ifnet_get_ifvlan_retained(ifp);
1054    if (ifv == NULL) {
1055	vlan_unlock();
1056	return (ENODEV);
1057    }
1058    switch (mode) {
1059        case BPF_TAP_DISABLE:
1060            ifv->ifv_bpf_input = ifv->ifv_bpf_output = NULL;
1061            break;
1062
1063        case BPF_TAP_INPUT:
1064            ifv->ifv_bpf_input = func;
1065            break;
1066
1067        case BPF_TAP_OUTPUT:
1068	    ifv->ifv_bpf_output = func;
1069            break;
1070
1071        case BPF_TAP_INPUT_OUTPUT:
1072            ifv->ifv_bpf_input = ifv->ifv_bpf_output = func;
1073            break;
1074        default:
1075            break;
1076    }
1077    vlan_unlock();
1078    ifvlan_release(ifv);
1079    return 0;
1080}
1081
1082static int
1083vlan_output(struct ifnet * ifp, struct mbuf * m)
1084{
1085    bpf_packet_func 		bpf_func;
1086    struct ether_vlan_header *	evl;
1087    int				encaplen;
1088    ifvlan_ref			ifv;
1089    struct ifnet *		p;
1090    int 			soft_vlan;
1091    u_short			tag;
1092    vlan_parent_ref		vlp = NULL;
1093    int				err;
1094    struct flowadv		adv = { FADV_SUCCESS };
1095
1096    if (m == 0) {
1097	return (0);
1098    }
1099    if ((m->m_flags & M_PKTHDR) == 0) {
1100	m_freem_list(m);
1101	return (0);
1102    }
1103    vlan_lock();
1104    ifv = ifnet_get_ifvlan_retained(ifp);
1105    if (ifv == NULL || ifvlan_flags_ready(ifv) == 0) {
1106	goto unlock_done;
1107    }
1108    vlp = ifvlan_get_vlan_parent_retained(ifv);
1109    if (vlp == NULL) {
1110	goto unlock_done;
1111    }
1112    p = vlp->vlp_ifp;
1113    (void)ifnet_stat_increment_out(ifp, 1, m->m_pkthdr.len, 0);
1114    soft_vlan = (ifnet_offload(p) & IF_HWASSIST_VLAN_TAGGING) == 0;
1115    bpf_func = ifv->ifv_bpf_output;
1116    tag = ifv->ifv_tag;
1117    encaplen = ifv->ifv_encaplen;
1118    vlan_unlock();
1119
1120    ifvlan_release(ifv);
1121    vlan_parent_release(vlp);
1122
1123    vlan_bpf_output(ifp, m, bpf_func);
1124
1125    /* do not run parent's if_output() if the parent is not up */
1126    if ((ifnet_flags(p) & (IFF_UP | IFF_RUNNING)) != (IFF_UP | IFF_RUNNING)) {
1127	m_freem(m);
1128	atomic_add_64(&ifp->if_collisions, 1);
1129	return (0);
1130    }
1131    /*
1132     * If underlying interface can do VLAN tag insertion itself,
1133     * just pass the packet along. However, we need some way to
1134     * tell the interface where the packet came from so that it
1135     * knows how to find the VLAN tag to use.  We use a field in
1136     * the mbuf header to store the VLAN tag, and a bit in the
1137     * csum_flags field to mark the field as valid.
1138     */
1139    if (soft_vlan == 0) {
1140	m->m_pkthdr.csum_flags |= CSUM_VLAN_TAG_VALID;
1141	m->m_pkthdr.vlan_tag = tag;
1142    } else {
1143	M_PREPEND(m, encaplen, M_DONTWAIT);
1144	if (m == NULL) {
1145	    printf("%s%d: unable to prepend VLAN header\n", ifnet_name(ifp),
1146		   ifnet_unit(ifp));
1147	    atomic_add_64(&ifp->if_oerrors, 1);
1148	    return (0);
1149	}
1150	/* M_PREPEND takes care of m_len, m_pkthdr.len for us */
1151	if (m->m_len < (int)sizeof(*evl)) {
1152	    m = m_pullup(m, sizeof(*evl));
1153	    if (m == NULL) {
1154		printf("%s%d: unable to pullup VLAN header\n", ifnet_name(ifp),
1155		       ifnet_unit(ifp));
1156		atomic_add_64(&ifp->if_oerrors, 1);
1157		return (0);
1158	    }
1159	}
1160
1161	/*
1162	 * Transform the Ethernet header into an Ethernet header
1163	 * with 802.1Q encapsulation.
1164	 */
1165	bcopy(mtod(m, char *) + encaplen,
1166	      mtod(m, char *), ETHER_HDR_LEN);
1167	evl = mtod(m, struct ether_vlan_header *);
1168	evl->evl_proto = evl->evl_encap_proto;
1169	evl->evl_encap_proto = htons(ETHERTYPE_VLAN);
1170	evl->evl_tag = htons(tag);
1171    }
1172
1173    err = dlil_output(p, PF_VLAN, m, NULL, NULL, 1, &adv);
1174
1175    if (err == 0) {
1176	if (adv.code == FADV_FLOW_CONTROLLED) {
1177	    err = EQFULL;
1178	} else if (adv.code == FADV_SUSPENDED) {
1179	    err = EQSUSPENDED;
1180	}
1181    }
1182
1183    return (err);
1184
1185 unlock_done:
1186    vlan_unlock();
1187    if (ifv != NULL) {
1188	ifvlan_release(ifv);
1189    }
1190    if (vlp != NULL) {
1191	vlan_parent_release(vlp);
1192    }
1193    m_freem_list(m);
1194    return (0);
1195
1196}
1197
1198static int
1199vlan_input(ifnet_t p, __unused protocol_family_t protocol,
1200					   mbuf_t m, char *frame_header)
1201{
1202    bpf_packet_func 		bpf_func = NULL;
1203    struct ether_vlan_header *	evl;
1204    struct ifnet *		ifp = NULL;
1205    int 			soft_vlan = 0;
1206    u_int 			tag = 0;
1207
1208    if (m->m_pkthdr.csum_flags & CSUM_VLAN_TAG_VALID) {
1209	/*
1210	 * Packet is tagged, m contains a normal
1211	 * Ethernet frame; the tag is stored out-of-band.
1212	 */
1213	m->m_pkthdr.csum_flags &= ~CSUM_VLAN_TAG_VALID;
1214	tag = EVL_VLANOFTAG(m->m_pkthdr.vlan_tag);
1215	m->m_pkthdr.vlan_tag = 0;
1216    } else {
1217	soft_vlan = 1;
1218	switch (ifnet_type(p)) {
1219	case IFT_ETHER:
1220	    if (m->m_len < ETHER_VLAN_ENCAP_LEN) {
1221		m_freem(m);
1222		return 0;
1223	    }
1224	    evl = (struct ether_vlan_header *)(void *)frame_header;
1225	    if (ntohs(evl->evl_proto) == ETHERTYPE_VLAN) {
1226		/* don't allow VLAN within VLAN */
1227		m_freem(m);
1228		return (0);
1229	    }
1230	    tag = EVL_VLANOFTAG(ntohs(evl->evl_tag));
1231
1232	    /*
1233	     * Restore the original ethertype.  We'll remove
1234	     * the encapsulation after we've found the vlan
1235	     * interface corresponding to the tag.
1236	     */
1237	    evl->evl_encap_proto = evl->evl_proto;
1238	    break;
1239	default:
1240	    printf("vlan_demux: unsupported if type %u",
1241		   ifnet_type(p));
1242	    m_freem(m);
1243	    return 0;
1244	    break;
1245	}
1246    }
1247    if (tag != 0) {
1248	ifvlan_ref		ifv;
1249
1250	if ((ifnet_eflags(p) & IFEF_VLAN) == 0) {
1251	    /* don't bother looking through the VLAN list */
1252	    m_freem(m);
1253	    return 0;
1254	}
1255	vlan_lock();
1256	ifv = vlan_lookup_parent_and_tag(p, tag);
1257	if (ifv != NULL) {
1258	    ifp = ifv->ifv_ifp;
1259	}
1260	if (ifv == NULL
1261	    || ifvlan_flags_ready(ifv) == 0
1262	    || (ifnet_flags(ifp) & IFF_UP) == 0) {
1263	    vlan_unlock();
1264	    m_freem(m);
1265	    return 0;
1266	}
1267	bpf_func = ifv->ifv_bpf_input;
1268	vlan_unlock();
1269    }
1270    if (soft_vlan) {
1271	/*
1272	 * Packet had an in-line encapsulation header;
1273	 * remove it.  The original header has already
1274	 * been fixed up above.
1275	 */
1276	m->m_len -= ETHER_VLAN_ENCAP_LEN;
1277	m->m_data += ETHER_VLAN_ENCAP_LEN;
1278	m->m_pkthdr.len -= ETHER_VLAN_ENCAP_LEN;
1279	m->m_pkthdr.csum_flags = 0; /* can't trust hardware checksum */
1280    }
1281    if (tag != 0) {
1282	m->m_pkthdr.rcvif = ifp;
1283	m->m_pkthdr.header = frame_header;
1284	(void)ifnet_stat_increment_in(ifp, 1,
1285				      m->m_pkthdr.len + ETHER_HDR_LEN, 0);
1286	vlan_bpf_input(ifp, m, bpf_func, frame_header, ETHER_HDR_LEN,
1287		       soft_vlan ? ETHER_VLAN_ENCAP_LEN : 0);
1288	/* We found a vlan interface, inject on that interface. */
1289	dlil_input_packet_list(ifp, m);
1290    } else {
1291	m->m_pkthdr.header = frame_header;
1292	/* Send priority-tagged packet up through the parent */
1293	dlil_input_packet_list(p, m);
1294    }
1295    return 0;
1296}
1297
1298static int
1299vlan_config(struct ifnet * ifp, struct ifnet * p, int tag)
1300{
1301    int			error;
1302    int			first_vlan = FALSE;
1303    ifvlan_ref 		ifv = NULL;
1304    int			ifv_added = FALSE;
1305    int			need_vlp_release = 0;
1306    vlan_parent_ref	new_vlp = NULL;
1307    ifnet_offload_t	offload;
1308    u_int16_t		parent_flags;
1309    vlan_parent_ref	vlp = NULL;
1310
1311    /* pre-allocate space for vlan_parent, in case we're first */
1312    error = vlan_parent_create(p, &new_vlp);
1313    if (error != 0) {
1314	return (error);
1315    }
1316
1317    vlan_lock();
1318    ifv = ifnet_get_ifvlan_retained(ifp);
1319    if (ifv == NULL || ifv->ifv_vlp != NULL) {
1320	vlan_unlock();
1321	if (ifv != NULL) {
1322	    ifvlan_release(ifv);
1323	}
1324	vlan_parent_release(new_vlp);
1325	return (EBUSY);
1326    }
1327    vlp = parent_list_lookup(p);
1328    if (vlp != NULL) {
1329	vlan_parent_retain(vlp);
1330	need_vlp_release++;
1331	if (vlan_parent_lookup_tag(vlp, tag) != NULL) {
1332	    /* already a VLAN with that tag on this interface */
1333	    error = EADDRINUSE;
1334	    goto unlock_done;
1335	}
1336    }
1337    else {
1338	/* one for being in the list */
1339	vlan_parent_retain(new_vlp);
1340
1341	/* we're the first VLAN on this interface */
1342	LIST_INSERT_HEAD(&g_vlan->parent_list, new_vlp, vlp_parent_list);
1343	vlp = new_vlp;
1344
1345	vlan_parent_retain(vlp);
1346	need_vlp_release++;
1347    }
1348
1349    /* need to wait to ensure no one else is trying to add/remove */
1350    vlan_parent_wait(vlp, "vlan_config");
1351
1352    if (ifnet_get_ifvlan(ifp) != ifv) {
1353	error = EINVAL;
1354	goto signal_done;
1355    }
1356
1357    /* check again because someone might have gotten in */
1358    if (parent_list_lookup(p) != vlp) {
1359	error = EBUSY;
1360	goto signal_done;
1361    }
1362
1363    if (vlan_parent_flags_detaching(vlp)
1364	|| ifvlan_flags_detaching(ifv) || ifv->ifv_vlp != NULL) {
1365	error = EBUSY;
1366	goto signal_done;
1367    }
1368
1369    /* check again because someone might have gotten the tag */
1370    if (vlan_parent_lookup_tag(vlp, tag) != NULL) {
1371	/* already a VLAN with that tag on this interface */
1372	error = EADDRINUSE;
1373	goto signal_done;
1374    }
1375
1376    if (vlan_parent_no_vlans(vlp)) {
1377	first_vlan = TRUE;
1378    }
1379    vlan_parent_add_vlan(vlp, ifv, tag);
1380    ifvlan_retain(ifv);	/* parent references ifv */
1381    ifv_added = TRUE;
1382
1383    /* check whether bond interface is using parent interface */
1384    ifnet_lock_exclusive(p);
1385    if ((ifnet_eflags(p) & IFEF_BOND) != 0) {
1386	ifnet_lock_done(p);
1387	/* don't allow VLAN over interface that's already part of a bond */
1388	error = EBUSY;
1389	goto signal_done;
1390    }
1391    /* prevent BOND interface from using it */
1392    /* Can't use ifnet_set_eflags because that would take the lock */
1393    p->if_eflags |= IFEF_VLAN;
1394    ifnet_lock_done(p);
1395    vlan_unlock();
1396
1397    if (first_vlan) {
1398	/* attach our VLAN "protocol" to the interface */
1399	error = vlan_attach_protocol(p);
1400	if (error) {
1401	    vlan_lock();
1402	    goto signal_done;
1403	}
1404    }
1405
1406    /* configure parent to receive our multicast addresses */
1407    error = multicast_list_program(&ifv->ifv_multicast, ifp, p);
1408    if (error != 0) {
1409	if (first_vlan) {
1410	    (void)vlan_detach_protocol(p);
1411	}
1412	vlan_lock();
1413	goto signal_done;
1414    }
1415
1416    /* set our ethernet address to that of the parent */
1417    ifnet_set_lladdr_and_type(ifp, ifnet_lladdr(p), ETHER_ADDR_LEN, IFT_ETHER);
1418
1419    /* no failures past this point */
1420    vlan_lock();
1421
1422    ifv->ifv_encaplen = ETHER_VLAN_ENCAP_LEN;
1423    ifv->ifv_flags = 0;
1424    if (vlan_parent_flags_supports_vlan_mtu(vlp)) {
1425	ifv->ifv_mtufudge = 0;
1426    } else {
1427	/*
1428	 * Fudge the MTU by the encapsulation size.  This
1429	 * makes us incompatible with strictly compliant
1430	 * 802.1Q implementations, but allows us to use
1431	 * the feature with other NetBSD implementations,
1432	 * which might still be useful.
1433	 */
1434	ifv->ifv_mtufudge = ifv->ifv_encaplen;
1435    }
1436    ifnet_set_mtu(ifp, ETHERMTU - ifv->ifv_mtufudge);
1437
1438    /*
1439     * Copy only a selected subset of flags from the parent.
1440     * Other flags are none of our business.
1441     */
1442    parent_flags = ifnet_flags(p)
1443	& (IFF_BROADCAST | IFF_MULTICAST | IFF_SIMPLEX);
1444    ifnet_set_flags(ifp, parent_flags,
1445		    IFF_BROADCAST | IFF_MULTICAST | IFF_SIMPLEX);
1446
1447    /* use hwassist bits from parent interface, but exclude VLAN bits */
1448    offload = ifnet_offload(p) & ~(IFNET_VLAN_TAGGING | IFNET_VLAN_MTU);
1449    ifnet_set_offload(ifp, offload);
1450
1451    ifnet_set_flags(ifp, IFF_RUNNING, IFF_RUNNING);
1452    ifvlan_flags_set_ready(ifv);
1453    vlan_parent_signal(vlp, "vlan_config");
1454    vlan_unlock();
1455    if (new_vlp != vlp) {
1456	/* throw it away, it wasn't needed */
1457	vlan_parent_release(new_vlp);
1458    }
1459    if (ifv != NULL) {
1460	ifvlan_release(ifv);
1461    }
1462    if (first_vlan) {
1463	/* mark the parent interface up */
1464	ifnet_set_flags(p, IFF_UP, IFF_UP);
1465	(void)ifnet_ioctl(p, 0, SIOCSIFFLAGS, (caddr_t)NULL);
1466    }
1467    return 0;
1468
1469 signal_done:
1470    vlan_assert_lock_held();
1471
1472    if (ifv_added) {
1473	vlan_parent_remove_vlan(vlp, ifv);
1474	if (!vlan_parent_flags_detaching(vlp) && vlan_parent_no_vlans(vlp)) {
1475	    /* the vlan parent has no more VLAN's */
1476	    ifnet_set_eflags(p, 0, IFEF_VLAN);
1477	    LIST_REMOVE(vlp, vlp_parent_list);
1478	    /* release outside of the lock below */
1479	    need_vlp_release++;
1480
1481	    /* one for being in the list */
1482	    need_vlp_release++;
1483	}
1484    }
1485    vlan_parent_signal(vlp, "vlan_config");
1486
1487 unlock_done:
1488    vlan_unlock();
1489
1490    while (need_vlp_release--) {
1491	vlan_parent_release(vlp);
1492    }
1493    if (new_vlp != vlp) {
1494	vlan_parent_release(new_vlp);
1495    }
1496    if (ifv != NULL) {
1497	if (ifv_added) {
1498	    ifvlan_release(ifv);
1499	}
1500	ifvlan_release(ifv);
1501    }
1502    return (error);
1503}
1504
1505static void
1506vlan_link_event(struct ifnet * ifp, struct ifnet * p)
1507{
1508    struct ifmediareq ifmr;
1509
1510    /* generate a link event based on the state of the underlying interface */
1511    bzero(&ifmr, sizeof(ifmr));
1512    snprintf(ifmr.ifm_name, sizeof(ifmr.ifm_name),
1513	     "%s%d", ifnet_name(p), ifnet_unit(p));
1514    if (ifnet_ioctl(p, 0, SIOCGIFMEDIA, &ifmr) == 0
1515	&& ifmr.ifm_count > 0 && ifmr.ifm_status & IFM_AVALID) {
1516	u_int32_t	event;
1517
1518	event = (ifmr.ifm_status & IFM_ACTIVE)
1519	    ? KEV_DL_LINK_ON : KEV_DL_LINK_OFF;
1520	interface_link_event(ifp, event);
1521    }
1522    return;
1523}
1524
1525static int
1526vlan_unconfig(ifvlan_ref ifv, int need_to_wait)
1527{
1528    struct ifnet *	ifp = ifv->ifv_ifp;
1529    int			last_vlan = FALSE;
1530    int			need_ifv_release = 0;
1531    int			need_vlp_release = 0;
1532    struct ifnet *	p;
1533    vlan_parent_ref	vlp;
1534
1535    vlan_assert_lock_held();
1536    vlp = ifv->ifv_vlp;
1537    if (vlp == NULL) {
1538	return (0);
1539    }
1540    if (need_to_wait) {
1541	need_vlp_release++;
1542	vlan_parent_retain(vlp);
1543	vlan_parent_wait(vlp, "vlan_unconfig");
1544
1545        /* check again because another thread could be in vlan_unconfig */
1546	if (ifv != ifnet_get_ifvlan(ifp)) {
1547	    goto signal_done;
1548	}
1549	if (ifv->ifv_vlp != vlp) {
1550	    /* vlan parent changed */
1551	    goto signal_done;
1552	}
1553    }
1554
1555    /* ifv has a reference on vlp, need to remove it */
1556    need_vlp_release++;
1557    p = vlp->vlp_ifp;
1558
1559    /* remember whether we're the last VLAN on the parent */
1560    if (LIST_NEXT(LIST_FIRST(&vlp->vlp_vlan_list), ifv_vlan_list) == NULL) {
1561	if (g_vlan->verbose) {
1562	    printf("vlan_unconfig: last vlan on %s%d\n",
1563		   ifnet_name(p), ifnet_unit(p));
1564	}
1565	last_vlan = TRUE;
1566    }
1567
1568    /* back-out any effect our mtu might have had on the parent */
1569    (void)ifvlan_new_mtu(ifv, ETHERMTU - ifv->ifv_mtufudge);
1570
1571    vlan_unlock();
1572
1573    /* un-join multicast on parent interface */
1574    (void)multicast_list_remove(&ifv->ifv_multicast);
1575
1576    /* Clear our MAC address. */
1577    ifnet_set_lladdr_and_type(ifp, NULL, 0, IFT_L2VLAN);
1578
1579    /* detach VLAN "protocol" */
1580    if (last_vlan) {
1581	(void)vlan_detach_protocol(p);
1582    }
1583
1584    vlan_lock();
1585
1586    /* return to the state we were in before SIFVLAN */
1587    ifnet_set_mtu(ifp, 0);
1588    ifnet_set_flags(ifp, 0,
1589		    IFF_BROADCAST | IFF_MULTICAST | IFF_SIMPLEX | IFF_RUNNING);
1590    ifnet_set_offload(ifp, 0);
1591    ifv->ifv_mtufudge = 0;
1592
1593    /* Disconnect from parent. */
1594    vlan_parent_remove_vlan(vlp, ifv);
1595    ifv->ifv_flags = 0;
1596
1597    /* vlan_parent has reference to ifv, remove it */
1598    need_ifv_release++;
1599
1600    /* from this point on, no more referencing ifv */
1601    if (last_vlan && !vlan_parent_flags_detaching(vlp)) {
1602	/* the vlan parent has no more VLAN's */
1603	ifnet_set_eflags(p, 0, IFEF_VLAN);
1604	LIST_REMOVE(vlp, vlp_parent_list);
1605
1606	/* one for being in the list */
1607	need_vlp_release++;
1608
1609	/* release outside of the lock below */
1610	need_vlp_release++;
1611    }
1612
1613 signal_done:
1614    if (need_to_wait) {
1615	vlan_parent_signal(vlp, "vlan_unconfig");
1616    }
1617    vlan_unlock();
1618    while (need_ifv_release--) {
1619	ifvlan_release(ifv);
1620    }
1621    while (need_vlp_release--) {	/* references to vlp */
1622	vlan_parent_release(vlp);
1623    }
1624    vlan_lock();
1625    return (0);
1626}
1627
1628static int
1629vlan_set_promisc(struct ifnet * ifp)
1630{
1631    int 			error = 0;
1632    ifvlan_ref			ifv;
1633    vlan_parent_ref		vlp;
1634
1635    vlan_lock();
1636    ifv = ifnet_get_ifvlan_retained(ifp);
1637    if (ifv == NULL) {
1638	error = EBUSY;
1639	goto done;
1640    }
1641
1642    vlp = ifv->ifv_vlp;
1643    if (vlp == NULL) {
1644	goto done;
1645    }
1646    if ((ifnet_flags(ifp) & IFF_PROMISC) != 0) {
1647	if (!ifvlan_flags_promisc(ifv)) {
1648	    error = ifnet_set_promiscuous(vlp->vlp_ifp, 1);
1649	    if (error == 0) {
1650		ifvlan_flags_set_promisc(ifv);
1651	    }
1652	}
1653    } else {
1654	if (ifvlan_flags_promisc(ifv)) {
1655	    error = ifnet_set_promiscuous(vlp->vlp_ifp, 0);
1656	    if (error == 0) {
1657		ifvlan_flags_clear_promisc(ifv);
1658	    }
1659	}
1660    }
1661 done:
1662    vlan_unlock();
1663    if (ifv != NULL) {
1664	ifvlan_release(ifv);
1665    }
1666    return (error);
1667}
1668
1669static int
1670ifvlan_new_mtu(ifvlan_ref ifv, int mtu)
1671{
1672    struct ifdevmtu *	devmtu_p;
1673    int			error = 0;
1674    struct ifnet * 	ifp = ifv->ifv_ifp;
1675    int			max_mtu;
1676    int			new_mtu = 0;
1677    int			req_mtu;
1678    vlan_parent_ref	vlp;
1679
1680    vlan_assert_lock_held();
1681    vlp = ifv->ifv_vlp;
1682    devmtu_p = &vlp->vlp_devmtu;
1683    req_mtu = mtu + ifv->ifv_mtufudge;
1684    if (req_mtu > devmtu_p->ifdm_max || req_mtu < devmtu_p->ifdm_min) {
1685	return (EINVAL);
1686    }
1687    max_mtu = vlan_parent_find_max_mtu(vlp, ifv);
1688    if (req_mtu > max_mtu) {
1689	new_mtu = req_mtu;
1690    }
1691    else if (max_mtu < devmtu_p->ifdm_current) {
1692	new_mtu = max_mtu;
1693    }
1694    if (new_mtu != 0) {
1695	struct ifnet * 	p = vlp->vlp_ifp;
1696	vlan_unlock();
1697	error = siocsifaltmtu(p, new_mtu);
1698	vlan_lock();
1699    }
1700    if (error == 0) {
1701	if (new_mtu != 0) {
1702	    devmtu_p->ifdm_current = new_mtu;
1703	}
1704	ifnet_set_mtu(ifp, mtu);
1705    }
1706    return (error);
1707}
1708
1709static int
1710vlan_set_mtu(struct ifnet * ifp, int mtu)
1711{
1712    int			error = 0;
1713    ifvlan_ref		ifv;
1714    vlan_parent_ref	vlp;
1715
1716    if (mtu < IF_MINMTU) {
1717	return (EINVAL);
1718    }
1719    vlan_lock();
1720    ifv = ifnet_get_ifvlan_retained(ifp);
1721    if (ifv == NULL) {
1722	vlan_unlock();
1723	return (EBUSY);
1724    }
1725    vlp = ifvlan_get_vlan_parent_retained(ifv);
1726    if (vlp == NULL) {
1727	vlan_unlock();
1728	ifvlan_release(ifv);
1729	if (mtu != 0) {
1730	    return (EINVAL);
1731	}
1732	return (0);
1733    }
1734    vlan_parent_wait(vlp, "vlan_set_mtu");
1735
1736    /* check again, something might have changed */
1737    if (ifnet_get_ifvlan(ifp) != ifv
1738	|| ifvlan_flags_detaching(ifv)) {
1739	error = EBUSY;
1740	goto signal_done;
1741    }
1742    if (ifv->ifv_vlp != vlp) {
1743	/* vlan parent changed */
1744	goto signal_done;
1745    }
1746    if (vlan_parent_flags_detaching(vlp)) {
1747	if (mtu != 0) {
1748	    error = EINVAL;
1749	}
1750	goto signal_done;
1751    }
1752    error = ifvlan_new_mtu(ifv, mtu);
1753
1754 signal_done:
1755    vlan_parent_signal(vlp, "vlan_set_mtu");
1756    vlan_unlock();
1757    vlan_parent_release(vlp);
1758    ifvlan_release(ifv);
1759
1760    return (error);
1761}
1762
1763static int
1764vlan_ioctl(ifnet_t ifp, u_long cmd, void * data)
1765{
1766    struct ifdevmtu *	devmtu_p;
1767    int 		error = 0;
1768    struct ifaddr *	ifa;
1769    struct ifmediareq	*ifmr;
1770    struct ifreq *	ifr;
1771    ifvlan_ref		ifv;
1772    struct ifnet *	p;
1773    u_short		tag;
1774    user_addr_t		user_addr;
1775    vlan_parent_ref	vlp;
1776    struct vlanreq 	vlr;
1777
1778    if (ifnet_type(ifp) != IFT_L2VLAN) {
1779	return (EOPNOTSUPP);
1780    }
1781    ifr = (struct ifreq *)data;
1782    ifa = (struct ifaddr *)data;
1783
1784    switch (cmd) {
1785    case SIOCSIFADDR:
1786    ifnet_set_flags(ifp, IFF_UP, IFF_UP);
1787	break;
1788
1789    case SIOCGIFMEDIA32:
1790    case SIOCGIFMEDIA64:
1791	vlan_lock();
1792	ifv = (ifvlan_ref)ifnet_softc(ifp);
1793	if (ifv == NULL || ifvlan_flags_detaching(ifv)) {
1794	    vlan_unlock();
1795	    return (ifv == NULL ? EOPNOTSUPP : EBUSY);
1796	}
1797	p = (ifv->ifv_vlp == NULL) ? NULL : ifv->ifv_vlp->vlp_ifp;
1798	vlan_unlock();
1799	ifmr = (struct ifmediareq *)data;
1800	user_addr =  (cmd == SIOCGIFMEDIA64) ?
1801	    ((struct ifmediareq64 *)ifmr)->ifmu_ulist :
1802	    CAST_USER_ADDR_T(((struct ifmediareq32 *)ifmr)->ifmu_ulist);
1803	if (p != NULL) {
1804	    struct ifmediareq p_ifmr;
1805
1806	    bzero(&p_ifmr, sizeof(p_ifmr));
1807	    error = ifnet_ioctl(p, 0, SIOCGIFMEDIA, &p_ifmr);
1808	    if (error == 0) {
1809		ifmr->ifm_active = p_ifmr.ifm_active;
1810		ifmr->ifm_current = p_ifmr.ifm_current;
1811		ifmr->ifm_mask = p_ifmr.ifm_mask;
1812		ifmr->ifm_status = p_ifmr.ifm_status;
1813		ifmr->ifm_count = p_ifmr.ifm_count;
1814		/* Limit the result to the parent's current config. */
1815		if (ifmr->ifm_count >= 1 && user_addr != USER_ADDR_NULL) {
1816		    ifmr->ifm_count = 1;
1817		    error = copyout(&ifmr->ifm_current, user_addr,
1818				    sizeof(int));
1819		}
1820	    }
1821	} else {
1822	    ifmr->ifm_active = ifmr->ifm_current = IFM_NONE;
1823	    ifmr->ifm_mask = 0;
1824	    ifmr->ifm_status = IFM_AVALID;
1825	    ifmr->ifm_count = 1;
1826	    if (user_addr != USER_ADDR_NULL) {
1827		error = copyout(&ifmr->ifm_current, user_addr, sizeof(int));
1828	    }
1829	}
1830	break;
1831
1832    case SIOCSIFMEDIA:
1833	error = EOPNOTSUPP;
1834	break;
1835
1836    case SIOCGIFDEVMTU:
1837	vlan_lock();
1838	ifv = (ifvlan_ref)ifnet_softc(ifp);
1839	if (ifv == NULL || ifvlan_flags_detaching(ifv)) {
1840	    vlan_unlock();
1841	    return (ifv == NULL ? EOPNOTSUPP : EBUSY);
1842	}
1843	vlp = ifv->ifv_vlp;
1844	if (vlp != NULL) {
1845	    int		min_mtu = vlp->vlp_devmtu.ifdm_min - ifv->ifv_mtufudge;
1846	    devmtu_p = &ifr->ifr_devmtu;
1847	    devmtu_p->ifdm_current = ifnet_mtu(ifp);
1848	    devmtu_p->ifdm_min = max(min_mtu, IF_MINMTU);
1849	    devmtu_p->ifdm_max = vlp->vlp_devmtu.ifdm_max - ifv->ifv_mtufudge;
1850	}
1851	else {
1852	    devmtu_p = &ifr->ifr_devmtu;
1853	    devmtu_p->ifdm_current = 0;
1854	    devmtu_p->ifdm_min = 0;
1855	    devmtu_p->ifdm_max = 0;
1856	}
1857	vlan_unlock();
1858	break;
1859
1860    case SIOCSIFMTU:
1861	error = vlan_set_mtu(ifp, ifr->ifr_mtu);
1862	break;
1863
1864    case SIOCSIFVLAN:
1865	user_addr = proc_is64bit(current_proc())
1866	    ? ifr->ifr_data64 : CAST_USER_ADDR_T(ifr->ifr_data);
1867	error = copyin(user_addr, &vlr, sizeof(vlr));
1868	if (error) {
1869	    break;
1870	}
1871	p = NULL;
1872	if (vlr.vlr_parent[0] != '\0') {
1873	    if (vlr.vlr_tag & ~EVL_VLID_MASK) {
1874		/*
1875		 * Don't let the caller set up a VLAN tag with
1876		 * anything except VLID bits.
1877		 */
1878		error = EINVAL;
1879		break;
1880	    }
1881	    p = ifunit(vlr.vlr_parent);
1882	    if (p == NULL) {
1883		error = ENXIO;
1884		break;
1885	    }
1886	    /* can't do VLAN over anything but ethernet or ethernet aggregate */
1887	    if (ifnet_type(p) != IFT_ETHER
1888		&& ifnet_type(p) != IFT_IEEE8023ADLAG) {
1889		error = EPROTONOSUPPORT;
1890		break;
1891	    }
1892	    error = vlan_config(ifp, p, vlr.vlr_tag);
1893	    if (error) {
1894		break;
1895	    }
1896
1897	    /* Update promiscuous mode, if necessary. */
1898	    (void)vlan_set_promisc(ifp);
1899
1900	    /* generate a link event based on the state of the parent */
1901	    vlan_link_event(ifp, p);
1902	}
1903	else {
1904	    int		need_link_event = FALSE;
1905
1906	    vlan_lock();
1907	    ifv = (ifvlan_ref)ifnet_softc(ifp);
1908	    if (ifv == NULL || ifvlan_flags_detaching(ifv)) {
1909		vlan_unlock();
1910		error = (ifv == NULL ? EOPNOTSUPP : EBUSY);
1911		break;
1912	    }
1913	    need_link_event = vlan_remove(ifv, TRUE);
1914	    vlan_unlock();
1915	    if (need_link_event) {
1916		interface_link_event(ifp, KEV_DL_LINK_OFF);
1917	    }
1918	}
1919	break;
1920
1921    case SIOCGIFVLAN:
1922	bzero(&vlr, sizeof vlr);
1923	vlan_lock();
1924	ifv = (ifvlan_ref)ifnet_softc(ifp);
1925	if (ifv == NULL || ifvlan_flags_detaching(ifv)) {
1926	    vlan_unlock();
1927	    return (ifv == NULL ? EOPNOTSUPP : EBUSY);
1928	}
1929	p = (ifv->ifv_vlp == NULL) ? NULL : ifv->ifv_vlp->vlp_ifp;
1930	tag = ifv->ifv_tag;
1931	vlan_unlock();
1932	if (p != NULL) {
1933	    snprintf(vlr.vlr_parent, sizeof(vlr.vlr_parent),
1934		     "%s%d", ifnet_name(p), ifnet_unit(p));
1935	    vlr.vlr_tag = tag;
1936	}
1937	user_addr = proc_is64bit(current_proc())
1938	    ? ifr->ifr_data64 : CAST_USER_ADDR_T(ifr->ifr_data);
1939	error = copyout(&vlr, user_addr, sizeof(vlr));
1940	break;
1941
1942    case SIOCSIFFLAGS:
1943	/*
1944	 * For promiscuous mode, we enable promiscuous mode on
1945	 * the parent if we need promiscuous on the VLAN interface.
1946	 */
1947	error = vlan_set_promisc(ifp);
1948	break;
1949
1950    case SIOCADDMULTI:
1951    case SIOCDELMULTI:
1952	error = vlan_setmulti(ifp);
1953	break;
1954    default:
1955	error = EOPNOTSUPP;
1956    }
1957    return error;
1958}
1959
1960static void
1961vlan_if_free(struct ifnet * ifp)
1962{
1963    ifvlan_ref	ifv;
1964
1965    if (ifp == NULL) {
1966	return;
1967    }
1968    ifv = (ifvlan_ref)ifnet_softc(ifp);
1969    if (ifv == NULL) {
1970	return;
1971    }
1972    ifvlan_release(ifv);
1973    ifnet_release(ifp);
1974    return;
1975}
1976
1977static void
1978vlan_event(struct ifnet	* p, __unused protocol_family_t protocol,
1979		   const struct kev_msg * event)
1980{
1981    int			event_code;
1982
1983    /* Check if the interface we are attached to is being detached */
1984    if (event->vendor_code != KEV_VENDOR_APPLE
1985	|| event->kev_class != KEV_NETWORK_CLASS
1986	|| event->kev_subclass != KEV_DL_SUBCLASS) {
1987	return;
1988    }
1989    event_code = event->event_code;
1990    switch (event_code) {
1991    case KEV_DL_LINK_OFF:
1992    case KEV_DL_LINK_ON:
1993	vlan_parent_link_event(p, event_code);
1994	break;
1995    default:
1996	return;
1997    }
1998    return;
1999}
2000
2001static errno_t
2002vlan_detached(ifnet_t p, __unused protocol_family_t protocol)
2003{
2004    if (ifnet_is_attached(p, 0) == 0) {
2005	/* if the parent isn't attached, remove all VLANs */
2006	vlan_parent_remove_all_vlans(p);
2007    }
2008    return (0);
2009}
2010
2011static void
2012interface_link_event(struct ifnet * ifp, u_int32_t event_code)
2013{
2014    struct {
2015	struct kern_event_msg	header;
2016	u_int32_t			unit;
2017	char			if_name[IFNAMSIZ];
2018    } event;
2019
2020    bzero(&event, sizeof(event));
2021    event.header.total_size    = sizeof(event);
2022    event.header.vendor_code   = KEV_VENDOR_APPLE;
2023    event.header.kev_class     = KEV_NETWORK_CLASS;
2024    event.header.kev_subclass  = KEV_DL_SUBCLASS;
2025    event.header.event_code    = event_code;
2026    event.header.event_data[0] = ifnet_family(ifp);
2027    event.unit                 = (u_int32_t) ifnet_unit(ifp);
2028    strncpy(event.if_name, ifnet_name(ifp), IFNAMSIZ);
2029    ifnet_event(ifp, &event.header);
2030    return;
2031}
2032
2033static void
2034vlan_parent_link_event(struct ifnet * p, u_int32_t event_code)
2035{
2036    ifvlan_ref 		ifv;
2037    vlan_parent_ref 	vlp;
2038
2039    vlan_lock();
2040    if ((ifnet_eflags(p) & IFEF_VLAN) == 0) {
2041	vlan_unlock();
2042	/* no VLAN's */
2043	return;
2044    }
2045    vlp = parent_list_lookup(p);
2046    if (vlp == NULL) {
2047	/* no VLAN's */
2048	vlan_unlock();
2049	return;
2050    }
2051
2052    vlan_parent_retain(vlp);
2053    vlan_parent_wait(vlp, "vlan_parent_link_event");
2054    if (vlan_parent_flags_detaching(vlp)) {
2055	goto signal_done;
2056    }
2057
2058    vlan_unlock();
2059
2060    /* vlan_parent_wait() gives us exclusive access to the list */
2061    LIST_FOREACH(ifv, &vlp->vlp_vlan_list, ifv_vlan_list) {
2062	struct ifnet *	ifp = ifv->ifv_ifp;
2063
2064	interface_link_event(ifp, event_code);
2065    }
2066
2067    vlan_lock();
2068
2069 signal_done:
2070    vlan_parent_signal(vlp, "vlan_parent_link_event");
2071    vlan_unlock();
2072    vlan_parent_release(vlp);
2073    return;
2074
2075}
2076
2077/*
2078 * Function: vlan_attach_protocol
2079 * Purpose:
2080 *   Attach a DLIL protocol to the interface, using the ETHERTYPE_VLAN
2081 *   demux ether type.
2082 *
2083 *	 The ethernet demux actually special cases VLAN to support hardware.
2084 *	 The demux here isn't used. The demux will return PF_VLAN for the
2085 *	 appropriate packets and our vlan_input function will be called.
2086 */
2087static int
2088vlan_attach_protocol(struct ifnet *ifp)
2089{
2090    int								error;
2091    struct ifnet_attach_proto_param	reg;
2092
2093    bzero(&reg, sizeof(reg));
2094    reg.input            = vlan_input;
2095    reg.event            = vlan_event;
2096    reg.detached         = vlan_detached;
2097    error = ifnet_attach_protocol(ifp, PF_VLAN, &reg);
2098    if (error) {
2099	printf("vlan_proto_attach(%s%d) ifnet_attach_protocol failed, %d\n",
2100	       ifnet_name(ifp), ifnet_unit(ifp), error);
2101    }
2102    return (error);
2103}
2104
2105/*
2106 * Function: vlan_detach_protocol
2107 * Purpose:
2108 *   Detach our DLIL protocol from an interface
2109 */
2110static int
2111vlan_detach_protocol(struct ifnet *ifp)
2112{
2113    int         error;
2114
2115    error = ifnet_detach_protocol(ifp, PF_VLAN);
2116    if (error) {
2117	printf("vlan_proto_detach(%s%d) ifnet_detach_protocol failed, %d\n",
2118	       ifnet_name(ifp), ifnet_unit(ifp), error);
2119    }
2120
2121    return (error);
2122}
2123
2124/*
2125 * DLIL interface family functions
2126 *   We use the ethernet plumb functions, since that's all we support.
2127 *   If we wanted to handle multiple LAN types (tokenring, etc.), we'd
2128 *   call the appropriate routines for that LAN type instead of hard-coding
2129 *   ethernet.
2130 */
2131static errno_t
2132vlan_attach_inet(struct ifnet *ifp, protocol_family_t protocol_family)
2133{
2134    return (ether_attach_inet(ifp, protocol_family));
2135}
2136
2137static void
2138vlan_detach_inet(struct ifnet *ifp, protocol_family_t protocol_family)
2139{
2140    ether_detach_inet(ifp, protocol_family);
2141}
2142
2143#if INET6
2144static errno_t
2145vlan_attach_inet6(struct ifnet *ifp, protocol_family_t protocol_family)
2146{
2147    return (ether_attach_inet6(ifp, protocol_family));
2148}
2149
2150static void
2151vlan_detach_inet6(struct ifnet *ifp, protocol_family_t protocol_family)
2152{
2153    ether_detach_inet6(ifp, protocol_family);
2154}
2155#endif /* INET6 */
2156
2157#if NETAT
2158static errno_t
2159vlan_attach_at(struct ifnet *ifp, protocol_family_t protocol_family)
2160{
2161    return (ether_attach_at(ifp, protocol_family));
2162}
2163
2164static void
2165vlan_detach_at(struct ifnet *ifp, protocol_family_t protocol_family)
2166{
2167    ether_detach_at(ifp, protocol_family);
2168}
2169#endif /* NETAT */
2170
2171__private_extern__ int
2172vlan_family_init(void)
2173{
2174    int error=0;
2175
2176    error = proto_register_plumber(PF_INET, IFNET_FAMILY_VLAN,
2177				   vlan_attach_inet, vlan_detach_inet);
2178    if (error != 0) {
2179	printf("proto_register_plumber failed for AF_INET error=%d\n",
2180	       error);
2181	goto done;
2182    }
2183#if INET6
2184    error = proto_register_plumber(PF_INET6, IFNET_FAMILY_VLAN,
2185				   vlan_attach_inet6, vlan_detach_inet6);
2186    if (error != 0) {
2187	printf("proto_register_plumber failed for AF_INET6 error=%d\n",
2188	       error);
2189	goto done;
2190    }
2191#endif
2192#if NETAT
2193    error = proto_register_plumber(PF_APPLETALK, IFNET_FAMILY_VLAN,
2194				  vlan_attach_at, vlan_detach_at);
2195    if (error != 0) {
2196	printf("proto_register_plumber failed for AF_APPLETALK error=%d\n",
2197	       error);
2198	goto done;
2199    }
2200#endif /* NETAT */
2201    error = vlan_clone_attach();
2202    if (error != 0) {
2203        printf("proto_register_plumber failed vlan_clone_attach error=%d\n",
2204               error);
2205        goto done;
2206    }
2207
2208
2209 done:
2210    return (error);
2211}
2212