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