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(®, 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, ®);
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