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