]> git.saurik.com Git - apple/xnu.git/blob - bsd/net/if_vlan.c
a9d91c0555a08a532b758e2b63f8465a4b13ea97
[apple/xnu.git] / bsd / net / if_vlan.c
1 /*
2 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22 /*
23 * Copyright 1998 Massachusetts Institute of Technology
24 *
25 * Permission to use, copy, modify, and distribute this software and
26 * its documentation for any purpose and without fee is hereby
27 * granted, provided that both the above copyright notice and this
28 * permission notice appear in all copies, that both the above
29 * copyright notice and this permission notice appear in all
30 * supporting documentation, and that the name of M.I.T. not be used
31 * in advertising or publicity pertaining to distribution of the
32 * software without specific, written prior permission. M.I.T. makes
33 * no representations about the suitability of this software for any
34 * purpose. It is provided "as is" without express or implied
35 * warranty.
36 *
37 * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
38 * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
39 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
40 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
41 * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48 * SUCH DAMAGE.
49 *
50 * $FreeBSD: src/sys/net/if_vlan.c,v 1.54 2003/10/31 18:32:08 brooks Exp $
51 */
52
53 /*
54 * if_vlan.c - pseudo-device driver for IEEE 802.1Q virtual LANs.
55 * Might be extended some day to also handle IEEE 802.1p priority
56 * tagging. This is sort of sneaky in the implementation, since
57 * we need to pretend to be enough of an Ethernet implementation
58 * to make arp work. The way we do this is by telling everyone
59 * that we are an Ethernet, and then catch the packets that
60 * ether_output() left on our output queue when it calls
61 * if_start(), rewrite them for use by the real outgoing interface,
62 * and ask it to send them.
63 */
64
65
66 #include <sys/param.h>
67 #include <sys/kernel.h>
68 #include <sys/malloc.h>
69 #include <sys/mbuf.h>
70 #include <sys/queue.h>
71 #include <sys/socket.h>
72 #include <sys/sockio.h>
73 #include <sys/sysctl.h>
74 #include <sys/systm.h>
75 #include <sys/kern_event.h>
76
77 #include <net/bpf.h>
78 #include <net/ethernet.h>
79 #include <net/if.h>
80 #include <net/if_arp.h>
81 #include <net/if_dl.h>
82 #include <net/if_ether.h>
83 #include <net/if_types.h>
84 #include <net/if_vlan_var.h>
85 #include <libkern/OSAtomic.h>
86
87 #include <net/dlil.h>
88
89 #include <kern/locks.h>
90
91 #ifdef INET
92 #include <netinet/in.h>
93 #include <netinet/if_ether.h>
94 #endif
95
96 #include <net/if_media.h>
97 #include <net/multicast_list.h>
98
99 #define IF_MAXUNIT 0x7fff /* historical value */
100
101 #define VLANNAME "vlan"
102
103 typedef int (bpf_callback_func)(struct ifnet *, struct mbuf *);
104 typedef int (if_set_bpf_tap_func)(struct ifnet *ifp, int mode, bpf_callback_func * func);
105
106 /**
107 ** vlan locks
108 **/
109 static __inline__ lck_grp_t *
110 my_lck_grp_alloc_init(const char * grp_name)
111 {
112 lck_grp_t * grp;
113 lck_grp_attr_t * grp_attrs;
114
115 grp_attrs = lck_grp_attr_alloc_init();
116 grp = lck_grp_alloc_init(grp_name, grp_attrs);
117 lck_grp_attr_free(grp_attrs);
118 return (grp);
119 }
120
121 static __inline__ lck_mtx_t *
122 my_lck_mtx_alloc_init(lck_grp_t * lck_grp)
123 {
124 lck_attr_t * lck_attrs;
125 lck_mtx_t * lck_mtx;
126
127 lck_attrs = lck_attr_alloc_init();
128 lck_mtx = lck_mtx_alloc_init(lck_grp, lck_attrs);
129 lck_attr_free(lck_attrs);
130 return (lck_mtx);
131 }
132
133 static lck_mtx_t * vlan_lck_mtx;
134
135 static __inline__ void
136 vlan_lock_init(void)
137 {
138 lck_grp_t * vlan_lck_grp;
139
140 vlan_lck_grp = my_lck_grp_alloc_init("if_vlan");
141 vlan_lck_mtx = my_lck_mtx_alloc_init(vlan_lck_grp);
142 }
143
144 static __inline__ void
145 vlan_assert_lock_held(void)
146 {
147 lck_mtx_assert(vlan_lck_mtx, LCK_MTX_ASSERT_OWNED);
148 return;
149 }
150
151 static __inline__ void
152 vlan_assert_lock_not_held(void)
153 {
154 lck_mtx_assert(vlan_lck_mtx, LCK_MTX_ASSERT_NOTOWNED);
155 return;
156 }
157
158 static __inline__ void
159 vlan_lock(void)
160 {
161 lck_mtx_lock(vlan_lck_mtx);
162 return;
163 }
164
165 static __inline__ void
166 vlan_unlock(void)
167 {
168 lck_mtx_unlock(vlan_lck_mtx);
169 return;
170 }
171
172 /**
173 ** vlan structures, types
174 **/
175 struct vlan_parent;
176 LIST_HEAD(vlan_parent_list, vlan_parent);
177 struct ifvlan;
178 LIST_HEAD(ifvlan_list, ifvlan);
179
180 typedef struct vlan_parent {
181 LIST_ENTRY(vlan_parent) vlp_parent_list;/* list of parents */
182 struct ifnet * vlp_ifp; /* interface */
183 struct ifvlan_list vlp_vlan_list; /* list of VLAN's */
184 #define VLPF_SUPPORTS_VLAN_MTU 0x1
185 #define VLPF_CHANGE_IN_PROGRESS 0x2
186 #define VLPF_DETACHING 0x4
187 u_int32_t vlp_flags;
188 struct ifdevmtu vlp_devmtu;
189 UInt32 vlp_retain_count;
190 } vlan_parent, * vlan_parent_ref;
191
192 struct ifvlan {
193 LIST_ENTRY(ifvlan) ifv_vlan_list;
194 char ifv_name[IFNAMSIZ]; /* our unique id */
195 struct ifnet * ifv_ifp; /* our interface */
196 vlan_parent_ref ifv_vlp; /* parent information */
197 struct ifv_linkmib {
198 u_int16_t ifvm_encaplen;/* encapsulation length */
199 u_int16_t ifvm_mtufudge;/* MTU fudged by this much */
200 u_int16_t ifvm_proto; /* encapsulation ethertype */
201 u_int16_t ifvm_tag; /* tag to apply on packets leaving if */
202 } ifv_mib;
203 struct multicast_list ifv_multicast;
204 #define IFVF_PROMISC 0x1 /* promiscuous mode enabled */
205 #define IFVF_DETACHING 0x2 /* interface is detaching */
206 #define IFVF_READY 0x4 /* interface is ready */
207 u_int32_t ifv_flags;
208 bpf_packet_func ifv_bpf_input;
209 bpf_packet_func ifv_bpf_output;
210 };
211
212 typedef struct ifvlan * ifvlan_ref;
213
214 typedef struct vlan_globals_s {
215 struct vlan_parent_list parent_list;
216 int verbose;
217 } * vlan_globals_ref;
218
219 static vlan_globals_ref g_vlan;
220
221 #define ifv_tag ifv_mib.ifvm_tag
222 #define ifv_encaplen ifv_mib.ifvm_encaplen
223 #define ifv_mtufudge ifv_mib.ifvm_mtufudge
224
225
226 /**
227 ** vlan_parent_ref vlp_flags in-lines
228 **/
229 static __inline__ int
230 vlan_parent_flags_supports_vlan_mtu(vlan_parent_ref vlp)
231 {
232 return ((vlp->vlp_flags & VLPF_SUPPORTS_VLAN_MTU) != 0);
233 }
234
235 static __inline__ void
236 vlan_parent_flags_set_supports_vlan_mtu(vlan_parent_ref vlp)
237 {
238 vlp->vlp_flags |= VLPF_SUPPORTS_VLAN_MTU;
239 return;
240 }
241
242 static __inline__ void
243 vlan_parent_flags_clear_supports_vlan_mtu(vlan_parent_ref vlp)
244 {
245 vlp->vlp_flags &= ~VLPF_SUPPORTS_VLAN_MTU;
246 return;
247 }
248
249 static __inline__ int
250 vlan_parent_flags_change_in_progress(vlan_parent_ref vlp)
251 {
252 return ((vlp->vlp_flags & VLPF_CHANGE_IN_PROGRESS) != 0);
253 }
254
255 static __inline__ void
256 vlan_parent_flags_set_change_in_progress(vlan_parent_ref vlp)
257 {
258 vlp->vlp_flags |= VLPF_CHANGE_IN_PROGRESS;
259 return;
260 }
261
262 static __inline__ void
263 vlan_parent_flags_clear_change_in_progress(vlan_parent_ref vlp)
264 {
265 vlp->vlp_flags &= ~VLPF_CHANGE_IN_PROGRESS;
266 return;
267 }
268
269 static __inline__ int
270 vlan_parent_flags_detaching(struct vlan_parent * vlp)
271 {
272 return ((vlp->vlp_flags & VLPF_DETACHING) != 0);
273 }
274
275 static __inline__ void
276 vlan_parent_flags_set_detaching(struct vlan_parent * vlp)
277 {
278 vlp->vlp_flags |= VLPF_DETACHING;
279 return;
280 }
281
282
283 /**
284 ** ifvlan_flags in-lines routines
285 **/
286 static __inline__ int
287 ifvlan_flags_promisc(ifvlan_ref ifv)
288 {
289 return ((ifv->ifv_flags & IFVF_PROMISC) != 0);
290 }
291
292 static __inline__ void
293 ifvlan_flags_set_promisc(ifvlan_ref ifv)
294 {
295 ifv->ifv_flags |= IFVF_PROMISC;
296 return;
297 }
298
299 static __inline__ void
300 ifvlan_flags_clear_promisc(ifvlan_ref ifv)
301 {
302 ifv->ifv_flags &= ~IFVF_PROMISC;
303 return;
304 }
305
306 static __inline__ int
307 ifvlan_flags_ready(ifvlan_ref ifv)
308 {
309 return ((ifv->ifv_flags & IFVF_READY) != 0);
310 }
311
312 static __inline__ void
313 ifvlan_flags_set_ready(ifvlan_ref ifv)
314 {
315 ifv->ifv_flags |= IFVF_READY;
316 return;
317 }
318
319 static __inline__ void
320 ifvlan_flags_clear_ready(ifvlan_ref ifv)
321 {
322 ifv->ifv_flags &= ~IFVF_READY;
323 return;
324 }
325
326 static __inline__ int
327 ifvlan_flags_detaching(ifvlan_ref ifv)
328 {
329 return ((ifv->ifv_flags & IFVF_DETACHING) != 0);
330 }
331
332 static __inline__ void
333 ifvlan_flags_set_detaching(ifvlan_ref ifv)
334 {
335 ifv->ifv_flags |= IFVF_DETACHING;
336 return;
337 }
338
339 #if 0
340 SYSCTL_DECL(_net_link);
341 SYSCTL_NODE(_net_link, IFT_L2VLAN, vlan, CTLFLAG_RW, 0, "IEEE 802.1Q VLAN");
342 SYSCTL_NODE(_net_link_vlan, PF_LINK, link, CTLFLAG_RW, 0, "for consistency");
343 #endif 0
344
345 #define M_VLAN M_DEVBUF
346
347 static int vlan_clone_create(struct if_clone *, int);
348 static void vlan_clone_destroy(struct ifnet *);
349 static int vlan_input(struct mbuf *m, char *frame_header, struct ifnet *ifp,
350 u_long protocol_family, int sync_ok);
351 static int vlan_output(struct ifnet *ifp, struct mbuf *m);
352 static int vlan_ioctl(ifnet_t ifp, u_int32_t cmd, void * addr);
353 static int vlan_set_bpf_tap(ifnet_t ifp, bpf_tap_mode mode,
354 bpf_packet_func func);
355 static int vlan_attach_protocol(struct ifnet *ifp);
356 static int vlan_detach_protocol(struct ifnet *ifp);
357 static int vlan_setmulti(struct ifnet *ifp);
358 static int vlan_unconfig(struct ifnet *ifp);
359 static int vlan_config(struct ifnet * ifp, struct ifnet * p, int tag);
360 static void vlan_if_free(struct ifnet * ifp);
361 static void vlan_remove(ifvlan_ref ifv);
362 static void vlan_if_detach(struct ifnet * ifp);
363 static int vlan_new_mtu(struct ifnet * ifp, int mtu);
364
365 static struct if_clone vlan_cloner = IF_CLONE_INITIALIZER(VLANNAME,
366 vlan_clone_create,
367 vlan_clone_destroy,
368 0,
369 IF_MAXUNIT);
370 static void interface_link_event(struct ifnet * ifp, u_long event_code);
371 static void vlan_parent_link_event(vlan_parent_ref vlp,
372 u_long event_code);
373 extern int dlil_input_packet(struct ifnet *ifp, struct mbuf *m, char *frame_header);
374
375 static int
376 vlan_globals_init(void)
377 {
378 vlan_globals_ref v;
379
380 vlan_assert_lock_not_held();
381
382 if (g_vlan != NULL) {
383 return (0);
384 }
385 v = _MALLOC(sizeof(*v), M_VLAN, M_WAITOK);
386 if (v != NULL) {
387 LIST_INIT(&v->parent_list);
388 v->verbose = 0;
389 }
390 vlan_lock();
391 if (g_vlan != NULL) {
392 vlan_unlock();
393 if (v != NULL) {
394 _FREE(v, M_VLAN);
395 }
396 return (0);
397 }
398 g_vlan = v;
399 vlan_unlock();
400 if (v == NULL) {
401 return (ENOMEM);
402 }
403 return (0);
404 }
405
406 static int
407 siocgifdevmtu(struct ifnet * ifp, struct ifdevmtu * ifdm_p)
408 {
409 struct ifreq ifr;
410 int error;
411
412 bzero(&ifr, sizeof(ifr));
413 error = dlil_ioctl(0, ifp, SIOCGIFDEVMTU, (caddr_t)&ifr);
414 if (error == 0) {
415 *ifdm_p = ifr.ifr_devmtu;
416 }
417 return (error);
418 }
419
420 static int
421 siocsifaltmtu(struct ifnet * ifp, int mtu)
422 {
423 struct ifreq ifr;
424
425 bzero(&ifr, sizeof(ifr));
426 ifr.ifr_mtu = mtu;
427 return (dlil_ioctl(0, ifp, SIOCSIFALTMTU, (caddr_t)&ifr));
428 }
429
430 static __inline__ void
431 vlan_bpf_output(struct ifnet * ifp, struct mbuf * m,
432 bpf_packet_func func)
433 {
434 if (func != NULL) {
435 (*func)(ifp, m);
436 }
437 return;
438 }
439
440 static __inline__ void
441 vlan_bpf_input(struct ifnet * ifp, struct mbuf * m,
442 bpf_packet_func func, char * frame_header,
443 int frame_header_len, int encap_len)
444 {
445 if (func != NULL) {
446 if (encap_len > 0) {
447 /* present the right header to bpf */
448 bcopy(frame_header, frame_header + encap_len, frame_header_len);
449 }
450 m->m_data -= frame_header_len;
451 m->m_len += frame_header_len;
452 (*func)(ifp, m);
453 m->m_data += frame_header_len;
454 m->m_len -= frame_header_len;
455 if (encap_len > 0) {
456 /* restore the header */
457 bcopy(frame_header + encap_len, frame_header, frame_header_len);
458 }
459 }
460 return;
461 }
462
463 static struct ifaddr *
464 ifaddr_byindex(int i)
465 {
466 if (i > if_index || i == 0) {
467 return (NULL);
468 }
469 return (ifnet_addrs[i - 1]);
470 }
471
472 /**
473 ** vlan_parent synchronization routines
474 **/
475 static __inline__ void
476 vlan_parent_retain(vlan_parent_ref vlp)
477 {
478 OSIncrementAtomic(&vlp->vlp_retain_count);
479 }
480
481 static __inline__ void
482 vlan_parent_release(vlan_parent_ref vlp)
483 {
484 UInt32 old_retain_count;
485
486 old_retain_count = OSDecrementAtomic(&vlp->vlp_retain_count);
487 switch (old_retain_count) {
488 case 0:
489 panic("vlan_parent_release: retain count is 0\n");
490 break;
491 case 1:
492 if (g_vlan->verbose) {
493 struct ifnet * ifp = vlp->vlp_ifp;
494 printf("vlan_parent_release(%s%d)\n", ifp->if_name,
495 ifp->if_unit);
496 }
497 FREE(vlp, M_VLAN);
498 break;
499 default:
500 break;
501 }
502 return;
503 }
504
505 /*
506 * Function: vlan_parent_wait
507 * Purpose:
508 * Allows a single thread to gain exclusive access to the vlan_parent
509 * data structure. Some operations take a long time to complete,
510 * and some have side-effects that we can't predict. Holding the
511 * vlan_lock() across such operations is not possible.
512 *
513 * Notes:
514 * Before calling, you must be holding the vlan_lock and have taken
515 * a reference on the vlan_parent_ref.
516 */
517 static void
518 vlan_parent_wait(vlan_parent_ref vlp, const char * msg)
519 {
520 int waited = 0;
521
522 /* other add/remove/multicast-change in progress */
523 while (vlan_parent_flags_change_in_progress(vlp)) {
524 if (g_vlan->verbose) {
525 struct ifnet * ifp = vlp->vlp_ifp;
526
527 printf("%s%d: %s msleep\n", ifp->if_name, ifp->if_unit, msg);
528 }
529 waited = 1;
530 (void)msleep(vlp, vlan_lck_mtx, PZERO, msg, 0);
531 }
532 /* prevent other vlan parent remove/add from taking place */
533 vlan_parent_flags_set_change_in_progress(vlp);
534 if (g_vlan->verbose && waited) {
535 struct ifnet * ifp = vlp->vlp_ifp;
536
537 printf("%s: %s woke up\n", ifp->if_name, ifp->if_unit, msg);
538 }
539 return;
540 }
541
542 /*
543 * Function: vlan_parent_signal
544 * Purpose:
545 * Allows the thread that previously invoked vlan_parent_wait() to
546 * give up exclusive access to the vlan_parent data structure, and wake up
547 * any other threads waiting to access
548 * Notes:
549 * Before calling, you must be holding the vlan_lock and have taken
550 * a reference on the vlan_parent_ref.
551 */
552 static void
553 vlan_parent_signal(vlan_parent_ref vlp, const char * msg)
554 {
555 vlan_parent_flags_clear_change_in_progress(vlp);
556 wakeup((caddr_t)vlp);
557 if (g_vlan->verbose) {
558 struct ifnet * ifp = vlp->vlp_ifp;
559
560 printf("%s%d: %s wakeup\n", ifp->if_name, ifp->if_unit, msg);
561 }
562 return;
563 }
564
565
566 /*
567 * Program our multicast filter. What we're actually doing is
568 * programming the multicast filter of the parent. This has the
569 * side effect of causing the parent interface to receive multicast
570 * traffic that it doesn't really want, which ends up being discarded
571 * later by the upper protocol layers. Unfortunately, there's no way
572 * to avoid this: there really is only one physical interface.
573 */
574 static int
575 vlan_setmulti(struct ifnet * ifp)
576 {
577 int error = 0;
578 ifvlan_ref ifv;
579 struct ifnet * p;
580 vlan_parent_ref vlp;
581
582 vlan_lock();
583 ifv = (ifvlan_ref)ifp->if_private;
584 if (ifv == NULL || ifvlan_flags_detaching(ifv)) {
585 goto unlock_done;
586 }
587 vlp = ifv->ifv_vlp;
588 if (vlp == NULL) {
589 /* no parent, no need to program the multicast filter */
590 goto unlock_done;
591 }
592 if (vlan_parent_flags_detaching(vlp)) {
593 goto unlock_done;
594 }
595 vlan_parent_retain(vlp);
596 vlan_parent_wait(vlp, "vlan_setmulti");
597
598 /* check again, things could have changed */
599 ifv = (ifvlan_ref)ifp->if_private;
600 if (ifv == NULL || ifvlan_flags_detaching(ifv)) {
601 goto signal_done;
602 }
603 if (ifv->ifv_vlp != vlp) {
604 /* vlan parent changed */
605 goto signal_done;
606 }
607 if (vlp == NULL) {
608 /* no parent, no need to program the multicast filter */
609 goto signal_done;
610 }
611 p = vlp->vlp_ifp;
612 vlan_unlock();
613
614 /* update parent interface with our multicast addresses */
615 error = multicast_list_program(&ifv->ifv_multicast, ifp, p);
616
617 vlan_lock();
618
619 signal_done:
620 vlan_parent_signal(vlp, "vlan_setmulti");
621
622 unlock_done:
623 vlan_unlock();
624 return (error);
625 }
626
627 /**
628 ** vlan_parent list manipulation/lookup routines
629 **/
630 static vlan_parent_ref
631 parent_list_lookup(struct ifnet * p)
632 {
633 vlan_parent_ref vlp;
634
635 LIST_FOREACH(vlp, &g_vlan->parent_list, vlp_parent_list) {
636 if (vlp->vlp_ifp == p) {
637 return (vlp);
638 }
639 }
640 return (NULL);
641 }
642
643 static ifvlan_ref
644 vlan_parent_lookup_tag(vlan_parent_ref vlp, int tag)
645 {
646 ifvlan_ref ifv;
647
648 LIST_FOREACH(ifv, &vlp->vlp_vlan_list, ifv_vlan_list) {
649 if (tag == ifv->ifv_tag) {
650 return (ifv);
651 }
652 }
653 return (NULL);
654 }
655
656 static ifvlan_ref
657 vlan_lookup_parent_and_tag(struct ifnet * p, int tag)
658 {
659 vlan_parent_ref vlp;
660
661 vlp = parent_list_lookup(p);
662 if (vlp != NULL) {
663 return (vlan_parent_lookup_tag(vlp, tag));
664 }
665 return (NULL);
666 }
667
668 static int
669 vlan_parent_find_max_mtu(vlan_parent_ref vlp, ifvlan_ref exclude_ifv)
670 {
671 int max_mtu = 0;
672 ifvlan_ref ifv;
673
674 LIST_FOREACH(ifv, &vlp->vlp_vlan_list, ifv_vlan_list) {
675 int req_mtu;
676
677 if (exclude_ifv == ifv) {
678 continue;
679 }
680 req_mtu = ifv->ifv_ifp->if_mtu + ifv->ifv_mtufudge;
681 if (req_mtu > max_mtu) {
682 max_mtu = req_mtu;
683 }
684 }
685 return (max_mtu);
686 }
687
688 /*
689 * Function: vlan_parent_create
690 * Purpose:
691 * Create a vlan_parent structure to hold the VLAN's for the given
692 * interface. Add it to the list of VLAN parents.
693 */
694 static int
695 vlan_parent_create(struct ifnet * p, vlan_parent_ref * ret_vlp)
696 {
697 int error;
698 vlan_parent_ref vlp;
699
700 *ret_vlp = NULL;
701 vlp = _MALLOC(sizeof(*vlp), M_VLAN, M_WAITOK);
702 if (vlp == NULL) {
703 return (ENOMEM);
704 }
705 bzero(vlp, sizeof(*vlp));
706 error = siocgifdevmtu(p, &vlp->vlp_devmtu);
707 if (error != 0) {
708 printf("vlan_parent_create (%s%d): siocgifdevmtu failed, %d\n",
709 p->if_name, p->if_unit, error);
710 FREE(vlp, M_VLAN);
711 return (error);
712 }
713 LIST_INIT(&vlp->vlp_vlan_list);
714 vlp->vlp_ifp = p;
715 vlan_parent_retain(vlp);
716 if (p->if_hwassist
717 & (IF_HWASSIST_VLAN_MTU | IF_HWASSIST_VLAN_TAGGING)) {
718 vlan_parent_flags_set_supports_vlan_mtu(vlp);
719 }
720 *ret_vlp = vlp;
721 return (0);
722 }
723
724 static void
725 vlan_parent_remove_all_vlans(vlan_parent_ref vlp)
726 {
727 ifvlan_ref ifv;
728 struct ifnet * p;
729
730 vlan_assert_lock_held();
731
732 while ((ifv = LIST_FIRST(&vlp->vlp_vlan_list)) != NULL) {
733 vlan_remove(ifv);
734 vlan_unlock();
735 vlan_if_detach(ifv->ifv_ifp);
736 vlan_lock();
737 }
738
739 /* the vlan parent has no more VLAN's */
740 p = vlp->vlp_ifp;
741 ifnet_lock_exclusive(p);
742 p->if_eflags &= ~IFEF_VLAN;
743 ifnet_lock_done(p);
744 LIST_REMOVE(vlp, vlp_parent_list);
745 vlan_unlock();
746 vlan_parent_release(vlp);
747 vlan_lock();
748
749 return;
750 }
751
752 static __inline__ int
753 vlan_parent_no_vlans(vlan_parent_ref vlp)
754 {
755 return (LIST_EMPTY(&vlp->vlp_vlan_list));
756 }
757
758 static void
759 vlan_parent_add_vlan(vlan_parent_ref vlp, ifvlan_ref ifv, int tag)
760 {
761 LIST_INSERT_HEAD(&vlp->vlp_vlan_list, ifv, ifv_vlan_list);
762 ifv->ifv_vlp = vlp;
763 ifv->ifv_tag = tag;
764 return;
765 }
766
767 static void
768 vlan_parent_remove_vlan(__unused vlan_parent_ref vlp, ifvlan_ref ifv)
769 {
770 ifv->ifv_vlp = NULL;
771 LIST_REMOVE(ifv, ifv_vlan_list);
772 return;
773 }
774
775 static void
776 vlan_clone_attach(void)
777 {
778 if_clone_attach(&vlan_cloner);
779 vlan_lock_init();
780 return;
781 }
782
783 static int
784 vlan_clone_create(struct if_clone *ifc, int unit)
785 {
786 int error;
787 ifvlan_ref ifv;
788 struct ifnet * ifp;
789
790 error = vlan_globals_init();
791 if (error != 0) {
792 return (error);
793 }
794 ifv = _MALLOC(sizeof(struct ifvlan), M_VLAN, M_WAITOK);
795 bzero(ifv, sizeof(struct ifvlan));
796 multicast_list_init(&ifv->ifv_multicast);
797
798 /* use the interface name as the unique id for ifp recycle */
799 if ((unsigned int)snprintf(ifv->ifv_name, sizeof(ifv->ifv_name), "%s%d",
800 ifc->ifc_name, unit) >= sizeof(ifv->ifv_name)) {
801 FREE(ifv, M_VLAN);
802 return (EINVAL);
803 }
804 error = dlil_if_acquire(APPLE_IF_FAM_VLAN,
805 ifv->ifv_name,
806 strlen(ifv->ifv_name),
807 &ifp);
808 if (error) {
809 FREE(ifv, M_VLAN);
810 return (error);
811 }
812 ifp->if_name = ifc->ifc_name;
813 ifp->if_unit = unit;
814 ifp->if_family = APPLE_IF_FAM_VLAN;
815
816 #if 0
817 /* NB: flags are not set here */
818 ifp->if_linkmib = &ifv->ifv_mib;
819 ifp->if_linkmiblen = sizeof ifv->ifv_mib;
820 /* NB: mtu is not set here */
821 #endif 0
822
823 ifp->if_ioctl = vlan_ioctl;
824 ifp->if_set_bpf_tap = vlan_set_bpf_tap;
825 ifp->if_free = vlan_if_free;
826 ifp->if_output = vlan_output;
827 ifp->if_hwassist = 0;
828 ifp->if_addrlen = ETHER_ADDR_LEN; /* XXX ethernet specific */
829 ifp->if_baudrate = 0;
830 ifp->if_type = IFT_L2VLAN;
831 ifp->if_hdrlen = ETHER_VLAN_ENCAP_LEN;
832
833 /* XXX ethernet specific */
834 ifp->if_broadcast.length = ETHER_ADDR_LEN;
835 bcopy(etherbroadcastaddr, ifp->if_broadcast.u.buffer, ETHER_ADDR_LEN);
836
837 error = dlil_if_attach(ifp);
838 if (error) {
839 dlil_if_release(ifp);
840 FREE(ifv, M_VLAN);
841 return (error);
842 }
843 ifp->if_private = ifv;
844 ifv->ifv_ifp = ifp;
845
846 /* attach as ethernet */
847 bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header));
848 return (0);
849 }
850
851 static void
852 vlan_remove(ifvlan_ref ifv)
853 {
854 vlan_assert_lock_held();
855 ifvlan_flags_set_detaching(ifv);
856 vlan_unconfig(ifv->ifv_ifp);
857 return;
858 }
859
860 static void
861 vlan_if_detach(struct ifnet * ifp)
862 {
863 if (dlil_if_detach(ifp) != DLIL_WAIT_FOR_FREE) {
864 vlan_if_free(ifp);
865 }
866 return;
867 }
868
869 static void
870 vlan_clone_destroy(struct ifnet *ifp)
871 {
872 ifvlan_ref ifv;
873
874 vlan_lock();
875 ifv = ifp->if_private;
876 if (ifv == NULL || ifp->if_type != IFT_L2VLAN) {
877 vlan_unlock();
878 return;
879 }
880 if (ifvlan_flags_detaching(ifv)) {
881 vlan_unlock();
882 return;
883 }
884 vlan_remove(ifv);
885 vlan_unlock();
886 vlan_if_detach(ifp);
887 return;
888 }
889
890 static int
891 vlan_set_bpf_tap(ifnet_t ifp, bpf_tap_mode mode, bpf_packet_func func)
892 {
893 ifvlan_ref ifv;
894
895 vlan_lock();
896 ifv = ifp->if_private;
897 if (ifv == NULL || ifvlan_flags_detaching(ifv)) {
898 vlan_unlock();
899 return (ENODEV);
900 }
901 switch (mode) {
902 case BPF_TAP_DISABLE:
903 ifv->ifv_bpf_input = ifv->ifv_bpf_output = NULL;
904 break;
905
906 case BPF_TAP_INPUT:
907 ifv->ifv_bpf_input = func;
908 break;
909
910 case BPF_TAP_OUTPUT:
911 ifv->ifv_bpf_output = func;
912 break;
913
914 case BPF_TAP_INPUT_OUTPUT:
915 ifv->ifv_bpf_input = ifv->ifv_bpf_output = func;
916 break;
917 default:
918 break;
919 }
920 vlan_unlock();
921 return 0;
922 }
923
924 static int
925 vlan_output(struct ifnet * ifp, struct mbuf * m)
926 {
927 bpf_packet_func bpf_func;
928 struct ether_vlan_header * evl;
929 int encaplen;
930 ifvlan_ref ifv;
931 struct ifnet * p;
932 int soft_vlan;
933 u_short tag;
934 vlan_parent_ref vlp;
935
936 if (m == 0) {
937 return (0);
938 }
939 if ((m->m_flags & M_PKTHDR) == 0) {
940 m_freem_list(m);
941 return (0);
942 }
943 vlan_lock();
944 ifv = (ifvlan_ref)ifp->if_private;
945 if (ifv == NULL || ifvlan_flags_detaching(ifv)
946 || ifvlan_flags_ready(ifv) == 0) {
947 vlan_unlock();
948 m_freem_list(m);
949 return (0);
950 }
951 vlp = ifv->ifv_vlp;
952 if (vlp == NULL) {
953 vlan_unlock();
954 m_freem_list(m);
955 return (0);
956 }
957 p = vlp->vlp_ifp;
958 (void)ifnet_stat_increment_out(ifp, 1, m->m_pkthdr.len, 0);
959 soft_vlan = (p->if_hwassist & IF_HWASSIST_VLAN_TAGGING) == 0;
960 bpf_func = ifv->ifv_bpf_output;
961 tag = ifv->ifv_tag;
962 encaplen = ifv->ifv_encaplen;
963 vlan_unlock();
964 vlan_bpf_output(ifp, m, bpf_func);
965
966 /* do not run parent's if_output() if the parent is not up */
967 if ((p->if_flags & (IFF_UP | IFF_RUNNING)) != (IFF_UP | IFF_RUNNING)) {
968 m_freem(m);
969 ifp->if_collisions++;
970 return (0);
971 }
972 /*
973 * If underlying interface can do VLAN tag insertion itself,
974 * just pass the packet along. However, we need some way to
975 * tell the interface where the packet came from so that it
976 * knows how to find the VLAN tag to use. We use a field in
977 * the mbuf header to store the VLAN tag, and a bit in the
978 * csum_flags field to mark the field as valid.
979 */
980 if (soft_vlan == 0) {
981 m->m_pkthdr.csum_flags |= CSUM_VLAN_TAG_VALID;
982 m->m_pkthdr.vlan_tag = tag;
983 } else {
984 M_PREPEND(m, encaplen, M_DONTWAIT);
985 if (m == NULL) {
986 printf("%s%d: unable to prepend VLAN header\n", ifp->if_name,
987 ifp->if_unit);
988 ifp->if_oerrors++;
989 return (0);
990 }
991 /* M_PREPEND takes care of m_len, m_pkthdr.len for us */
992 if (m->m_len < (int)sizeof(*evl)) {
993 m = m_pullup(m, sizeof(*evl));
994 if (m == NULL) {
995 printf("%s%d: unable to pullup VLAN header\n", ifp->if_name,
996 ifp->if_unit);
997 ifp->if_oerrors++;
998 return (0);
999 }
1000 }
1001
1002 /*
1003 * Transform the Ethernet header into an Ethernet header
1004 * with 802.1Q encapsulation.
1005 */
1006 bcopy(mtod(m, char *) + encaplen,
1007 mtod(m, char *), ETHER_HDR_LEN);
1008 evl = mtod(m, struct ether_vlan_header *);
1009 evl->evl_proto = evl->evl_encap_proto;
1010 evl->evl_encap_proto = htons(ETHERTYPE_VLAN);
1011 evl->evl_tag = htons(tag);
1012 }
1013 return dlil_output(p, 0, m, NULL, NULL, 1);
1014 }
1015
1016 static int
1017 vlan_input(struct mbuf * m, char * frame_header, struct ifnet * p,
1018 __unused u_long protocol_family, __unused int sync_ok)
1019 {
1020 bpf_packet_func bpf_func = NULL;
1021 struct ether_vlan_header * evl;
1022 struct ifnet * ifp = NULL;
1023 int soft_vlan = 0;
1024 u_int tag = 0;
1025
1026 if (m->m_pkthdr.csum_flags & CSUM_VLAN_TAG_VALID) {
1027 /*
1028 * Packet is tagged, m contains a normal
1029 * Ethernet frame; the tag is stored out-of-band.
1030 */
1031 m->m_pkthdr.csum_flags &= ~CSUM_VLAN_TAG_VALID;
1032 tag = EVL_VLANOFTAG(m->m_pkthdr.vlan_tag);
1033 m->m_pkthdr.vlan_tag = 0;
1034 } else {
1035 soft_vlan = 1;
1036 switch (p->if_type) {
1037 case IFT_ETHER:
1038 if (m->m_len < ETHER_VLAN_ENCAP_LEN) {
1039 m_freem(m);
1040 return 0;
1041 }
1042 evl = (struct ether_vlan_header *)frame_header;
1043 if (ntohs(evl->evl_proto) == ETHERTYPE_VLAN) {
1044 /* don't allow VLAN within VLAN */
1045 m_freem(m);
1046 return (0);
1047 }
1048 tag = EVL_VLANOFTAG(ntohs(evl->evl_tag));
1049
1050 /*
1051 * Restore the original ethertype. We'll remove
1052 * the encapsulation after we've found the vlan
1053 * interface corresponding to the tag.
1054 */
1055 evl->evl_encap_proto = evl->evl_proto;
1056 break;
1057 default:
1058 printf("vlan_demux: unsupported if type %u",
1059 p->if_type);
1060 m_freem(m);
1061 return 0;
1062 break;
1063 }
1064 }
1065 if (tag != 0) {
1066 ifvlan_ref ifv;
1067
1068 if ((p->if_eflags & IFEF_VLAN) == 0) {
1069 /* don't bother looking through the VLAN list */
1070 m_freem(m);
1071 return 0;
1072 }
1073 vlan_lock();
1074 ifv = vlan_lookup_parent_and_tag(p, tag);
1075 if (ifv != NULL) {
1076 ifp = ifv->ifv_ifp;
1077 }
1078 if (ifv == NULL
1079 || ifvlan_flags_ready(ifv) == 0
1080 || (ifp->if_flags & IFF_UP) == 0) {
1081 vlan_unlock();
1082 m_freem(m);
1083 return 0;
1084 }
1085 bpf_func = ifv->ifv_bpf_input;
1086 vlan_unlock();
1087 }
1088 if (soft_vlan) {
1089 /*
1090 * Packet had an in-line encapsulation header;
1091 * remove it. The original header has already
1092 * been fixed up above.
1093 */
1094 m->m_len -= ETHER_VLAN_ENCAP_LEN;
1095 m->m_data += ETHER_VLAN_ENCAP_LEN;
1096 m->m_pkthdr.len -= ETHER_VLAN_ENCAP_LEN;
1097 m->m_pkthdr.csum_flags = 0; /* can't trust hardware checksum */
1098 }
1099 if (tag != 0) {
1100 m->m_pkthdr.rcvif = ifp;
1101 (void)ifnet_stat_increment_in(ifp, 1,
1102 m->m_pkthdr.len + ETHER_HDR_LEN, 0);
1103 vlan_bpf_input(ifp, m, bpf_func, frame_header, ETHER_HDR_LEN,
1104 soft_vlan ? ETHER_VLAN_ENCAP_LEN : 0);
1105 /* We found a vlan interface, inject on that interface. */
1106 dlil_input_packet(ifp, m, frame_header);
1107 } else {
1108 /* Send priority-tagged packet up through the parent */
1109 dlil_input_packet(p, m, frame_header);
1110 }
1111 return 0;
1112 }
1113
1114 #define VLAN_CONFIG_PROGRESS_VLP_RETAINED 0x1
1115 #define VLAN_CONFIG_PROGRESS_IN_LIST 0x2
1116
1117 static int
1118 vlan_config(struct ifnet * ifp, struct ifnet * p, int tag)
1119 {
1120 int error;
1121 int first_vlan = 0;
1122 ifvlan_ref ifv = NULL;
1123 struct ifaddr * ifa1;
1124 struct ifaddr * ifa2;
1125 vlan_parent_ref new_vlp = NULL;
1126 int need_vlp_release = 0;
1127 u_int32_t progress = 0;
1128 struct sockaddr_dl *sdl1;
1129 struct sockaddr_dl *sdl2;
1130 vlan_parent_ref vlp = NULL;
1131
1132 /* pre-allocate space for vlan_parent, in case we're first */
1133 error = vlan_parent_create(p, &new_vlp);
1134 if (error != 0) {
1135 return (error);
1136 }
1137
1138 vlan_lock();
1139 ifv = (ifvlan_ref)ifp->if_private;
1140 if (ifv != NULL && ifv->ifv_vlp != NULL) {
1141 vlan_unlock();
1142 vlan_parent_release(new_vlp);
1143 return (EBUSY);
1144 }
1145 vlp = parent_list_lookup(p);
1146 if (vlp != NULL) {
1147 if (vlan_parent_lookup_tag(vlp, tag) != NULL) {
1148 /* already a VLAN with that tag on this interface */
1149 error = EADDRINUSE;
1150 goto unlock_done;
1151 }
1152 }
1153 else {
1154 /* we're the first VLAN on this interface */
1155 LIST_INSERT_HEAD(&g_vlan->parent_list, new_vlp, vlp_parent_list);
1156 vlp = new_vlp;
1157 }
1158
1159 /* need to wait to ensure no one else is trying to add/remove */
1160 vlan_parent_retain(vlp);
1161 progress |= VLAN_CONFIG_PROGRESS_VLP_RETAINED;
1162 vlan_parent_wait(vlp, "vlan_config");
1163
1164 ifv = (ifvlan_ref)ifp->if_private;
1165 if (ifv == NULL) {
1166 error = EOPNOTSUPP;
1167 goto signal_done;
1168 }
1169 if (vlan_parent_flags_detaching(vlp)
1170 || ifvlan_flags_detaching(ifv) || ifv->ifv_vlp != NULL) {
1171 error = EBUSY;
1172 goto signal_done;
1173 }
1174
1175 /* check again because someone might have gotten in */
1176 if (vlan_parent_lookup_tag(vlp, tag) != NULL) {
1177 /* already a VLAN with that tag on this interface */
1178 error = EADDRINUSE;
1179 goto signal_done;
1180 }
1181
1182 if (vlan_parent_no_vlans(vlp)) {
1183 first_vlan = 1;
1184 }
1185 vlan_parent_add_vlan(vlp, ifv, tag);
1186 progress |= VLAN_CONFIG_PROGRESS_IN_LIST;
1187
1188 /* check whether bond interface is using parent interface */
1189 ifnet_lock_exclusive(p);
1190 if ((p->if_eflags & IFEF_BOND) != 0) {
1191 ifnet_lock_done(p);
1192 /* don't allow VLAN over interface that's already part of a bond */
1193 error = EBUSY;
1194 goto signal_done;
1195 }
1196 /* prevent BOND interface from using it */
1197 p->if_eflags |= IFEF_VLAN;
1198 ifnet_lock_done(p);
1199 vlan_unlock();
1200
1201 if (first_vlan) {
1202 /* attach our VLAN "protocol" to the interface */
1203 error = vlan_attach_protocol(p);
1204 if (error) {
1205 vlan_lock();
1206 goto signal_done;
1207 }
1208 /* mark the parent interface up */
1209 ifnet_lock_exclusive(p);
1210 p->if_flags |= IFF_UP;
1211 ifnet_lock_done(p);
1212 (void)dlil_ioctl(0, p, SIOCSIFFLAGS, (caddr_t)NULL);
1213 }
1214
1215 /* configure parent to receive our multicast addresses */
1216 error = multicast_list_program(&ifv->ifv_multicast, ifp, p);
1217 if (error != 0) {
1218 if (first_vlan) {
1219 (void)vlan_detach_protocol(p);
1220 }
1221 vlan_lock();
1222 goto signal_done;
1223 }
1224
1225 /* no failures past this point */
1226 vlan_lock();
1227
1228 ifv->ifv_encaplen = ETHER_VLAN_ENCAP_LEN;
1229 ifv->ifv_flags = 0;
1230 if (vlan_parent_flags_supports_vlan_mtu(vlp)) {
1231 ifv->ifv_mtufudge = 0;
1232 } else {
1233 /*
1234 * Fudge the MTU by the encapsulation size. This
1235 * makes us incompatible with strictly compliant
1236 * 802.1Q implementations, but allows us to use
1237 * the feature with other NetBSD implementations,
1238 * which might still be useful.
1239 */
1240 ifv->ifv_mtufudge = ifv->ifv_encaplen;
1241 }
1242 ifp->if_mtu = ETHERMTU - ifv->ifv_mtufudge;
1243
1244 /*
1245 * Copy only a selected subset of flags from the parent.
1246 * Other flags are none of our business.
1247 */
1248 ifp->if_flags |= (p->if_flags &
1249 (IFF_BROADCAST | IFF_MULTICAST | IFF_SIMPLEX));
1250 /*
1251 * If the parent interface can do hardware-assisted
1252 * VLAN encapsulation, then propagate its hardware-
1253 * assisted checksumming flags.
1254 */
1255 if (p->if_hwassist & IF_HWASSIST_VLAN_TAGGING) {
1256 ifp->if_hwassist |= IF_HWASSIST_CSUM_FLAGS(p->if_hwassist);
1257 }
1258
1259 /* set our ethernet address to that of the parent */
1260 ifa1 = ifaddr_byindex(ifp->if_index);
1261 ifa2 = ifaddr_byindex(p->if_index);
1262 sdl1 = (struct sockaddr_dl *)ifa1->ifa_addr;
1263 sdl2 = (struct sockaddr_dl *)ifa2->ifa_addr;
1264 sdl1->sdl_type = IFT_ETHER;
1265 sdl1->sdl_alen = ETHER_ADDR_LEN;
1266 bcopy(LLADDR(sdl2), LLADDR(sdl1), ETHER_ADDR_LEN);
1267
1268 ifp->if_flags |= IFF_RUNNING;
1269 ifvlan_flags_set_ready(ifv);
1270 vlan_parent_signal(vlp, "vlan_config");
1271 vlan_unlock();
1272 if (new_vlp != vlp) {
1273 /* throw it away, it wasn't needed */
1274 vlan_parent_release(new_vlp);
1275 }
1276 return 0;
1277
1278 signal_done:
1279 vlan_assert_lock_held();
1280 vlan_parent_signal(vlp, "vlan_config");
1281
1282 unlock_done:
1283 if ((progress & VLAN_CONFIG_PROGRESS_IN_LIST) != 0) {
1284 vlan_parent_remove_vlan(vlp, ifv);
1285 }
1286 if (!vlan_parent_flags_detaching(vlp) && vlan_parent_no_vlans(vlp)) {
1287 /* the vlan parent has no more VLAN's */
1288 ifnet_lock_exclusive(p);
1289 p->if_eflags &= ~IFEF_VLAN;
1290 ifnet_lock_done(p);
1291 LIST_REMOVE(vlp, vlp_parent_list);
1292 /* release outside of the lock below */
1293 need_vlp_release = 1;
1294 }
1295 vlan_unlock();
1296
1297 if ((progress & VLAN_CONFIG_PROGRESS_VLP_RETAINED) != 0) {
1298 vlan_parent_release(vlp);
1299 }
1300 if (need_vlp_release) {
1301 vlan_parent_release(vlp);
1302 }
1303 if (new_vlp != vlp) {
1304 vlan_parent_release(new_vlp);
1305 }
1306 return (error);
1307 }
1308
1309 static void
1310 vlan_link_event(struct ifnet * ifp, struct ifnet * p)
1311 {
1312 struct ifmediareq ifmr;
1313
1314 /* generate a link event based on the state of the underlying interface */
1315 bzero(&ifmr, sizeof(ifmr));
1316 snprintf(ifmr.ifm_name, sizeof(ifmr.ifm_name),
1317 "%s%d", p->if_name, p->if_unit);
1318 if ((*p->if_ioctl)(p, SIOCGIFMEDIA, (caddr_t)&ifmr) == 0
1319 && ifmr.ifm_count > 0 && ifmr.ifm_status & IFM_AVALID) {
1320 u_long event;
1321
1322 event = (ifmr.ifm_status & IFM_ACTIVE)
1323 ? KEV_DL_LINK_ON : KEV_DL_LINK_OFF;
1324 interface_link_event(ifp, event);
1325 }
1326 return;
1327 }
1328
1329 static int
1330 vlan_unconfig(struct ifnet * ifp)
1331 {
1332 int error = 0;
1333 struct ifaddr * ifa;
1334 ifvlan_ref ifv;
1335 int last_vlan = 0;
1336 int need_vlp_release = 0;
1337 struct ifnet * p;
1338 struct sockaddr_dl *sdl;
1339 vlan_parent_ref vlp;
1340
1341 vlan_assert_lock_held();
1342 ifv = (ifvlan_ref)ifp->if_private;
1343 if (ifv == NULL) {
1344 return (0);
1345 }
1346 vlp = ifv->ifv_vlp;
1347 if (vlp == NULL) {
1348 return (0);
1349 }
1350 vlan_parent_retain(vlp);
1351 vlan_parent_wait(vlp, "vlan_unconfig");
1352
1353 /* check again because another thread could be in vlan_unconfig */
1354 ifv = (ifvlan_ref)ifp->if_private;
1355 if (ifv == NULL) {
1356 goto signal_done;
1357 }
1358 if (ifv->ifv_vlp != vlp) {
1359 /* vlan parent changed */
1360 goto signal_done;
1361 }
1362 need_vlp_release++;
1363 p = vlp->vlp_ifp;
1364
1365 /* remember whether we're the last VLAN on the parent */
1366 if (LIST_NEXT(LIST_FIRST(&vlp->vlp_vlan_list), ifv_vlan_list) == NULL) {
1367 if (g_vlan->verbose) {
1368 printf("vlan_unconfig: last vlan on %s%d\n",
1369 p->if_name, p->if_unit);
1370 }
1371 last_vlan = 1;
1372 }
1373
1374 /* back-out any effect our mtu might have had on the parent */
1375 (void)vlan_new_mtu(ifp, ETHERMTU - ifv->ifv_mtufudge);
1376
1377 vlan_unlock();
1378
1379 /* detach VLAN "protocol" */
1380 if (last_vlan) {
1381 (void)vlan_detach_protocol(p);
1382 }
1383
1384 /* un-join multicast on parent interface */
1385 (void)multicast_list_remove(&ifv->ifv_multicast);
1386
1387 vlan_lock();
1388
1389 /* Disconnect from parent. */
1390 vlan_parent_remove_vlan(vlp, ifv);
1391
1392 /* return to the state we were in before SIFVLAN */
1393 ifp->if_mtu = 0;
1394 ifp->if_flags &= ~(IFF_BROADCAST | IFF_MULTICAST
1395 | IFF_SIMPLEX | IFF_RUNNING);
1396 ifp->if_hwassist = 0;
1397 ifv->ifv_flags = 0;
1398 ifv->ifv_mtufudge = 0;
1399
1400 /* Clear our MAC address. */
1401 ifa = ifaddr_byindex(ifp->if_index);
1402 sdl = (struct sockaddr_dl *)(ifa->ifa_addr);
1403 sdl->sdl_type = IFT_L2VLAN;
1404 sdl->sdl_alen = 0;
1405 bzero(LLADDR(sdl), ETHER_ADDR_LEN);
1406
1407 if (!vlan_parent_flags_detaching(vlp) && vlan_parent_no_vlans(vlp)) {
1408 /* the vlan parent has no more VLAN's */
1409 ifnet_lock_exclusive(p);
1410 p->if_eflags &= ~IFEF_VLAN;
1411 ifnet_lock_done(p);
1412 LIST_REMOVE(vlp, vlp_parent_list);
1413 /* release outside of the lock below */
1414 need_vlp_release++;
1415 }
1416
1417 signal_done:
1418 vlan_parent_signal(vlp, "vlan_unconfig");
1419 vlan_unlock();
1420 vlan_parent_release(vlp); /* one because we waited */
1421
1422 while (need_vlp_release--) {
1423 vlan_parent_release(vlp);
1424 }
1425 vlan_lock();
1426 return (error);
1427 }
1428
1429 static int
1430 vlan_set_promisc(struct ifnet * ifp)
1431 {
1432 int error = 0;
1433 ifvlan_ref ifv;
1434 vlan_parent_ref vlp;
1435
1436 vlan_lock();
1437 ifv = (ifvlan_ref)ifp->if_private;
1438 if (ifv == NULL || ifvlan_flags_detaching(ifv)) {
1439 error = (ifv == NULL) ? EOPNOTSUPP : EBUSY;
1440 goto done;
1441 }
1442
1443 vlp = ifv->ifv_vlp;
1444 if (vlp == NULL) {
1445 goto done;
1446 }
1447 if ((ifp->if_flags & IFF_PROMISC) != 0) {
1448 if (!ifvlan_flags_promisc(ifv)) {
1449 error = ifnet_set_promiscuous(vlp->vlp_ifp, 1);
1450 if (error == 0) {
1451 ifvlan_flags_set_promisc(ifv);
1452 }
1453 }
1454 } else {
1455 if (ifvlan_flags_promisc(ifv)) {
1456 error = ifnet_set_promiscuous(vlp->vlp_ifp, 0);
1457 if (error == 0) {
1458 ifvlan_flags_clear_promisc(ifv);
1459 }
1460 }
1461 }
1462 done:
1463 vlan_unlock();
1464 return (error);
1465 }
1466
1467 static int
1468 vlan_new_mtu(struct ifnet * ifp, int mtu)
1469 {
1470 struct ifdevmtu * devmtu_p;
1471 int error = 0;
1472 ifvlan_ref ifv;
1473 int max_mtu;
1474 int new_mtu = 0;
1475 int req_mtu;
1476 vlan_parent_ref vlp;
1477
1478 vlan_assert_lock_held();
1479 ifv = (ifvlan_ref)ifp->if_private;
1480 vlp = ifv->ifv_vlp;
1481 devmtu_p = &vlp->vlp_devmtu;
1482 req_mtu = mtu + ifv->ifv_mtufudge;
1483 if (req_mtu > devmtu_p->ifdm_max || req_mtu < devmtu_p->ifdm_min) {
1484 return (EINVAL);
1485 }
1486 max_mtu = vlan_parent_find_max_mtu(vlp, ifv);
1487 if (req_mtu > max_mtu) {
1488 new_mtu = req_mtu;
1489 }
1490 else if (max_mtu < devmtu_p->ifdm_current) {
1491 new_mtu = max_mtu;
1492 }
1493 if (new_mtu != 0) {
1494 struct ifnet * p = vlp->vlp_ifp;
1495 vlan_unlock();
1496 error = siocsifaltmtu(p, new_mtu);
1497 vlan_lock();
1498 }
1499 if (error == 0) {
1500 if (new_mtu != 0) {
1501 devmtu_p->ifdm_current = new_mtu;
1502 }
1503 ifp->if_mtu = mtu;
1504 }
1505 return (error);
1506 }
1507
1508 static int
1509 vlan_set_mtu(struct ifnet * ifp, int mtu)
1510 {
1511 int error = 0;
1512 ifvlan_ref ifv;
1513 vlan_parent_ref vlp;
1514
1515 if (mtu < IF_MINMTU) {
1516 return (EINVAL);
1517 }
1518 vlan_lock();
1519 ifv = (ifvlan_ref)ifp->if_private;
1520 if (ifv == NULL || ifvlan_flags_detaching(ifv)) {
1521 vlan_unlock();
1522 return ((ifv == NULL) ? EOPNOTSUPP : EBUSY);
1523 }
1524 vlp = ifv->ifv_vlp;
1525 if (vlp == NULL || vlan_parent_flags_detaching(vlp)) {
1526 vlan_unlock();
1527 if (mtu != 0) {
1528 return (EINVAL);
1529 }
1530 return (0);
1531 }
1532 vlan_parent_retain(vlp);
1533 vlan_parent_wait(vlp, "vlan_set_mtu");
1534
1535 /* check again, something might have changed */
1536 ifv = (ifvlan_ref)ifp->if_private;
1537 if (ifv == NULL || ifvlan_flags_detaching(ifv)) {
1538 error = (ifv == NULL) ? EOPNOTSUPP : EBUSY;
1539 goto signal_done;
1540 }
1541 if (ifv->ifv_vlp != vlp) {
1542 /* vlan parent changed */
1543 goto signal_done;
1544 }
1545 if (vlp == NULL || vlan_parent_flags_detaching(vlp)) {
1546 if (mtu != 0) {
1547 error = EINVAL;
1548 }
1549 goto signal_done;
1550 }
1551 error = vlan_new_mtu(ifp, mtu);
1552
1553 signal_done:
1554 vlan_parent_signal(vlp, "vlan_set_mtu");
1555 vlan_unlock();
1556 vlan_parent_release(vlp);
1557
1558 return (error);
1559 }
1560
1561 static int
1562 vlan_ioctl(ifnet_t ifp, u_int32_t cmd, void * data)
1563 {
1564 struct ifdevmtu * devmtu_p;
1565 int error = 0;
1566 struct ifaddr * ifa;
1567 struct ifmediareq64 * ifmr;
1568 struct ifreq * ifr;
1569 ifvlan_ref ifv;
1570 struct ifnet * p;
1571 u_short tag;
1572 user_addr_t user_addr;
1573 vlan_parent_ref vlp;
1574 struct vlanreq vlr;
1575
1576 if (ifp->if_type != IFT_L2VLAN) {
1577 return (EOPNOTSUPP);
1578 }
1579 ifr = (struct ifreq *)data;
1580 ifa = (struct ifaddr *)data;
1581
1582 switch (cmd) {
1583 case SIOCSIFADDR:
1584 ifnet_set_flags(ifp, IFF_UP, IFF_UP);
1585 break;
1586
1587 case SIOCGIFMEDIA64:
1588 case SIOCGIFMEDIA:
1589 vlan_lock();
1590 ifv = (ifvlan_ref)ifp->if_private;
1591 if (ifv == NULL || ifvlan_flags_detaching(ifv)) {
1592 vlan_unlock();
1593 return (ifv == NULL ? EOPNOTSUPP : EBUSY);
1594 }
1595 p = (ifv->ifv_vlp == NULL) ? NULL : ifv->ifv_vlp->vlp_ifp;
1596 vlan_unlock();
1597 ifmr = (struct ifmediareq64 *)data;
1598 user_addr = (cmd == SIOCGIFMEDIA64)
1599 ? ifmr->ifm_ifmu.ifmu_ulist64
1600 : CAST_USER_ADDR_T(ifmr->ifm_ifmu.ifmu_ulist32);
1601 if (p != NULL) {
1602 struct ifmediareq64 p_ifmr;
1603
1604 bzero(&p_ifmr, sizeof(p_ifmr));
1605 error = dlil_ioctl(0, p, SIOCGIFMEDIA, (caddr_t)&p_ifmr);
1606 if (error == 0) {
1607 ifmr->ifm_active = p_ifmr.ifm_active;
1608 ifmr->ifm_current = p_ifmr.ifm_current;
1609 ifmr->ifm_mask = p_ifmr.ifm_mask;
1610 ifmr->ifm_status = p_ifmr.ifm_status;
1611 ifmr->ifm_count = p_ifmr.ifm_count;
1612 /* Limit the result to the parent's current config. */
1613 if (ifmr->ifm_count >= 1 && user_addr != USER_ADDR_NULL) {
1614 ifmr->ifm_count = 1;
1615 error = copyout(&ifmr->ifm_current, user_addr,
1616 sizeof(int));
1617 }
1618 }
1619 } else {
1620 ifmr->ifm_active = ifmr->ifm_current = IFM_NONE;
1621 ifmr->ifm_mask = 0;
1622 ifmr->ifm_status = IFM_AVALID;
1623 ifmr->ifm_count = 1;
1624 if (user_addr != USER_ADDR_NULL) {
1625 error = copyout(&ifmr->ifm_current, user_addr, sizeof(int));
1626 }
1627 }
1628 break;
1629
1630 case SIOCSIFMEDIA:
1631 error = EOPNOTSUPP;
1632 break;
1633
1634 case SIOCGIFDEVMTU:
1635 vlan_lock();
1636 ifv = (ifvlan_ref)ifp->if_private;
1637 if (ifv == NULL || ifvlan_flags_detaching(ifv)) {
1638 vlan_unlock();
1639 return (ifv == NULL ? EOPNOTSUPP : EBUSY);
1640 }
1641 vlp = ifv->ifv_vlp;
1642 if (vlp != NULL) {
1643 int min_mtu = vlp->vlp_devmtu.ifdm_min - ifv->ifv_mtufudge;
1644 devmtu_p = &ifr->ifr_devmtu;
1645 devmtu_p->ifdm_current = ifp->if_mtu;
1646 devmtu_p->ifdm_min = max(min_mtu, IF_MINMTU);
1647 devmtu_p->ifdm_max = vlp->vlp_devmtu.ifdm_max - ifv->ifv_mtufudge;
1648 }
1649 else {
1650 devmtu_p = &ifr->ifr_devmtu;
1651 devmtu_p->ifdm_current = 0;
1652 devmtu_p->ifdm_min = 0;
1653 devmtu_p->ifdm_max = 0;
1654 }
1655 vlan_unlock();
1656 break;
1657
1658 case SIOCSIFMTU:
1659 error = vlan_set_mtu(ifp, ifr->ifr_mtu);
1660 break;
1661
1662 case SIOCSIFVLAN:
1663 user_addr = proc_is64bit(current_proc())
1664 ? ifr->ifr_data64 : CAST_USER_ADDR_T(ifr->ifr_data);
1665 error = copyin(user_addr, &vlr, sizeof(vlr));
1666 if (error) {
1667 break;
1668 }
1669 p = NULL;
1670 if (vlr.vlr_parent[0] != '\0') {
1671 if (vlr.vlr_tag & ~EVL_VLID_MASK) {
1672 /*
1673 * Don't let the caller set up a VLAN tag with
1674 * anything except VLID bits.
1675 */
1676 error = EINVAL;
1677 break;
1678 }
1679 p = ifunit(vlr.vlr_parent);
1680 if (p == NULL) {
1681 error = ENXIO;
1682 break;
1683 }
1684 /* can't do VLAN over anything but ethernet or ethernet aggregate */
1685 if (p->if_type != IFT_ETHER && p->if_type != IFT_IEEE8023ADLAG) {
1686 error = EPROTONOSUPPORT;
1687 break;
1688 }
1689 error = vlan_config(ifp, p, vlr.vlr_tag);
1690 if (error) {
1691 break;
1692 }
1693
1694 /* Update promiscuous mode, if necessary. */
1695 (void)vlan_set_promisc(ifp);
1696
1697 /* generate a link event based on the state of the parent */
1698 vlan_link_event(ifp, p);
1699 } else {
1700 vlan_lock();
1701 ifv = (ifvlan_ref)ifp->if_private;
1702 if (ifv == NULL || ifvlan_flags_detaching(ifv)) {
1703 vlan_unlock();
1704 error = (ifv == NULL ? EOPNOTSUPP : EBUSY);
1705 break;
1706 }
1707 error = vlan_unconfig(ifp);
1708 vlan_unlock();
1709 if (error == 0) {
1710 interface_link_event(ifp, KEV_DL_LINK_OFF);
1711 }
1712 }
1713 break;
1714
1715 case SIOCGIFVLAN:
1716 bzero(&vlr, sizeof vlr);
1717 vlan_lock();
1718 ifv = (ifvlan_ref)ifp->if_private;
1719 if (ifv == NULL || ifvlan_flags_detaching(ifv)) {
1720 vlan_unlock();
1721 return (ifv == NULL ? EOPNOTSUPP : EBUSY);
1722 }
1723 p = (ifv->ifv_vlp == NULL) ? NULL : ifv->ifv_vlp->vlp_ifp;
1724 tag = ifv->ifv_tag;
1725 vlan_unlock();
1726 if (p != NULL) {
1727 snprintf(vlr.vlr_parent, sizeof(vlr.vlr_parent),
1728 "%s%d", p->if_name, p->if_unit);
1729 vlr.vlr_tag = tag;
1730 }
1731 user_addr = proc_is64bit(current_proc())
1732 ? ifr->ifr_data64 : CAST_USER_ADDR_T(ifr->ifr_data);
1733 error = copyout(&vlr, user_addr, sizeof(vlr));
1734 break;
1735
1736 case SIOCSIFFLAGS:
1737 /*
1738 * For promiscuous mode, we enable promiscuous mode on
1739 * the parent if we need promiscuous on the VLAN interface.
1740 */
1741 error = vlan_set_promisc(ifp);
1742 break;
1743
1744 case SIOCADDMULTI:
1745 case SIOCDELMULTI:
1746 error = vlan_setmulti(ifp);
1747 break;
1748 default:
1749 error = EOPNOTSUPP;
1750 }
1751 return error;
1752 }
1753
1754 static void
1755 vlan_if_free(struct ifnet * ifp)
1756 {
1757 ifvlan_ref ifv;
1758
1759 if (ifp == NULL) {
1760 return;
1761 }
1762 vlan_lock();
1763 ifv = (ifvlan_ref)ifp->if_private;
1764 if (ifv == NULL) {
1765 vlan_unlock();
1766 return;
1767 }
1768 ifp->if_private = NULL;
1769 vlan_unlock();
1770 dlil_if_release(ifp);
1771 FREE(ifv, M_VLAN);
1772 }
1773
1774 static void
1775 vlan_event(struct ifnet * p, struct kev_msg * event)
1776 {
1777 vlan_parent_ref vlp;
1778
1779 /* Check if the interface we are attached to is being detached */
1780 if (event->vendor_code != KEV_VENDOR_APPLE
1781 || event->kev_class != KEV_NETWORK_CLASS
1782 || event->kev_subclass != KEV_DL_SUBCLASS) {
1783 return;
1784 }
1785 switch (event->event_code) {
1786 case KEV_DL_IF_DETACHING:
1787 case KEV_DL_LINK_OFF:
1788 case KEV_DL_LINK_ON:
1789 break;
1790 default:
1791 return;
1792 }
1793 vlan_lock();
1794 if ((p->if_eflags & IFEF_VLAN) == 0) {
1795 vlan_unlock();
1796 /* no VLAN's */
1797 return;
1798 }
1799 vlp = parent_list_lookup(p);
1800 if (vlp == NULL) {
1801 /* no VLAN's */
1802 vlan_unlock();
1803 return;
1804 }
1805 switch (event->event_code) {
1806 case KEV_DL_IF_DETACHING:
1807 vlan_parent_flags_set_detaching(vlp);
1808 vlan_parent_remove_all_vlans(vlp);
1809 break;
1810
1811 case KEV_DL_LINK_OFF:
1812 case KEV_DL_LINK_ON:
1813 vlan_parent_link_event(vlp, event->event_code);
1814 break;
1815 default:
1816 break;
1817 }
1818 vlan_unlock();
1819 return;
1820 }
1821
1822 static void
1823 interface_link_event(struct ifnet * ifp, u_long event_code)
1824 {
1825 struct {
1826 struct kern_event_msg header;
1827 u_long unit;
1828 char if_name[IFNAMSIZ];
1829 } event;
1830
1831 event.header.total_size = sizeof(event);
1832 event.header.vendor_code = KEV_VENDOR_APPLE;
1833 event.header.kev_class = KEV_NETWORK_CLASS;
1834 event.header.kev_subclass = KEV_DL_SUBCLASS;
1835 event.header.event_code = event_code;
1836 event.header.event_data[0] = ifp->if_family;
1837 event.unit = (u_long) ifp->if_unit;
1838 strncpy(event.if_name, ifp->if_name, IFNAMSIZ);
1839 dlil_event(ifp, &event.header);
1840 return;
1841 }
1842
1843 static void
1844 vlan_parent_link_event(vlan_parent_ref vlp, u_long event_code)
1845 {
1846 ifvlan_ref ifv;
1847
1848 LIST_FOREACH(ifv, &vlp->vlp_vlan_list, ifv_vlan_list) {
1849 interface_link_event(ifv->ifv_ifp, event_code);
1850 }
1851 return;
1852
1853 }
1854
1855 /*
1856 * Function: vlan_attach_protocol
1857 * Purpose:
1858 * Attach a DLIL protocol to the interface, using the ETHERTYPE_VLAN
1859 * demux ether type.
1860 *
1861 * The ethernet demux actually special cases VLAN to support hardware.
1862 * The demux here isn't used. The demux will return PF_VLAN for the
1863 * appropriate packets and our vlan_input function will be called.
1864 */
1865 static int
1866 vlan_attach_protocol(struct ifnet *ifp)
1867 {
1868 int error;
1869 struct dlil_proto_reg_str reg;
1870
1871 bzero(&reg, sizeof(reg));
1872 TAILQ_INIT(&reg.demux_desc_head);
1873 reg.interface_family = ifp->if_family;
1874 reg.unit_number = ifp->if_unit;
1875 reg.input = vlan_input;
1876 reg.event = vlan_event;
1877 reg.protocol_family = PF_VLAN;
1878 error = dlil_attach_protocol(&reg);
1879 if (error) {
1880 printf("vlan_proto_attach(%s%d) dlil_attach_protocol failed, %d\n",
1881 ifp->if_name, ifp->if_unit, error);
1882 }
1883 return (error);
1884 }
1885
1886 /*
1887 * Function: vlan_detach_protocol
1888 * Purpose:
1889 * Detach our DLIL protocol from an interface
1890 */
1891 static int
1892 vlan_detach_protocol(struct ifnet *ifp)
1893 {
1894 int error;
1895
1896 error = dlil_detach_protocol(ifp, PF_VLAN);
1897 if (error) {
1898 printf("vlan_proto_detach(%s%d) dlil_detach_protocol failed, %d\n",
1899 ifp->if_name, ifp->if_unit, error);
1900 }
1901
1902 return (error);
1903 }
1904
1905 /*
1906 * DLIL interface family functions
1907 * We use the ethernet dlil functions, since that's all we support.
1908 * If we wanted to handle multiple LAN types (tokenring, etc.), we'd
1909 * call the appropriate routines for that LAN type instead of hard-coding
1910 * ethernet.
1911 */
1912 extern int ether_add_if(struct ifnet *ifp);
1913 extern int ether_del_if(struct ifnet *ifp);
1914 extern int ether_init_if(struct ifnet *ifp);
1915 extern int ether_add_proto_old(struct ifnet *ifp, u_long protocol_family,
1916 struct ddesc_head_str *desc_head);
1917
1918 extern int ether_attach_inet(struct ifnet *ifp, u_long protocol_family);
1919 extern int ether_detach_inet(struct ifnet *ifp, u_long protocol_family);
1920 extern int ether_attach_inet6(struct ifnet *ifp, u_long protocol_family);
1921 extern int ether_detach_inet6(struct ifnet *ifp, u_long protocol_family);
1922
1923 static int
1924 vlan_attach_inet(struct ifnet *ifp, u_long protocol_family)
1925 {
1926 return (ether_attach_inet(ifp, protocol_family));
1927 }
1928
1929 static int
1930 vlan_detach_inet(struct ifnet *ifp, u_long protocol_family)
1931 {
1932 return (ether_detach_inet(ifp, protocol_family));
1933 }
1934
1935 static int
1936 vlan_attach_inet6(struct ifnet *ifp, u_long protocol_family)
1937 {
1938 return (ether_attach_inet6(ifp, protocol_family));
1939 }
1940
1941 static int
1942 vlan_detach_inet6(struct ifnet *ifp, u_long protocol_family)
1943 {
1944 return (ether_detach_inet6(ifp, protocol_family));
1945 }
1946
1947 static int
1948 vlan_add_if(struct ifnet *ifp)
1949 {
1950 return (ether_add_if(ifp));
1951 }
1952
1953 static int
1954 vlan_del_if(struct ifnet *ifp)
1955 {
1956 return (ether_del_if(ifp));
1957 }
1958
1959
1960 __private_extern__ int
1961 vlan_family_init(void)
1962 {
1963 int error=0;
1964 struct dlil_ifmod_reg_str ifmod_reg;
1965
1966 bzero(&ifmod_reg, sizeof(ifmod_reg));
1967 ifmod_reg.add_if = vlan_add_if;
1968 ifmod_reg.del_if = vlan_del_if;
1969 ifmod_reg.init_if = NULL;
1970 ifmod_reg.add_proto = ether_add_proto_old;
1971 ifmod_reg.del_proto = ether_del_proto;
1972 ifmod_reg.ifmod_ioctl = ether_ioctl;
1973 ifmod_reg.shutdown = NULL;
1974
1975 if (dlil_reg_if_modules(APPLE_IF_FAM_VLAN, &ifmod_reg)) {
1976 printf("WARNING: vlan_family_init -- "
1977 "Can't register if family modules\n");
1978 error = EIO;
1979 goto done;
1980 }
1981
1982 error = dlil_reg_proto_module(PF_INET, APPLE_IF_FAM_VLAN,
1983 vlan_attach_inet, vlan_detach_inet);
1984 if (error != 0) {
1985 printf("dlil_reg_proto_module failed for AF_INET error=%d\n",
1986 error);
1987 goto done;
1988 }
1989 error = dlil_reg_proto_module(PF_INET6, APPLE_IF_FAM_VLAN,
1990 vlan_attach_inet6, vlan_detach_inet6);
1991 if (error != 0) {
1992 printf("dlil_reg_proto_module failed for AF_INET6 error=%d\n",
1993 error);
1994 goto done;
1995 }
1996 vlan_clone_attach();
1997
1998 done:
1999 return (error);
2000 }