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