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