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