]> git.saurik.com Git - apple/xnu.git/blob - bsd/net/if.c
31d3cd0825cbe6913958e10c59daf405084cfa84
[apple/xnu.git] / bsd / net / if.c
1 /*
2 * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 /*
29 * Copyright (c) 1980, 1986, 1993
30 * The Regents of the University of California. All rights reserved.
31 *
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
34 * are met:
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * 3. All advertising materials mentioning features or use of this software
41 * must display the following acknowledgement:
42 * This product includes software developed by the University of
43 * California, Berkeley and its contributors.
44 * 4. Neither the name of the University nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
47 *
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE.
59 *
60 * @(#)if.c 8.3 (Berkeley) 1/4/94
61 * $FreeBSD: src/sys/net/if.c,v 1.85.2.9 2001/07/24 19:10:17 brooks Exp $
62 */
63 /*
64 * NOTICE: This file was modified by SPARTA, Inc. in 2006 to introduce
65 * support for mandatory and extensible security protections. This notice
66 * is included in support of clause 2.2 (b) of the Apple Public License,
67 * Version 2.0.
68 */
69
70 #include <kern/locks.h>
71
72 #include <sys/param.h>
73 #include <sys/malloc.h>
74 #include <sys/mbuf.h>
75 #include <sys/systm.h>
76 #include <sys/proc.h>
77 #include <sys/socket.h>
78 #include <sys/socketvar.h>
79 #include <sys/protosw.h>
80 #include <sys/kernel.h>
81 #include <sys/sockio.h>
82 #include <sys/syslog.h>
83 #include <sys/sysctl.h>
84
85 #include <net/if.h>
86 #include <net/if_arp.h>
87 #include <net/if_dl.h>
88 #include <net/if_types.h>
89 #include <net/if_var.h>
90 #include <net/net_osdep.h>
91 #include <net/ethernet.h>
92
93 #include <net/radix.h>
94 #include <net/route.h>
95 #ifdef __APPLE__
96 #include <net/dlil.h>
97 //#include <string.h>
98 #include <sys/domain.h>
99 #include <libkern/OSAtomic.h>
100 #endif
101
102 #if INET || INET6
103 /*XXX*/
104 #include <netinet/in.h>
105 #include <netinet/in_var.h>
106 #if INET6
107 #include <netinet6/in6_var.h>
108 #include <netinet6/in6_ifattach.h>
109 #endif
110 #endif
111
112 extern u_long route_generation;
113 extern int use_routegenid;
114 extern int dlil_multithreaded_input;
115 extern struct dlil_threading_info *dlil_lo_thread_ptr;
116
117 #if CONFIG_MACF_NET
118 #include <security/mac_framework.h>
119 #endif
120
121 /*
122 * System initialization
123 */
124
125 static int ifconf(u_long cmd, user_addr_t ifrp, int * ret_space);
126 static void if_qflush(struct ifqueue *);
127 __private_extern__ void link_rtrequest(int, struct rtentry *, struct sockaddr *);
128 void if_rtproto_del(struct ifnet *ifp, int protocol);
129
130 static int if_rtmtu(struct radix_node *, void *);
131 static void if_rtmtu_update(struct ifnet *);
132
133 static struct if_clone *if_clone_lookup(const char *, int *);
134 #ifdef IF_CLONE_LIST
135 static int if_clone_list(int count, int * total, user_addr_t dst);
136 #endif
137
138 MALLOC_DEFINE(M_IFADDR, "ifaddr", "interface address");
139 MALLOC_DEFINE(M_IFMADDR, "ether_multi", "link-level multicast address");
140
141 int ifqmaxlen = IFQ_MAXLEN;
142 struct ifnethead ifnet_head = TAILQ_HEAD_INITIALIZER(ifnet_head);
143
144 static int if_cloners_count;
145 LIST_HEAD(, if_clone) if_cloners = LIST_HEAD_INITIALIZER(if_cloners);
146
147 #if INET6
148 /*
149 * XXX: declare here to avoid to include many inet6 related files..
150 * should be more generalized?
151 */
152 extern void nd6_setmtu(struct ifnet *);
153 #endif
154
155 #define M_CLONE M_IFADDR
156
157 /*
158 * Network interface utility routines.
159 *
160 * Routines with ifa_ifwith* names take sockaddr *'s as
161 * parameters.
162 */
163
164 int if_index;
165 struct ifaddr **ifnet_addrs;
166 struct ifnet **ifindex2ifnet;
167
168 __private_extern__ void
169 if_attach_ifa(
170 struct ifnet *ifp,
171 struct ifaddr *ifa)
172 {
173 ifnet_lock_assert(ifp, LCK_MTX_ASSERT_OWNED);
174 if (ifa->ifa_debug & IFA_ATTACHED) {
175 panic("if_attach_ifa: Attempted to attach address that's already attached!\n");
176 }
177 ifaref(ifa);
178 ifa->ifa_debug |= IFA_ATTACHED;
179 TAILQ_INSERT_TAIL(&ifp->if_addrhead, ifa, ifa_link);
180 }
181
182 __private_extern__ void
183 if_detach_ifa(
184 struct ifnet *ifp,
185 struct ifaddr *ifa)
186 {
187 ifnet_lock_assert(ifp, LCK_MTX_ASSERT_OWNED);
188 #if 1
189 /* Debugging code */
190 if ((ifa->ifa_debug & IFA_ATTACHED) == 0) {
191 printf("if_detach_ifa: ifa is not attached to any interface! flags=%lu\n", ifa->ifa_debug);
192 return;
193 }
194 else {
195 struct ifaddr *ifa2;
196 TAILQ_FOREACH(ifa2, &ifp->if_addrhead, ifa_link) {
197 if (ifa2 == ifa)
198 break;
199 }
200 if (ifa2 != ifa) {
201 printf("if_detach_ifa: Attempted to detach IFA that was not attached!\n");
202 }
203 }
204 #endif
205 TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link);
206 ifa->ifa_debug &= ~IFA_ATTACHED;
207 ifafree(ifa);
208 }
209
210 #define INITIAL_IF_INDEXLIM 8
211
212 /*
213 * Function: if_next_index
214 * Purpose:
215 * Return the next available interface index.
216 * Grow the ifnet_addrs[] and ifindex2ifnet[] arrays to accomodate the
217 * added entry when necessary.
218 *
219 * Note:
220 * ifnet_addrs[] is indexed by (if_index - 1), whereas
221 * ifindex2ifnet[] is indexed by ifp->if_index. That requires us to
222 * always allocate one extra element to hold ifindex2ifnet[0], which
223 * is unused.
224 */
225 int if_next_index(void);
226
227 __private_extern__ int
228 if_next_index(void)
229 {
230 static int if_indexlim = 0;
231 int new_index;
232
233 new_index = ++if_index;
234 if (if_index > if_indexlim) {
235 unsigned n;
236 int new_if_indexlim;
237 caddr_t new_ifnet_addrs;
238 caddr_t new_ifindex2ifnet;
239 caddr_t old_ifnet_addrs;
240
241 old_ifnet_addrs = (caddr_t)ifnet_addrs;
242 if (ifnet_addrs == NULL) {
243 new_if_indexlim = INITIAL_IF_INDEXLIM;
244 } else {
245 new_if_indexlim = if_indexlim << 1;
246 }
247
248 /* allocate space for the larger arrays */
249 n = (2 * new_if_indexlim + 1) * sizeof(caddr_t);
250 new_ifnet_addrs = _MALLOC(n, M_IFADDR, M_WAITOK);
251 new_ifindex2ifnet = new_ifnet_addrs
252 + new_if_indexlim * sizeof(caddr_t);
253 bzero(new_ifnet_addrs, n);
254 if (ifnet_addrs != NULL) {
255 /* copy the existing data */
256 bcopy((caddr_t)ifnet_addrs, new_ifnet_addrs,
257 if_indexlim * sizeof(caddr_t));
258 bcopy((caddr_t)ifindex2ifnet,
259 new_ifindex2ifnet,
260 (if_indexlim + 1) * sizeof(caddr_t));
261 }
262
263 /* switch to the new tables and size */
264 ifnet_addrs = (struct ifaddr **)new_ifnet_addrs;
265 ifindex2ifnet = (struct ifnet **)new_ifindex2ifnet;
266 if_indexlim = new_if_indexlim;
267
268 /* release the old data */
269 if (old_ifnet_addrs != NULL) {
270 _FREE((caddr_t)old_ifnet_addrs, M_IFADDR);
271 }
272 }
273 return (new_index);
274 }
275
276 /*
277 * Create a clone network interface.
278 */
279 static int
280 if_clone_create(char *name, int len)
281 {
282 struct if_clone *ifc;
283 char *dp;
284 int wildcard, bytoff, bitoff;
285 int unit;
286 int err;
287
288 ifc = if_clone_lookup(name, &unit);
289 if (ifc == NULL)
290 return (EINVAL);
291
292 if (ifunit(name) != NULL)
293 return (EEXIST);
294
295 bytoff = bitoff = 0;
296 wildcard = (unit < 0);
297 /*
298 * Find a free unit if none was given.
299 */
300 if (wildcard) {
301 while ((bytoff < ifc->ifc_bmlen)
302 && (ifc->ifc_units[bytoff] == 0xff))
303 bytoff++;
304 if (bytoff >= ifc->ifc_bmlen)
305 return (ENOSPC);
306 while ((ifc->ifc_units[bytoff] & (1 << bitoff)) != 0)
307 bitoff++;
308 unit = (bytoff << 3) + bitoff;
309 }
310
311 if (unit > ifc->ifc_maxunit)
312 return (ENXIO);
313
314 err = (*ifc->ifc_create)(ifc, unit);
315 if (err != 0)
316 return (err);
317
318 if (!wildcard) {
319 bytoff = unit >> 3;
320 bitoff = unit - (bytoff << 3);
321 }
322
323 /*
324 * Allocate the unit in the bitmap.
325 */
326 KASSERT((ifc->ifc_units[bytoff] & (1 << bitoff)) == 0,
327 ("%s: bit is already set", __func__));
328 ifc->ifc_units[bytoff] |= (1 << bitoff);
329
330 /* In the wildcard case, we need to update the name. */
331 if (wildcard) {
332 for (dp = name; *dp != '\0'; dp++);
333 if (snprintf(dp, len - (dp-name), "%d", unit) >
334 len - (dp-name) - 1) {
335 /*
336 * This can only be a programmer error and
337 * there's no straightforward way to recover if
338 * it happens.
339 */
340 panic("if_clone_create(): interface name too long");
341 }
342
343 }
344
345 return (0);
346 }
347
348 /*
349 * Destroy a clone network interface.
350 */
351 static int
352 if_clone_destroy(const char *name)
353 {
354 struct if_clone *ifc;
355 struct ifnet *ifp;
356 int bytoff, bitoff;
357 int unit;
358
359 ifc = if_clone_lookup(name, &unit);
360 if (ifc == NULL)
361 return (EINVAL);
362
363 if (unit < ifc->ifc_minifs)
364 return (EINVAL);
365
366 ifp = ifunit(name);
367 if (ifp == NULL)
368 return (ENXIO);
369
370 if (ifc->ifc_destroy == NULL)
371 return (EOPNOTSUPP);
372
373 (*ifc->ifc_destroy)(ifp);
374
375 /*
376 * Compute offset in the bitmap and deallocate the unit.
377 */
378 bytoff = unit >> 3;
379 bitoff = unit - (bytoff << 3);
380 KASSERT((ifc->ifc_units[bytoff] & (1 << bitoff)) != 0,
381 ("%s: bit is already cleared", __func__));
382 ifc->ifc_units[bytoff] &= ~(1 << bitoff);
383 return (0);
384 }
385
386 /*
387 * Look up a network interface cloner.
388 */
389
390 static struct if_clone *
391 if_clone_lookup(const char *name, int *unitp)
392 {
393 struct if_clone *ifc;
394 const char *cp;
395 size_t i;
396
397 for (ifc = LIST_FIRST(&if_cloners); ifc != NULL;) {
398 for (cp = name, i = 0; i < ifc->ifc_namelen; i++, cp++) {
399 if (ifc->ifc_name[i] != *cp)
400 goto next_ifc;
401 }
402 goto found_name;
403 next_ifc:
404 ifc = LIST_NEXT(ifc, ifc_list);
405 }
406
407 /* No match. */
408 return ((struct if_clone *)NULL);
409
410 found_name:
411 if (*cp == '\0') {
412 i = -1;
413 } else {
414 for (i = 0; *cp != '\0'; cp++) {
415 if (*cp < '0' || *cp > '9') {
416 /* Bogus unit number. */
417 return (NULL);
418 }
419 i = (i * 10) + (*cp - '0');
420 }
421 }
422
423 if (unitp != NULL)
424 *unitp = i;
425 return (ifc);
426 }
427
428 /*
429 * Register a network interface cloner.
430 */
431 void
432 if_clone_attach(struct if_clone *ifc)
433 {
434 int bytoff, bitoff;
435 int err;
436 int len, maxclone;
437 int unit;
438
439 KASSERT(ifc->ifc_minifs - 1 <= ifc->ifc_maxunit,
440 ("%s: %s requested more units then allowed (%d > %d)",
441 __func__, ifc->ifc_name, ifc->ifc_minifs,
442 ifc->ifc_maxunit + 1));
443 /*
444 * Compute bitmap size and allocate it.
445 */
446 maxclone = ifc->ifc_maxunit + 1;
447 len = maxclone >> 3;
448 if ((len << 3) < maxclone)
449 len++;
450 ifc->ifc_units = _MALLOC(len, M_CLONE, M_WAITOK | M_ZERO);
451 bzero(ifc->ifc_units, len);
452 ifc->ifc_bmlen = len;
453
454 LIST_INSERT_HEAD(&if_cloners, ifc, ifc_list);
455 if_cloners_count++;
456
457 for (unit = 0; unit < ifc->ifc_minifs; unit++) {
458 err = (*ifc->ifc_create)(ifc, unit);
459 KASSERT(err == 0,
460 ("%s: failed to create required interface %s%d",
461 __func__, ifc->ifc_name, unit));
462
463 /* Allocate the unit in the bitmap. */
464 bytoff = unit >> 3;
465 bitoff = unit - (bytoff << 3);
466 ifc->ifc_units[bytoff] |= (1 << bitoff);
467 }
468 }
469
470 /*
471 * Unregister a network interface cloner.
472 */
473 void
474 if_clone_detach(struct if_clone *ifc)
475 {
476
477 LIST_REMOVE(ifc, ifc_list);
478 FREE(ifc->ifc_units, M_CLONE);
479 if_cloners_count--;
480 }
481
482 #ifdef IF_CLONE_LIST
483 /*
484 * Provide list of interface cloners to userspace.
485 */
486 static int
487 if_clone_list(int count, int * total, user_addr_t dst)
488 {
489 char outbuf[IFNAMSIZ];
490 struct if_clone *ifc;
491 int error = 0;
492
493 *total = if_cloners_count;
494 if (dst == USER_ADDR_NULL) {
495 /* Just asking how many there are. */
496 return (0);
497 }
498
499 if (count < 0)
500 return (EINVAL);
501
502 count = (if_cloners_count < count) ? if_cloners_count : count;
503
504 for (ifc = LIST_FIRST(&if_cloners); ifc != NULL && count != 0;
505 ifc = LIST_NEXT(ifc, ifc_list), count--, dst += IFNAMSIZ) {
506 strlcpy(outbuf, ifc->ifc_name, IFNAMSIZ);
507 error = copyout(outbuf, dst, IFNAMSIZ);
508 if (error)
509 break;
510 }
511
512 return (error);
513 }
514 #endif IF_CLONE_LIST
515
516 __private_extern__ int
517 ifa_foraddr(
518 unsigned int addr)
519 {
520 struct ifnet *ifp;
521 struct ifaddr *ifa;
522 unsigned int addr2;
523 int result = 0;
524
525 ifnet_head_lock_shared();
526 for (ifp = ifnet_head.tqh_first; ifp && !result; ifp = ifp->if_link.tqe_next) {
527 ifnet_lock_shared(ifp);
528 for (ifa = ifp->if_addrhead.tqh_first; ifa;
529 ifa = ifa->ifa_link.tqe_next) {
530 if (ifa->ifa_addr->sa_family != AF_INET)
531 continue;
532 addr2 = IA_SIN(ifa)->sin_addr.s_addr;
533
534 if (addr == addr2) {
535 result = 1;
536 break;
537 }
538 }
539 ifnet_lock_done(ifp);
540 }
541 ifnet_head_done();
542
543 return result;
544 }
545
546 /*
547 * Return the first (primary) address of a given family on an interface.
548 */
549 __private_extern__ struct ifaddr *
550 ifa_ifpgetprimary(struct ifnet *ifp, int family)
551 {
552 struct ifaddr *ifa0 = NULL, *ifa;
553
554 ifnet_lock_shared(ifp);
555 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
556 if (ifa->ifa_addr->sa_family == family && ifa0 == NULL) {
557 ifa0 = ifa;
558 break;
559 }
560 }
561 if (ifa0 != NULL)
562 ifaref(ifa0);
563 ifnet_lock_done(ifp);
564
565 return (ifa0);
566 }
567
568 /*
569 * Locate an interface based on a complete address.
570 */
571 /*ARGSUSED*/
572 struct ifaddr *
573 ifa_ifwithaddr(
574 const struct sockaddr *addr)
575 {
576 struct ifnet *ifp;
577 struct ifaddr *ifa;
578 struct ifaddr *result = NULL;
579
580 #define equal(a1, a2) \
581 (bcmp((const void*)(a1), (const void*)(a2), ((const struct sockaddr *)(a1))->sa_len) == 0)
582
583 ifnet_head_lock_shared();
584 for (ifp = ifnet_head.tqh_first; ifp && !result; ifp = ifp->if_link.tqe_next) {
585 ifnet_lock_shared(ifp);
586 for (ifa = ifp->if_addrhead.tqh_first; ifa;
587 ifa = ifa->ifa_link.tqe_next) {
588 if (ifa->ifa_addr->sa_family != addr->sa_family)
589 continue;
590 if (equal(addr, ifa->ifa_addr)) {
591 result = ifa;
592 break;
593 }
594 if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr &&
595 /* IP6 doesn't have broadcast */
596 ifa->ifa_broadaddr->sa_len != 0 &&
597 equal(ifa->ifa_broadaddr, addr)) {
598 result = ifa;
599 break;
600 }
601 }
602 if (result)
603 ifaref(result);
604 ifnet_lock_done(ifp);
605 }
606 ifnet_head_done();
607
608 return result;
609 }
610 /*
611 * Locate the point to point interface with a given destination address.
612 */
613 /*ARGSUSED*/
614 struct ifaddr *
615 ifa_ifwithdstaddr(
616 const struct sockaddr *addr)
617 {
618 struct ifnet *ifp;
619 struct ifaddr *ifa;
620 struct ifaddr *result = NULL;
621
622 ifnet_head_lock_shared();
623 for (ifp = ifnet_head.tqh_first; ifp && !result; ifp = ifp->if_link.tqe_next) {
624 if (ifp->if_flags & IFF_POINTOPOINT) {
625 ifnet_lock_shared(ifp);
626 for (ifa = ifp->if_addrhead.tqh_first; ifa;
627 ifa = ifa->ifa_link.tqe_next) {
628 if (ifa->ifa_addr->sa_family != addr->sa_family)
629 continue;
630 if (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)) {
631 result = ifa;
632 break;
633 }
634 }
635 if (result)
636 ifaref(result);
637 ifnet_lock_done(ifp);
638 }
639 }
640 ifnet_head_done();
641 return result;
642 }
643
644 /*
645 * Find an interface on a specific network. If many, choice
646 * is most specific found.
647 */
648 struct ifaddr *
649 ifa_ifwithnet(
650 const struct sockaddr *addr)
651 {
652 struct ifnet *ifp;
653 struct ifaddr *ifa = NULL;
654 struct ifaddr *ifa_maybe = (struct ifaddr *) 0;
655 u_int af = addr->sa_family;
656 const char *addr_data = addr->sa_data, *cplim;
657
658 ifnet_head_lock_shared();
659 /*
660 * AF_LINK addresses can be looked up directly by their index number,
661 * so do that if we can.
662 */
663 if (af == AF_LINK) {
664 const struct sockaddr_dl *sdl = (const struct sockaddr_dl *)addr;
665 if (sdl->sdl_index && sdl->sdl_index <= if_index) {
666 ifa = ifnet_addrs[sdl->sdl_index - 1];
667
668 if (ifa)
669 ifaref(ifa);
670
671 ifnet_head_done();
672 return ifa;
673 }
674 }
675
676 /*
677 * Scan though each interface, looking for ones that have
678 * addresses in this address family.
679 */
680 for (ifp = ifnet_head.tqh_first; ifp; ifp = ifp->if_link.tqe_next) {
681 ifnet_lock_shared(ifp);
682 for (ifa = ifp->if_addrhead.tqh_first; ifa;
683 ifa = ifa->ifa_link.tqe_next) {
684 const char *cp, *cp2, *cp3;
685
686 if (ifa->ifa_addr->sa_family != af)
687 next: continue;
688 #ifndef __APPLE__
689 /* This breaks tunneling application trying to install a route with
690 * a specific subnet and the local address as the destination
691 * It's breaks binary compatibility with previous version of MacOS X
692 */
693 if (
694
695 #if INET6 /* XXX: for maching gif tunnel dst as routing entry gateway */
696 addr->sa_family != AF_INET6 &&
697 #endif
698 ifp->if_flags & IFF_POINTOPOINT) {
699 /*
700 * This is a bit broken as it doesn't
701 * take into account that the remote end may
702 * be a single node in the network we are
703 * looking for.
704 * The trouble is that we don't know the
705 * netmask for the remote end.
706 */
707 if (ifa->ifa_dstaddr != 0
708 && equal(addr, ifa->ifa_dstaddr)) {
709 break;
710 }
711 } else
712 #endif /* __APPLE__*/
713 {
714 /*
715 * if we have a special address handler,
716 * then use it instead of the generic one.
717 */
718 if (ifa->ifa_claim_addr) {
719 if (ifa->ifa_claim_addr(ifa, addr)) {
720 break;
721 } else {
722 continue;
723 }
724 }
725
726 /*
727 * Scan all the bits in the ifa's address.
728 * If a bit dissagrees with what we are
729 * looking for, mask it with the netmask
730 * to see if it really matters.
731 * (A byte at a time)
732 */
733 if (ifa->ifa_netmask == 0)
734 continue;
735 cp = addr_data;
736 cp2 = ifa->ifa_addr->sa_data;
737 cp3 = ifa->ifa_netmask->sa_data;
738 cplim = ifa->ifa_netmask->sa_len
739 + (char *)ifa->ifa_netmask;
740 while (cp3 < cplim)
741 if ((*cp++ ^ *cp2++) & *cp3++)
742 goto next; /* next address! */
743 /*
744 * If the netmask of what we just found
745 * is more specific than what we had before
746 * (if we had one) then remember the new one
747 * before continuing to search
748 * for an even better one.
749 */
750 if (ifa_maybe == 0 ||
751 rn_refines((caddr_t)ifa->ifa_netmask,
752 (caddr_t)ifa_maybe->ifa_netmask)) {
753 ifaref(ifa);
754 if (ifa_maybe)
755 ifafree(ifa_maybe);
756 ifa_maybe = ifa;
757 }
758 }
759 }
760
761 if (ifa) {
762 ifaref(ifa);
763 }
764
765 /*
766 * ifa is set if we found an exact match.
767 * take a reference to the ifa before
768 * releasing the ifp lock
769 */
770 ifnet_lock_done(ifp);
771
772 if (ifa) {
773 break;
774 }
775 }
776 ifnet_head_done();
777 if (!ifa)
778 ifa = ifa_maybe;
779 else if (ifa_maybe) {
780 ifafree(ifa_maybe);
781 ifa_maybe = NULL;
782 }
783 return ifa;
784 }
785
786 /*
787 * Find an interface address specific to an interface best matching
788 * a given address.
789 */
790 struct ifaddr *
791 ifaof_ifpforaddr(
792 const struct sockaddr *addr,
793 struct ifnet *ifp)
794 {
795 struct ifaddr *ifa = NULL;
796 const char *cp, *cp2, *cp3;
797 char *cplim;
798 struct ifaddr *ifa_maybe = NULL;
799 struct ifaddr *better_ifa_maybe = NULL;
800 u_int af = addr->sa_family;
801
802 if (af >= AF_MAX)
803 return (NULL);
804
805 ifnet_lock_shared(ifp);
806 for (ifa = ifp->if_addrhead.tqh_first; ifa;
807 ifa = ifa->ifa_link.tqe_next) {
808 if (ifa->ifa_addr->sa_family != af)
809 continue;
810 if (ifa_maybe == 0)
811 ifa_maybe = ifa;
812 if (ifa->ifa_netmask == 0) {
813 if (equal(addr, ifa->ifa_addr) ||
814 (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)))
815 break;
816 continue;
817 }
818 if (ifp->if_flags & IFF_POINTOPOINT) {
819 if (equal(addr, ifa->ifa_dstaddr))
820 break;
821 } else {
822 if (equal(addr, ifa->ifa_addr)) {
823 /* exact match */
824 break;
825 }
826 cp = addr->sa_data;
827 cp2 = ifa->ifa_addr->sa_data;
828 cp3 = ifa->ifa_netmask->sa_data;
829 cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
830 for (; cp3 < cplim; cp3++)
831 if ((*cp++ ^ *cp2++) & *cp3)
832 break;
833 if (cp3 == cplim) {
834 /* subnet match */
835 if (better_ifa_maybe == NULL) {
836 better_ifa_maybe = ifa;
837 }
838 }
839 }
840 }
841
842 if (ifa == NULL) {
843 if (better_ifa_maybe != NULL) {
844 ifa = better_ifa_maybe;
845 } else {
846 ifa = ifa_maybe;
847 }
848 }
849 if (ifa) ifaref(ifa);
850
851 ifnet_lock_done(ifp);
852 return ifa;
853 }
854
855 #include <net/route.h>
856
857 /*
858 * Default action when installing a route with a Link Level gateway.
859 * Lookup an appropriate real ifa to point to.
860 * This should be moved to /sys/net/link.c eventually.
861 */
862 void
863 link_rtrequest(int cmd, struct rtentry *rt, struct sockaddr *sa)
864 {
865 struct ifaddr *ifa;
866 struct sockaddr *dst;
867 struct ifnet *ifp;
868
869 if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) ||
870 ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0))
871 return;
872 ifa = ifaof_ifpforaddr(dst, ifp);
873 if (ifa) {
874 rtsetifa(rt, ifa);
875 if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
876 ifa->ifa_rtrequest(cmd, rt, sa);
877 ifafree(ifa);
878 }
879 }
880
881 /*
882 * if_updown will set the interface up or down. It will
883 * prevent other up/down events from occurring until this
884 * up/down event has completed.
885 *
886 * Caller must lock ifnet. This function will drop the
887 * lock. This allows ifnet_set_flags to set the rest of
888 * the flags after we change the up/down state without
889 * dropping the interface lock between setting the
890 * up/down state and updating the rest of the flags.
891 */
892 __private_extern__ void
893 if_updown(
894 struct ifnet *ifp,
895 int up)
896 {
897 int i;
898 struct ifaddr **ifa;
899 struct timespec tv;
900
901 /* Wait until no one else is changing the up/down state */
902 while ((ifp->if_eflags & IFEF_UPDOWNCHANGE) != 0) {
903 tv.tv_sec = 0;
904 tv.tv_nsec = NSEC_PER_SEC / 10;
905 ifnet_lock_done(ifp);
906 msleep(&ifp->if_eflags, NULL, 0, "if_updown", &tv);
907 ifnet_lock_exclusive(ifp);
908 }
909
910 /* Verify that the interface isn't already in the right state */
911 if ((!up && (ifp->if_flags & IFF_UP) == 0) ||
912 (up && (ifp->if_flags & IFF_UP) == IFF_UP)) {
913 return;
914 }
915
916 /* Indicate that the up/down state is changing */
917 ifp->if_eflags |= IFEF_UPDOWNCHANGE;
918
919 /* Mark interface up or down */
920 if (up) {
921 ifp->if_flags |= IFF_UP;
922 }
923 else {
924 ifp->if_flags &= ~IFF_UP;
925 }
926
927 ifnet_touch_lastchange(ifp);
928
929 /* Drop the lock to notify addresses and route */
930 ifnet_lock_done(ifp);
931 if (ifnet_get_address_list(ifp, &ifa) == 0) {
932 for (i = 0; ifa[i] != 0; i++) {
933 pfctlinput(up ? PRC_IFUP : PRC_IFDOWN, ifa[i]->ifa_addr);
934 }
935 ifnet_free_address_list(ifa);
936 }
937 rt_ifmsg(ifp);
938
939 /* Aquire the lock to clear the changing flag and flush the send queue */
940 ifnet_lock_exclusive(ifp);
941 if (!up)
942 if_qflush(&ifp->if_snd);
943 ifp->if_eflags &= ~IFEF_UPDOWNCHANGE;
944 wakeup(&ifp->if_eflags);
945
946 return;
947 }
948
949 /*
950 * Mark an interface down and notify protocols of
951 * the transition.
952 */
953 void
954 if_down(
955 struct ifnet *ifp)
956 {
957 ifnet_lock_exclusive(ifp);
958 if_updown(ifp, 0);
959 ifnet_lock_done(ifp);
960 }
961
962 /*
963 * Mark an interface up and notify protocols of
964 * the transition.
965 */
966 void
967 if_up(
968 struct ifnet *ifp)
969 {
970 ifnet_lock_exclusive(ifp);
971 if_updown(ifp, 1);
972 ifnet_lock_done(ifp);
973 }
974
975 /*
976 * Flush an interface queue.
977 */
978 static void
979 if_qflush(struct ifqueue *ifq)
980 {
981 struct mbuf *m, *n;
982
983 n = ifq->ifq_head;
984 while ((m = n) != 0) {
985 n = m->m_act;
986 m_freem(m);
987 }
988 ifq->ifq_head = NULL;
989 ifq->ifq_tail = NULL;
990 ifq->ifq_len = 0;
991 }
992
993 /*
994 * Map interface name to
995 * interface structure pointer.
996 */
997 struct ifnet *
998 ifunit(const char *name)
999 {
1000 char namebuf[IFNAMSIZ + 1];
1001 const char *cp;
1002 struct ifnet *ifp;
1003 int unit;
1004 unsigned len, m;
1005 char c;
1006
1007 len = strlen(name);
1008 if (len < 2 || len > IFNAMSIZ)
1009 return NULL;
1010 cp = name + len - 1;
1011 c = *cp;
1012 if (c < '0' || c > '9')
1013 return NULL; /* trailing garbage */
1014 unit = 0;
1015 m = 1;
1016 do {
1017 if (cp == name)
1018 return NULL; /* no interface name */
1019 unit += (c - '0') * m;
1020 if (unit > 1000000)
1021 return NULL; /* number is unreasonable */
1022 m *= 10;
1023 c = *--cp;
1024 } while (c >= '0' && c <= '9');
1025 len = cp - name + 1;
1026 bcopy(name, namebuf, len);
1027 namebuf[len] = '\0';
1028 /*
1029 * Now search all the interfaces for this name/number
1030 */
1031 ifnet_head_lock_shared();
1032 TAILQ_FOREACH(ifp, &ifnet_head, if_link) {
1033 if (strncmp(ifp->if_name, namebuf, len))
1034 continue;
1035 if (unit == ifp->if_unit)
1036 break;
1037 }
1038 ifnet_head_done();
1039 return (ifp);
1040 }
1041
1042
1043 /*
1044 * Map interface name in a sockaddr_dl to
1045 * interface structure pointer.
1046 */
1047 struct ifnet *
1048 if_withname(struct sockaddr *sa)
1049 {
1050 char ifname[IFNAMSIZ+1];
1051 struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;
1052
1053 if ( (sa->sa_family != AF_LINK) || (sdl->sdl_nlen == 0) ||
1054 (sdl->sdl_nlen > IFNAMSIZ) )
1055 return NULL;
1056
1057 /*
1058 * ifunit wants a null-terminated name. It may not be null-terminated
1059 * in the sockaddr. We don't want to change the caller's sockaddr,
1060 * and there might not be room to put the trailing null anyway, so we
1061 * make a local copy that we know we can null terminate safely.
1062 */
1063
1064 bcopy(sdl->sdl_data, ifname, sdl->sdl_nlen);
1065 ifname[sdl->sdl_nlen] = '\0';
1066 return ifunit(ifname);
1067 }
1068
1069
1070 /*
1071 * Interface ioctls.
1072 */
1073 int
1074 ifioctl(struct socket *so, u_long cmd, caddr_t data, struct proc *p)
1075 {
1076 struct ifnet *ifp;
1077 struct ifreq *ifr;
1078 struct ifstat *ifs;
1079 int error = 0;
1080 short oif_flags;
1081 struct kev_msg ev_msg;
1082 struct net_event_data ev_data;
1083
1084 switch (cmd) {
1085 case SIOCGIFCONF:
1086 case OSIOCGIFCONF:
1087 case SIOCGIFCONF64:
1088 {
1089 struct ifconf64 * ifc = (struct ifconf64 *)data;
1090 user_addr_t user_addr;
1091
1092 user_addr = proc_is64bit(p)
1093 ? ifc->ifc_req64 : CAST_USER_ADDR_T(ifc->ifc_req);
1094 return (ifconf(cmd, user_addr, &ifc->ifc_len));
1095 }
1096 break;
1097 }
1098 ifr = (struct ifreq *)data;
1099 switch (cmd) {
1100 case SIOCIFCREATE:
1101 case SIOCIFDESTROY:
1102 error = proc_suser(p);
1103 if (error)
1104 return (error);
1105 return ((cmd == SIOCIFCREATE) ?
1106 if_clone_create(ifr->ifr_name, sizeof(ifr->ifr_name)) :
1107 if_clone_destroy(ifr->ifr_name));
1108 #if IF_CLONE_LIST
1109 case SIOCIFGCLONERS:
1110 case SIOCIFGCLONERS64:
1111 {
1112 struct if_clonereq64 * ifcr = (struct if_clonereq64 *)data;
1113 user_addr = proc_is64bit(p)
1114 ? ifcr->ifcr_ifcru.ifcru_buffer64
1115 : CAST_USER_ADDR_T(ifcr->ifcr_ifcru.ifcru_buffer32);
1116 return (if_clone_list(ifcr->ifcr_count, &ifcr->ifcr_total,
1117 user_data));
1118 }
1119 #endif IF_CLONE_LIST
1120 }
1121
1122 ifp = ifunit(ifr->ifr_name);
1123 if (ifp == 0)
1124 return (ENXIO);
1125 switch (cmd) {
1126
1127 case SIOCGIFFLAGS:
1128 ifnet_lock_shared(ifp);
1129 ifr->ifr_flags = ifp->if_flags;
1130 ifnet_lock_done(ifp);
1131 break;
1132
1133 #if CONFIG_MACF_NET
1134 case SIOCGIFMAC:
1135 error = mac_ifnet_label_get(kauth_cred_get(), ifr, ifp);
1136 if (error)
1137 return (error);
1138 break;
1139 #endif
1140 case SIOCGIFMETRIC:
1141 ifnet_lock_shared(ifp);
1142 ifr->ifr_metric = ifp->if_metric;
1143 ifnet_lock_done(ifp);
1144 break;
1145
1146 case SIOCGIFMTU:
1147 ifnet_lock_shared(ifp);
1148 ifr->ifr_mtu = ifp->if_mtu;
1149 ifnet_lock_done(ifp);
1150 break;
1151
1152 case SIOCGIFPHYS:
1153 ifnet_lock_shared(ifp);
1154 ifr->ifr_phys = ifp->if_physical;
1155 ifnet_lock_done(ifp);
1156 break;
1157
1158 case SIOCSIFFLAGS:
1159 error = proc_suser(p);
1160 if (error)
1161 return (error);
1162
1163 ifnet_set_flags(ifp, ifr->ifr_flags, (u_int16_t)~IFF_CANTCHANGE);
1164
1165 error = ifnet_ioctl(ifp, so->so_proto->pr_domain->dom_family,
1166 cmd, data);
1167
1168 if (error == 0) {
1169 ev_msg.vendor_code = KEV_VENDOR_APPLE;
1170 ev_msg.kev_class = KEV_NETWORK_CLASS;
1171 ev_msg.kev_subclass = KEV_DL_SUBCLASS;
1172
1173 ev_msg.event_code = KEV_DL_SIFFLAGS;
1174 strlcpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ);
1175 ev_data.if_family = ifp->if_family;
1176 ev_data.if_unit = (unsigned long) ifp->if_unit;
1177 ev_msg.dv[0].data_length = sizeof(struct net_event_data);
1178 ev_msg.dv[0].data_ptr = &ev_data;
1179 ev_msg.dv[1].data_length = 0;
1180 kev_post_msg(&ev_msg);
1181 }
1182 ifnet_touch_lastchange(ifp);
1183 break;
1184
1185 #if CONFIG_MACF_NET
1186 case SIOCSIFMAC:
1187 error = mac_ifnet_label_set(kauth_cred_get(), ifr, ifp);
1188 if (error)
1189 return (error);
1190 break;
1191 #endif
1192 case SIOCSIFMETRIC:
1193 error = proc_suser(p);
1194 if (error)
1195 return (error);
1196 ifp->if_metric = ifr->ifr_metric;
1197
1198
1199 ev_msg.vendor_code = KEV_VENDOR_APPLE;
1200 ev_msg.kev_class = KEV_NETWORK_CLASS;
1201 ev_msg.kev_subclass = KEV_DL_SUBCLASS;
1202
1203 ev_msg.event_code = KEV_DL_SIFMETRICS;
1204 strlcpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ);
1205 ev_data.if_family = ifp->if_family;
1206 ev_data.if_unit = (unsigned long) ifp->if_unit;
1207 ev_msg.dv[0].data_length = sizeof(struct net_event_data);
1208 ev_msg.dv[0].data_ptr = &ev_data;
1209
1210 ev_msg.dv[1].data_length = 0;
1211 kev_post_msg(&ev_msg);
1212
1213 ifnet_touch_lastchange(ifp);
1214 break;
1215
1216 case SIOCSIFPHYS:
1217 error = proc_suser(p);
1218 if (error)
1219 return error;
1220
1221 error = ifnet_ioctl(ifp, so->so_proto->pr_domain->dom_family,
1222 cmd, data);
1223
1224 if (error == 0) {
1225 ev_msg.vendor_code = KEV_VENDOR_APPLE;
1226 ev_msg.kev_class = KEV_NETWORK_CLASS;
1227 ev_msg.kev_subclass = KEV_DL_SUBCLASS;
1228
1229 ev_msg.event_code = KEV_DL_SIFPHYS;
1230 strlcpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ);
1231 ev_data.if_family = ifp->if_family;
1232 ev_data.if_unit = (unsigned long) ifp->if_unit;
1233 ev_msg.dv[0].data_length = sizeof(struct net_event_data);
1234 ev_msg.dv[0].data_ptr = &ev_data;
1235 ev_msg.dv[1].data_length = 0;
1236 kev_post_msg(&ev_msg);
1237
1238 ifnet_touch_lastchange(ifp);
1239 }
1240 return(error);
1241
1242 case SIOCSIFMTU:
1243 {
1244 u_long oldmtu = ifp->if_mtu;
1245
1246 error = proc_suser(p);
1247 if (error)
1248 return (error);
1249 if (ifp->if_ioctl == NULL)
1250 return (EOPNOTSUPP);
1251 if (ifr->ifr_mtu < IF_MINMTU || ifr->ifr_mtu > IF_MAXMTU)
1252 return (EINVAL);
1253
1254 error = ifnet_ioctl(ifp, so->so_proto->pr_domain->dom_family,
1255 cmd, data);
1256
1257 if (error == 0) {
1258 ev_msg.vendor_code = KEV_VENDOR_APPLE;
1259 ev_msg.kev_class = KEV_NETWORK_CLASS;
1260 ev_msg.kev_subclass = KEV_DL_SUBCLASS;
1261
1262 ev_msg.event_code = KEV_DL_SIFMTU;
1263 strlcpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ);
1264 ev_data.if_family = ifp->if_family;
1265 ev_data.if_unit = (unsigned long) ifp->if_unit;
1266 ev_msg.dv[0].data_length = sizeof(struct net_event_data);
1267 ev_msg.dv[0].data_ptr = &ev_data;
1268 ev_msg.dv[1].data_length = 0;
1269 kev_post_msg(&ev_msg);
1270
1271 ifnet_touch_lastchange(ifp);
1272 rt_ifmsg(ifp);
1273 }
1274 /*
1275 * If the link MTU changed, do network layer specific procedure
1276 * and update all route entries associated with the interface,
1277 * so that their MTU metric gets updated.
1278 */
1279 if (error == 0 && ifp->if_mtu != oldmtu) {
1280 if_rtmtu_update(ifp);
1281 #if INET6
1282 nd6_setmtu(ifp);
1283 #endif
1284 }
1285 return (error);
1286 }
1287
1288 case SIOCADDMULTI:
1289 case SIOCDELMULTI:
1290 error = proc_suser(p);
1291 if (error)
1292 return (error);
1293
1294 /* Don't allow group membership on non-multicast interfaces. */
1295 if ((ifp->if_flags & IFF_MULTICAST) == 0)
1296 return EOPNOTSUPP;
1297
1298 #ifndef __APPLE__
1299 /* Don't let users screw up protocols' entries. */
1300 if (ifr->ifr_addr.sa_family != AF_LINK)
1301 return EINVAL;
1302 #endif
1303
1304 if (cmd == SIOCADDMULTI) {
1305 error = if_addmulti(ifp, &ifr->ifr_addr, NULL);
1306 ev_msg.event_code = KEV_DL_ADDMULTI;
1307 } else {
1308 error = if_delmulti(ifp, &ifr->ifr_addr);
1309 ev_msg.event_code = KEV_DL_DELMULTI;
1310 }
1311 if (error == 0) {
1312 ev_msg.vendor_code = KEV_VENDOR_APPLE;
1313 ev_msg.kev_class = KEV_NETWORK_CLASS;
1314 ev_msg.kev_subclass = KEV_DL_SUBCLASS;
1315 strlcpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ);
1316
1317 ev_data.if_family = ifp->if_family;
1318 ev_data.if_unit = (unsigned long) ifp->if_unit;
1319 ev_msg.dv[0].data_length = sizeof(struct net_event_data);
1320 ev_msg.dv[0].data_ptr = &ev_data;
1321 ev_msg.dv[1].data_length = 0;
1322 kev_post_msg(&ev_msg);
1323
1324 ifnet_touch_lastchange(ifp);
1325 }
1326 return error;
1327
1328 case SIOCSIFPHYADDR:
1329 case SIOCDIFPHYADDR:
1330 #if INET6
1331 case SIOCSIFPHYADDR_IN6:
1332 #endif
1333 case SIOCSLIFPHYADDR:
1334 case SIOCSIFMEDIA:
1335 case SIOCSIFGENERIC:
1336 case SIOCSIFLLADDR:
1337 case SIOCSIFALTMTU:
1338 case SIOCSIFVLAN:
1339 case SIOCSIFBOND:
1340 error = proc_suser(p);
1341 if (error)
1342 return (error);
1343
1344 error = ifnet_ioctl(ifp, so->so_proto->pr_domain->dom_family,
1345 cmd, data);
1346
1347 if (error == 0)
1348 ifnet_touch_lastchange(ifp);
1349 return error;
1350
1351 case SIOCGIFSTATUS:
1352 ifs = (struct ifstat *)data;
1353 ifs->ascii[0] = '\0';
1354
1355 case SIOCGIFPSRCADDR:
1356 case SIOCGIFPDSTADDR:
1357 case SIOCGLIFPHYADDR:
1358 case SIOCGIFMEDIA:
1359 case SIOCGIFGENERIC:
1360 case SIOCGIFDEVMTU:
1361 return ifnet_ioctl(ifp, so->so_proto->pr_domain->dom_family,
1362 cmd, data);
1363 case SIOCGIFVLAN:
1364 case SIOCGIFBOND:
1365 return ifnet_ioctl(ifp, so->so_proto->pr_domain->dom_family,
1366 cmd, data);
1367
1368 default:
1369 oif_flags = ifp->if_flags;
1370 if (so->so_proto == 0)
1371 return (EOPNOTSUPP);
1372 {
1373 int ocmd = cmd;
1374
1375 switch (cmd) {
1376
1377 case SIOCSIFDSTADDR:
1378 case SIOCSIFADDR:
1379 case SIOCSIFBRDADDR:
1380 case SIOCSIFNETMASK:
1381 #if BYTE_ORDER != BIG_ENDIAN
1382 if (ifr->ifr_addr.sa_family == 0 &&
1383 ifr->ifr_addr.sa_len < 16) {
1384 ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len;
1385 ifr->ifr_addr.sa_len = 16;
1386 }
1387 #else
1388 if (ifr->ifr_addr.sa_len == 0)
1389 ifr->ifr_addr.sa_len = 16;
1390 #endif
1391 break;
1392
1393 case OSIOCGIFADDR:
1394 cmd = SIOCGIFADDR;
1395 break;
1396
1397 case OSIOCGIFDSTADDR:
1398 cmd = SIOCGIFDSTADDR;
1399 break;
1400
1401 case OSIOCGIFBRDADDR:
1402 cmd = SIOCGIFBRDADDR;
1403 break;
1404
1405 case OSIOCGIFNETMASK:
1406 cmd = SIOCGIFNETMASK;
1407 }
1408 socket_lock(so, 1);
1409 error = ((*so->so_proto->pr_usrreqs->pru_control)(so, cmd,
1410 data, ifp, p));
1411 socket_unlock(so, 1);
1412 switch (ocmd) {
1413
1414 case OSIOCGIFADDR:
1415 case OSIOCGIFDSTADDR:
1416 case OSIOCGIFBRDADDR:
1417 case OSIOCGIFNETMASK:
1418 *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family;
1419
1420 }
1421 }
1422 if (cmd == SIOCSIFKPI) {
1423 int temperr = proc_suser(p);
1424 if (temperr != 0)
1425 error = temperr;
1426 }
1427
1428 if (error == EOPNOTSUPP || error == ENOTSUP)
1429 error = ifnet_ioctl(ifp, so->so_proto->pr_domain->dom_family,
1430 cmd, data);
1431
1432 return (error);
1433 }
1434 return (0);
1435 }
1436
1437 int
1438 ifioctllocked(struct socket *so, u_long cmd, caddr_t data, struct proc *p)
1439 {
1440 int error;
1441
1442 socket_unlock(so, 0);
1443 error = ifioctl(so, cmd, data, p);
1444 socket_lock(so, 0);
1445 return(error);
1446 }
1447
1448 /*
1449 * Set/clear promiscuous mode on interface ifp based on the truth value
1450 * of pswitch. The calls are reference counted so that only the first
1451 * "on" request actually has an effect, as does the final "off" request.
1452 * Results are undefined if the "off" and "on" requests are not matched.
1453 */
1454 errno_t
1455 ifnet_set_promiscuous(
1456 ifnet_t ifp,
1457 int pswitch)
1458 {
1459 struct ifreq ifr;
1460 int error = 0;
1461 int oldflags;
1462 int locked = 0;
1463 int changed = 0;
1464
1465 ifnet_lock_exclusive(ifp);
1466 locked = 1;
1467 oldflags = ifp->if_flags;
1468 if (pswitch) {
1469 /*
1470 * If the device is not configured up, we cannot put it in
1471 * promiscuous mode.
1472 */
1473 if ((ifp->if_flags & IFF_UP) == 0) {
1474 error = ENETDOWN;
1475 goto done;
1476 }
1477 if (ifp->if_pcount++ != 0) {
1478 goto done;
1479 }
1480 ifp->if_flags |= IFF_PROMISC;
1481 } else {
1482 if (--ifp->if_pcount > 0)
1483 goto done;
1484 ifp->if_flags &= ~IFF_PROMISC;
1485 }
1486 ifr.ifr_flags = ifp->if_flags;
1487 locked = 0;
1488 ifnet_lock_done(ifp);
1489 error = ifnet_ioctl(ifp, 0, SIOCSIFFLAGS, &ifr);
1490 if (error == 0)
1491 rt_ifmsg(ifp);
1492 else
1493 ifp->if_flags = oldflags;
1494 done:
1495 if (locked) ifnet_lock_done(ifp);
1496 if (changed) {
1497 log(LOG_INFO, "%s%d: promiscuous mode %s\n",
1498 ifp->if_name, ifp->if_unit,
1499 pswitch != 0 ? "enabled" : "disabled");
1500 }
1501 return error;
1502 }
1503
1504 /*
1505 * Return interface configuration
1506 * of system. List may be used
1507 * in later ioctl's (above) to get
1508 * other information.
1509 */
1510 /*ARGSUSED*/
1511 static int
1512 ifconf(u_long cmd, user_addr_t ifrp, int * ret_space)
1513 {
1514 struct ifnet *ifp = NULL;
1515 struct ifaddr *ifa;
1516 struct ifreq ifr;
1517 int error = 0;
1518 size_t space;
1519
1520 /*
1521 * Zero the ifr buffer to make sure we don't
1522 * disclose the contents of the stack.
1523 */
1524 bzero(&ifr, sizeof(struct ifreq));
1525
1526 space = *ret_space;
1527 ifnet_head_lock_shared();
1528 for (ifp = ifnet_head.tqh_first; space > sizeof(ifr) && ifp; ifp = ifp->if_link.tqe_next) {
1529 char workbuf[64];
1530 size_t ifnlen, addrs;
1531
1532 ifnlen = snprintf(workbuf, sizeof(workbuf),
1533 "%s%d", ifp->if_name, ifp->if_unit);
1534 if(ifnlen + 1 > sizeof ifr.ifr_name) {
1535 error = ENAMETOOLONG;
1536 break;
1537 } else {
1538 strlcpy(ifr.ifr_name, workbuf, IFNAMSIZ);
1539 }
1540
1541 ifnet_lock_shared(ifp);
1542
1543 addrs = 0;
1544 ifa = ifp->if_addrhead.tqh_first;
1545 for ( ; space > sizeof (ifr) && ifa;
1546 ifa = ifa->ifa_link.tqe_next) {
1547 struct sockaddr *sa = ifa->ifa_addr;
1548 #ifndef __APPLE__
1549 if (curproc->p_prison && prison_if(curproc, sa))
1550 continue;
1551 #endif
1552 addrs++;
1553 if (cmd == OSIOCGIFCONF) {
1554 struct osockaddr *osa =
1555 (struct osockaddr *)&ifr.ifr_addr;
1556 ifr.ifr_addr = *sa;
1557 osa->sa_family = sa->sa_family;
1558 error = copyout((caddr_t)&ifr, ifrp, sizeof(ifr));
1559 ifrp += sizeof(struct ifreq);
1560 } else if (sa->sa_len <= sizeof(*sa)) {
1561 ifr.ifr_addr = *sa;
1562 error = copyout((caddr_t)&ifr, ifrp, sizeof(ifr));
1563 ifrp += sizeof(struct ifreq);
1564 } else {
1565 if (space < sizeof (ifr) + sa->sa_len - sizeof(*sa))
1566 break;
1567 space -= sa->sa_len - sizeof(*sa);
1568 error = copyout((caddr_t)&ifr, ifrp, sizeof (ifr.ifr_name));
1569 if (error == 0) {
1570 error = copyout((caddr_t)sa,
1571 (ifrp + offsetof(struct ifreq, ifr_addr)),
1572 sa->sa_len);
1573 }
1574 ifrp += (sa->sa_len + offsetof(struct ifreq, ifr_addr));
1575 }
1576 if (error)
1577 break;
1578 space -= sizeof (ifr);
1579 }
1580 ifnet_lock_done(ifp);
1581
1582 if (error)
1583 break;
1584 if (!addrs) {
1585 bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
1586 error = copyout((caddr_t)&ifr, ifrp, sizeof (ifr));
1587 if (error)
1588 break;
1589 space -= sizeof (ifr);
1590 ifrp += sizeof(struct ifreq);
1591 }
1592 }
1593 ifnet_head_done();
1594 *ret_space -= space;
1595 return (error);
1596 }
1597
1598 /*
1599 * Just like if_promisc(), but for all-multicast-reception mode.
1600 */
1601 int
1602 if_allmulti(struct ifnet *ifp, int onswitch)
1603 {
1604 int error = 0;
1605 int modified = 0;
1606
1607 ifnet_lock_exclusive(ifp);
1608
1609 if (onswitch) {
1610 if (ifp->if_amcount++ == 0) {
1611 ifp->if_flags |= IFF_ALLMULTI;
1612 modified = 1;
1613 }
1614 } else {
1615 if (ifp->if_amcount > 1) {
1616 ifp->if_amcount--;
1617 } else {
1618 ifp->if_amcount = 0;
1619 ifp->if_flags &= ~IFF_ALLMULTI;
1620 modified = 1;
1621 }
1622 }
1623 ifnet_lock_done(ifp);
1624
1625 if (modified)
1626 error = ifnet_ioctl(ifp, 0, SIOCSIFFLAGS, NULL);
1627
1628 if (error == 0)
1629 rt_ifmsg(ifp);
1630 return error;
1631 }
1632
1633 void
1634 ifma_reference(
1635 struct ifmultiaddr *ifma)
1636 {
1637 if (OSIncrementAtomic((SInt32 *)&ifma->ifma_refcount) <= 0)
1638 panic("ifma_reference: ifma already released or invalid\n");
1639 }
1640
1641 void
1642 ifma_release(
1643 struct ifmultiaddr *ifma)
1644 {
1645 while (ifma) {
1646 struct ifmultiaddr *next;
1647 int32_t prevValue = OSDecrementAtomic((SInt32 *)&ifma->ifma_refcount);
1648 if (prevValue < 1)
1649 panic("ifma_release: ifma already released or invalid\n");
1650 if (prevValue != 1)
1651 break;
1652
1653 /* Allow the allocator of the protospec to free it */
1654 if (ifma->ifma_protospec && ifma->ifma_free) {
1655 ifma->ifma_free(ifma->ifma_protospec);
1656 }
1657
1658 next = ifma->ifma_ll;
1659 FREE(ifma->ifma_addr, M_IFMADDR);
1660 FREE(ifma, M_IFMADDR);
1661 ifma = next;
1662 }
1663 }
1664
1665 /*
1666 * Find an ifmultiaddr that matches a socket address on an interface.
1667 *
1668 * Caller is responsible for holding the ifnet_lock while calling
1669 * this function.
1670 */
1671 static int
1672 if_addmulti_doesexist(
1673 struct ifnet *ifp,
1674 const struct sockaddr *sa,
1675 struct ifmultiaddr **retifma)
1676 {
1677 struct ifmultiaddr *ifma;
1678 for (ifma = ifp->if_multiaddrs.lh_first; ifma;
1679 ifma = ifma->ifma_link.le_next) {
1680 if (equal(sa, ifma->ifma_addr)) {
1681 ifma->ifma_usecount++;
1682 if (retifma) {
1683 *retifma = ifma;
1684 ifma_reference(*retifma);
1685 }
1686 return 0;
1687 }
1688 }
1689
1690 return ENOENT;
1691 }
1692
1693 /*
1694 * Radar 3642395, make sure all multicasts are in a standard format.
1695 */
1696 static struct sockaddr*
1697 copy_and_normalize(
1698 const struct sockaddr *original)
1699 {
1700 int alen = 0;
1701 const u_char *aptr = NULL;
1702 struct sockaddr *copy = NULL;
1703 struct sockaddr_dl *sdl_new = NULL;
1704 int len = 0;
1705
1706 if (original->sa_family != AF_LINK &&
1707 original->sa_family != AF_UNSPEC) {
1708 /* Just make a copy */
1709 MALLOC(copy, struct sockaddr*, original->sa_len, M_IFADDR, M_WAITOK);
1710 if (copy != NULL)
1711 bcopy(original, copy, original->sa_len);
1712 return copy;
1713 }
1714
1715 switch (original->sa_family) {
1716 case AF_LINK: {
1717 const struct sockaddr_dl *sdl_original =
1718 (const struct sockaddr_dl*)original;
1719
1720 if (sdl_original->sdl_nlen + sdl_original->sdl_alen + sdl_original->sdl_slen +
1721 offsetof(struct sockaddr_dl, sdl_data) > sdl_original->sdl_len)
1722 return NULL;
1723
1724 alen = sdl_original->sdl_alen;
1725 aptr = CONST_LLADDR(sdl_original);
1726 }
1727 break;
1728
1729 case AF_UNSPEC: {
1730 if (original->sa_len < ETHER_ADDR_LEN +
1731 offsetof(struct sockaddr, sa_data)) {
1732 return NULL;
1733 }
1734
1735 alen = ETHER_ADDR_LEN;
1736 aptr = (const u_char*)original->sa_data;
1737 }
1738 break;
1739 }
1740
1741 if (alen == 0 || aptr == NULL)
1742 return NULL;
1743
1744 len = alen + offsetof(struct sockaddr_dl, sdl_data);
1745 MALLOC(sdl_new, struct sockaddr_dl*, len, M_IFADDR, M_WAITOK);
1746
1747 if (sdl_new != NULL) {
1748 bzero(sdl_new, len);
1749 sdl_new->sdl_len = len;
1750 sdl_new->sdl_family = AF_LINK;
1751 sdl_new->sdl_alen = alen;
1752 bcopy(aptr, LLADDR(sdl_new), alen);
1753 }
1754
1755 return (struct sockaddr*)sdl_new;
1756 }
1757
1758 /*
1759 * Add a multicast listenership to the interface in question.
1760 * The link layer provides a routine which converts
1761 */
1762 int
1763 if_addmulti(
1764 struct ifnet *ifp, /* interface to manipulate */
1765 const struct sockaddr *sa, /* address to add */
1766 struct ifmultiaddr **retifma)
1767 {
1768 struct sockaddr_storage storage;
1769 struct sockaddr *llsa = NULL;
1770 struct sockaddr *dupsa = NULL;
1771 int error = 0;
1772 struct ifmultiaddr *ifma = NULL;
1773 struct ifmultiaddr *llifma = NULL;
1774
1775 /* If sa is a AF_LINK or AF_UNSPEC, duplicate and normalize it */
1776 if (sa->sa_family == AF_LINK || sa->sa_family == AF_UNSPEC) {
1777 dupsa = copy_and_normalize(sa);
1778 if (dupsa == NULL) {
1779 return ENOMEM;
1780 }
1781 sa = dupsa;
1782 }
1783
1784 ifnet_lock_exclusive(ifp);
1785 error = if_addmulti_doesexist(ifp, sa, retifma);
1786 ifnet_lock_done(ifp);
1787
1788 if (error == 0) {
1789 goto cleanup;
1790 }
1791
1792 /*
1793 * Give the link layer a chance to accept/reject it, and also
1794 * find out which AF_LINK address this maps to, if it isn't one
1795 * already.
1796 */
1797 error = dlil_resolve_multi(ifp, sa, (struct sockaddr*)&storage,
1798 sizeof(storage));
1799 if (error == 0 && storage.ss_len != 0) {
1800 llsa = copy_and_normalize((struct sockaddr*)&storage);
1801 if (llsa == NULL) {
1802 error = ENOMEM;
1803 goto cleanup;
1804 }
1805
1806 MALLOC(llifma, struct ifmultiaddr *, sizeof *llifma, M_IFMADDR, M_WAITOK);
1807 if (llifma == NULL) {
1808 error = ENOMEM;
1809 goto cleanup;
1810 }
1811 }
1812
1813 /* to be similar to FreeBSD */
1814 if (error == EOPNOTSUPP) {
1815 error = 0;
1816 }
1817 else if (error) {
1818 goto cleanup;
1819 }
1820
1821 /* Allocate while we aren't holding any locks */
1822 if (dupsa == NULL) {
1823 dupsa = copy_and_normalize(sa);
1824 if (dupsa == NULL) {
1825 error = ENOMEM;
1826 goto cleanup;
1827 }
1828 }
1829 MALLOC(ifma, struct ifmultiaddr *, sizeof *ifma, M_IFMADDR, M_WAITOK);
1830 if (ifma == NULL) {
1831 error = ENOMEM;
1832 goto cleanup;
1833 }
1834
1835 ifnet_lock_exclusive(ifp);
1836 /*
1837 * Check again for the matching multicast.
1838 */
1839 if ((error = if_addmulti_doesexist(ifp, sa, retifma)) == 0) {
1840 ifnet_lock_done(ifp);
1841 goto cleanup;
1842 }
1843
1844 bzero(ifma, sizeof(*ifma));
1845 ifma->ifma_addr = dupsa;
1846 ifma->ifma_ifp = ifp;
1847 ifma->ifma_usecount = 1;
1848 ifma->ifma_refcount = 1;
1849
1850 if (llifma != 0) {
1851 if (if_addmulti_doesexist(ifp, llsa, &ifma->ifma_ll) == 0) {
1852 FREE(llsa, M_IFMADDR);
1853 FREE(llifma, M_IFMADDR);
1854 } else {
1855 bzero(llifma, sizeof(*llifma));
1856 llifma->ifma_addr = llsa;
1857 llifma->ifma_ifp = ifp;
1858 llifma->ifma_usecount = 1;
1859 llifma->ifma_refcount = 1;
1860 LIST_INSERT_HEAD(&ifp->if_multiaddrs, llifma, ifma_link);
1861
1862 ifma->ifma_ll = llifma;
1863 ifma_reference(ifma->ifma_ll);
1864 }
1865 }
1866
1867 LIST_INSERT_HEAD(&ifp->if_multiaddrs, ifma, ifma_link);
1868
1869 if (retifma) {
1870 *retifma = ifma;
1871 ifma_reference(*retifma);
1872 }
1873
1874 ifnet_lock_done(ifp);
1875
1876 if (llsa != 0)
1877 rt_newmaddrmsg(RTM_NEWMADDR, ifma);
1878
1879 /*
1880 * We are certain we have added something, so call down to the
1881 * interface to let them know about it.
1882 */
1883 ifnet_ioctl(ifp, 0, SIOCADDMULTI, NULL);
1884
1885 return 0;
1886
1887 cleanup:
1888 if (ifma)
1889 FREE(ifma, M_IFADDR);
1890 if (dupsa)
1891 FREE(dupsa, M_IFADDR);
1892 if (llifma)
1893 FREE(llifma, M_IFADDR);
1894 if (llsa)
1895 FREE(llsa, M_IFADDR);
1896
1897 return error;
1898 }
1899
1900 int
1901 if_delmultiaddr(
1902 struct ifmultiaddr *ifma,
1903 int locked)
1904 {
1905 struct ifnet *ifp;
1906 int do_del_multi = 0;
1907
1908 ifp = ifma->ifma_ifp;
1909
1910 if (!locked && ifp) {
1911 ifnet_lock_exclusive(ifp);
1912 }
1913
1914 while (ifma != NULL) {
1915 struct ifmultiaddr *ll_ifma;
1916
1917 if (ifma->ifma_usecount > 1) {
1918 ifma->ifma_usecount--;
1919 break;
1920 }
1921
1922 if (ifp)
1923 LIST_REMOVE(ifma, ifma_link);
1924
1925 ll_ifma = ifma->ifma_ll;
1926
1927 if (ll_ifma) { /* send a routing msg for network addresses only */
1928 if (ifp)
1929 ifnet_lock_done(ifp);
1930 rt_newmaddrmsg(RTM_DELMADDR, ifma);
1931 if (ifp)
1932 ifnet_lock_exclusive(ifp);
1933 }
1934
1935 /*
1936 * Make sure the interface driver is notified
1937 * in the case of a link layer mcast group being left.
1938 */
1939 if (ll_ifma == 0) {
1940 if (ifp && ifma->ifma_addr->sa_family == AF_LINK)
1941 do_del_multi = 1;
1942 break;
1943 }
1944
1945 if (ifp)
1946 ifma_release(ifma);
1947
1948 ifma = ll_ifma;
1949 }
1950
1951 if (!locked && ifp) {
1952 /* This wasn't initially locked, we should unlock it */
1953 ifnet_lock_done(ifp);
1954 }
1955
1956 if (do_del_multi) {
1957 if (locked)
1958 ifnet_lock_done(ifp);
1959 ifnet_ioctl(ifp, 0, SIOCDELMULTI, NULL);
1960 if (locked)
1961 ifnet_lock_exclusive(ifp);
1962 }
1963
1964 return 0;
1965 }
1966
1967 /*
1968 * Remove a reference to a multicast address on this interface. Yell
1969 * if the request does not match an existing membership.
1970 */
1971 int
1972 if_delmulti(
1973 struct ifnet *ifp,
1974 const struct sockaddr *sa)
1975 {
1976 struct ifmultiaddr *ifma;
1977 struct sockaddr *dupsa = NULL;
1978 int retval = 0;
1979
1980 if (sa->sa_family == AF_LINK || sa->sa_family == AF_UNSPEC) {
1981 dupsa = copy_and_normalize(sa);
1982 if (dupsa == NULL) {
1983 return ENOMEM;
1984 }
1985 sa = dupsa;
1986 }
1987
1988 ifnet_lock_exclusive(ifp);
1989 for (ifma = ifp->if_multiaddrs.lh_first; ifma;
1990 ifma = ifma->ifma_link.le_next)
1991 if (equal(sa, ifma->ifma_addr))
1992 break;
1993 if (ifma == 0) {
1994 ifnet_lock_done(ifp);
1995 if (dupsa)
1996 FREE(dupsa, M_IFADDR);
1997 return ENOENT;
1998 }
1999
2000 retval = if_delmultiaddr(ifma, 1);
2001 ifnet_lock_done(ifp);
2002 if (dupsa)
2003 FREE(dupsa, M_IFADDR);
2004
2005 return retval;
2006 }
2007
2008
2009 /*
2010 * We don't use if_setlladdr, our interfaces are responsible for
2011 * handling the SIOCSIFLLADDR ioctl.
2012 */
2013 #ifndef __APPLE__
2014 int
2015 if_setlladdr(struct ifnet *ifp, const u_char *lladdr, int len)
2016 {
2017 ...
2018 }
2019 #endif
2020
2021 struct ifmultiaddr *
2022 ifmaof_ifpforaddr(const struct sockaddr *sa, struct ifnet *ifp)
2023 {
2024 struct ifmultiaddr *ifma;
2025
2026 ifnet_lock_shared(ifp);
2027 for (ifma = ifp->if_multiaddrs.lh_first; ifma;
2028 ifma = ifma->ifma_link.le_next)
2029 if (equal(ifma->ifma_addr, sa))
2030 break;
2031 ifnet_lock_done(ifp);
2032
2033 return ifma;
2034 }
2035
2036 SYSCTL_NODE(_net, PF_LINK, link, CTLFLAG_RW|CTLFLAG_LOCKED, 0, "Link layers");
2037 SYSCTL_NODE(_net_link, 0, generic, CTLFLAG_RW|CTLFLAG_LOCKED, 0, "Generic link-management");
2038
2039
2040 /*
2041 * Shutdown all network activity. Used boot() when halting
2042 * system.
2043 */
2044 int
2045 if_down_all(void)
2046 {
2047 struct ifnet **ifp;
2048 u_int32_t count;
2049 u_int32_t i;
2050
2051 if (ifnet_list_get_all(IFNET_FAMILY_ANY, &ifp, &count) == 0) {
2052 for (i = 0; i < count; i++) {
2053 if_down(ifp[i]);
2054 dlil_proto_unplumb_all(ifp[i]);
2055 }
2056 ifnet_list_free(ifp);
2057 }
2058
2059 return 0;
2060 }
2061
2062 /*
2063 * Delete Routes for a Network Interface
2064 *
2065 * Called for each routing entry via the rnh->rnh_walktree() call above
2066 * to delete all route entries referencing a detaching network interface.
2067 *
2068 * Arguments:
2069 * rn pointer to node in the routing table
2070 * arg argument passed to rnh->rnh_walktree() - detaching interface
2071 *
2072 * Returns:
2073 * 0 successful
2074 * errno failed - reason indicated
2075 *
2076 */
2077 static int
2078 if_rtdel(
2079 struct radix_node *rn,
2080 void *arg)
2081 {
2082 struct rtentry *rt = (struct rtentry *)rn;
2083 struct ifnet *ifp = arg;
2084 int err;
2085
2086 if (rt != NULL && rt->rt_ifp == ifp) {
2087
2088 /*
2089 * Protect (sorta) against walktree recursion problems
2090 * with cloned routes
2091 */
2092 if ((rt->rt_flags & RTF_UP) == 0)
2093 return (0);
2094
2095 err = rtrequest_locked(RTM_DELETE, rt_key(rt), rt->rt_gateway,
2096 rt_mask(rt), rt->rt_flags,
2097 (struct rtentry **) NULL);
2098 if (err) {
2099 log(LOG_WARNING, "if_rtdel: error %d\n", err);
2100 }
2101 }
2102
2103 return (0);
2104 }
2105
2106 /*
2107 * Removes routing table reference to a given interfacei
2108 * for a given protocol family
2109 */
2110 void if_rtproto_del(struct ifnet *ifp, int protocol)
2111 {
2112 struct radix_node_head *rnh;
2113 if (use_routegenid)
2114 route_generation++;
2115 if ((protocol <= AF_MAX) && (protocol >= 0) &&
2116 ((rnh = rt_tables[protocol]) != NULL) && (ifp != NULL)) {
2117 lck_mtx_lock(rt_mtx);
2118 (void) rnh->rnh_walktree(rnh, if_rtdel, ifp);
2119 lck_mtx_unlock(rt_mtx);
2120 }
2121 }
2122
2123 static int
2124 if_rtmtu(struct radix_node *rn, void *arg)
2125 {
2126 struct rtentry *rt = (struct rtentry *)rn;
2127 struct ifnet *ifp = arg;
2128
2129 if (rt->rt_ifp == ifp) {
2130 /*
2131 * Update the MTU of this entry only if the MTU
2132 * has not been locked (RTV_MTU is not set) and
2133 * if it was non-zero to begin with.
2134 */
2135 if (!(rt->rt_rmx.rmx_locks & RTV_MTU) && rt->rt_rmx.rmx_mtu)
2136 rt->rt_rmx.rmx_mtu = ifp->if_mtu;
2137 }
2138
2139 return (0);
2140 }
2141
2142 /*
2143 * Update the MTU metric of all route entries in all protocol tables
2144 * associated with a particular interface; this is called when the
2145 * MTU of that interface has changed.
2146 */
2147 static
2148 void if_rtmtu_update(struct ifnet *ifp)
2149 {
2150 struct radix_node_head *rnh;
2151 int p;
2152
2153 for (p = 0; p < AF_MAX + 1; p++) {
2154 if ((rnh = rt_tables[p]) == NULL)
2155 continue;
2156
2157 lck_mtx_lock(rt_mtx);
2158 (void) rnh->rnh_walktree(rnh, if_rtmtu, ifp);
2159 lck_mtx_unlock(rt_mtx);
2160 }
2161
2162 if (use_routegenid)
2163 route_generation++;
2164 }
2165
2166 __private_extern__ void
2167 if_data_internal_to_if_data(
2168 struct ifnet *ifp,
2169 const struct if_data_internal *if_data_int,
2170 struct if_data *if_data)
2171 {
2172 struct dlil_threading_info *thread;
2173 if ((thread = ifp->if_input_thread) == NULL || (dlil_multithreaded_input == 0))
2174 thread = dlil_lo_thread_ptr;
2175
2176 #define COPYFIELD(fld) if_data->fld = if_data_int->fld
2177 #define COPYFIELD32(fld) if_data->fld = (u_int32_t)(if_data_int->fld)
2178 COPYFIELD(ifi_type);
2179 COPYFIELD(ifi_typelen);
2180 COPYFIELD(ifi_physical);
2181 COPYFIELD(ifi_addrlen);
2182 COPYFIELD(ifi_hdrlen);
2183 COPYFIELD(ifi_recvquota);
2184 COPYFIELD(ifi_xmitquota);
2185 if_data->ifi_unused1 = 0;
2186 COPYFIELD(ifi_mtu);
2187 COPYFIELD(ifi_metric);
2188 if (if_data_int->ifi_baudrate & 0xFFFFFFFF00000000LL) {
2189 if_data->ifi_baudrate = 0xFFFFFFFF;
2190 }
2191 else {
2192 COPYFIELD32(ifi_baudrate);
2193 }
2194
2195 lck_mtx_lock(thread->input_lck);
2196 COPYFIELD32(ifi_ipackets);
2197 COPYFIELD32(ifi_ierrors);
2198 COPYFIELD32(ifi_opackets);
2199 COPYFIELD32(ifi_oerrors);
2200 COPYFIELD32(ifi_collisions);
2201 COPYFIELD32(ifi_ibytes);
2202 COPYFIELD32(ifi_obytes);
2203 COPYFIELD32(ifi_imcasts);
2204 COPYFIELD32(ifi_omcasts);
2205 COPYFIELD32(ifi_iqdrops);
2206 COPYFIELD32(ifi_noproto);
2207 COPYFIELD32(ifi_recvtiming);
2208 COPYFIELD32(ifi_xmittiming);
2209 COPYFIELD(ifi_lastchange);
2210 lck_mtx_unlock(thread->input_lck);
2211
2212 #if IF_LASTCHANGEUPTIME
2213 if_data->ifi_lastchange.tv_sec += boottime_sec();
2214 #endif
2215
2216 if_data->ifi_unused2 = 0;
2217 COPYFIELD(ifi_hwassist);
2218 if_data->ifi_reserved1 = 0;
2219 if_data->ifi_reserved2 = 0;
2220 #undef COPYFIELD32
2221 #undef COPYFIELD
2222 }
2223
2224 __private_extern__ void
2225 if_data_internal_to_if_data64(
2226 struct ifnet *ifp,
2227 const struct if_data_internal *if_data_int,
2228 struct if_data64 *if_data64)
2229 {
2230 struct dlil_threading_info *thread;
2231 if ((thread = ifp->if_input_thread) == NULL || (dlil_multithreaded_input == 0))
2232 thread = dlil_lo_thread_ptr;
2233
2234 #define COPYFIELD(fld) if_data64->fld = if_data_int->fld
2235 COPYFIELD(ifi_type);
2236 COPYFIELD(ifi_typelen);
2237 COPYFIELD(ifi_physical);
2238 COPYFIELD(ifi_addrlen);
2239 COPYFIELD(ifi_hdrlen);
2240 COPYFIELD(ifi_recvquota);
2241 COPYFIELD(ifi_xmitquota);
2242 if_data64->ifi_unused1 = 0;
2243 COPYFIELD(ifi_mtu);
2244 COPYFIELD(ifi_metric);
2245 COPYFIELD(ifi_baudrate);
2246
2247 lck_mtx_lock(thread->input_lck);
2248 COPYFIELD(ifi_ipackets);
2249 COPYFIELD(ifi_ierrors);
2250 COPYFIELD(ifi_opackets);
2251 COPYFIELD(ifi_oerrors);
2252 COPYFIELD(ifi_collisions);
2253 COPYFIELD(ifi_ibytes);
2254 COPYFIELD(ifi_obytes);
2255 COPYFIELD(ifi_imcasts);
2256 COPYFIELD(ifi_omcasts);
2257 COPYFIELD(ifi_iqdrops);
2258 COPYFIELD(ifi_noproto);
2259 COPYFIELD(ifi_recvtiming);
2260 COPYFIELD(ifi_xmittiming);
2261 COPYFIELD(ifi_lastchange);
2262 lck_mtx_unlock(thread->input_lck);
2263
2264 #if IF_LASTCHANGEUPTIME
2265 if_data64->ifi_lastchange.tv_sec += boottime_sec();
2266 #endif
2267
2268 #undef COPYFIELD
2269 }