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