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