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