]> git.saurik.com Git - apple/xnu.git/blame - bsd/net/if.c
xnu-1699.26.8.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>
6d2010ae
A
84#include <sys/mcache.h>
85#include <kern/zalloc.h>
9bccf70c 86
b0d623f7
A
87#include <machine/endian.h>
88
6d2010ae
A
89#include <pexpert/pexpert.h>
90
1c79356b 91#include <net/if.h>
9bccf70c 92#include <net/if_arp.h>
1c79356b 93#include <net/if_dl.h>
9bccf70c
A
94#include <net/if_types.h>
95#include <net/if_var.h>
91447636 96#include <net/net_osdep.h>
2d21ac55 97#include <net/ethernet.h>
91447636 98
1c79356b 99#include <net/radix.h>
9bccf70c
A
100#include <net/route.h>
101#ifdef __APPLE__
1c79356b 102#include <net/dlil.h>
9bccf70c 103//#include <string.h>
1c79356b 104#include <sys/domain.h>
91447636 105#include <libkern/OSAtomic.h>
9bccf70c
A
106#endif
107
2d21ac55 108#if INET || INET6
9bccf70c
A
109/*XXX*/
110#include <netinet/in.h>
111#include <netinet/in_var.h>
c910b4d9 112#include <netinet/ip_var.h>
6d2010ae 113#include <netinet/ip6.h>
9bccf70c
A
114#if INET6
115#include <netinet6/in6_var.h>
116#include <netinet6/in6_ifattach.h>
6d2010ae 117#include <netinet6/ip6_var.h>
9bccf70c
A
118#endif
119#endif
120
2d21ac55
A
121#if CONFIG_MACF_NET
122#include <security/mac_framework.h>
123#endif
124
b0d623f7 125
1c79356b
A
126/*
127 * System initialization
128 */
129
6d2010ae
A
130/* Lock group and attribute for ifaddr lock */
131lck_attr_t *ifa_mtx_attr;
132lck_grp_t *ifa_mtx_grp;
133static lck_grp_attr_t *ifa_mtx_grp_attr;
134
91447636
A
135static int ifconf(u_long cmd, user_addr_t ifrp, int * ret_space);
136static void if_qflush(struct ifqueue *);
137__private_extern__ void link_rtrequest(int, struct rtentry *, struct sockaddr *);
138void if_rtproto_del(struct ifnet *ifp, int protocol);
1c79356b 139
6d2010ae
A
140static int if_addmulti_common(struct ifnet *, const struct sockaddr *,
141 struct ifmultiaddr **, int);
142static int if_delmulti_common(struct ifmultiaddr *, struct ifnet *,
143 const struct sockaddr *, int);
144
2d21ac55
A
145static int if_rtmtu(struct radix_node *, void *);
146static void if_rtmtu_update(struct ifnet *);
147
b0d623f7 148#if IF_CLONE_LIST
91447636 149static int if_clone_list(int count, int * total, user_addr_t dst);
b0d623f7 150#endif /* IF_CLONE_LIST */
4a249263 151
1c79356b 152MALLOC_DEFINE(M_IFADDR, "ifaddr", "interface address");
1c79356b
A
153
154int ifqmaxlen = IFQ_MAXLEN;
91447636 155struct ifnethead ifnet_head = TAILQ_HEAD_INITIALIZER(ifnet_head);
1c79356b 156
4a249263
A
157static int if_cloners_count;
158LIST_HEAD(, if_clone) if_cloners = LIST_HEAD_INITIALIZER(if_cloners);
159
c910b4d9
A
160static struct ifaddr *ifa_ifwithnet_common(const struct sockaddr *,
161 unsigned int);
6d2010ae
A
162static void if_attach_ifa_common(struct ifnet *, struct ifaddr *, int);
163static void if_detach_ifa_common(struct ifnet *, struct ifaddr *, int);
164
165static void if_attach_ifma(struct ifnet *, struct ifmultiaddr *, int);
166static int if_detach_ifma(struct ifnet *, struct ifmultiaddr *, int);
167
168static struct ifmultiaddr *ifma_alloc(int);
169static void ifma_free(struct ifmultiaddr *);
170static void ifma_trace(struct ifmultiaddr *, int);
171
172#if DEBUG
173static unsigned int ifma_debug = 1; /* debugging (enabled) */
174#else
175static unsigned int ifma_debug; /* debugging (disabled) */
176#endif /* !DEBUG */
177static unsigned int ifma_size; /* size of zone element */
178static struct zone *ifma_zone; /* zone for ifmultiaddr */
179
180#define IFMA_TRACE_HIST_SIZE 32 /* size of trace history */
181
182/* For gdb */
183__private_extern__ unsigned int ifma_trace_hist_size = IFMA_TRACE_HIST_SIZE;
184
185struct ifmultiaddr_dbg {
186 struct ifmultiaddr ifma; /* ifmultiaddr */
187 u_int16_t ifma_refhold_cnt; /* # of ref */
188 u_int16_t ifma_refrele_cnt; /* # of rele */
189 /*
190 * Circular lists of IFA_ADDREF and IFA_REMREF callers.
191 */
192 ctrace_t ifma_refhold[IFMA_TRACE_HIST_SIZE];
193 ctrace_t ifma_refrele[IFMA_TRACE_HIST_SIZE];
194 /*
195 * Trash list linkage
196 */
197 TAILQ_ENTRY(ifmultiaddr_dbg) ifma_trash_link;
198};
199
200/* List of trash ifmultiaddr entries protected by ifma_trash_lock */
201static TAILQ_HEAD(, ifmultiaddr_dbg) ifma_trash_head;
202static decl_lck_mtx_data(, ifma_trash_lock);
203
204#define IFMA_ZONE_MAX 64 /* maximum elements in zone */
205#define IFMA_ZONE_NAME "ifmultiaddr" /* zone name */
c910b4d9 206
1c79356b
A
207#if INET6
208/*
209 * XXX: declare here to avoid to include many inet6 related files..
210 * should be more generalized?
211 */
91447636 212extern void nd6_setmtu(struct ifnet *);
6d2010ae 213extern lck_mtx_t *nd6_mutex;
9bccf70c 214#endif
1c79356b 215
4a249263 216
6d2010ae
A
217void
218ifa_init(void)
219{
220 /* Setup lock group and attribute for ifaddr */
221 ifa_mtx_grp_attr = lck_grp_attr_alloc_init();
222 ifa_mtx_grp = lck_grp_alloc_init("ifaddr", ifa_mtx_grp_attr);
223 ifa_mtx_attr = lck_attr_alloc_init();
224
225 PE_parse_boot_argn("ifa_debug", &ifma_debug, sizeof (ifma_debug));
226
227 ifma_size = (ifma_debug == 0) ? sizeof (struct ifmultiaddr) :
228 sizeof (struct ifmultiaddr_dbg);
229
230 ifma_zone = zinit(ifma_size, IFMA_ZONE_MAX * ifma_size, 0,
231 IFMA_ZONE_NAME);
232 if (ifma_zone == NULL) {
233 panic("%s: failed allocating %s", __func__, IFMA_ZONE_NAME);
234 /* NOTREACHED */
235 }
236 zone_change(ifma_zone, Z_EXPAND, TRUE);
237 zone_change(ifma_zone, Z_CALLERACCT, FALSE);
238
239 lck_mtx_init(&ifma_trash_lock, ifa_mtx_grp, ifa_mtx_attr);
240 TAILQ_INIT(&ifma_trash_head);
241}
242
1c79356b
A
243/*
244 * Network interface utility routines.
245 *
246 * Routines with ifa_ifwith* names take sockaddr *'s as
247 * parameters.
1c79356b 248 */
1c79356b 249
ab86ba33 250int if_index;
1c79356b 251struct ifaddr **ifnet_addrs;
ab86ba33 252struct ifnet **ifindex2ifnet;
1c79356b 253
91447636 254__private_extern__ void
6d2010ae
A
255if_attach_ifa(struct ifnet *ifp, struct ifaddr *ifa)
256{
257 if_attach_ifa_common(ifp, ifa, 0);
258}
259
260__private_extern__ void
261if_attach_link_ifa(struct ifnet *ifp, struct ifaddr *ifa)
262{
263 if_attach_ifa_common(ifp, ifa, 1);
264}
265
266static void
267if_attach_ifa_common(struct ifnet *ifp, struct ifaddr *ifa, int link)
91447636 268{
6d2010ae
A
269 ifnet_lock_assert(ifp, IFNET_LCK_ASSERT_EXCLUSIVE);
270 IFA_LOCK_ASSERT_HELD(ifa);
271
272 if (ifa->ifa_ifp != ifp) {
273 panic("%s: Mismatch ifa_ifp=%p != ifp=%p", __func__,
274 ifa->ifa_ifp, ifp);
275 /* NOTREACHED */
276 } else if (ifa->ifa_debug & IFD_ATTACHED) {
277 panic("%s: Attempt to attach an already attached ifa=%p",
278 __func__, ifa);
279 /* NOTREACHED */
280 } else if (link && !(ifa->ifa_debug & IFD_LINK)) {
281 panic("%s: Unexpected non-link address ifa=%p", __func__, ifa);
282 /* NOTREACHED */
283 } else if (!link && (ifa->ifa_debug & IFD_LINK)) {
284 panic("%s: Unexpected link address ifa=%p", __func__, ifa);
285 /* NOTREACHED */
91447636 286 }
6d2010ae 287 IFA_ADDREF_LOCKED(ifa);
b0d623f7 288 ifa->ifa_debug |= IFD_ATTACHED;
6d2010ae
A
289 if (link)
290 TAILQ_INSERT_HEAD(&ifp->if_addrhead, ifa, ifa_link);
291 else
292 TAILQ_INSERT_TAIL(&ifp->if_addrhead, ifa, ifa_link);
293
294 if (ifa->ifa_attached != NULL)
295 (*ifa->ifa_attached)(ifa);
91447636
A
296}
297
298__private_extern__ void
6d2010ae
A
299if_detach_ifa(struct ifnet *ifp, struct ifaddr *ifa)
300{
301 if_detach_ifa_common(ifp, ifa, 0);
302}
303
304__private_extern__ void
305if_detach_link_ifa(struct ifnet *ifp, struct ifaddr *ifa)
306{
307 if_detach_ifa_common(ifp, ifa, 1);
308}
309
310static void
311if_detach_ifa_common(struct ifnet *ifp, struct ifaddr *ifa, int link)
312{
313 ifnet_lock_assert(ifp, IFNET_LCK_ASSERT_EXCLUSIVE);
314 IFA_LOCK_ASSERT_HELD(ifa);
315
316 if (link && !(ifa->ifa_debug & IFD_LINK)) {
317 panic("%s: Unexpected non-link address ifa=%p", __func__, ifa);
318 /* NOTREACHED */
319 } else if (link && ifa != TAILQ_FIRST(&ifp->if_addrhead)) {
320 panic("%s: Link address ifa=%p not first", __func__, ifa);
321 /* NOTREACHED */
322 } else if (!link && (ifa->ifa_debug & IFD_LINK)) {
323 panic("%s: Unexpected link address ifa=%p", __func__, ifa);
324 /* NOTREACHED */
325 } else if (!(ifa->ifa_debug & IFD_ATTACHED)) {
326 panic("%s: Attempt to detach an unattached address ifa=%p",
327 __func__, ifa);
328 /* NOTREACHED */
329 } else if (ifa->ifa_ifp != ifp) {
330 panic("%s: Mismatch ifa_ifp=%p, ifp=%p", __func__,
331 ifa->ifa_ifp, ifp);
332 /* NOTREACHED */
333 } else if (ifa->ifa_debug & IFD_DEBUG) {
91447636
A
334 struct ifaddr *ifa2;
335 TAILQ_FOREACH(ifa2, &ifp->if_addrhead, ifa_link) {
336 if (ifa2 == ifa)
337 break;
338 }
339 if (ifa2 != ifa) {
6d2010ae
A
340 panic("%s: Attempt to detach a stray address ifa=%p",
341 __func__, ifa);
342 /* NOTREACHED */
343 }
91447636 344 }
91447636 345 TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link);
6d2010ae
A
346 /* This must not be the last reference to the ifaddr */
347 if (IFA_REMREF_LOCKED(ifa) == NULL) {
348 panic("%s: unexpected (missing) refcnt ifa=%p", __func__, ifa);
349 /* NOTREACHED */
350 }
b0d623f7 351 ifa->ifa_debug &= ~IFD_ATTACHED;
6d2010ae
A
352
353 if (ifa->ifa_detached != NULL)
354 (*ifa->ifa_detached)(ifa);
91447636
A
355}
356
ab86ba33
A
357#define INITIAL_IF_INDEXLIM 8
358
359/*
360 * Function: if_next_index
361 * Purpose:
362 * Return the next available interface index.
363 * Grow the ifnet_addrs[] and ifindex2ifnet[] arrays to accomodate the
364 * added entry when necessary.
365 *
366 * Note:
367 * ifnet_addrs[] is indexed by (if_index - 1), whereas
368 * ifindex2ifnet[] is indexed by ifp->if_index. That requires us to
369 * always allocate one extra element to hold ifindex2ifnet[0], which
370 * is unused.
371 */
91447636
A
372int if_next_index(void);
373
374__private_extern__ int
ab86ba33
A
375if_next_index(void)
376{
377 static int if_indexlim = 0;
ab86ba33
A
378 int new_index;
379
ab86ba33
A
380 new_index = ++if_index;
381 if (if_index > if_indexlim) {
382 unsigned n;
383 int new_if_indexlim;
384 caddr_t new_ifnet_addrs;
385 caddr_t new_ifindex2ifnet;
386 caddr_t old_ifnet_addrs;
387
ab86ba33
A
388 old_ifnet_addrs = (caddr_t)ifnet_addrs;
389 if (ifnet_addrs == NULL) {
390 new_if_indexlim = INITIAL_IF_INDEXLIM;
391 } else {
392 new_if_indexlim = if_indexlim << 1;
393 }
394
395 /* allocate space for the larger arrays */
396 n = (2 * new_if_indexlim + 1) * sizeof(caddr_t);
397 new_ifnet_addrs = _MALLOC(n, M_IFADDR, M_WAITOK);
b0d623f7
A
398 if (new_ifnet_addrs == NULL) {
399 --if_index;
400 return -1;
401 }
402
ab86ba33
A
403 new_ifindex2ifnet = new_ifnet_addrs
404 + new_if_indexlim * sizeof(caddr_t);
405 bzero(new_ifnet_addrs, n);
406 if (ifnet_addrs != NULL) {
407 /* copy the existing data */
408 bcopy((caddr_t)ifnet_addrs, new_ifnet_addrs,
409 if_indexlim * sizeof(caddr_t));
410 bcopy((caddr_t)ifindex2ifnet,
411 new_ifindex2ifnet,
412 (if_indexlim + 1) * sizeof(caddr_t));
413 }
414
415 /* switch to the new tables and size */
416 ifnet_addrs = (struct ifaddr **)new_ifnet_addrs;
417 ifindex2ifnet = (struct ifnet **)new_ifindex2ifnet;
418 if_indexlim = new_if_indexlim;
419
420 /* release the old data */
421 if (old_ifnet_addrs != NULL) {
422 _FREE((caddr_t)old_ifnet_addrs, M_IFADDR);
423 }
ab86ba33
A
424 }
425 return (new_index);
1c79356b 426}
9bccf70c 427
4a249263
A
428/*
429 * Create a clone network interface.
430 */
431static int
d1ecb069 432if_clone_create(char *name, int len, void *params)
4a249263
A
433{
434 struct if_clone *ifc;
435 char *dp;
d1ecb069
A
436 int wildcard;
437 u_int32_t bytoff, bitoff;
438 u_int32_t unit;
4a249263
A
439 int err;
440
441 ifc = if_clone_lookup(name, &unit);
442 if (ifc == NULL)
443 return (EINVAL);
444
445 if (ifunit(name) != NULL)
446 return (EEXIST);
447
448 bytoff = bitoff = 0;
d1ecb069 449 wildcard = (unit == UINT32_MAX);
4a249263
A
450 /*
451 * Find a free unit if none was given.
452 */
453 if (wildcard) {
454 while ((bytoff < ifc->ifc_bmlen)
455 && (ifc->ifc_units[bytoff] == 0xff))
456 bytoff++;
457 if (bytoff >= ifc->ifc_bmlen)
458 return (ENOSPC);
459 while ((ifc->ifc_units[bytoff] & (1 << bitoff)) != 0)
460 bitoff++;
461 unit = (bytoff << 3) + bitoff;
462 }
463
464 if (unit > ifc->ifc_maxunit)
465 return (ENXIO);
466
d1ecb069 467 err = (*ifc->ifc_create)(ifc, unit, params);
4a249263
A
468 if (err != 0)
469 return (err);
470
471 if (!wildcard) {
472 bytoff = unit >> 3;
473 bitoff = unit - (bytoff << 3);
474 }
475
476 /*
477 * Allocate the unit in the bitmap.
478 */
479 KASSERT((ifc->ifc_units[bytoff] & (1 << bitoff)) == 0,
480 ("%s: bit is already set", __func__));
481 ifc->ifc_units[bytoff] |= (1 << bitoff);
482
483 /* In the wildcard case, we need to update the name. */
484 if (wildcard) {
485 for (dp = name; *dp != '\0'; dp++);
486 if (snprintf(dp, len - (dp-name), "%d", unit) >
487 len - (dp-name) - 1) {
488 /*
489 * This can only be a programmer error and
490 * there's no straightforward way to recover if
491 * it happens.
492 */
6d2010ae
A
493 panic("%s: interface name too long", __func__);
494 /* NOTREACHED */
4a249263
A
495 }
496
497 }
498
499 return (0);
500}
501
502/*
503 * Destroy a clone network interface.
504 */
91447636 505static int
4a249263
A
506if_clone_destroy(const char *name)
507{
508 struct if_clone *ifc;
509 struct ifnet *ifp;
510 int bytoff, bitoff;
d1ecb069 511 u_int32_t unit;
4a249263
A
512
513 ifc = if_clone_lookup(name, &unit);
514 if (ifc == NULL)
515 return (EINVAL);
516
517 if (unit < ifc->ifc_minifs)
518 return (EINVAL);
519
520 ifp = ifunit(name);
521 if (ifp == NULL)
522 return (ENXIO);
523
524 if (ifc->ifc_destroy == NULL)
525 return (EOPNOTSUPP);
526
527 (*ifc->ifc_destroy)(ifp);
528
529 /*
530 * Compute offset in the bitmap and deallocate the unit.
531 */
532 bytoff = unit >> 3;
533 bitoff = unit - (bytoff << 3);
534 KASSERT((ifc->ifc_units[bytoff] & (1 << bitoff)) != 0,
535 ("%s: bit is already cleared", __func__));
536 ifc->ifc_units[bytoff] &= ~(1 << bitoff);
537 return (0);
538}
539
540/*
541 * Look up a network interface cloner.
542 */
543
d1ecb069
A
544__private_extern__ struct if_clone *
545if_clone_lookup(const char *name, u_int32_t *unitp)
4a249263
A
546{
547 struct if_clone *ifc;
548 const char *cp;
91447636 549 size_t i;
4a249263
A
550
551 for (ifc = LIST_FIRST(&if_cloners); ifc != NULL;) {
552 for (cp = name, i = 0; i < ifc->ifc_namelen; i++, cp++) {
553 if (ifc->ifc_name[i] != *cp)
554 goto next_ifc;
555 }
556 goto found_name;
557 next_ifc:
558 ifc = LIST_NEXT(ifc, ifc_list);
559 }
560
561 /* No match. */
562 return ((struct if_clone *)NULL);
563
564 found_name:
565 if (*cp == '\0') {
d1ecb069 566 i = 0xffff;
4a249263
A
567 } else {
568 for (i = 0; *cp != '\0'; cp++) {
569 if (*cp < '0' || *cp > '9') {
570 /* Bogus unit number. */
571 return (NULL);
572 }
573 i = (i * 10) + (*cp - '0');
574 }
575 }
576
577 if (unitp != NULL)
578 *unitp = i;
579 return (ifc);
580}
581
582/*
583 * Register a network interface cloner.
584 */
b0d623f7 585int
4a249263
A
586if_clone_attach(struct if_clone *ifc)
587{
588 int bytoff, bitoff;
589 int err;
590 int len, maxclone;
d1ecb069 591 u_int32_t unit;
4a249263
A
592
593 KASSERT(ifc->ifc_minifs - 1 <= ifc->ifc_maxunit,
594 ("%s: %s requested more units then allowed (%d > %d)",
595 __func__, ifc->ifc_name, ifc->ifc_minifs,
596 ifc->ifc_maxunit + 1));
597 /*
598 * Compute bitmap size and allocate it.
599 */
600 maxclone = ifc->ifc_maxunit + 1;
601 len = maxclone >> 3;
602 if ((len << 3) < maxclone)
603 len++;
604 ifc->ifc_units = _MALLOC(len, M_CLONE, M_WAITOK | M_ZERO);
b0d623f7
A
605 if (ifc->ifc_units == NULL)
606 return ENOBUFS;
4a249263
A
607 bzero(ifc->ifc_units, len);
608 ifc->ifc_bmlen = len;
609
610 LIST_INSERT_HEAD(&if_cloners, ifc, ifc_list);
611 if_cloners_count++;
612
613 for (unit = 0; unit < ifc->ifc_minifs; unit++) {
d1ecb069 614 err = (*ifc->ifc_create)(ifc, unit, NULL);
4a249263
A
615 KASSERT(err == 0,
616 ("%s: failed to create required interface %s%d",
617 __func__, ifc->ifc_name, unit));
618
619 /* Allocate the unit in the bitmap. */
620 bytoff = unit >> 3;
621 bitoff = unit - (bytoff << 3);
622 ifc->ifc_units[bytoff] |= (1 << bitoff);
623 }
b0d623f7
A
624
625 return 0;
4a249263
A
626}
627
628/*
629 * Unregister a network interface cloner.
630 */
631void
632if_clone_detach(struct if_clone *ifc)
633{
634
635 LIST_REMOVE(ifc, ifc_list);
636 FREE(ifc->ifc_units, M_CLONE);
637 if_cloners_count--;
638}
639
b0d623f7 640#if IF_CLONE_LIST
4a249263
A
641/*
642 * Provide list of interface cloners to userspace.
643 */
644static int
91447636 645if_clone_list(int count, int * total, user_addr_t dst)
4a249263 646{
91447636 647 char outbuf[IFNAMSIZ];
4a249263 648 struct if_clone *ifc;
91447636 649 int error = 0;
4a249263 650
91447636
A
651 *total = if_cloners_count;
652 if (dst == USER_ADDR_NULL) {
4a249263
A
653 /* Just asking how many there are. */
654 return (0);
655 }
656
91447636 657 if (count < 0)
4a249263
A
658 return (EINVAL);
659
91447636 660 count = (if_cloners_count < count) ? if_cloners_count : count;
4a249263
A
661
662 for (ifc = LIST_FIRST(&if_cloners); ifc != NULL && count != 0;
663 ifc = LIST_NEXT(ifc, ifc_list), count--, dst += IFNAMSIZ) {
2d21ac55 664 strlcpy(outbuf, ifc->ifc_name, IFNAMSIZ);
4a249263
A
665 error = copyout(outbuf, dst, IFNAMSIZ);
666 if (error)
667 break;
668 }
669
670 return (error);
671}
b0d623f7 672#endif /* IF_CLONE_LIST */
4a249263 673
b0d623f7
A
674/*
675 * Similar to ifa_ifwithaddr, except that this is IPv4 specific
676 * and that it matches only the local (not broadcast) address.
677 */
678__private_extern__ struct in_ifaddr *
679ifa_foraddr(unsigned int addr)
55e303ae 680{
b0d623f7
A
681 return (ifa_foraddr_scoped(addr, IFSCOPE_NONE));
682}
683
684/*
685 * Similar to ifa_foraddr, except with the added interface scope
686 * constraint (unless the caller passes in IFSCOPE_NONE in which
687 * case there is no scope restriction).
688 */
689__private_extern__ struct in_ifaddr *
690ifa_foraddr_scoped(unsigned int addr, unsigned int scope)
691{
692 struct in_ifaddr *ia = NULL;
693
694 lck_rw_lock_shared(in_ifaddr_rwlock);
695 TAILQ_FOREACH(ia, INADDR_HASH(addr), ia_hash) {
6d2010ae 696 IFA_LOCK_SPIN(&ia->ia_ifa);
b0d623f7 697 if (ia->ia_addr.sin_addr.s_addr == addr &&
6d2010ae
A
698 (scope == IFSCOPE_NONE || ia->ia_ifp->if_index == scope)) {
699 IFA_ADDREF_LOCKED(&ia->ia_ifa); /* for caller */
700 IFA_UNLOCK(&ia->ia_ifa);
b0d623f7 701 break;
6d2010ae
A
702 }
703 IFA_UNLOCK(&ia->ia_ifa);
55e303ae 704 }
b0d623f7
A
705 lck_rw_done(in_ifaddr_rwlock);
706 return (ia);
55e303ae
A
707}
708
6d2010ae
A
709#if INET6
710/*
711 * Similar to ifa_foraddr, except that this for IPv6.
712 */
713__private_extern__ struct in6_ifaddr *
714ifa_foraddr6(struct in6_addr *addr6)
715{
716 return (ifa_foraddr6_scoped(addr6, IFSCOPE_NONE));
717}
718
719__private_extern__ struct in6_ifaddr *
720ifa_foraddr6_scoped(struct in6_addr *addr6, unsigned int scope)
721{
722 struct in6_ifaddr *ia = NULL;
723
724 lck_rw_lock_shared(&in6_ifaddr_rwlock);
725 for (ia = in6_ifaddrs; ia; ia = ia->ia_next) {
726 IFA_LOCK(&ia->ia_ifa);
727 if (IN6_ARE_ADDR_EQUAL(&ia->ia_addr.sin6_addr, addr6) &&
728 (scope == IFSCOPE_NONE || ia->ia_ifp->if_index == scope)) {
729 IFA_ADDREF_LOCKED(&ia->ia_ifa); /* for caller */
730 IFA_UNLOCK(&ia->ia_ifa);
731 break;
732 }
733 IFA_UNLOCK(&ia->ia_ifa);
734 }
735 lck_rw_done(&in6_ifaddr_rwlock);
736
737 return (ia);
738}
739#endif /* INET6 */
740
2d21ac55
A
741/*
742 * Return the first (primary) address of a given family on an interface.
743 */
744__private_extern__ struct ifaddr *
745ifa_ifpgetprimary(struct ifnet *ifp, int family)
746{
6d2010ae 747 struct ifaddr *ifa;
2d21ac55
A
748
749 ifnet_lock_shared(ifp);
750 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
6d2010ae
A
751 IFA_LOCK_SPIN(ifa);
752 if (ifa->ifa_addr->sa_family == family) {
753 IFA_ADDREF_LOCKED(ifa); /* for caller */
754 IFA_UNLOCK(ifa);
2d21ac55
A
755 break;
756 }
6d2010ae 757 IFA_UNLOCK(ifa);
2d21ac55 758 }
2d21ac55
A
759 ifnet_lock_done(ifp);
760
6d2010ae 761 return (ifa);
2d21ac55
A
762}
763
1c79356b
A
764/*
765 * Locate an interface based on a complete address.
766 */
767/*ARGSUSED*/
768struct ifaddr *
6d2010ae 769ifa_ifwithaddr(const struct sockaddr *addr)
1c79356b 770{
91447636
A
771 struct ifnet *ifp;
772 struct ifaddr *ifa;
2d21ac55 773 struct ifaddr *result = NULL;
1c79356b 774
6d2010ae
A
775#define equal(a1, a2) \
776 (bcmp((const void*)(a1), (const void*)(a2), \
777 ((const struct sockaddr *)(a1))->sa_len) == 0)
778
91447636 779 ifnet_head_lock_shared();
6d2010ae
A
780 for (ifp = ifnet_head.tqh_first; ifp && !result;
781 ifp = ifp->if_link.tqe_next) {
91447636
A
782 ifnet_lock_shared(ifp);
783 for (ifa = ifp->if_addrhead.tqh_first; ifa;
6d2010ae
A
784 ifa = ifa->ifa_link.tqe_next) {
785 IFA_LOCK_SPIN(ifa);
786 if (ifa->ifa_addr->sa_family != addr->sa_family) {
787 IFA_UNLOCK(ifa);
91447636 788 continue;
6d2010ae 789 }
91447636
A
790 if (equal(addr, ifa->ifa_addr)) {
791 result = ifa;
6d2010ae
A
792 IFA_ADDREF_LOCKED(ifa); /* for caller */
793 IFA_UNLOCK(ifa);
91447636
A
794 break;
795 }
6d2010ae
A
796 if ((ifp->if_flags & IFF_BROADCAST) &&
797 ifa->ifa_broadaddr != NULL &&
798 /* IP6 doesn't have broadcast */
799 ifa->ifa_broadaddr->sa_len != 0 &&
800 equal(ifa->ifa_broadaddr, addr)) {
91447636 801 result = ifa;
6d2010ae
A
802 IFA_ADDREF_LOCKED(ifa); /* for caller */
803 IFA_UNLOCK(ifa);
91447636
A
804 break;
805 }
6d2010ae 806 IFA_UNLOCK(ifa);
91447636 807 }
91447636 808 ifnet_lock_done(ifp);
1c79356b 809 }
91447636 810 ifnet_head_done();
6d2010ae
A
811
812 return (result);
1c79356b
A
813}
814/*
815 * Locate the point to point interface with a given destination address.
816 */
817/*ARGSUSED*/
818struct ifaddr *
6d2010ae 819ifa_ifwithdstaddr(const struct sockaddr *addr)
1c79356b 820{
91447636
A
821 struct ifnet *ifp;
822 struct ifaddr *ifa;
2d21ac55 823 struct ifaddr *result = NULL;
91447636
A
824
825 ifnet_head_lock_shared();
6d2010ae
A
826 for (ifp = ifnet_head.tqh_first; ifp && !result;
827 ifp = ifp->if_link.tqe_next) {
828 if ((ifp->if_flags & IFF_POINTOPOINT)) {
91447636
A
829 ifnet_lock_shared(ifp);
830 for (ifa = ifp->if_addrhead.tqh_first; ifa;
6d2010ae
A
831 ifa = ifa->ifa_link.tqe_next) {
832 IFA_LOCK_SPIN(ifa);
833 if (ifa->ifa_addr->sa_family !=
834 addr->sa_family) {
835 IFA_UNLOCK(ifa);
91447636 836 continue;
6d2010ae
A
837 }
838 if (ifa->ifa_dstaddr &&
839 equal(addr, ifa->ifa_dstaddr)) {
91447636 840 result = ifa;
6d2010ae
A
841 IFA_ADDREF_LOCKED(ifa); /* for caller */
842 IFA_UNLOCK(ifa);
91447636
A
843 break;
844 }
6d2010ae 845 IFA_UNLOCK(ifa);
91447636 846 }
91447636
A
847 ifnet_lock_done(ifp);
848 }
1c79356b 849 }
91447636 850 ifnet_head_done();
6d2010ae 851 return (result);
1c79356b
A
852}
853
c910b4d9
A
854/*
855 * Locate the source address of an interface based on a complete address.
856 */
857struct ifaddr *
858ifa_ifwithaddr_scoped(const struct sockaddr *addr, unsigned int ifscope)
859{
860 struct ifaddr *result = NULL;
861 struct ifnet *ifp;
862
863 if (ifscope == IFSCOPE_NONE)
864 return (ifa_ifwithaddr(addr));
865
866 ifnet_head_lock_shared();
867 if (ifscope > (unsigned int)if_index) {
868 ifnet_head_done();
869 return (NULL);
870 }
871
872 ifp = ifindex2ifnet[ifscope];
873 if (ifp != NULL) {
874 struct ifaddr *ifa = NULL;
875
876 /*
877 * This is suboptimal; there should be a better way
b0d623f7
A
878 * to search for a given address of an interface
879 * for any given address family.
c910b4d9
A
880 */
881 ifnet_lock_shared(ifp);
882 for (ifa = ifp->if_addrhead.tqh_first; ifa != NULL;
883 ifa = ifa->ifa_link.tqe_next) {
6d2010ae
A
884 IFA_LOCK_SPIN(ifa);
885 if (ifa->ifa_addr->sa_family != addr->sa_family) {
886 IFA_UNLOCK(ifa);
c910b4d9 887 continue;
6d2010ae 888 }
c910b4d9
A
889 if (equal(addr, ifa->ifa_addr)) {
890 result = ifa;
6d2010ae
A
891 IFA_ADDREF_LOCKED(ifa); /* for caller */
892 IFA_UNLOCK(ifa);
c910b4d9
A
893 break;
894 }
895 if ((ifp->if_flags & IFF_BROADCAST) &&
896 ifa->ifa_broadaddr != NULL &&
897 /* IP6 doesn't have broadcast */
898 ifa->ifa_broadaddr->sa_len != 0 &&
899 equal(ifa->ifa_broadaddr, addr)) {
900 result = ifa;
6d2010ae
A
901 IFA_ADDREF_LOCKED(ifa); /* for caller */
902 IFA_UNLOCK(ifa);
c910b4d9
A
903 break;
904 }
6d2010ae 905 IFA_UNLOCK(ifa);
c910b4d9 906 }
c910b4d9
A
907 ifnet_lock_done(ifp);
908 }
909 ifnet_head_done();
910
911 return (result);
912}
913
914struct ifaddr *
915ifa_ifwithnet(const struct sockaddr *addr)
916{
917 return (ifa_ifwithnet_common(addr, IFSCOPE_NONE));
918}
919
920struct ifaddr *
921ifa_ifwithnet_scoped(const struct sockaddr *addr, unsigned int ifscope)
922{
923 return (ifa_ifwithnet_common(addr, ifscope));
924}
925
1c79356b
A
926/*
927 * Find an interface on a specific network. If many, choice
928 * is most specific found.
929 */
c910b4d9
A
930static struct ifaddr *
931ifa_ifwithnet_common(const struct sockaddr *addr, unsigned int ifscope)
1c79356b 932{
91447636
A
933 struct ifnet *ifp;
934 struct ifaddr *ifa = NULL;
6d2010ae 935 struct ifaddr *ifa_maybe = NULL;
1c79356b 936 u_int af = addr->sa_family;
cf7d32b8 937 const char *addr_data = addr->sa_data, *cplim;
1c79356b 938
6d2010ae
A
939#if INET6
940 if ((af != AF_INET && af != AF_INET6) ||
941 (af == AF_INET && !ip_doscopedroute) ||
942 (af == AF_INET6 && !ip6_doscopedroute))
943#else
944 if (af != AF_INET || !ip_doscopedroute)
945#endif /* !INET6 */
c910b4d9
A
946 ifscope = IFSCOPE_NONE;
947
91447636 948 ifnet_head_lock_shared();
1c79356b
A
949 /*
950 * AF_LINK addresses can be looked up directly by their index number,
951 * so do that if we can.
952 */
953 if (af == AF_LINK) {
6d2010ae
A
954 const struct sockaddr_dl *sdl = (const struct sockaddr_dl *)addr;
955 if (sdl->sdl_index && sdl->sdl_index <= if_index) {
91447636 956 ifa = ifnet_addrs[sdl->sdl_index - 1];
6d2010ae
A
957 if (ifa != NULL)
958 IFA_ADDREF(ifa);
959
91447636 960 ifnet_head_done();
6d2010ae 961 return (ifa);
91447636 962 }
1c79356b
A
963 }
964
9bccf70c 965 /*
1c79356b
A
966 * Scan though each interface, looking for ones that have
967 * addresses in this address family.
968 */
91447636
A
969 for (ifp = ifnet_head.tqh_first; ifp; ifp = ifp->if_link.tqe_next) {
970 ifnet_lock_shared(ifp);
1c79356b
A
971 for (ifa = ifp->if_addrhead.tqh_first; ifa;
972 ifa = ifa->ifa_link.tqe_next) {
cf7d32b8 973 const char *cp, *cp2, *cp3;
1c79356b 974
6d2010ae
A
975 IFA_LOCK(ifa);
976 if (ifa->ifa_addr == NULL ||
977 ifa->ifa_addr->sa_family != af) {
978next:
979 IFA_UNLOCK(ifa);
980 continue;
981 }
9bccf70c
A
982#ifndef __APPLE__
983/* This breaks tunneling application trying to install a route with
984 * a specific subnet and the local address as the destination
985 * It's breaks binary compatibility with previous version of MacOS X
986 */
987 if (
9bccf70c
A
988#if INET6 /* XXX: for maching gif tunnel dst as routing entry gateway */
989 addr->sa_family != AF_INET6 &&
990#endif
991 ifp->if_flags & IFF_POINTOPOINT) {
1c79356b 992 /*
9bccf70c
A
993 * This is a bit broken as it doesn't
994 * take into account that the remote end may
1c79356b
A
995 * be a single node in the network we are
996 * looking for.
9bccf70c 997 * The trouble is that we don't know the
1c79356b
A
998 * netmask for the remote end.
999 */
6d2010ae
A
1000 if (ifa->ifa_dstaddr != 0 &&
1001 equal(addr, ifa->ifa_dstaddr)) {
1002 IFA_ADDREF_LOCKED(ifa);
1003 IFA_UNLOCK(ifa);
1004 break;
1005 }
1006 IFA_UNLOCK(ifa);
1c79356b 1007 } else
9bccf70c 1008#endif /* __APPLE__*/
1c79356b 1009 {
c910b4d9
A
1010 /*
1011 * If we're looking up with a scope,
1012 * find using a matching interface.
1013 */
1014 if (ifscope != IFSCOPE_NONE &&
6d2010ae
A
1015 ifp->if_index != ifscope) {
1016 IFA_UNLOCK(ifa);
c910b4d9 1017 continue;
6d2010ae 1018 }
c910b4d9 1019
1c79356b
A
1020 /*
1021 * Scan all the bits in the ifa's address.
1022 * If a bit dissagrees with what we are
1023 * looking for, mask it with the netmask
1024 * to see if it really matters.
1025 * (A byte at a time)
1026 */
6d2010ae
A
1027 if (ifa->ifa_netmask == 0) {
1028 IFA_UNLOCK(ifa);
1c79356b 1029 continue;
6d2010ae 1030 }
1c79356b
A
1031 cp = addr_data;
1032 cp2 = ifa->ifa_addr->sa_data;
1033 cp3 = ifa->ifa_netmask->sa_data;
1034 cplim = ifa->ifa_netmask->sa_len
1035 + (char *)ifa->ifa_netmask;
1036 while (cp3 < cplim)
1037 if ((*cp++ ^ *cp2++) & *cp3++)
1038 goto next; /* next address! */
1039 /*
1040 * If the netmask of what we just found
1041 * is more specific than what we had before
1042 * (if we had one) then remember the new one
1043 * before continuing to search
1044 * for an even better one.
1045 */
6d2010ae 1046 if (ifa_maybe == NULL ||
1c79356b 1047 rn_refines((caddr_t)ifa->ifa_netmask,
91447636 1048 (caddr_t)ifa_maybe->ifa_netmask)) {
6d2010ae
A
1049 IFA_ADDREF_LOCKED(ifa); /* ifa_maybe */
1050 IFA_UNLOCK(ifa);
1051 if (ifa_maybe != NULL)
1052 IFA_REMREF(ifa_maybe);
1c79356b 1053 ifa_maybe = ifa;
6d2010ae
A
1054 } else {
1055 IFA_UNLOCK(ifa);
91447636 1056 }
1c79356b 1057 }
6d2010ae 1058 IFA_LOCK_ASSERT_NOTHELD(ifa);
1c79356b 1059 }
91447636 1060 ifnet_lock_done(ifp);
6d2010ae
A
1061
1062 if (ifa != NULL)
91447636 1063 break;
91447636
A
1064 }
1065 ifnet_head_done();
6d2010ae
A
1066
1067 if (ifa == NULL)
91447636 1068 ifa = ifa_maybe;
6d2010ae
A
1069 else if (ifa_maybe != NULL)
1070 IFA_REMREF(ifa_maybe);
1071
1072 return (ifa);
1c79356b
A
1073}
1074
1075/*
1076 * Find an interface address specific to an interface best matching
1077 * a given address.
1078 */
1079struct ifaddr *
6d2010ae 1080ifaof_ifpforaddr(const struct sockaddr *addr, struct ifnet *ifp)
1c79356b 1081{
2d21ac55 1082 struct ifaddr *ifa = NULL;
91447636
A
1083 const char *cp, *cp2, *cp3;
1084 char *cplim;
2d21ac55
A
1085 struct ifaddr *ifa_maybe = NULL;
1086 struct ifaddr *better_ifa_maybe = NULL;
1c79356b
A
1087 u_int af = addr->sa_family;
1088
1089 if (af >= AF_MAX)
2d21ac55 1090 return (NULL);
6d2010ae 1091
91447636 1092 ifnet_lock_shared(ifp);
9bccf70c 1093 for (ifa = ifp->if_addrhead.tqh_first; ifa;
1c79356b 1094 ifa = ifa->ifa_link.tqe_next) {
6d2010ae
A
1095 IFA_LOCK(ifa);
1096 if (ifa->ifa_addr->sa_family != af) {
1097 IFA_UNLOCK(ifa);
1c79356b 1098 continue;
6d2010ae
A
1099 }
1100 if (ifa_maybe == NULL) {
1101 IFA_ADDREF_LOCKED(ifa); /* for ifa_maybe */
1c79356b 1102 ifa_maybe = ifa;
6d2010ae 1103 }
1c79356b 1104 if (ifa->ifa_netmask == 0) {
6d2010ae
A
1105 if (equal(addr, ifa->ifa_addr) || (ifa->ifa_dstaddr &&
1106 equal(addr, ifa->ifa_dstaddr))) {
1107 IFA_ADDREF_LOCKED(ifa); /* for caller */
1108 IFA_UNLOCK(ifa);
1109 break;
1110 }
1111 IFA_UNLOCK(ifa);
1c79356b
A
1112 continue;
1113 }
1114 if (ifp->if_flags & IFF_POINTOPOINT) {
6d2010ae
A
1115 if (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)) {
1116 IFA_ADDREF_LOCKED(ifa); /* for caller */
1117 IFA_UNLOCK(ifa);
91447636 1118 break;
6d2010ae 1119 }
1c79356b 1120 } else {
6d2010ae 1121 if (equal(addr, ifa->ifa_addr)) {
2d21ac55 1122 /* exact match */
6d2010ae
A
1123 IFA_ADDREF_LOCKED(ifa); /* for caller */
1124 IFA_UNLOCK(ifa);
2d21ac55
A
1125 break;
1126 }
1c79356b
A
1127 cp = addr->sa_data;
1128 cp2 = ifa->ifa_addr->sa_data;
1129 cp3 = ifa->ifa_netmask->sa_data;
6d2010ae
A
1130 cplim = ifa->ifa_netmask->sa_len +
1131 (char *)ifa->ifa_netmask;
1c79356b
A
1132 for (; cp3 < cplim; cp3++)
1133 if ((*cp++ ^ *cp2++) & *cp3)
1134 break;
2d21ac55
A
1135 if (cp3 == cplim) {
1136 /* subnet match */
1137 if (better_ifa_maybe == NULL) {
6d2010ae
A
1138 /* for better_ifa_maybe */
1139 IFA_ADDREF_LOCKED(ifa);
2d21ac55
A
1140 better_ifa_maybe = ifa;
1141 }
1142 }
1c79356b 1143 }
6d2010ae 1144 IFA_UNLOCK(ifa);
1c79356b 1145 }
6d2010ae 1146
2d21ac55
A
1147 if (ifa == NULL) {
1148 if (better_ifa_maybe != NULL) {
1149 ifa = better_ifa_maybe;
6d2010ae 1150 better_ifa_maybe = NULL;
2d21ac55
A
1151 } else {
1152 ifa = ifa_maybe;
6d2010ae 1153 ifa_maybe = NULL;
2d21ac55
A
1154 }
1155 }
6d2010ae 1156
91447636 1157 ifnet_lock_done(ifp);
6d2010ae
A
1158
1159 if (better_ifa_maybe != NULL)
1160 IFA_REMREF(better_ifa_maybe);
1161 if (ifa_maybe != NULL)
1162 IFA_REMREF(ifa_maybe);
1163
1164 return (ifa);
1c79356b
A
1165}
1166
1167#include <net/route.h>
1168
1169/*
1170 * Default action when installing a route with a Link Level gateway.
1171 * Lookup an appropriate real ifa to point to.
1172 * This should be moved to /sys/net/link.c eventually.
1173 */
91447636 1174void
2d21ac55 1175link_rtrequest(int cmd, struct rtentry *rt, struct sockaddr *sa)
1c79356b 1176{
91447636 1177 struct ifaddr *ifa;
1c79356b
A
1178 struct sockaddr *dst;
1179 struct ifnet *ifp;
6d2010ae 1180 void (*ifa_rtrequest)(int, struct rtentry *, struct sockaddr *);
1c79356b 1181
b0d623f7
A
1182 lck_mtx_assert(rnh_lock, LCK_MTX_ASSERT_OWNED);
1183 RT_LOCK_ASSERT_HELD(rt);
1184
1c79356b
A
1185 if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) ||
1186 ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0))
1187 return;
6d2010ae
A
1188
1189 /* Become a regular mutex, just in case */
1190 RT_CONVERT_LOCK(rt);
1191
1c79356b
A
1192 ifa = ifaof_ifpforaddr(dst, ifp);
1193 if (ifa) {
9bccf70c 1194 rtsetifa(rt, ifa);
6d2010ae
A
1195 IFA_LOCK_SPIN(ifa);
1196 ifa_rtrequest = ifa->ifa_rtrequest;
1197 IFA_UNLOCK(ifa);
1198 if (ifa_rtrequest != NULL && ifa_rtrequest != link_rtrequest)
1199 ifa_rtrequest(cmd, rt, sa);
1200 IFA_REMREF(ifa);
1c79356b
A
1201 }
1202}
1203
1204/*
91447636
A
1205 * if_updown will set the interface up or down. It will
1206 * prevent other up/down events from occurring until this
1207 * up/down event has completed.
1208 *
1209 * Caller must lock ifnet. This function will drop the
1210 * lock. This allows ifnet_set_flags to set the rest of
1211 * the flags after we change the up/down state without
1212 * dropping the interface lock between setting the
1213 * up/down state and updating the rest of the flags.
1c79356b 1214 */
91447636
A
1215__private_extern__ void
1216if_updown(
1217 struct ifnet *ifp,
1218 int up)
1c79356b 1219{
91447636
A
1220 int i;
1221 struct ifaddr **ifa;
1222 struct timespec tv;
1223
1224 /* Wait until no one else is changing the up/down state */
1225 while ((ifp->if_eflags & IFEF_UPDOWNCHANGE) != 0) {
1226 tv.tv_sec = 0;
1227 tv.tv_nsec = NSEC_PER_SEC / 10;
1228 ifnet_lock_done(ifp);
1229 msleep(&ifp->if_eflags, NULL, 0, "if_updown", &tv);
1230 ifnet_lock_exclusive(ifp);
1231 }
1232
1233 /* Verify that the interface isn't already in the right state */
1234 if ((!up && (ifp->if_flags & IFF_UP) == 0) ||
1235 (up && (ifp->if_flags & IFF_UP) == IFF_UP)) {
1236 return;
1237 }
1238
1239 /* Indicate that the up/down state is changing */
1240 ifp->if_eflags |= IFEF_UPDOWNCHANGE;
1241
1242 /* Mark interface up or down */
1243 if (up) {
1244 ifp->if_flags |= IFF_UP;
1245 }
1246 else {
1247 ifp->if_flags &= ~IFF_UP;
1248 }
1249
1250 ifnet_touch_lastchange(ifp);
1251
1252 /* Drop the lock to notify addresses and route */
1253 ifnet_lock_done(ifp);
1254 if (ifnet_get_address_list(ifp, &ifa) == 0) {
1255 for (i = 0; ifa[i] != 0; i++) {
1256 pfctlinput(up ? PRC_IFUP : PRC_IFDOWN, ifa[i]->ifa_addr);
1257 }
1258 ifnet_free_address_list(ifa);
1259 }
1c79356b 1260 rt_ifmsg(ifp);
91447636
A
1261
1262 /* Aquire the lock to clear the changing flag and flush the send queue */
1263 ifnet_lock_exclusive(ifp);
1264 if (!up)
1265 if_qflush(&ifp->if_snd);
1266 ifp->if_eflags &= ~IFEF_UPDOWNCHANGE;
1267 wakeup(&ifp->if_eflags);
1268
1269 return;
1c79356b
A
1270}
1271
1272/*
1273 * Mark an interface down and notify protocols of
1274 * the transition.
1c79356b
A
1275 */
1276void
91447636
A
1277if_down(
1278 struct ifnet *ifp)
1c79356b 1279{
91447636
A
1280 ifnet_lock_exclusive(ifp);
1281 if_updown(ifp, 0);
1282 ifnet_lock_done(ifp);
1c79356b
A
1283}
1284
1285/*
1286 * Mark an interface up and notify protocols of
1287 * the transition.
1c79356b
A
1288 */
1289void
91447636
A
1290if_up(
1291 struct ifnet *ifp)
1c79356b 1292{
91447636
A
1293 ifnet_lock_exclusive(ifp);
1294 if_updown(ifp, 1);
1295 ifnet_lock_done(ifp);
1c79356b
A
1296}
1297
1298/*
1299 * Flush an interface queue.
1300 */
1301static void
2d21ac55 1302if_qflush(struct ifqueue *ifq)
1c79356b 1303{
91447636 1304 struct mbuf *m, *n;
1c79356b
A
1305
1306 n = ifq->ifq_head;
1307 while ((m = n) != 0) {
1308 n = m->m_act;
1309 m_freem(m);
1310 }
2d21ac55
A
1311 ifq->ifq_head = NULL;
1312 ifq->ifq_tail = NULL;
1c79356b
A
1313 ifq->ifq_len = 0;
1314}
1315
1c79356b
A
1316/*
1317 * Map interface name to
1318 * interface structure pointer.
1319 */
1320struct ifnet *
9bccf70c 1321ifunit(const char *name)
1c79356b
A
1322{
1323 char namebuf[IFNAMSIZ + 1];
9bccf70c
A
1324 const char *cp;
1325 struct ifnet *ifp;
1c79356b 1326 int unit;
9bccf70c
A
1327 unsigned len, m;
1328 char c;
1c79356b 1329
9bccf70c
A
1330 len = strlen(name);
1331 if (len < 2 || len > IFNAMSIZ)
6d2010ae 1332 return (NULL);
9bccf70c
A
1333 cp = name + len - 1;
1334 c = *cp;
1335 if (c < '0' || c > '9')
6d2010ae 1336 return (NULL); /* trailing garbage */
9bccf70c
A
1337 unit = 0;
1338 m = 1;
1339 do {
1340 if (cp == name)
6d2010ae 1341 return (NULL); /* no interface name */
9bccf70c
A
1342 unit += (c - '0') * m;
1343 if (unit > 1000000)
6d2010ae 1344 return (NULL); /* number is unreasonable */
9bccf70c
A
1345 m *= 10;
1346 c = *--cp;
1347 } while (c >= '0' && c <= '9');
1c79356b 1348 len = cp - name + 1;
9bccf70c
A
1349 bcopy(name, namebuf, len);
1350 namebuf[len] = '\0';
1c79356b
A
1351 /*
1352 * Now search all the interfaces for this name/number
1353 */
91447636
A
1354 ifnet_head_lock_shared();
1355 TAILQ_FOREACH(ifp, &ifnet_head, if_link) {
2d21ac55 1356 if (strncmp(ifp->if_name, namebuf, len))
1c79356b
A
1357 continue;
1358 if (unit == ifp->if_unit)
1359 break;
1360 }
91447636 1361 ifnet_head_done();
1c79356b
A
1362 return (ifp);
1363}
1364
1365
1366/*
1367 * Map interface name in a sockaddr_dl to
1368 * interface structure pointer.
1369 */
1370struct ifnet *
2d21ac55 1371if_withname(struct sockaddr *sa)
1c79356b
A
1372{
1373 char ifname[IFNAMSIZ+1];
1374 struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;
1375
1376 if ( (sa->sa_family != AF_LINK) || (sdl->sdl_nlen == 0) ||
1377 (sdl->sdl_nlen > IFNAMSIZ) )
6d2010ae 1378 return (NULL);
1c79356b
A
1379
1380 /*
1381 * ifunit wants a null-terminated name. It may not be null-terminated
1382 * in the sockaddr. We don't want to change the caller's sockaddr,
1383 * and there might not be room to put the trailing null anyway, so we
1384 * make a local copy that we know we can null terminate safely.
1385 */
1386
1387 bcopy(sdl->sdl_data, ifname, sdl->sdl_nlen);
1388 ifname[sdl->sdl_nlen] = '\0';
6d2010ae 1389 return (ifunit(ifname));
1c79356b
A
1390}
1391
1392
1393/*
1394 * Interface ioctls.
1395 */
1396int
2d21ac55 1397ifioctl(struct socket *so, u_long cmd, caddr_t data, struct proc *p)
1c79356b 1398{
91447636
A
1399 struct ifnet *ifp;
1400 struct ifreq *ifr;
9bccf70c 1401 struct ifstat *ifs;
1c79356b 1402 int error = 0;
1c79356b 1403 short oif_flags;
9bccf70c 1404 struct kev_msg ev_msg;
1c79356b
A
1405 struct net_event_data ev_data;
1406
6d2010ae
A
1407 bzero(&ev_data, sizeof(struct net_event_data));
1408 bzero(&ev_msg, sizeof(struct kev_msg));
1c79356b 1409 switch (cmd) {
b0d623f7
A
1410 case OSIOCGIFCONF32:
1411 case SIOCGIFCONF32: {
1412 struct ifconf32 *ifc = (struct ifconf32 *)data;
1413 return (ifconf(cmd, CAST_USER_ADDR_T(ifc->ifc_req),
1414 &ifc->ifc_len));
1415 /* NOTREACHED */
1416 }
91447636 1417 case SIOCGIFCONF64:
b0d623f7
A
1418 case OSIOCGIFCONF64: {
1419 struct ifconf64 *ifc = (struct ifconf64 *)data;
1420 return (ifconf(cmd, ifc->ifc_req, &ifc->ifc_len));
1421 /* NOTREACHED */
1422 }
1c79356b
A
1423 }
1424 ifr = (struct ifreq *)data;
4a249263
A
1425 switch (cmd) {
1426 case SIOCIFCREATE:
d1ecb069
A
1427 case SIOCIFCREATE2:
1428 error = proc_suser(p);
1429 if (error)
1430 return (error);
1431 return if_clone_create(ifr->ifr_name, sizeof(ifr->ifr_name),
1432 cmd == SIOCIFCREATE2 ? ifr->ifr_data : NULL);
4a249263 1433 case SIOCIFDESTROY:
91447636 1434 error = proc_suser(p);
4a249263
A
1435 if (error)
1436 return (error);
d1ecb069 1437 return if_clone_destroy(ifr->ifr_name);
91447636 1438#if IF_CLONE_LIST
b0d623f7
A
1439 case SIOCIFGCLONERS32: {
1440 struct if_clonereq32 *ifcr = (struct if_clonereq32 *)data;
1441 return (if_clone_list(ifcr->ifcr_count, &ifcr->ifcr_total,
1442 CAST_USER_ADDR_T(ifcr->ifcru_buffer)));
1443 /* NOTREACHED */
1444
1445 }
1446 case SIOCIFGCLONERS64: {
1447 struct if_clonereq64 *ifcr = (struct if_clonereq64 *)data;
91447636 1448 return (if_clone_list(ifcr->ifcr_count, &ifcr->ifcr_total,
b0d623f7
A
1449 ifcr->ifcru_buffer));
1450 /* NOTREACHED */
91447636 1451 }
b0d623f7 1452#endif /* IF_CLONE_LIST */
4a249263
A
1453 }
1454
7ddcb079
A
1455 /*
1456 * ioctls which require ifp. Note that we acquire dlil_ifnet_lock
1457 * here to ensure that the ifnet, if found, has been fully attached.
1458 */
1459 dlil_if_lock();
1c79356b 1460 ifp = ifunit(ifr->ifr_name);
7ddcb079 1461 dlil_if_unlock();
6d2010ae 1462 if (ifp == NULL)
1c79356b 1463 return (ENXIO);
1c79356b 1464
6d2010ae 1465 switch (cmd) {
1c79356b 1466 case SIOCGIFFLAGS:
91447636 1467 ifnet_lock_shared(ifp);
1c79356b 1468 ifr->ifr_flags = ifp->if_flags;
91447636 1469 ifnet_lock_done(ifp);
1c79356b
A
1470 break;
1471
6d2010ae
A
1472 case SIOCGIFCAP:
1473 ifnet_lock_shared(ifp);
1474 ifr->ifr_reqcap = ifp->if_capabilities;
1475 ifr->ifr_curcap = ifp->if_capenable;
1476 ifnet_lock_done(ifp);
1477 break;
1478
2d21ac55
A
1479#if CONFIG_MACF_NET
1480 case SIOCGIFMAC:
1481 error = mac_ifnet_label_get(kauth_cred_get(), ifr, ifp);
2d21ac55
A
1482 break;
1483#endif
1c79356b 1484 case SIOCGIFMETRIC:
91447636 1485 ifnet_lock_shared(ifp);
1c79356b 1486 ifr->ifr_metric = ifp->if_metric;
91447636 1487 ifnet_lock_done(ifp);
1c79356b
A
1488 break;
1489
1490 case SIOCGIFMTU:
91447636 1491 ifnet_lock_shared(ifp);
1c79356b 1492 ifr->ifr_mtu = ifp->if_mtu;
91447636 1493 ifnet_lock_done(ifp);
1c79356b
A
1494 break;
1495
1496 case SIOCGIFPHYS:
91447636 1497 ifnet_lock_shared(ifp);
1c79356b 1498 ifr->ifr_phys = ifp->if_physical;
91447636 1499 ifnet_lock_done(ifp);
1c79356b
A
1500 break;
1501
1502 case SIOCSIFFLAGS:
91447636 1503 error = proc_suser(p);
6d2010ae
A
1504 if (error != 0)
1505 break;
1c79356b 1506
6d2010ae
A
1507 (void) ifnet_set_flags(ifp, ifr->ifr_flags,
1508 (u_int16_t)~IFF_CANTCHANGE);
2d21ac55 1509
6d2010ae
A
1510 /*
1511 * Note that we intentionally ignore any error from below
1512 * for the SIOCSIFFLAGS case.
1513 */
1514 (void) ifnet_ioctl(ifp, so->so_proto->pr_domain->dom_family,
1515 cmd, data);
1c79356b 1516
6d2010ae
A
1517 /*
1518 * Send the event even upon error from the driver because
1519 * we changed the flags.
1520 */
b0d623f7
A
1521 ev_msg.vendor_code = KEV_VENDOR_APPLE;
1522 ev_msg.kev_class = KEV_NETWORK_CLASS;
1523 ev_msg.kev_subclass = KEV_DL_SUBCLASS;
6d2010ae 1524
b0d623f7
A
1525 ev_msg.event_code = KEV_DL_SIFFLAGS;
1526 strlcpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ);
1527 ev_data.if_family = ifp->if_family;
1528 ev_data.if_unit = (u_int32_t) ifp->if_unit;
1529 ev_msg.dv[0].data_length = sizeof(struct net_event_data);
1530 ev_msg.dv[0].data_ptr = &ev_data;
1531 ev_msg.dv[1].data_length = 0;
1532 kev_post_msg(&ev_msg);
1533
91447636 1534 ifnet_touch_lastchange(ifp);
1c79356b
A
1535 break;
1536
6d2010ae
A
1537 case SIOCSIFCAP:
1538 error = proc_suser(p);
1539 if (error != 0)
1540 break;
1541
1542 if ((ifr->ifr_reqcap & ~ifp->if_capabilities)) {
1543 error = EINVAL;
1544 break;
1545 }
1546 error = ifnet_ioctl(ifp, so->so_proto->pr_domain->dom_family,
1547 cmd, data);
1548
1549 ifnet_touch_lastchange(ifp);
1550 break;
1551
2d21ac55
A
1552#if CONFIG_MACF_NET
1553 case SIOCSIFMAC:
1554 error = mac_ifnet_label_set(kauth_cred_get(), ifr, ifp);
2d21ac55
A
1555 break;
1556#endif
1c79356b 1557 case SIOCSIFMETRIC:
91447636 1558 error = proc_suser(p);
6d2010ae
A
1559 if (error != 0)
1560 break;
1c79356b 1561
6d2010ae 1562 ifp->if_metric = ifr->ifr_metric;
1c79356b
A
1563
1564 ev_msg.vendor_code = KEV_VENDOR_APPLE;
1565 ev_msg.kev_class = KEV_NETWORK_CLASS;
1566 ev_msg.kev_subclass = KEV_DL_SUBCLASS;
6d2010ae 1567
1c79356b 1568 ev_msg.event_code = KEV_DL_SIFMETRICS;
2d21ac55 1569 strlcpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ);
1c79356b 1570 ev_data.if_family = ifp->if_family;
b0d623f7 1571 ev_data.if_unit = (u_int32_t) ifp->if_unit;
1c79356b
A
1572 ev_msg.dv[0].data_length = sizeof(struct net_event_data);
1573 ev_msg.dv[0].data_ptr = &ev_data;
1574
1575 ev_msg.dv[1].data_length = 0;
1576 kev_post_msg(&ev_msg);
1577
91447636 1578 ifnet_touch_lastchange(ifp);
1c79356b
A
1579 break;
1580
1581 case SIOCSIFPHYS:
91447636 1582 error = proc_suser(p);
6d2010ae
A
1583 if (error != 0)
1584 break;
1c79356b 1585
6d2010ae
A
1586 error = ifnet_ioctl(ifp, so->so_proto->pr_domain->dom_family,
1587 cmd, data);
1588 if (error != 0)
1589 break;
1c79356b 1590
6d2010ae
A
1591 ev_msg.vendor_code = KEV_VENDOR_APPLE;
1592 ev_msg.kev_class = KEV_NETWORK_CLASS;
1593 ev_msg.kev_subclass = KEV_DL_SUBCLASS;
1594
1595 ev_msg.event_code = KEV_DL_SIFPHYS;
1596 strlcpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ);
1597 ev_data.if_family = ifp->if_family;
1598 ev_data.if_unit = (u_int32_t) ifp->if_unit;
1599 ev_msg.dv[0].data_length = sizeof(struct net_event_data);
1600 ev_msg.dv[0].data_ptr = &ev_data;
1601 ev_msg.dv[1].data_length = 0;
1602 kev_post_msg(&ev_msg);
1603
1604 ifnet_touch_lastchange(ifp);
1605 break;
1c79356b
A
1606
1607 case SIOCSIFMTU:
1608 {
b0d623f7 1609 u_int32_t oldmtu = ifp->if_mtu;
1c79356b 1610
91447636 1611 error = proc_suser(p);
6d2010ae
A
1612 if (error != 0)
1613 break;
1c79356b 1614
6d2010ae
A
1615 if (ifp->if_ioctl == NULL) {
1616 error = EOPNOTSUPP;
1617 break;
1618 }
1619 if (ifr->ifr_mtu < IF_MINMTU || ifr->ifr_mtu > IF_MAXMTU) {
1620 error = EINVAL;
1621 break;
1c79356b 1622 }
6d2010ae
A
1623 error = ifnet_ioctl(ifp, so->so_proto->pr_domain->dom_family,
1624 cmd, data);
1625 if (error != 0)
1626 break;
1627
1628 ev_msg.vendor_code = KEV_VENDOR_APPLE;
1629 ev_msg.kev_class = KEV_NETWORK_CLASS;
1630 ev_msg.kev_subclass = KEV_DL_SUBCLASS;
1631
1632 ev_msg.event_code = KEV_DL_SIFMTU;
1633 strlcpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ);
1634 ev_data.if_family = ifp->if_family;
1635 ev_data.if_unit = (u_int32_t) ifp->if_unit;
1636 ev_msg.dv[0].data_length = sizeof(struct net_event_data);
1637 ev_msg.dv[0].data_ptr = &ev_data;
1638 ev_msg.dv[1].data_length = 0;
1639 kev_post_msg(&ev_msg);
1640
1641 ifnet_touch_lastchange(ifp);
1642 rt_ifmsg(ifp);
1643
1c79356b 1644 /*
2d21ac55
A
1645 * If the link MTU changed, do network layer specific procedure
1646 * and update all route entries associated with the interface,
1647 * so that their MTU metric gets updated.
1c79356b 1648 */
6d2010ae 1649 if (ifp->if_mtu != oldmtu) {
2d21ac55 1650 if_rtmtu_update(ifp);
9bccf70c
A
1651#if INET6
1652 nd6_setmtu(ifp);
1653#endif
1c79356b 1654 }
6d2010ae 1655 break;
9bccf70c 1656 }
1c79356b
A
1657
1658 case SIOCADDMULTI:
1659 case SIOCDELMULTI:
91447636 1660 error = proc_suser(p);
6d2010ae
A
1661 if (error != 0)
1662 break;
1c79356b
A
1663
1664 /* Don't allow group membership on non-multicast interfaces. */
6d2010ae
A
1665 if ((ifp->if_flags & IFF_MULTICAST) == 0) {
1666 error = EOPNOTSUPP;
1667 break;
1668 }
1c79356b 1669
9bccf70c 1670 /* Don't let users screw up protocols' entries. */
6d2010ae
A
1671 if (ifr->ifr_addr.sa_family != AF_UNSPEC &&
1672 ifr->ifr_addr.sa_family != AF_LINK) {
1673 error = EINVAL;
1674 break;
1675 }
9bccf70c 1676
6d2010ae
A
1677 /*
1678 * User is permitted to anonymously join a particular link
1679 * multicast group via SIOCADDMULTI. Subsequent join requested
1680 * for the same record which has an outstanding refcnt from a
1681 * past if_addmulti_anon() will not result in EADDRINUSE error
1682 * (unlike other BSDs.) Anonymously leaving a group is also
1683 * allowed only as long as there is an outstanding refcnt held
1684 * by a previous anonymous request, or else ENOENT (even if the
1685 * link-layer multicast membership exists for a network-layer
1686 * membership.)
1687 */
1c79356b 1688 if (cmd == SIOCADDMULTI) {
6d2010ae 1689 error = if_addmulti_anon(ifp, &ifr->ifr_addr, NULL);
1c79356b
A
1690 ev_msg.event_code = KEV_DL_ADDMULTI;
1691 } else {
6d2010ae 1692 error = if_delmulti_anon(ifp, &ifr->ifr_addr);
1c79356b
A
1693 ev_msg.event_code = KEV_DL_DELMULTI;
1694 }
6d2010ae
A
1695 if (error != 0)
1696 break;
1697
1698 ev_msg.vendor_code = KEV_VENDOR_APPLE;
1699 ev_msg.kev_class = KEV_NETWORK_CLASS;
1700 ev_msg.kev_subclass = KEV_DL_SUBCLASS;
1701 strlcpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ);
1702
1703 ev_data.if_family = ifp->if_family;
1704 ev_data.if_unit = (u_int32_t) ifp->if_unit;
1705 ev_msg.dv[0].data_length = sizeof(struct net_event_data);
1706 ev_msg.dv[0].data_ptr = &ev_data;
1707 ev_msg.dv[1].data_length = 0;
1708 kev_post_msg(&ev_msg);
1709
1710 ifnet_touch_lastchange(ifp);
1711 break;
1c79356b 1712
9bccf70c
A
1713 case SIOCSIFPHYADDR:
1714 case SIOCDIFPHYADDR:
2d21ac55 1715#if INET6
b0d623f7
A
1716 case SIOCSIFPHYADDR_IN6_32:
1717 case SIOCSIFPHYADDR_IN6_64:
9bccf70c
A
1718#endif
1719 case SIOCSLIFPHYADDR:
1720 case SIOCSIFMEDIA:
1c79356b 1721 case SIOCSIFGENERIC:
9bccf70c 1722 case SIOCSIFLLADDR:
91447636
A
1723 case SIOCSIFALTMTU:
1724 case SIOCSIFVLAN:
1725 case SIOCSIFBOND:
1726 error = proc_suser(p);
6d2010ae
A
1727 if (error != 0)
1728 break;
1c79356b 1729
6d2010ae
A
1730 error = ifnet_ioctl(ifp, so->so_proto->pr_domain->dom_family,
1731 cmd, data);
1732 if (error != 0)
1733 break;
1c79356b 1734
6d2010ae
A
1735 ifnet_touch_lastchange(ifp);
1736 break;
1c79356b 1737
9bccf70c
A
1738 case SIOCGIFSTATUS:
1739 ifs = (struct ifstat *)data;
1740 ifs->ascii[0] = '\0';
6d2010ae 1741
9bccf70c
A
1742 case SIOCGIFPSRCADDR:
1743 case SIOCGIFPDSTADDR:
1744 case SIOCGLIFPHYADDR:
b0d623f7
A
1745 case SIOCGIFMEDIA32:
1746 case SIOCGIFMEDIA64:
1c79356b 1747 case SIOCGIFGENERIC:
91447636 1748 case SIOCGIFDEVMTU:
6d2010ae
A
1749 error = ifnet_ioctl(ifp, so->so_proto->pr_domain->dom_family,
1750 cmd, data);
1751 break;
1752
91447636
A
1753 case SIOCGIFVLAN:
1754 case SIOCGIFBOND:
6d2010ae
A
1755 error = ifnet_ioctl(ifp, so->so_proto->pr_domain->dom_family,
1756 cmd, data);
1757 break;
1c79356b 1758
b0d623f7
A
1759 case SIOCGIFWAKEFLAGS:
1760 ifnet_lock_shared(ifp);
1761 ifr->ifr_wake_flags = ifnet_get_wake_flags(ifp);
1762 ifnet_lock_done(ifp);
1763 break;
d1ecb069
A
1764
1765 case SIOCGIFGETRTREFCNT:
d1ecb069
A
1766 ifnet_lock_shared(ifp);
1767 ifr->ifr_route_refcnt = ifp->if_route_refcnt;
1768 ifnet_lock_done(ifp);
1769 break;
d1ecb069 1770
1c79356b
A
1771 default:
1772 oif_flags = ifp->if_flags;
6d2010ae
A
1773 if (so->so_proto == NULL) {
1774 error = EOPNOTSUPP;
1775 break;
1776 }
1c79356b 1777 {
6d2010ae 1778 u_long ocmd = cmd;
1c79356b
A
1779
1780 switch (cmd) {
1c79356b
A
1781 case SIOCSIFDSTADDR:
1782 case SIOCSIFADDR:
1783 case SIOCSIFBRDADDR:
1784 case SIOCSIFNETMASK:
1785#if BYTE_ORDER != BIG_ENDIAN
1786 if (ifr->ifr_addr.sa_family == 0 &&
1787 ifr->ifr_addr.sa_len < 16) {
1788 ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len;
1789 ifr->ifr_addr.sa_len = 16;
1790 }
1791#else
1792 if (ifr->ifr_addr.sa_len == 0)
1793 ifr->ifr_addr.sa_len = 16;
1794#endif
1c79356b
A
1795 break;
1796
1797 case OSIOCGIFADDR:
1798 cmd = SIOCGIFADDR;
1799 break;
1800
1801 case OSIOCGIFDSTADDR:
1802 cmd = SIOCGIFDSTADDR;
1803 break;
1804
1805 case OSIOCGIFBRDADDR:
1806 cmd = SIOCGIFBRDADDR;
1807 break;
1808
1809 case OSIOCGIFNETMASK:
1810 cmd = SIOCGIFNETMASK;
1811 }
6d2010ae 1812
91447636 1813 socket_lock(so, 1);
6d2010ae
A
1814 error = ((*so->so_proto->pr_usrreqs->pru_control)(so, cmd,
1815 data, ifp, p));
91447636 1816 socket_unlock(so, 1);
1c79356b 1817
6d2010ae 1818 switch (ocmd) {
1c79356b
A
1819 case OSIOCGIFADDR:
1820 case OSIOCGIFDSTADDR:
1821 case OSIOCGIFBRDADDR:
1822 case OSIOCGIFNETMASK:
9bccf70c 1823 *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family;
1c79356b 1824
1c79356b
A
1825 }
1826 }
2d21ac55
A
1827 if (cmd == SIOCSIFKPI) {
1828 int temperr = proc_suser(p);
1829 if (temperr != 0)
1830 error = temperr;
1831 }
1c79356b 1832
91447636 1833 if (error == EOPNOTSUPP || error == ENOTSUP)
6d2010ae
A
1834 error = ifnet_ioctl(ifp,
1835 so->so_proto->pr_domain->dom_family, cmd, data);
9bccf70c 1836
6d2010ae 1837 break;
1c79356b 1838 }
6d2010ae 1839 return (error);
1c79356b
A
1840}
1841
91447636 1842int
2d21ac55 1843ifioctllocked(struct socket *so, u_long cmd, caddr_t data, struct proc *p)
91447636
A
1844{
1845 int error;
1846
1847 socket_unlock(so, 0);
1848 error = ifioctl(so, cmd, data, p);
1849 socket_lock(so, 0);
1850 return(error);
1851}
1852
1c79356b
A
1853/*
1854 * Set/clear promiscuous mode on interface ifp based on the truth value
1855 * of pswitch. The calls are reference counted so that only the first
1856 * "on" request actually has an effect, as does the final "off" request.
1857 * Results are undefined if the "off" and "on" requests are not matched.
1858 */
91447636
A
1859errno_t
1860ifnet_set_promiscuous(
1861 ifnet_t ifp,
1862 int pswitch)
1c79356b 1863{
91447636 1864 int error = 0;
6d2010ae
A
1865 int oldflags = 0;
1866 int newflags = 0;
1c79356b 1867
91447636 1868 ifnet_lock_exclusive(ifp);
9bccf70c 1869 oldflags = ifp->if_flags;
6d2010ae
A
1870 ifp->if_pcount += pswitch ? 1 : -1;
1871
1872 if (ifp->if_pcount > 0)
1c79356b 1873 ifp->if_flags |= IFF_PROMISC;
6d2010ae 1874 else
1c79356b 1875 ifp->if_flags &= ~IFF_PROMISC;
6d2010ae
A
1876
1877 newflags = ifp->if_flags;
91447636 1878 ifnet_lock_done(ifp);
6d2010ae
A
1879
1880 if (newflags != oldflags && (newflags & IFF_UP) != 0) {
1881 error = ifnet_ioctl(ifp, 0, SIOCSIFFLAGS, NULL);
1882 if (error == 0) {
1883 rt_ifmsg(ifp);
1884 } else {
1885 ifnet_lock_exclusive(ifp);
1886 // revert the flags
1887 ifp->if_pcount -= pswitch ? 1 : -1;
1888 if (ifp->if_pcount > 0)
1889 ifp->if_flags |= IFF_PROMISC;
1890 else
1891 ifp->if_flags &= ~IFF_PROMISC;
1892 ifnet_lock_done(ifp);
1893 }
1894 }
1895
1896 if (newflags != oldflags) {
1897 log(LOG_INFO, "%s%d: promiscuous mode %s%s\n",
91447636 1898 ifp->if_name, ifp->if_unit,
6d2010ae
A
1899 (newflags & IFF_PROMISC) != 0 ? "enable" : "disable",
1900 error != 0 ? " failed" : " succeeded");
91447636 1901 }
1c79356b
A
1902 return error;
1903}
1904
1905/*
1906 * Return interface configuration
1907 * of system. List may be used
1908 * in later ioctl's (above) to get
1909 * other information.
1910 */
1911/*ARGSUSED*/
1912static int
91447636 1913ifconf(u_long cmd, user_addr_t ifrp, int * ret_space)
1c79356b 1914{
91447636
A
1915 struct ifnet *ifp = NULL;
1916 struct ifaddr *ifa;
1917 struct ifreq ifr;
1918 int error = 0;
1919 size_t space;
6d2010ae 1920
3a60a9f5
A
1921 /*
1922 * Zero the ifr buffer to make sure we don't
1923 * disclose the contents of the stack.
1924 */
1925 bzero(&ifr, sizeof(struct ifreq));
1926
91447636
A
1927 space = *ret_space;
1928 ifnet_head_lock_shared();
6d2010ae
A
1929 for (ifp = ifnet_head.tqh_first; space > sizeof(ifr) &&
1930 ifp; ifp = ifp->if_link.tqe_next) {
1c79356b 1931 char workbuf[64];
91447636 1932 size_t ifnlen, addrs;
1c79356b
A
1933
1934 ifnlen = snprintf(workbuf, sizeof(workbuf),
1935 "%s%d", ifp->if_name, ifp->if_unit);
1936 if(ifnlen + 1 > sizeof ifr.ifr_name) {
1937 error = ENAMETOOLONG;
9bccf70c 1938 break;
1c79356b 1939 } else {
2d21ac55 1940 strlcpy(ifr.ifr_name, workbuf, IFNAMSIZ);
1c79356b 1941 }
6d2010ae 1942
91447636 1943 ifnet_lock_shared(ifp);
1c79356b 1944
9bccf70c
A
1945 addrs = 0;
1946 ifa = ifp->if_addrhead.tqh_first;
1947 for ( ; space > sizeof (ifr) && ifa;
1948 ifa = ifa->ifa_link.tqe_next) {
6d2010ae
A
1949 struct sockaddr *sa;
1950
1951 IFA_LOCK(ifa);
1952 sa = ifa->ifa_addr;
9bccf70c 1953#ifndef __APPLE__
6d2010ae
A
1954 if (curproc->p_prison && prison_if(curproc, sa)) {
1955 IFA_UNLOCK(ifa);
9bccf70c 1956 continue;
6d2010ae 1957 }
9bccf70c
A
1958#endif
1959 addrs++;
b0d623f7 1960 if (cmd == OSIOCGIFCONF32 || cmd == OSIOCGIFCONF64) {
1c79356b
A
1961 struct osockaddr *osa =
1962 (struct osockaddr *)&ifr.ifr_addr;
1963 ifr.ifr_addr = *sa;
1964 osa->sa_family = sa->sa_family;
6d2010ae
A
1965 error = copyout((caddr_t)&ifr, ifrp,
1966 sizeof (ifr));
91447636 1967 ifrp += sizeof(struct ifreq);
2d21ac55 1968 } else if (sa->sa_len <= sizeof(*sa)) {
1c79356b 1969 ifr.ifr_addr = *sa;
6d2010ae
A
1970 error = copyout((caddr_t)&ifr, ifrp,
1971 sizeof (ifr));
91447636 1972 ifrp += sizeof(struct ifreq);
1c79356b 1973 } else {
6d2010ae
A
1974 if (space <
1975 sizeof (ifr) + sa->sa_len - sizeof(*sa)) {
1976 IFA_UNLOCK(ifa);
1c79356b 1977 break;
6d2010ae 1978 }
9bccf70c 1979 space -= sa->sa_len - sizeof(*sa);
6d2010ae
A
1980 error = copyout((caddr_t)&ifr, ifrp,
1981 sizeof (ifr.ifr_name));
91447636 1982 if (error == 0) {
6d2010ae
A
1983 error = copyout((caddr_t)sa, (ifrp +
1984 offsetof(struct ifreq, ifr_addr)),
1985 sa->sa_len);
91447636 1986 }
6d2010ae
A
1987 ifrp += (sa->sa_len + offsetof(struct ifreq,
1988 ifr_addr));
1c79356b 1989 }
6d2010ae 1990 IFA_UNLOCK(ifa);
1c79356b
A
1991 if (error)
1992 break;
1993 space -= sizeof (ifr);
1994 }
91447636 1995 ifnet_lock_done(ifp);
6d2010ae 1996
9bccf70c
A
1997 if (error)
1998 break;
1999 if (!addrs) {
2000 bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
91447636 2001 error = copyout((caddr_t)&ifr, ifrp, sizeof (ifr));
9bccf70c
A
2002 if (error)
2003 break;
2004 space -= sizeof (ifr);
91447636 2005 ifrp += sizeof(struct ifreq);
9bccf70c 2006 }
1c79356b 2007 }
91447636
A
2008 ifnet_head_done();
2009 *ret_space -= space;
1c79356b
A
2010 return (error);
2011}
2012
2013/*
2014 * Just like if_promisc(), but for all-multicast-reception mode.
2015 */
2016int
2d21ac55 2017if_allmulti(struct ifnet *ifp, int onswitch)
1c79356b
A
2018{
2019 int error = 0;
91447636
A
2020 int modified = 0;
2021
2022 ifnet_lock_exclusive(ifp);
1c79356b
A
2023
2024 if (onswitch) {
2025 if (ifp->if_amcount++ == 0) {
2026 ifp->if_flags |= IFF_ALLMULTI;
91447636 2027 modified = 1;
1c79356b
A
2028 }
2029 } else {
2030 if (ifp->if_amcount > 1) {
2031 ifp->if_amcount--;
2032 } else {
2033 ifp->if_amcount = 0;
2034 ifp->if_flags &= ~IFF_ALLMULTI;
91447636 2035 modified = 1;
1c79356b
A
2036 }
2037 }
91447636
A
2038 ifnet_lock_done(ifp);
2039
2040 if (modified)
2d21ac55 2041 error = ifnet_ioctl(ifp, 0, SIOCSIFFLAGS, NULL);
1c79356b
A
2042
2043 if (error == 0)
2044 rt_ifmsg(ifp);
2045 return error;
2046}
2047
6d2010ae
A
2048static struct ifmultiaddr *
2049ifma_alloc(int how)
2050{
2051 struct ifmultiaddr *ifma;
2052
2053 ifma = (how == M_WAITOK) ? zalloc(ifma_zone) :
2054 zalloc_noblock(ifma_zone);
2055
2056 if (ifma != NULL) {
2057 bzero(ifma, ifma_size);
2058 lck_mtx_init(&ifma->ifma_lock, ifa_mtx_grp, ifa_mtx_attr);
2059 ifma->ifma_debug |= IFD_ALLOC;
2060 if (ifma_debug != 0) {
2061 ifma->ifma_debug |= IFD_DEBUG;
2062 ifma->ifma_trace = ifma_trace;
2063 }
2064 }
2065 return (ifma);
2066}
2067
2068static void
2069ifma_free(struct ifmultiaddr *ifma)
2070{
2071 IFMA_LOCK(ifma);
2072
2073 if (ifma->ifma_protospec != NULL) {
2074 panic("%s: Protospec not NULL for ifma=%p", __func__, ifma);
2075 /* NOTREACHED */
2076 } else if ((ifma->ifma_flags & IFMAF_ANONYMOUS) ||
2077 ifma->ifma_anoncnt != 0) {
2078 panic("%s: Freeing ifma=%p with outstanding anon req",
2079 __func__, ifma);
2080 /* NOTREACHED */
2081 } else if (ifma->ifma_debug & IFD_ATTACHED) {
2082 panic("%s: ifma=%p attached to ifma_ifp=%p is being freed",
2083 __func__, ifma, ifma->ifma_ifp);
2084 /* NOTREACHED */
2085 } else if (!(ifma->ifma_debug & IFD_ALLOC)) {
2086 panic("%s: ifma %p cannot be freed", __func__, ifma);
2087 /* NOTREACHED */
2088 } else if (ifma->ifma_refcount != 0) {
2089 panic("%s: non-zero refcount ifma=%p", __func__, ifma);
2090 /* NOTREACHED */
2091 } else if (ifma->ifma_reqcnt != 0) {
2092 panic("%s: non-zero reqcnt ifma=%p", __func__, ifma);
2093 /* NOTREACHED */
2094 } else if (ifma->ifma_ifp != NULL) {
2095 panic("%s: non-NULL ifma_ifp=%p for ifma=%p", __func__,
2096 ifma->ifma_ifp, ifma);
2097 /* NOTREACHED */
2098 } else if (ifma->ifma_ll != NULL) {
2099 panic("%s: non-NULL ifma_ll=%p for ifma=%p", __func__,
2100 ifma->ifma_ll, ifma);
2101 /* NOTREACHED */
2102 }
2103 ifma->ifma_debug &= ~IFD_ALLOC;
2104 if ((ifma->ifma_debug & (IFD_DEBUG | IFD_TRASHED)) ==
2105 (IFD_DEBUG | IFD_TRASHED)) {
2106 lck_mtx_lock(&ifma_trash_lock);
2107 TAILQ_REMOVE(&ifma_trash_head, (struct ifmultiaddr_dbg *)ifma,
2108 ifma_trash_link);
2109 lck_mtx_unlock(&ifma_trash_lock);
2110 ifma->ifma_debug &= ~IFD_TRASHED;
2111 }
2112 IFMA_UNLOCK(ifma);
2113
2114 if (ifma->ifma_addr != NULL) {
2115 FREE(ifma->ifma_addr, M_IFADDR);
2116 ifma->ifma_addr = NULL;
2117 }
2118 lck_mtx_destroy(&ifma->ifma_lock, ifa_mtx_grp);
2119 zfree(ifma_zone, ifma);
2120}
2121
2122static void
2123ifma_trace(struct ifmultiaddr *ifma, int refhold)
2124{
2125 struct ifmultiaddr_dbg *ifma_dbg = (struct ifmultiaddr_dbg *)ifma;
2126 ctrace_t *tr;
2127 u_int32_t idx;
2128 u_int16_t *cnt;
2129
2130 if (!(ifma->ifma_debug & IFD_DEBUG)) {
2131 panic("%s: ifma %p has no debug structure", __func__, ifma);
2132 /* NOTREACHED */
2133 }
2134 if (refhold) {
2135 cnt = &ifma_dbg->ifma_refhold_cnt;
2136 tr = ifma_dbg->ifma_refhold;
2137 } else {
2138 cnt = &ifma_dbg->ifma_refrele_cnt;
2139 tr = ifma_dbg->ifma_refrele;
2140 }
2141
2142 idx = atomic_add_16_ov(cnt, 1) % IFMA_TRACE_HIST_SIZE;
2143 ctrace_record(&tr[idx]);
2144}
2145
91447636 2146void
6d2010ae 2147ifma_addref(struct ifmultiaddr *ifma, int locked)
1c79356b 2148{
6d2010ae
A
2149 if (!locked)
2150 IFMA_LOCK(ifma);
2151 else
2152 IFMA_LOCK_ASSERT_HELD(ifma);
2153
2154 if (++ifma->ifma_refcount == 0) {
2155 panic("%s: ifma=%p wraparound refcnt", __func__, ifma);
2156 /* NOTREACHED */
2157 } else if (ifma->ifma_trace != NULL) {
2158 (*ifma->ifma_trace)(ifma, TRUE);
2159 }
2160 if (!locked)
2161 IFMA_UNLOCK(ifma);
91447636 2162}
1c79356b 2163
91447636 2164void
6d2010ae
A
2165ifma_remref(struct ifmultiaddr *ifma)
2166{
2167 struct ifmultiaddr *ll;
2168
2169 IFMA_LOCK(ifma);
2170
2171 if (ifma->ifma_refcount == 0) {
2172 panic("%s: ifma=%p negative refcnt", __func__, ifma);
2173 /* NOTREACHED */
2174 } else if (ifma->ifma_trace != NULL) {
2175 (*ifma->ifma_trace)(ifma, FALSE);
2176 }
2177
2178 --ifma->ifma_refcount;
2179 if (ifma->ifma_refcount > 0) {
2180 IFMA_UNLOCK(ifma);
2181 return;
91447636 2182 }
6d2010ae
A
2183
2184 ll = ifma->ifma_ll;
2185 ifma->ifma_ifp = NULL;
2186 ifma->ifma_ll = NULL;
2187 IFMA_UNLOCK(ifma);
2188 ifma_free(ifma); /* deallocate it */
2189
2190 if (ll != NULL)
2191 IFMA_REMREF(ll);
2192}
2193
2194static void
2195if_attach_ifma(struct ifnet *ifp, struct ifmultiaddr *ifma, int anon)
2196{
2197 ifnet_lock_assert(ifp, IFNET_LCK_ASSERT_EXCLUSIVE);
2198 IFMA_LOCK_ASSERT_HELD(ifma);
2199
2200 if (ifma->ifma_ifp != ifp) {
2201 panic("%s: Mismatch ifma_ifp=%p != ifp=%p", __func__,
2202 ifma->ifma_ifp, ifp);
2203 /* NOTREACHED */
2204 } else if (ifma->ifma_debug & IFD_ATTACHED) {
2205 panic("%s: Attempt to attach an already attached ifma=%p",
2206 __func__, ifma);
2207 /* NOTREACHED */
2208 } else if (anon && (ifma->ifma_flags & IFMAF_ANONYMOUS)) {
2209 panic("%s: ifma=%p unexpected IFMAF_ANONYMOUS", __func__, ifma);
2210 /* NOTREACHED */
2211 } else if (ifma->ifma_debug & IFD_TRASHED) {
2212 panic("%s: Attempt to reattach a detached ifma=%p",
2213 __func__, ifma);
2214 /* NOTREACHED */
2215 }
2216
2217 ifma->ifma_reqcnt++;
2218 VERIFY(ifma->ifma_reqcnt == 1);
2219 IFMA_ADDREF_LOCKED(ifma);
2220 ifma->ifma_debug |= IFD_ATTACHED;
2221 if (anon) {
2222 ifma->ifma_anoncnt++;
2223 VERIFY(ifma->ifma_anoncnt == 1);
2224 ifma->ifma_flags |= IFMAF_ANONYMOUS;
2225 }
2226
2227 LIST_INSERT_HEAD(&ifp->if_multiaddrs, ifma, ifma_link);
91447636
A
2228}
2229
91447636 2230static int
6d2010ae
A
2231if_detach_ifma(struct ifnet *ifp, struct ifmultiaddr *ifma, int anon)
2232{
2233 ifnet_lock_assert(ifp, IFNET_LCK_ASSERT_EXCLUSIVE);
2234 IFMA_LOCK_ASSERT_HELD(ifma);
2235
2236 if (ifma->ifma_reqcnt == 0) {
2237 panic("%s: ifma=%p negative reqcnt", __func__, ifma);
2238 /* NOTREACHED */
2239 } else if (anon && !(ifma->ifma_flags & IFMAF_ANONYMOUS)) {
2240 panic("%s: ifma=%p missing IFMAF_ANONYMOUS", __func__, ifma);
2241 /* NOTREACHED */
2242 } else if (anon && ifma->ifma_anoncnt == 0) {
2243 panic("%s: ifma=%p negative anonreqcnt", __func__, ifma);
2244 /* NOTREACHED */
2245 } else if (ifma->ifma_ifp != ifp) {
2246 panic("%s: Mismatch ifma_ifp=%p, ifp=%p", __func__,
2247 ifma->ifma_ifp, ifp);
2248 /* NOTREACHED */
2249 }
2250
2251 if (anon) {
2252 --ifma->ifma_anoncnt;
2253 if (ifma->ifma_anoncnt > 0)
2254 return (0);
2255 ifma->ifma_flags &= ~IFMAF_ANONYMOUS;
2256 }
2257
2258 --ifma->ifma_reqcnt;
2259 if (ifma->ifma_reqcnt > 0)
2260 return (0);
2261
2262 if (ifma->ifma_protospec != NULL) {
2263 panic("%s: Protospec not NULL for ifma=%p", __func__, ifma);
2264 /* NOTREACHED */
2265 } else if ((ifma->ifma_flags & IFMAF_ANONYMOUS) ||
2266 ifma->ifma_anoncnt != 0) {
2267 panic("%s: Detaching ifma=%p with outstanding anon req",
2268 __func__, ifma);
2269 /* NOTREACHED */
2270 } else if (!(ifma->ifma_debug & IFD_ATTACHED)) {
2271 panic("%s: Attempt to detach an unattached address ifma=%p",
2272 __func__, ifma);
2273 /* NOTREACHED */
2274 } else if (ifma->ifma_debug & IFD_TRASHED) {
2275 panic("%s: ifma %p is already in trash list", __func__, ifma);
2276 /* NOTREACHED */
2277 }
2278
2279 /*
2280 * NOTE: Caller calls IFMA_REMREF
2281 */
2282 ifma->ifma_debug &= ~IFD_ATTACHED;
2283 LIST_REMOVE(ifma, ifma_link);
2284 if (LIST_EMPTY(&ifp->if_multiaddrs))
2285 ifp->if_updatemcasts = 0;
2286
2287 if (ifma->ifma_debug & IFD_DEBUG) {
2288 /* Become a regular mutex, just in case */
2289 IFMA_CONVERT_LOCK(ifma);
2290 lck_mtx_lock(&ifma_trash_lock);
2291 TAILQ_INSERT_TAIL(&ifma_trash_head,
2292 (struct ifmultiaddr_dbg *)ifma, ifma_trash_link);
2293 lck_mtx_unlock(&ifma_trash_lock);
2294 ifma->ifma_debug |= IFD_TRASHED;
2295 }
2296
2297 return (1);
2298}
2299
2300/*
2301 * Find an ifmultiaddr that matches a socket address on an interface.
2302 *
2303 * Caller is responsible for holding the ifnet_lock while calling
2304 * this function.
2305 */
2306static int
2307if_addmulti_doesexist(struct ifnet *ifp, const struct sockaddr *sa,
2308 struct ifmultiaddr **retifma, int anon)
91447636
A
2309{
2310 struct ifmultiaddr *ifma;
6d2010ae
A
2311
2312 for (ifma = LIST_FIRST(&ifp->if_multiaddrs); ifma != NULL;
2313 ifma = LIST_NEXT(ifma, ifma_link)) {
2314 IFMA_LOCK_SPIN(ifma);
2315 if (!equal(sa, ifma->ifma_addr)) {
2316 IFMA_UNLOCK(ifma);
2317 continue;
2318 }
2319 if (anon) {
2320 VERIFY(!(ifma->ifma_flags & IFMAF_ANONYMOUS) ||
2321 ifma->ifma_anoncnt != 0);
2322 VERIFY((ifma->ifma_flags & IFMAF_ANONYMOUS) ||
2323 ifma->ifma_anoncnt == 0);
2324 ifma->ifma_anoncnt++;
2325 if (!(ifma->ifma_flags & IFMAF_ANONYMOUS)) {
2326 VERIFY(ifma->ifma_anoncnt == 1);
2327 ifma->ifma_flags |= IFMAF_ANONYMOUS;
91447636 2328 }
1c79356b 2329 }
6d2010ae
A
2330 if (!anon || ifma->ifma_anoncnt == 1) {
2331 ifma->ifma_reqcnt++;
2332 VERIFY(ifma->ifma_reqcnt > 1);
2333 }
2334 if (retifma != NULL) {
2335 *retifma = ifma;
2336 IFMA_ADDREF_LOCKED(ifma);
2337 }
2338 IFMA_UNLOCK(ifma);
2339 return (0);
1c79356b 2340 }
6d2010ae 2341 return (ENOENT);
91447636
A
2342}
2343
2d21ac55
A
2344/*
2345 * Radar 3642395, make sure all multicasts are in a standard format.
2346 */
2347static struct sockaddr*
2348copy_and_normalize(
2349 const struct sockaddr *original)
2350{
2351 int alen = 0;
2352 const u_char *aptr = NULL;
2353 struct sockaddr *copy = NULL;
2354 struct sockaddr_dl *sdl_new = NULL;
2355 int len = 0;
2356
2357 if (original->sa_family != AF_LINK &&
2358 original->sa_family != AF_UNSPEC) {
2359 /* Just make a copy */
2360 MALLOC(copy, struct sockaddr*, original->sa_len, M_IFADDR, M_WAITOK);
2361 if (copy != NULL)
2362 bcopy(original, copy, original->sa_len);
2363 return copy;
2364 }
2365
2366 switch (original->sa_family) {
2367 case AF_LINK: {
2368 const struct sockaddr_dl *sdl_original =
2369 (const struct sockaddr_dl*)original;
2370
2371 if (sdl_original->sdl_nlen + sdl_original->sdl_alen + sdl_original->sdl_slen +
2372 offsetof(struct sockaddr_dl, sdl_data) > sdl_original->sdl_len)
2373 return NULL;
2374
2375 alen = sdl_original->sdl_alen;
2376 aptr = CONST_LLADDR(sdl_original);
2377 }
2378 break;
2379
2380 case AF_UNSPEC: {
2381 if (original->sa_len < ETHER_ADDR_LEN +
2382 offsetof(struct sockaddr, sa_data)) {
2383 return NULL;
2384 }
2385
2386 alen = ETHER_ADDR_LEN;
2387 aptr = (const u_char*)original->sa_data;
2388 }
2389 break;
2390 }
2391
2392 if (alen == 0 || aptr == NULL)
2393 return NULL;
2394
2395 len = alen + offsetof(struct sockaddr_dl, sdl_data);
2396 MALLOC(sdl_new, struct sockaddr_dl*, len, M_IFADDR, M_WAITOK);
2397
2398 if (sdl_new != NULL) {
2399 bzero(sdl_new, len);
2400 sdl_new->sdl_len = len;
2401 sdl_new->sdl_family = AF_LINK;
2402 sdl_new->sdl_alen = alen;
2403 bcopy(aptr, LLADDR(sdl_new), alen);
2404 }
2405
2406 return (struct sockaddr*)sdl_new;
2407}
2408
91447636 2409/*
6d2010ae
A
2410 * Network-layer protocol domains which hold references to the underlying
2411 * link-layer record must use this routine.
91447636
A
2412 */
2413int
6d2010ae
A
2414if_addmulti(struct ifnet *ifp, const struct sockaddr *sa,
2415 struct ifmultiaddr **retifma)
2416{
2417 return (if_addmulti_common(ifp, sa, retifma, 0));
2418}
2419
2420/*
2421 * Anything other than network-layer protocol domains which hold references
2422 * to the underlying link-layer record must use this routine: SIOCADDMULTI
2423 * ioctl, ifnet_add_multicast(), AppleTalk, if_bond.
2424 */
2425int
2426if_addmulti_anon(struct ifnet *ifp, const struct sockaddr *sa,
2427 struct ifmultiaddr **retifma)
2428{
2429 return (if_addmulti_common(ifp, sa, retifma, 1));
2430}
2431
2432/*
2433 * Register an additional multicast address with a network interface.
2434 *
2435 * - If the address is already present, bump the reference count on the
2436 * address and return.
2437 * - If the address is not link-layer, look up a link layer address.
2438 * - Allocate address structures for one or both addresses, and attach to the
2439 * multicast address list on the interface. If automatically adding a link
2440 * layer address, the protocol address will own a reference to the link
2441 * layer address, to be freed when it is freed.
2442 * - Notify the network device driver of an addition to the multicast address
2443 * list.
2444 *
2445 * 'sa' points to caller-owned memory with the desired multicast address.
2446 *
2447 * 'retifma' will be used to return a pointer to the resulting multicast
2448 * address reference, if desired.
2449 *
2450 * 'anon' indicates a link-layer address with no protocol address reference
2451 * made to it. Anything other than network-layer protocol domain requests
2452 * are considered as anonymous.
2453 */
2454static int
2455if_addmulti_common(struct ifnet *ifp, const struct sockaddr *sa,
2456 struct ifmultiaddr **retifma, int anon)
91447636
A
2457{
2458 struct sockaddr_storage storage;
2459 struct sockaddr *llsa = NULL;
2d21ac55 2460 struct sockaddr *dupsa = NULL;
6d2010ae 2461 int error = 0, ll_firstref = 0, lladdr;
2d21ac55 2462 struct ifmultiaddr *ifma = NULL;
91447636 2463 struct ifmultiaddr *llifma = NULL;
6d2010ae
A
2464
2465 /* Only AF_UNSPEC/AF_LINK is allowed for an "anonymous" address */
2466 VERIFY(!anon || sa->sa_family == AF_UNSPEC ||
2467 sa->sa_family == AF_LINK);
2468
2d21ac55
A
2469 /* If sa is a AF_LINK or AF_UNSPEC, duplicate and normalize it */
2470 if (sa->sa_family == AF_LINK || sa->sa_family == AF_UNSPEC) {
2471 dupsa = copy_and_normalize(sa);
2472 if (dupsa == NULL) {
6d2010ae
A
2473 error = ENOMEM;
2474 goto cleanup;
2d21ac55
A
2475 }
2476 sa = dupsa;
2477 }
6d2010ae 2478
91447636 2479 ifnet_lock_exclusive(ifp);
6d2010ae
A
2480 if (!(ifp->if_flags & IFF_MULTICAST)) {
2481 error = EADDRNOTAVAIL;
2482 ifnet_lock_done(ifp);
2d21ac55
A
2483 goto cleanup;
2484 }
1c79356b 2485
6d2010ae
A
2486 /* If the address is already present, return a new reference to it */
2487 error = if_addmulti_doesexist(ifp, sa, retifma, anon);
2488 ifnet_lock_done(ifp);
2489 if (error == 0)
2490 goto cleanup;
2491
1c79356b 2492 /*
6d2010ae
A
2493 * The address isn't already present; give the link layer a chance
2494 * to accept/reject it, and also find out which AF_LINK address this
2495 * maps to, if it isn't one already.
1c79356b 2496 */
6d2010ae
A
2497 error = dlil_resolve_multi(ifp, sa, (struct sockaddr *)&storage,
2498 sizeof (storage));
91447636 2499 if (error == 0 && storage.ss_len != 0) {
6d2010ae 2500 llsa = copy_and_normalize((struct sockaddr *)&storage);
2d21ac55
A
2501 if (llsa == NULL) {
2502 error = ENOMEM;
2503 goto cleanup;
2504 }
6d2010ae
A
2505
2506 llifma = ifma_alloc(M_WAITOK);
2d21ac55
A
2507 if (llifma == NULL) {
2508 error = ENOMEM;
2509 goto cleanup;
2510 }
91447636 2511 }
6d2010ae 2512
9bccf70c 2513 /* to be similar to FreeBSD */
6d2010ae 2514 if (error == EOPNOTSUPP)
9bccf70c 2515 error = 0;
6d2010ae 2516 else if (error != 0)
2d21ac55 2517 goto cleanup;
1c79356b 2518
91447636 2519 /* Allocate while we aren't holding any locks */
2d21ac55
A
2520 if (dupsa == NULL) {
2521 dupsa = copy_and_normalize(sa);
2522 if (dupsa == NULL) {
2523 error = ENOMEM;
2524 goto cleanup;
2525 }
2526 }
6d2010ae 2527 ifma = ifma_alloc(M_WAITOK);
2d21ac55
A
2528 if (ifma == NULL) {
2529 error = ENOMEM;
2530 goto cleanup;
2531 }
6d2010ae 2532
91447636
A
2533 ifnet_lock_exclusive(ifp);
2534 /*
2535 * Check again for the matching multicast.
2536 */
6d2010ae
A
2537 error = if_addmulti_doesexist(ifp, sa, retifma, anon);
2538 if (error == 0) {
91447636 2539 ifnet_lock_done(ifp);
2d21ac55 2540 goto cleanup;
91447636 2541 }
1c79356b 2542
6d2010ae
A
2543 if (llifma != NULL) {
2544 VERIFY(!anon); /* must not get here if "anonymous" */
2545 if (if_addmulti_doesexist(ifp, llsa, &ifma->ifma_ll, 0) == 0) {
2546 FREE(llsa, M_IFADDR);
2547 llsa = NULL;
2548 ifma_free(llifma);
2549 llifma = NULL;
2550 VERIFY(ifma->ifma_ll->ifma_ifp == ifp);
1c79356b 2551 } else {
6d2010ae 2552 ll_firstref = 1;
91447636
A
2553 llifma->ifma_addr = llsa;
2554 llifma->ifma_ifp = ifp;
6d2010ae
A
2555 IFMA_LOCK(llifma);
2556 if_attach_ifma(ifp, llifma, 0);
2557 /* add extra refcnt for ifma */
2558 IFMA_ADDREF_LOCKED(llifma);
2559 IFMA_UNLOCK(llifma);
91447636 2560 ifma->ifma_ll = llifma;
1c79356b
A
2561 }
2562 }
6d2010ae
A
2563
2564 /* "anonymous" request should not result in network address */
2565 VERIFY(!anon || ifma->ifma_ll == NULL);
2566
2567 ifma->ifma_addr = dupsa;
2568 ifma->ifma_ifp = ifp;
2569 IFMA_LOCK(ifma);
2570 if_attach_ifma(ifp, ifma, anon);
2571 IFMA_ADDREF_LOCKED(ifma); /* for this routine */
2572 if (retifma != NULL) {
91447636 2573 *retifma = ifma;
6d2010ae 2574 IFMA_ADDREF_LOCKED(*retifma); /* for caller */
91447636 2575 }
6d2010ae
A
2576 lladdr = (ifma->ifma_addr->sa_family == AF_UNSPEC ||
2577 ifma->ifma_addr->sa_family == AF_LINK);
2578 IFMA_UNLOCK(ifma);
91447636 2579 ifnet_lock_done(ifp);
6d2010ae
A
2580
2581 rt_newmaddrmsg(RTM_NEWMADDR, ifma);
2582 IFMA_REMREF(ifma); /* for this routine */
91447636 2583
1c79356b
A
2584 /*
2585 * We are certain we have added something, so call down to the
6d2010ae
A
2586 * interface to let them know about it. Do this only for newly-
2587 * added AF_LINK/AF_UNSPEC address in the if_multiaddrs set.
1c79356b 2588 */
6d2010ae
A
2589 if (lladdr || ll_firstref)
2590 (void) ifnet_ioctl(ifp, 0, SIOCADDMULTI, NULL);
2591
2592 if (ifp->if_updatemcasts > 0)
2593 ifp->if_updatemcasts = 0;
2594
2595 return (0);
2596
2d21ac55 2597cleanup:
6d2010ae
A
2598 if (ifma != NULL)
2599 ifma_free(ifma);
2600 if (dupsa != NULL)
2d21ac55 2601 FREE(dupsa, M_IFADDR);
6d2010ae
A
2602 if (llifma != NULL)
2603 ifma_free(llifma);
2604 if (llsa != NULL)
2d21ac55 2605 FREE(llsa, M_IFADDR);
6d2010ae
A
2606
2607 return (error);
1c79356b
A
2608}
2609
6d2010ae
A
2610/*
2611 * Delete a multicast group membership by network-layer group address.
2612 * This routine is deprecated.
2613 */
1c79356b 2614int
6d2010ae 2615if_delmulti(struct ifnet *ifp, const struct sockaddr *sa)
1c79356b 2616{
6d2010ae 2617 return (if_delmulti_common(NULL, ifp, sa, 0));
55e303ae 2618}
1c79356b 2619
55e303ae 2620/*
6d2010ae
A
2621 * Delete a multicast group membership by group membership pointer.
2622 * Network-layer protocol domains must use this routine.
55e303ae
A
2623 */
2624int
6d2010ae
A
2625if_delmulti_ifma(struct ifmultiaddr *ifma)
2626{
2627 return (if_delmulti_common(ifma, NULL, NULL, 0));
2628}
2629
2630/*
2631 * Anything other than network-layer protocol domains which hold references
2632 * to the underlying link-layer record must use this routine: SIOCDELMULTI
2633 * ioctl, ifnet_remove_multicast(), AppleTalk, if_bond.
2634 */
2635int
2636if_delmulti_anon(struct ifnet *ifp, const struct sockaddr *sa)
2637{
2638 return (if_delmulti_common(NULL, ifp, sa, 1));
2639}
2640
2641/*
2642 * Delete a multicast group membership by network-layer group address.
2643 *
2644 * Returns ENOENT if the entry could not be found.
2645 */
2646static int
2647if_delmulti_common(struct ifmultiaddr *ifma, struct ifnet *ifp,
2648 const struct sockaddr *sa, int anon)
55e303ae 2649{
2d21ac55 2650 struct sockaddr *dupsa = NULL;
6d2010ae
A
2651 int lastref, ll_lastref = 0, lladdr;
2652 struct ifmultiaddr *ll = NULL;
55e303ae 2653
6d2010ae
A
2654 /* sanity check for callers */
2655 VERIFY(ifma != NULL || (ifp != NULL && sa != NULL));
2656
2657 if (ifma != NULL)
2658 ifp = ifma->ifma_ifp;
2659
2660 if (sa != NULL &&
2661 (sa->sa_family == AF_LINK || sa->sa_family == AF_UNSPEC)) {
2d21ac55 2662 dupsa = copy_and_normalize(sa);
6d2010ae
A
2663 if (dupsa == NULL)
2664 return (ENOMEM);
2d21ac55
A
2665 sa = dupsa;
2666 }
6d2010ae 2667
91447636 2668 ifnet_lock_exclusive(ifp);
6d2010ae
A
2669 if (ifma == NULL) {
2670 for (ifma = LIST_FIRST(&ifp->if_multiaddrs); ifma != NULL;
2671 ifma = LIST_NEXT(ifma, ifma_link)) {
2672 IFMA_LOCK(ifma);
2673 if (!equal(sa, ifma->ifma_addr) ||
2674 (anon && !(ifma->ifma_flags & IFMAF_ANONYMOUS))) {
2675 VERIFY(!(ifma->ifma_flags & IFMAF_ANONYMOUS) ||
2676 ifma->ifma_anoncnt != 0);
2677 IFMA_UNLOCK(ifma);
2678 continue;
2679 }
2680 /* found; keep it locked */
55e303ae 2681 break;
6d2010ae
A
2682 }
2683 if (ifma == NULL) {
2684 if (dupsa != NULL)
2685 FREE(dupsa, M_IFADDR);
2686 ifnet_lock_done(ifp);
2687 return (ENOENT);
2688 }
2689 } else {
2690 IFMA_LOCK(ifma);
2691 }
2692 IFMA_LOCK_ASSERT_HELD(ifma);
2693 IFMA_ADDREF_LOCKED(ifma); /* for this routine */
2694 lastref = if_detach_ifma(ifp, ifma, anon);
2695 VERIFY(!lastref || (!(ifma->ifma_debug & IFD_ATTACHED) &&
2696 ifma->ifma_reqcnt == 0));
2697 VERIFY(!anon || ifma->ifma_ll == NULL);
2698 ll = ifma->ifma_ll;
2699 lladdr = (ifma->ifma_addr->sa_family == AF_UNSPEC ||
2700 ifma->ifma_addr->sa_family == AF_LINK);
2701 IFMA_UNLOCK(ifma);
2702 if (lastref && ll != NULL) {
2703 IFMA_LOCK(ll);
2704 ll_lastref = if_detach_ifma(ifp, ll, 0);
2705 IFMA_UNLOCK(ll);
91447636 2706 }
91447636 2707 ifnet_lock_done(ifp);
6d2010ae
A
2708
2709 if (lastref)
2710 rt_newmaddrmsg(RTM_DELMADDR, ifma);
2711
2712 if ((ll == NULL && lastref && lladdr) || ll_lastref) {
2713 /*
2714 * Make sure the interface driver is notified in the
2715 * case of a link layer mcast group being left. Do
2716 * this only for a AF_LINK/AF_UNSPEC address that has
2717 * been removed from the if_multiaddrs set.
2718 */
2719 ifnet_ioctl(ifp, 0, SIOCDELMULTI, NULL);
2720 }
2721
2722 if (lastref)
2723 IFMA_REMREF(ifma); /* for if_multiaddrs list */
2724 if (ll_lastref)
2725 IFMA_REMREF(ll); /* for if_multiaddrs list */
2726
2727 IFMA_REMREF(ifma); /* for this routine */
2728 if (dupsa != NULL)
2d21ac55 2729 FREE(dupsa, M_IFADDR);
1c79356b 2730
6d2010ae
A
2731 return (0);
2732}
9bccf70c
A
2733
2734/*
2735 * We don't use if_setlladdr, our interfaces are responsible for
2736 * handling the SIOCSIFLLADDR ioctl.
2737 */
2738#ifndef __APPLE__
2739int
2740if_setlladdr(struct ifnet *ifp, const u_char *lladdr, int len)
2741{
2742 ...
2743}
2744#endif
2745
2d21ac55
A
2746SYSCTL_NODE(_net, PF_LINK, link, CTLFLAG_RW|CTLFLAG_LOCKED, 0, "Link layers");
2747SYSCTL_NODE(_net_link, 0, generic, CTLFLAG_RW|CTLFLAG_LOCKED, 0, "Generic link-management");
1c79356b
A
2748
2749
2750/*
2751 * Shutdown all network activity. Used boot() when halting
2752 * system.
2753 */
2d21ac55
A
2754int
2755if_down_all(void)
1c79356b 2756{
91447636
A
2757 struct ifnet **ifp;
2758 u_int32_t count;
2759 u_int32_t i;
1c79356b 2760
4a3eedf9 2761 if (ifnet_list_get_all(IFNET_FAMILY_ANY, &ifp, &count) == 0) {
91447636
A
2762 for (i = 0; i < count; i++) {
2763 if_down(ifp[i]);
4a3eedf9 2764 dlil_proto_unplumb_all(ifp[i]);
91447636
A
2765 }
2766 ifnet_list_free(ifp);
2767 }
4a3eedf9 2768
91447636 2769 return 0;
1c79356b 2770}
9bccf70c
A
2771
2772/*
2773 * Delete Routes for a Network Interface
2774 *
2775 * Called for each routing entry via the rnh->rnh_walktree() call above
2776 * to delete all route entries referencing a detaching network interface.
2777 *
2778 * Arguments:
2779 * rn pointer to node in the routing table
2780 * arg argument passed to rnh->rnh_walktree() - detaching interface
2781 *
2782 * Returns:
2783 * 0 successful
2784 * errno failed - reason indicated
2785 *
2786 */
2787static int
b0d623f7 2788if_rtdel(struct radix_node *rn, void *arg)
9bccf70c
A
2789{
2790 struct rtentry *rt = (struct rtentry *)rn;
2791 struct ifnet *ifp = arg;
2792 int err;
2793
b0d623f7
A
2794 if (rt == NULL)
2795 return (0);
2796 /*
2797 * Checking against RTF_UP protects against walktree
2798 * recursion problems with cloned routes.
2799 */
2800 RT_LOCK(rt);
2801 if (rt->rt_ifp == ifp && (rt->rt_flags & RTF_UP)) {
9bccf70c 2802 /*
b0d623f7
A
2803 * Safe to drop rt_lock and use rt_key, rt_gateway,
2804 * since holding rnh_lock here prevents another thread
2805 * from calling rt_setgate() on this route.
9bccf70c 2806 */
b0d623f7 2807 RT_UNLOCK(rt);
91447636 2808 err = rtrequest_locked(RTM_DELETE, rt_key(rt), rt->rt_gateway,
b0d623f7 2809 rt_mask(rt), rt->rt_flags, NULL);
9bccf70c
A
2810 if (err) {
2811 log(LOG_WARNING, "if_rtdel: error %d\n", err);
2812 }
b0d623f7
A
2813 } else {
2814 RT_UNLOCK(rt);
9bccf70c 2815 }
9bccf70c
A
2816 return (0);
2817}
2818
2819/*
b0d623f7 2820 * Removes routing table reference to a given interface
9bccf70c
A
2821 * for a given protocol family
2822 */
b0d623f7
A
2823void
2824if_rtproto_del(struct ifnet *ifp, int protocol)
9bccf70c 2825{
3a60a9f5 2826 struct radix_node_head *rnh;
b0d623f7
A
2827
2828 if (use_routegenid)
2829 routegenid_update();
3a60a9f5
A
2830 if ((protocol <= AF_MAX) && (protocol >= 0) &&
2831 ((rnh = rt_tables[protocol]) != NULL) && (ifp != NULL)) {
b0d623f7 2832 lck_mtx_lock(rnh_lock);
9bccf70c 2833 (void) rnh->rnh_walktree(rnh, if_rtdel, ifp);
b0d623f7 2834 lck_mtx_unlock(rnh_lock);
91447636
A
2835 }
2836}
2837
2d21ac55
A
2838static int
2839if_rtmtu(struct radix_node *rn, void *arg)
2840{
2841 struct rtentry *rt = (struct rtentry *)rn;
2842 struct ifnet *ifp = arg;
2843
b0d623f7 2844 RT_LOCK(rt);
2d21ac55
A
2845 if (rt->rt_ifp == ifp) {
2846 /*
2847 * Update the MTU of this entry only if the MTU
2848 * has not been locked (RTV_MTU is not set) and
2849 * if it was non-zero to begin with.
2850 */
2851 if (!(rt->rt_rmx.rmx_locks & RTV_MTU) && rt->rt_rmx.rmx_mtu)
2852 rt->rt_rmx.rmx_mtu = ifp->if_mtu;
2853 }
b0d623f7 2854 RT_UNLOCK(rt);
2d21ac55
A
2855
2856 return (0);
2857}
2858
2859/*
2860 * Update the MTU metric of all route entries in all protocol tables
2861 * associated with a particular interface; this is called when the
2862 * MTU of that interface has changed.
2863 */
2864static
2865void if_rtmtu_update(struct ifnet *ifp)
2866{
2867 struct radix_node_head *rnh;
2868 int p;
2869
2870 for (p = 0; p < AF_MAX + 1; p++) {
2871 if ((rnh = rt_tables[p]) == NULL)
2872 continue;
2873
b0d623f7 2874 lck_mtx_lock(rnh_lock);
2d21ac55 2875 (void) rnh->rnh_walktree(rnh, if_rtmtu, ifp);
b0d623f7 2876 lck_mtx_unlock(rnh_lock);
2d21ac55
A
2877 }
2878
2879 if (use_routegenid)
b0d623f7 2880 routegenid_update();
2d21ac55 2881}
91447636
A
2882
2883__private_extern__ void
6d2010ae
A
2884if_data_internal_to_if_data(struct ifnet *ifp,
2885 const struct if_data_internal *if_data_int, struct if_data *if_data)
91447636 2886{
6d2010ae
A
2887#pragma unused(ifp)
2888#define COPYFIELD(fld) if_data->fld = if_data_int->fld
91447636 2889#define COPYFIELD32(fld) if_data->fld = (u_int32_t)(if_data_int->fld)
6d2010ae
A
2890/* compiler will cast down to 32-bit */
2891#define COPYFIELD32_ATOMIC(fld) do { \
2892 atomic_get_64(if_data->fld, \
2893 (u_int64_t *)(void *)(uintptr_t)&if_data_int->fld); \
2894} while (0)
2895
91447636
A
2896 COPYFIELD(ifi_type);
2897 COPYFIELD(ifi_typelen);
2898 COPYFIELD(ifi_physical);
2899 COPYFIELD(ifi_addrlen);
2900 COPYFIELD(ifi_hdrlen);
2901 COPYFIELD(ifi_recvquota);
2902 COPYFIELD(ifi_xmitquota);
2903 if_data->ifi_unused1 = 0;
2904 COPYFIELD(ifi_mtu);
2905 COPYFIELD(ifi_metric);
2906 if (if_data_int->ifi_baudrate & 0xFFFFFFFF00000000LL) {
2907 if_data->ifi_baudrate = 0xFFFFFFFF;
6d2010ae 2908 } else {
91447636
A
2909 COPYFIELD32(ifi_baudrate);
2910 }
6d2010ae
A
2911
2912 COPYFIELD32_ATOMIC(ifi_ipackets);
2913 COPYFIELD32_ATOMIC(ifi_ierrors);
2914 COPYFIELD32_ATOMIC(ifi_opackets);
2915 COPYFIELD32_ATOMIC(ifi_oerrors);
2916 COPYFIELD32_ATOMIC(ifi_collisions);
2917 COPYFIELD32_ATOMIC(ifi_ibytes);
2918 COPYFIELD32_ATOMIC(ifi_obytes);
2919 COPYFIELD32_ATOMIC(ifi_imcasts);
2920 COPYFIELD32_ATOMIC(ifi_omcasts);
2921 COPYFIELD32_ATOMIC(ifi_iqdrops);
2922 COPYFIELD32_ATOMIC(ifi_noproto);
2923
2924 COPYFIELD(ifi_recvtiming);
2925 COPYFIELD(ifi_xmittiming);
91447636 2926
b0d623f7
A
2927 if_data->ifi_lastchange.tv_sec = if_data_int->ifi_lastchange.tv_sec;
2928 if_data->ifi_lastchange.tv_usec = if_data_int->ifi_lastchange.tv_usec;
6d2010ae 2929
91447636
A
2930#if IF_LASTCHANGEUPTIME
2931 if_data->ifi_lastchange.tv_sec += boottime_sec();
2932#endif
2933
2934 if_data->ifi_unused2 = 0;
2935 COPYFIELD(ifi_hwassist);
2936 if_data->ifi_reserved1 = 0;
2937 if_data->ifi_reserved2 = 0;
6d2010ae 2938#undef COPYFIELD32_ATOMIC
91447636
A
2939#undef COPYFIELD32
2940#undef COPYFIELD
2941}
2942
2943__private_extern__ void
6d2010ae
A
2944if_data_internal_to_if_data64(struct ifnet *ifp,
2945 const struct if_data_internal *if_data_int,
2946 struct if_data64 *if_data64)
91447636 2947{
6d2010ae
A
2948#pragma unused(ifp)
2949#define COPYFIELD64(fld) if_data64->fld = if_data_int->fld
2950#define COPYFIELD64_ATOMIC(fld) do { \
2951 atomic_get_64(if_data64->fld, \
2952 (u_int64_t *)(void *)(uintptr_t)&if_data_int->fld); \
2953} while (0)
2954
2955 COPYFIELD64(ifi_type);
2956 COPYFIELD64(ifi_typelen);
2957 COPYFIELD64(ifi_physical);
2958 COPYFIELD64(ifi_addrlen);
2959 COPYFIELD64(ifi_hdrlen);
2960 COPYFIELD64(ifi_recvquota);
2961 COPYFIELD64(ifi_xmitquota);
91447636 2962 if_data64->ifi_unused1 = 0;
6d2010ae
A
2963 COPYFIELD64(ifi_mtu);
2964 COPYFIELD64(ifi_metric);
2965 COPYFIELD64(ifi_baudrate);
2966
2967 COPYFIELD64_ATOMIC(ifi_ipackets);
2968 COPYFIELD64_ATOMIC(ifi_ierrors);
2969 COPYFIELD64_ATOMIC(ifi_opackets);
2970 COPYFIELD64_ATOMIC(ifi_oerrors);
2971 COPYFIELD64_ATOMIC(ifi_collisions);
2972 COPYFIELD64_ATOMIC(ifi_ibytes);
2973 COPYFIELD64_ATOMIC(ifi_obytes);
2974 COPYFIELD64_ATOMIC(ifi_imcasts);
2975 COPYFIELD64_ATOMIC(ifi_omcasts);
2976 COPYFIELD64_ATOMIC(ifi_iqdrops);
2977 COPYFIELD64_ATOMIC(ifi_noproto);
2978
2979 /* Note these two fields are actually 32 bit, so doing COPYFIELD64_ATOMIC will
2980 * cause them to be misaligned
2981 */
2982 COPYFIELD64(ifi_recvtiming);
2983 COPYFIELD64(ifi_xmittiming);
2984
b0d623f7
A
2985 if_data64->ifi_lastchange.tv_sec = if_data_int->ifi_lastchange.tv_sec;
2986 if_data64->ifi_lastchange.tv_usec = if_data_int->ifi_lastchange.tv_usec;
6d2010ae 2987
91447636
A
2988#if IF_LASTCHANGEUPTIME
2989 if_data64->ifi_lastchange.tv_sec += boottime_sec();
2990#endif
2991
6d2010ae 2992#undef COPYFIELD64
9bccf70c 2993}
b0d623f7 2994
6d2010ae
A
2995__private_extern__ void
2996if_copy_traffic_class(struct ifnet *ifp,
2997 struct if_traffic_class *if_tc)
b0d623f7 2998{
6d2010ae
A
2999#define COPY_IF_TC_FIELD64_ATOMIC(fld) do { \
3000 atomic_get_64(if_tc->fld, \
3001 (u_int64_t *)(void *)(uintptr_t)&ifp->if_tc.fld); \
3002} while (0)
3003
3004 COPY_IF_TC_FIELD64_ATOMIC(ifi_ibkpackets);
3005 COPY_IF_TC_FIELD64_ATOMIC(ifi_ibkbytes);
3006 COPY_IF_TC_FIELD64_ATOMIC(ifi_obkpackets);
3007 COPY_IF_TC_FIELD64_ATOMIC(ifi_obkbytes);
3008 COPY_IF_TC_FIELD64_ATOMIC(ifi_ivipackets);
3009 COPY_IF_TC_FIELD64_ATOMIC(ifi_ivibytes);
3010 COPY_IF_TC_FIELD64_ATOMIC(ifi_ovipackets);
3011 COPY_IF_TC_FIELD64_ATOMIC(ifi_ovibytes);
3012 COPY_IF_TC_FIELD64_ATOMIC(ifi_ivopackets);
3013 COPY_IF_TC_FIELD64_ATOMIC(ifi_ivobytes);
3014 COPY_IF_TC_FIELD64_ATOMIC(ifi_ovopackets);
3015 COPY_IF_TC_FIELD64_ATOMIC(ifi_ovobytes);
3016
3017#undef COPY_IF_TC_FIELD64_ATOMIC
3018}
b0d623f7 3019
6d2010ae
A
3020
3021struct ifaddr *
3022ifa_remref(struct ifaddr *ifa, int locked)
3023{
3024 if (!locked)
3025 IFA_LOCK_SPIN(ifa);
3026 else
3027 IFA_LOCK_ASSERT_HELD(ifa);
3028
3029 if (ifa->ifa_refcnt == 0)
b0d623f7 3030 panic("%s: ifa %p negative refcnt\n", __func__, ifa);
6d2010ae
A
3031 else if (ifa->ifa_trace != NULL)
3032 (*ifa->ifa_trace)(ifa, FALSE);
3033 if (--ifa->ifa_refcnt == 0) {
3034 if (ifa->ifa_debug & IFD_ATTACHED)
b0d623f7
A
3035 panic("ifa %p attached to ifp is being freed\n", ifa);
3036 /*
3037 * Some interface addresses are allocated either statically
3038 * or carved out of a larger block; e.g. AppleTalk addresses.
3039 * Only free it if it was allocated via MALLOC or via the
3040 * corresponding per-address family allocator. Otherwise,
3041 * leave it alone.
3042 */
3043 if (ifa->ifa_debug & IFD_ALLOC) {
6d2010ae
A
3044 if (ifa->ifa_free == NULL) {
3045 IFA_UNLOCK(ifa);
b0d623f7 3046 FREE(ifa, M_IFADDR);
6d2010ae
A
3047 } else {
3048 /* Become a regular mutex */
3049 IFA_CONVERT_LOCK(ifa);
3050 /* callee will unlock */
b0d623f7 3051 (*ifa->ifa_free)(ifa);
6d2010ae
A
3052 }
3053 } else {
3054 IFA_UNLOCK(ifa);
b0d623f7 3055 }
6d2010ae 3056 ifa = NULL;
b0d623f7 3057 }
6d2010ae
A
3058
3059 if (!locked && ifa != NULL)
3060 IFA_UNLOCK(ifa);
3061
3062 return (ifa);
b0d623f7
A
3063}
3064
3065void
6d2010ae 3066ifa_addref(struct ifaddr *ifa, int locked)
b0d623f7 3067{
6d2010ae
A
3068 if (!locked)
3069 IFA_LOCK_SPIN(ifa);
3070 else
3071 IFA_LOCK_ASSERT_HELD(ifa);
b0d623f7 3072
6d2010ae
A
3073 if (++ifa->ifa_refcnt == 0) {
3074 panic("%s: ifa %p wraparound refcnt\n", __func__, ifa);
3075 /* NOTREACHED */
3076 } else if (ifa->ifa_trace != NULL) {
b0d623f7 3077 (*ifa->ifa_trace)(ifa, TRUE);
6d2010ae
A
3078 }
3079 if (!locked)
3080 IFA_UNLOCK(ifa);
3081}
3082
3083void
3084ifa_lock_init(struct ifaddr *ifa)
3085{
3086 lck_mtx_init(&ifa->ifa_lock, ifa_mtx_grp, ifa_mtx_attr);
3087}
3088
3089void
3090ifa_lock_destroy(struct ifaddr *ifa)
3091{
3092 IFA_LOCK_ASSERT_NOTHELD(ifa);
3093 lck_mtx_destroy(&ifa->ifa_lock, ifa_mtx_grp);
b0d623f7 3094}