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