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