]> git.saurik.com Git - apple/xnu.git/blame - bsd/net/if.c
xnu-1699.22.81.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
1c79356b 1455 ifp = ifunit(ifr->ifr_name);
6d2010ae 1456 if (ifp == NULL)
1c79356b 1457 return (ENXIO);
1c79356b 1458
6d2010ae 1459 switch (cmd) {
1c79356b 1460 case SIOCGIFFLAGS:
91447636 1461 ifnet_lock_shared(ifp);
1c79356b 1462 ifr->ifr_flags = ifp->if_flags;
91447636 1463 ifnet_lock_done(ifp);
1c79356b
A
1464 break;
1465
6d2010ae
A
1466 case SIOCGIFCAP:
1467 ifnet_lock_shared(ifp);
1468 ifr->ifr_reqcap = ifp->if_capabilities;
1469 ifr->ifr_curcap = ifp->if_capenable;
1470 ifnet_lock_done(ifp);
1471 break;
1472
2d21ac55
A
1473#if CONFIG_MACF_NET
1474 case SIOCGIFMAC:
1475 error = mac_ifnet_label_get(kauth_cred_get(), ifr, ifp);
2d21ac55
A
1476 break;
1477#endif
1c79356b 1478 case SIOCGIFMETRIC:
91447636 1479 ifnet_lock_shared(ifp);
1c79356b 1480 ifr->ifr_metric = ifp->if_metric;
91447636 1481 ifnet_lock_done(ifp);
1c79356b
A
1482 break;
1483
1484 case SIOCGIFMTU:
91447636 1485 ifnet_lock_shared(ifp);
1c79356b 1486 ifr->ifr_mtu = ifp->if_mtu;
91447636 1487 ifnet_lock_done(ifp);
1c79356b
A
1488 break;
1489
1490 case SIOCGIFPHYS:
91447636 1491 ifnet_lock_shared(ifp);
1c79356b 1492 ifr->ifr_phys = ifp->if_physical;
91447636 1493 ifnet_lock_done(ifp);
1c79356b
A
1494 break;
1495
1496 case SIOCSIFFLAGS:
91447636 1497 error = proc_suser(p);
6d2010ae
A
1498 if (error != 0)
1499 break;
1c79356b 1500
6d2010ae
A
1501 (void) ifnet_set_flags(ifp, ifr->ifr_flags,
1502 (u_int16_t)~IFF_CANTCHANGE);
2d21ac55 1503
6d2010ae
A
1504 /*
1505 * Note that we intentionally ignore any error from below
1506 * for the SIOCSIFFLAGS case.
1507 */
1508 (void) ifnet_ioctl(ifp, so->so_proto->pr_domain->dom_family,
1509 cmd, data);
1c79356b 1510
6d2010ae
A
1511 /*
1512 * Send the event even upon error from the driver because
1513 * we changed the flags.
1514 */
b0d623f7
A
1515 ev_msg.vendor_code = KEV_VENDOR_APPLE;
1516 ev_msg.kev_class = KEV_NETWORK_CLASS;
1517 ev_msg.kev_subclass = KEV_DL_SUBCLASS;
6d2010ae 1518
b0d623f7
A
1519 ev_msg.event_code = KEV_DL_SIFFLAGS;
1520 strlcpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ);
1521 ev_data.if_family = ifp->if_family;
1522 ev_data.if_unit = (u_int32_t) ifp->if_unit;
1523 ev_msg.dv[0].data_length = sizeof(struct net_event_data);
1524 ev_msg.dv[0].data_ptr = &ev_data;
1525 ev_msg.dv[1].data_length = 0;
1526 kev_post_msg(&ev_msg);
1527
91447636 1528 ifnet_touch_lastchange(ifp);
1c79356b
A
1529 break;
1530
6d2010ae
A
1531 case SIOCSIFCAP:
1532 error = proc_suser(p);
1533 if (error != 0)
1534 break;
1535
1536 if ((ifr->ifr_reqcap & ~ifp->if_capabilities)) {
1537 error = EINVAL;
1538 break;
1539 }
1540 error = ifnet_ioctl(ifp, so->so_proto->pr_domain->dom_family,
1541 cmd, data);
1542
1543 ifnet_touch_lastchange(ifp);
1544 break;
1545
2d21ac55
A
1546#if CONFIG_MACF_NET
1547 case SIOCSIFMAC:
1548 error = mac_ifnet_label_set(kauth_cred_get(), ifr, ifp);
2d21ac55
A
1549 break;
1550#endif
1c79356b 1551 case SIOCSIFMETRIC:
91447636 1552 error = proc_suser(p);
6d2010ae
A
1553 if (error != 0)
1554 break;
1c79356b 1555
6d2010ae 1556 ifp->if_metric = ifr->ifr_metric;
1c79356b
A
1557
1558 ev_msg.vendor_code = KEV_VENDOR_APPLE;
1559 ev_msg.kev_class = KEV_NETWORK_CLASS;
1560 ev_msg.kev_subclass = KEV_DL_SUBCLASS;
6d2010ae 1561
1c79356b 1562 ev_msg.event_code = KEV_DL_SIFMETRICS;
2d21ac55 1563 strlcpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ);
1c79356b 1564 ev_data.if_family = ifp->if_family;
b0d623f7 1565 ev_data.if_unit = (u_int32_t) ifp->if_unit;
1c79356b
A
1566 ev_msg.dv[0].data_length = sizeof(struct net_event_data);
1567 ev_msg.dv[0].data_ptr = &ev_data;
1568
1569 ev_msg.dv[1].data_length = 0;
1570 kev_post_msg(&ev_msg);
1571
91447636 1572 ifnet_touch_lastchange(ifp);
1c79356b
A
1573 break;
1574
1575 case SIOCSIFPHYS:
91447636 1576 error = proc_suser(p);
6d2010ae
A
1577 if (error != 0)
1578 break;
1c79356b 1579
6d2010ae
A
1580 error = ifnet_ioctl(ifp, so->so_proto->pr_domain->dom_family,
1581 cmd, data);
1582 if (error != 0)
1583 break;
1c79356b 1584
6d2010ae
A
1585 ev_msg.vendor_code = KEV_VENDOR_APPLE;
1586 ev_msg.kev_class = KEV_NETWORK_CLASS;
1587 ev_msg.kev_subclass = KEV_DL_SUBCLASS;
1588
1589 ev_msg.event_code = KEV_DL_SIFPHYS;
1590 strlcpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ);
1591 ev_data.if_family = ifp->if_family;
1592 ev_data.if_unit = (u_int32_t) ifp->if_unit;
1593 ev_msg.dv[0].data_length = sizeof(struct net_event_data);
1594 ev_msg.dv[0].data_ptr = &ev_data;
1595 ev_msg.dv[1].data_length = 0;
1596 kev_post_msg(&ev_msg);
1597
1598 ifnet_touch_lastchange(ifp);
1599 break;
1c79356b
A
1600
1601 case SIOCSIFMTU:
1602 {
b0d623f7 1603 u_int32_t oldmtu = ifp->if_mtu;
1c79356b 1604
91447636 1605 error = proc_suser(p);
6d2010ae
A
1606 if (error != 0)
1607 break;
1c79356b 1608
6d2010ae
A
1609 if (ifp->if_ioctl == NULL) {
1610 error = EOPNOTSUPP;
1611 break;
1612 }
1613 if (ifr->ifr_mtu < IF_MINMTU || ifr->ifr_mtu > IF_MAXMTU) {
1614 error = EINVAL;
1615 break;
1c79356b 1616 }
6d2010ae
A
1617 error = ifnet_ioctl(ifp, so->so_proto->pr_domain->dom_family,
1618 cmd, data);
1619 if (error != 0)
1620 break;
1621
1622 ev_msg.vendor_code = KEV_VENDOR_APPLE;
1623 ev_msg.kev_class = KEV_NETWORK_CLASS;
1624 ev_msg.kev_subclass = KEV_DL_SUBCLASS;
1625
1626 ev_msg.event_code = KEV_DL_SIFMTU;
1627 strlcpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ);
1628 ev_data.if_family = ifp->if_family;
1629 ev_data.if_unit = (u_int32_t) ifp->if_unit;
1630 ev_msg.dv[0].data_length = sizeof(struct net_event_data);
1631 ev_msg.dv[0].data_ptr = &ev_data;
1632 ev_msg.dv[1].data_length = 0;
1633 kev_post_msg(&ev_msg);
1634
1635 ifnet_touch_lastchange(ifp);
1636 rt_ifmsg(ifp);
1637
1c79356b 1638 /*
2d21ac55
A
1639 * If the link MTU changed, do network layer specific procedure
1640 * and update all route entries associated with the interface,
1641 * so that their MTU metric gets updated.
1c79356b 1642 */
6d2010ae 1643 if (ifp->if_mtu != oldmtu) {
2d21ac55 1644 if_rtmtu_update(ifp);
9bccf70c
A
1645#if INET6
1646 nd6_setmtu(ifp);
1647#endif
1c79356b 1648 }
6d2010ae 1649 break;
9bccf70c 1650 }
1c79356b
A
1651
1652 case SIOCADDMULTI:
1653 case SIOCDELMULTI:
91447636 1654 error = proc_suser(p);
6d2010ae
A
1655 if (error != 0)
1656 break;
1c79356b
A
1657
1658 /* Don't allow group membership on non-multicast interfaces. */
6d2010ae
A
1659 if ((ifp->if_flags & IFF_MULTICAST) == 0) {
1660 error = EOPNOTSUPP;
1661 break;
1662 }
1c79356b 1663
9bccf70c 1664 /* Don't let users screw up protocols' entries. */
6d2010ae
A
1665 if (ifr->ifr_addr.sa_family != AF_UNSPEC &&
1666 ifr->ifr_addr.sa_family != AF_LINK) {
1667 error = EINVAL;
1668 break;
1669 }
9bccf70c 1670
6d2010ae
A
1671 /*
1672 * User is permitted to anonymously join a particular link
1673 * multicast group via SIOCADDMULTI. Subsequent join requested
1674 * for the same record which has an outstanding refcnt from a
1675 * past if_addmulti_anon() will not result in EADDRINUSE error
1676 * (unlike other BSDs.) Anonymously leaving a group is also
1677 * allowed only as long as there is an outstanding refcnt held
1678 * by a previous anonymous request, or else ENOENT (even if the
1679 * link-layer multicast membership exists for a network-layer
1680 * membership.)
1681 */
1c79356b 1682 if (cmd == SIOCADDMULTI) {
6d2010ae 1683 error = if_addmulti_anon(ifp, &ifr->ifr_addr, NULL);
1c79356b
A
1684 ev_msg.event_code = KEV_DL_ADDMULTI;
1685 } else {
6d2010ae 1686 error = if_delmulti_anon(ifp, &ifr->ifr_addr);
1c79356b
A
1687 ev_msg.event_code = KEV_DL_DELMULTI;
1688 }
6d2010ae
A
1689 if (error != 0)
1690 break;
1691
1692 ev_msg.vendor_code = KEV_VENDOR_APPLE;
1693 ev_msg.kev_class = KEV_NETWORK_CLASS;
1694 ev_msg.kev_subclass = KEV_DL_SUBCLASS;
1695 strlcpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ);
1696
1697 ev_data.if_family = ifp->if_family;
1698 ev_data.if_unit = (u_int32_t) ifp->if_unit;
1699 ev_msg.dv[0].data_length = sizeof(struct net_event_data);
1700 ev_msg.dv[0].data_ptr = &ev_data;
1701 ev_msg.dv[1].data_length = 0;
1702 kev_post_msg(&ev_msg);
1703
1704 ifnet_touch_lastchange(ifp);
1705 break;
1c79356b 1706
9bccf70c
A
1707 case SIOCSIFPHYADDR:
1708 case SIOCDIFPHYADDR:
2d21ac55 1709#if INET6
b0d623f7
A
1710 case SIOCSIFPHYADDR_IN6_32:
1711 case SIOCSIFPHYADDR_IN6_64:
9bccf70c
A
1712#endif
1713 case SIOCSLIFPHYADDR:
1714 case SIOCSIFMEDIA:
1c79356b 1715 case SIOCSIFGENERIC:
9bccf70c 1716 case SIOCSIFLLADDR:
91447636
A
1717 case SIOCSIFALTMTU:
1718 case SIOCSIFVLAN:
1719 case SIOCSIFBOND:
1720 error = proc_suser(p);
6d2010ae
A
1721 if (error != 0)
1722 break;
1c79356b 1723
6d2010ae
A
1724 error = ifnet_ioctl(ifp, so->so_proto->pr_domain->dom_family,
1725 cmd, data);
1726 if (error != 0)
1727 break;
1c79356b 1728
6d2010ae
A
1729 ifnet_touch_lastchange(ifp);
1730 break;
1c79356b 1731
9bccf70c
A
1732 case SIOCGIFSTATUS:
1733 ifs = (struct ifstat *)data;
1734 ifs->ascii[0] = '\0';
6d2010ae 1735
9bccf70c
A
1736 case SIOCGIFPSRCADDR:
1737 case SIOCGIFPDSTADDR:
1738 case SIOCGLIFPHYADDR:
b0d623f7
A
1739 case SIOCGIFMEDIA32:
1740 case SIOCGIFMEDIA64:
1c79356b 1741 case SIOCGIFGENERIC:
91447636 1742 case SIOCGIFDEVMTU:
6d2010ae
A
1743 error = ifnet_ioctl(ifp, so->so_proto->pr_domain->dom_family,
1744 cmd, data);
1745 break;
1746
91447636
A
1747 case SIOCGIFVLAN:
1748 case SIOCGIFBOND:
6d2010ae
A
1749 error = ifnet_ioctl(ifp, so->so_proto->pr_domain->dom_family,
1750 cmd, data);
1751 break;
1c79356b 1752
b0d623f7
A
1753 case SIOCGIFWAKEFLAGS:
1754 ifnet_lock_shared(ifp);
1755 ifr->ifr_wake_flags = ifnet_get_wake_flags(ifp);
1756 ifnet_lock_done(ifp);
1757 break;
d1ecb069
A
1758
1759 case SIOCGIFGETRTREFCNT:
d1ecb069
A
1760 ifnet_lock_shared(ifp);
1761 ifr->ifr_route_refcnt = ifp->if_route_refcnt;
1762 ifnet_lock_done(ifp);
1763 break;
d1ecb069 1764
1c79356b
A
1765 default:
1766 oif_flags = ifp->if_flags;
6d2010ae
A
1767 if (so->so_proto == NULL) {
1768 error = EOPNOTSUPP;
1769 break;
1770 }
1c79356b 1771 {
6d2010ae 1772 u_long ocmd = cmd;
1c79356b
A
1773
1774 switch (cmd) {
1c79356b
A
1775 case SIOCSIFDSTADDR:
1776 case SIOCSIFADDR:
1777 case SIOCSIFBRDADDR:
1778 case SIOCSIFNETMASK:
1779#if BYTE_ORDER != BIG_ENDIAN
1780 if (ifr->ifr_addr.sa_family == 0 &&
1781 ifr->ifr_addr.sa_len < 16) {
1782 ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len;
1783 ifr->ifr_addr.sa_len = 16;
1784 }
1785#else
1786 if (ifr->ifr_addr.sa_len == 0)
1787 ifr->ifr_addr.sa_len = 16;
1788#endif
1c79356b
A
1789 break;
1790
1791 case OSIOCGIFADDR:
1792 cmd = SIOCGIFADDR;
1793 break;
1794
1795 case OSIOCGIFDSTADDR:
1796 cmd = SIOCGIFDSTADDR;
1797 break;
1798
1799 case OSIOCGIFBRDADDR:
1800 cmd = SIOCGIFBRDADDR;
1801 break;
1802
1803 case OSIOCGIFNETMASK:
1804 cmd = SIOCGIFNETMASK;
1805 }
6d2010ae 1806
91447636 1807 socket_lock(so, 1);
6d2010ae
A
1808 error = ((*so->so_proto->pr_usrreqs->pru_control)(so, cmd,
1809 data, ifp, p));
91447636 1810 socket_unlock(so, 1);
1c79356b 1811
6d2010ae 1812 switch (ocmd) {
1c79356b
A
1813 case OSIOCGIFADDR:
1814 case OSIOCGIFDSTADDR:
1815 case OSIOCGIFBRDADDR:
1816 case OSIOCGIFNETMASK:
9bccf70c 1817 *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family;
1c79356b 1818
1c79356b
A
1819 }
1820 }
2d21ac55
A
1821 if (cmd == SIOCSIFKPI) {
1822 int temperr = proc_suser(p);
1823 if (temperr != 0)
1824 error = temperr;
1825 }
1c79356b 1826
91447636 1827 if (error == EOPNOTSUPP || error == ENOTSUP)
6d2010ae
A
1828 error = ifnet_ioctl(ifp,
1829 so->so_proto->pr_domain->dom_family, cmd, data);
9bccf70c 1830
6d2010ae 1831 break;
1c79356b 1832 }
6d2010ae 1833 return (error);
1c79356b
A
1834}
1835
91447636 1836int
2d21ac55 1837ifioctllocked(struct socket *so, u_long cmd, caddr_t data, struct proc *p)
91447636
A
1838{
1839 int error;
1840
1841 socket_unlock(so, 0);
1842 error = ifioctl(so, cmd, data, p);
1843 socket_lock(so, 0);
1844 return(error);
1845}
1846
1c79356b
A
1847/*
1848 * Set/clear promiscuous mode on interface ifp based on the truth value
1849 * of pswitch. The calls are reference counted so that only the first
1850 * "on" request actually has an effect, as does the final "off" request.
1851 * Results are undefined if the "off" and "on" requests are not matched.
1852 */
91447636
A
1853errno_t
1854ifnet_set_promiscuous(
1855 ifnet_t ifp,
1856 int pswitch)
1c79356b 1857{
91447636 1858 int error = 0;
6d2010ae
A
1859 int oldflags = 0;
1860 int newflags = 0;
1c79356b 1861
91447636 1862 ifnet_lock_exclusive(ifp);
9bccf70c 1863 oldflags = ifp->if_flags;
6d2010ae
A
1864 ifp->if_pcount += pswitch ? 1 : -1;
1865
1866 if (ifp->if_pcount > 0)
1c79356b 1867 ifp->if_flags |= IFF_PROMISC;
6d2010ae 1868 else
1c79356b 1869 ifp->if_flags &= ~IFF_PROMISC;
6d2010ae
A
1870
1871 newflags = ifp->if_flags;
91447636 1872 ifnet_lock_done(ifp);
6d2010ae
A
1873
1874 if (newflags != oldflags && (newflags & IFF_UP) != 0) {
1875 error = ifnet_ioctl(ifp, 0, SIOCSIFFLAGS, NULL);
1876 if (error == 0) {
1877 rt_ifmsg(ifp);
1878 } else {
1879 ifnet_lock_exclusive(ifp);
1880 // revert the flags
1881 ifp->if_pcount -= pswitch ? 1 : -1;
1882 if (ifp->if_pcount > 0)
1883 ifp->if_flags |= IFF_PROMISC;
1884 else
1885 ifp->if_flags &= ~IFF_PROMISC;
1886 ifnet_lock_done(ifp);
1887 }
1888 }
1889
1890 if (newflags != oldflags) {
1891 log(LOG_INFO, "%s%d: promiscuous mode %s%s\n",
91447636 1892 ifp->if_name, ifp->if_unit,
6d2010ae
A
1893 (newflags & IFF_PROMISC) != 0 ? "enable" : "disable",
1894 error != 0 ? " failed" : " succeeded");
91447636 1895 }
1c79356b
A
1896 return error;
1897}
1898
1899/*
1900 * Return interface configuration
1901 * of system. List may be used
1902 * in later ioctl's (above) to get
1903 * other information.
1904 */
1905/*ARGSUSED*/
1906static int
91447636 1907ifconf(u_long cmd, user_addr_t ifrp, int * ret_space)
1c79356b 1908{
91447636
A
1909 struct ifnet *ifp = NULL;
1910 struct ifaddr *ifa;
1911 struct ifreq ifr;
1912 int error = 0;
1913 size_t space;
6d2010ae 1914
3a60a9f5
A
1915 /*
1916 * Zero the ifr buffer to make sure we don't
1917 * disclose the contents of the stack.
1918 */
1919 bzero(&ifr, sizeof(struct ifreq));
1920
91447636
A
1921 space = *ret_space;
1922 ifnet_head_lock_shared();
6d2010ae
A
1923 for (ifp = ifnet_head.tqh_first; space > sizeof(ifr) &&
1924 ifp; ifp = ifp->if_link.tqe_next) {
1c79356b 1925 char workbuf[64];
91447636 1926 size_t ifnlen, addrs;
1c79356b
A
1927
1928 ifnlen = snprintf(workbuf, sizeof(workbuf),
1929 "%s%d", ifp->if_name, ifp->if_unit);
1930 if(ifnlen + 1 > sizeof ifr.ifr_name) {
1931 error = ENAMETOOLONG;
9bccf70c 1932 break;
1c79356b 1933 } else {
2d21ac55 1934 strlcpy(ifr.ifr_name, workbuf, IFNAMSIZ);
1c79356b 1935 }
6d2010ae 1936
91447636 1937 ifnet_lock_shared(ifp);
1c79356b 1938
9bccf70c
A
1939 addrs = 0;
1940 ifa = ifp->if_addrhead.tqh_first;
1941 for ( ; space > sizeof (ifr) && ifa;
1942 ifa = ifa->ifa_link.tqe_next) {
6d2010ae
A
1943 struct sockaddr *sa;
1944
1945 IFA_LOCK(ifa);
1946 sa = ifa->ifa_addr;
9bccf70c 1947#ifndef __APPLE__
6d2010ae
A
1948 if (curproc->p_prison && prison_if(curproc, sa)) {
1949 IFA_UNLOCK(ifa);
9bccf70c 1950 continue;
6d2010ae 1951 }
9bccf70c
A
1952#endif
1953 addrs++;
b0d623f7 1954 if (cmd == OSIOCGIFCONF32 || cmd == OSIOCGIFCONF64) {
1c79356b
A
1955 struct osockaddr *osa =
1956 (struct osockaddr *)&ifr.ifr_addr;
1957 ifr.ifr_addr = *sa;
1958 osa->sa_family = sa->sa_family;
6d2010ae
A
1959 error = copyout((caddr_t)&ifr, ifrp,
1960 sizeof (ifr));
91447636 1961 ifrp += sizeof(struct ifreq);
2d21ac55 1962 } else if (sa->sa_len <= sizeof(*sa)) {
1c79356b 1963 ifr.ifr_addr = *sa;
6d2010ae
A
1964 error = copyout((caddr_t)&ifr, ifrp,
1965 sizeof (ifr));
91447636 1966 ifrp += sizeof(struct ifreq);
1c79356b 1967 } else {
6d2010ae
A
1968 if (space <
1969 sizeof (ifr) + sa->sa_len - sizeof(*sa)) {
1970 IFA_UNLOCK(ifa);
1c79356b 1971 break;
6d2010ae 1972 }
9bccf70c 1973 space -= sa->sa_len - sizeof(*sa);
6d2010ae
A
1974 error = copyout((caddr_t)&ifr, ifrp,
1975 sizeof (ifr.ifr_name));
91447636 1976 if (error == 0) {
6d2010ae
A
1977 error = copyout((caddr_t)sa, (ifrp +
1978 offsetof(struct ifreq, ifr_addr)),
1979 sa->sa_len);
91447636 1980 }
6d2010ae
A
1981 ifrp += (sa->sa_len + offsetof(struct ifreq,
1982 ifr_addr));
1c79356b 1983 }
6d2010ae 1984 IFA_UNLOCK(ifa);
1c79356b
A
1985 if (error)
1986 break;
1987 space -= sizeof (ifr);
1988 }
91447636 1989 ifnet_lock_done(ifp);
6d2010ae 1990
9bccf70c
A
1991 if (error)
1992 break;
1993 if (!addrs) {
1994 bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
91447636 1995 error = copyout((caddr_t)&ifr, ifrp, sizeof (ifr));
9bccf70c
A
1996 if (error)
1997 break;
1998 space -= sizeof (ifr);
91447636 1999 ifrp += sizeof(struct ifreq);
9bccf70c 2000 }
1c79356b 2001 }
91447636
A
2002 ifnet_head_done();
2003 *ret_space -= space;
1c79356b
A
2004 return (error);
2005}
2006
2007/*
2008 * Just like if_promisc(), but for all-multicast-reception mode.
2009 */
2010int
2d21ac55 2011if_allmulti(struct ifnet *ifp, int onswitch)
1c79356b
A
2012{
2013 int error = 0;
91447636
A
2014 int modified = 0;
2015
2016 ifnet_lock_exclusive(ifp);
1c79356b
A
2017
2018 if (onswitch) {
2019 if (ifp->if_amcount++ == 0) {
2020 ifp->if_flags |= IFF_ALLMULTI;
91447636 2021 modified = 1;
1c79356b
A
2022 }
2023 } else {
2024 if (ifp->if_amcount > 1) {
2025 ifp->if_amcount--;
2026 } else {
2027 ifp->if_amcount = 0;
2028 ifp->if_flags &= ~IFF_ALLMULTI;
91447636 2029 modified = 1;
1c79356b
A
2030 }
2031 }
91447636
A
2032 ifnet_lock_done(ifp);
2033
2034 if (modified)
2d21ac55 2035 error = ifnet_ioctl(ifp, 0, SIOCSIFFLAGS, NULL);
1c79356b
A
2036
2037 if (error == 0)
2038 rt_ifmsg(ifp);
2039 return error;
2040}
2041
6d2010ae
A
2042static struct ifmultiaddr *
2043ifma_alloc(int how)
2044{
2045 struct ifmultiaddr *ifma;
2046
2047 ifma = (how == M_WAITOK) ? zalloc(ifma_zone) :
2048 zalloc_noblock(ifma_zone);
2049
2050 if (ifma != NULL) {
2051 bzero(ifma, ifma_size);
2052 lck_mtx_init(&ifma->ifma_lock, ifa_mtx_grp, ifa_mtx_attr);
2053 ifma->ifma_debug |= IFD_ALLOC;
2054 if (ifma_debug != 0) {
2055 ifma->ifma_debug |= IFD_DEBUG;
2056 ifma->ifma_trace = ifma_trace;
2057 }
2058 }
2059 return (ifma);
2060}
2061
2062static void
2063ifma_free(struct ifmultiaddr *ifma)
2064{
2065 IFMA_LOCK(ifma);
2066
2067 if (ifma->ifma_protospec != NULL) {
2068 panic("%s: Protospec not NULL for ifma=%p", __func__, ifma);
2069 /* NOTREACHED */
2070 } else if ((ifma->ifma_flags & IFMAF_ANONYMOUS) ||
2071 ifma->ifma_anoncnt != 0) {
2072 panic("%s: Freeing ifma=%p with outstanding anon req",
2073 __func__, ifma);
2074 /* NOTREACHED */
2075 } else if (ifma->ifma_debug & IFD_ATTACHED) {
2076 panic("%s: ifma=%p attached to ifma_ifp=%p is being freed",
2077 __func__, ifma, ifma->ifma_ifp);
2078 /* NOTREACHED */
2079 } else if (!(ifma->ifma_debug & IFD_ALLOC)) {
2080 panic("%s: ifma %p cannot be freed", __func__, ifma);
2081 /* NOTREACHED */
2082 } else if (ifma->ifma_refcount != 0) {
2083 panic("%s: non-zero refcount ifma=%p", __func__, ifma);
2084 /* NOTREACHED */
2085 } else if (ifma->ifma_reqcnt != 0) {
2086 panic("%s: non-zero reqcnt ifma=%p", __func__, ifma);
2087 /* NOTREACHED */
2088 } else if (ifma->ifma_ifp != NULL) {
2089 panic("%s: non-NULL ifma_ifp=%p for ifma=%p", __func__,
2090 ifma->ifma_ifp, ifma);
2091 /* NOTREACHED */
2092 } else if (ifma->ifma_ll != NULL) {
2093 panic("%s: non-NULL ifma_ll=%p for ifma=%p", __func__,
2094 ifma->ifma_ll, ifma);
2095 /* NOTREACHED */
2096 }
2097 ifma->ifma_debug &= ~IFD_ALLOC;
2098 if ((ifma->ifma_debug & (IFD_DEBUG | IFD_TRASHED)) ==
2099 (IFD_DEBUG | IFD_TRASHED)) {
2100 lck_mtx_lock(&ifma_trash_lock);
2101 TAILQ_REMOVE(&ifma_trash_head, (struct ifmultiaddr_dbg *)ifma,
2102 ifma_trash_link);
2103 lck_mtx_unlock(&ifma_trash_lock);
2104 ifma->ifma_debug &= ~IFD_TRASHED;
2105 }
2106 IFMA_UNLOCK(ifma);
2107
2108 if (ifma->ifma_addr != NULL) {
2109 FREE(ifma->ifma_addr, M_IFADDR);
2110 ifma->ifma_addr = NULL;
2111 }
2112 lck_mtx_destroy(&ifma->ifma_lock, ifa_mtx_grp);
2113 zfree(ifma_zone, ifma);
2114}
2115
2116static void
2117ifma_trace(struct ifmultiaddr *ifma, int refhold)
2118{
2119 struct ifmultiaddr_dbg *ifma_dbg = (struct ifmultiaddr_dbg *)ifma;
2120 ctrace_t *tr;
2121 u_int32_t idx;
2122 u_int16_t *cnt;
2123
2124 if (!(ifma->ifma_debug & IFD_DEBUG)) {
2125 panic("%s: ifma %p has no debug structure", __func__, ifma);
2126 /* NOTREACHED */
2127 }
2128 if (refhold) {
2129 cnt = &ifma_dbg->ifma_refhold_cnt;
2130 tr = ifma_dbg->ifma_refhold;
2131 } else {
2132 cnt = &ifma_dbg->ifma_refrele_cnt;
2133 tr = ifma_dbg->ifma_refrele;
2134 }
2135
2136 idx = atomic_add_16_ov(cnt, 1) % IFMA_TRACE_HIST_SIZE;
2137 ctrace_record(&tr[idx]);
2138}
2139
91447636 2140void
6d2010ae 2141ifma_addref(struct ifmultiaddr *ifma, int locked)
1c79356b 2142{
6d2010ae
A
2143 if (!locked)
2144 IFMA_LOCK(ifma);
2145 else
2146 IFMA_LOCK_ASSERT_HELD(ifma);
2147
2148 if (++ifma->ifma_refcount == 0) {
2149 panic("%s: ifma=%p wraparound refcnt", __func__, ifma);
2150 /* NOTREACHED */
2151 } else if (ifma->ifma_trace != NULL) {
2152 (*ifma->ifma_trace)(ifma, TRUE);
2153 }
2154 if (!locked)
2155 IFMA_UNLOCK(ifma);
91447636 2156}
1c79356b 2157
91447636 2158void
6d2010ae
A
2159ifma_remref(struct ifmultiaddr *ifma)
2160{
2161 struct ifmultiaddr *ll;
2162
2163 IFMA_LOCK(ifma);
2164
2165 if (ifma->ifma_refcount == 0) {
2166 panic("%s: ifma=%p negative refcnt", __func__, ifma);
2167 /* NOTREACHED */
2168 } else if (ifma->ifma_trace != NULL) {
2169 (*ifma->ifma_trace)(ifma, FALSE);
2170 }
2171
2172 --ifma->ifma_refcount;
2173 if (ifma->ifma_refcount > 0) {
2174 IFMA_UNLOCK(ifma);
2175 return;
91447636 2176 }
6d2010ae
A
2177
2178 ll = ifma->ifma_ll;
2179 ifma->ifma_ifp = NULL;
2180 ifma->ifma_ll = NULL;
2181 IFMA_UNLOCK(ifma);
2182 ifma_free(ifma); /* deallocate it */
2183
2184 if (ll != NULL)
2185 IFMA_REMREF(ll);
2186}
2187
2188static void
2189if_attach_ifma(struct ifnet *ifp, struct ifmultiaddr *ifma, int anon)
2190{
2191 ifnet_lock_assert(ifp, IFNET_LCK_ASSERT_EXCLUSIVE);
2192 IFMA_LOCK_ASSERT_HELD(ifma);
2193
2194 if (ifma->ifma_ifp != ifp) {
2195 panic("%s: Mismatch ifma_ifp=%p != ifp=%p", __func__,
2196 ifma->ifma_ifp, ifp);
2197 /* NOTREACHED */
2198 } else if (ifma->ifma_debug & IFD_ATTACHED) {
2199 panic("%s: Attempt to attach an already attached ifma=%p",
2200 __func__, ifma);
2201 /* NOTREACHED */
2202 } else if (anon && (ifma->ifma_flags & IFMAF_ANONYMOUS)) {
2203 panic("%s: ifma=%p unexpected IFMAF_ANONYMOUS", __func__, ifma);
2204 /* NOTREACHED */
2205 } else if (ifma->ifma_debug & IFD_TRASHED) {
2206 panic("%s: Attempt to reattach a detached ifma=%p",
2207 __func__, ifma);
2208 /* NOTREACHED */
2209 }
2210
2211 ifma->ifma_reqcnt++;
2212 VERIFY(ifma->ifma_reqcnt == 1);
2213 IFMA_ADDREF_LOCKED(ifma);
2214 ifma->ifma_debug |= IFD_ATTACHED;
2215 if (anon) {
2216 ifma->ifma_anoncnt++;
2217 VERIFY(ifma->ifma_anoncnt == 1);
2218 ifma->ifma_flags |= IFMAF_ANONYMOUS;
2219 }
2220
2221 LIST_INSERT_HEAD(&ifp->if_multiaddrs, ifma, ifma_link);
91447636
A
2222}
2223
91447636 2224static int
6d2010ae
A
2225if_detach_ifma(struct ifnet *ifp, struct ifmultiaddr *ifma, int anon)
2226{
2227 ifnet_lock_assert(ifp, IFNET_LCK_ASSERT_EXCLUSIVE);
2228 IFMA_LOCK_ASSERT_HELD(ifma);
2229
2230 if (ifma->ifma_reqcnt == 0) {
2231 panic("%s: ifma=%p negative reqcnt", __func__, ifma);
2232 /* NOTREACHED */
2233 } else if (anon && !(ifma->ifma_flags & IFMAF_ANONYMOUS)) {
2234 panic("%s: ifma=%p missing IFMAF_ANONYMOUS", __func__, ifma);
2235 /* NOTREACHED */
2236 } else if (anon && ifma->ifma_anoncnt == 0) {
2237 panic("%s: ifma=%p negative anonreqcnt", __func__, ifma);
2238 /* NOTREACHED */
2239 } else if (ifma->ifma_ifp != ifp) {
2240 panic("%s: Mismatch ifma_ifp=%p, ifp=%p", __func__,
2241 ifma->ifma_ifp, ifp);
2242 /* NOTREACHED */
2243 }
2244
2245 if (anon) {
2246 --ifma->ifma_anoncnt;
2247 if (ifma->ifma_anoncnt > 0)
2248 return (0);
2249 ifma->ifma_flags &= ~IFMAF_ANONYMOUS;
2250 }
2251
2252 --ifma->ifma_reqcnt;
2253 if (ifma->ifma_reqcnt > 0)
2254 return (0);
2255
2256 if (ifma->ifma_protospec != NULL) {
2257 panic("%s: Protospec not NULL for ifma=%p", __func__, ifma);
2258 /* NOTREACHED */
2259 } else if ((ifma->ifma_flags & IFMAF_ANONYMOUS) ||
2260 ifma->ifma_anoncnt != 0) {
2261 panic("%s: Detaching ifma=%p with outstanding anon req",
2262 __func__, ifma);
2263 /* NOTREACHED */
2264 } else if (!(ifma->ifma_debug & IFD_ATTACHED)) {
2265 panic("%s: Attempt to detach an unattached address ifma=%p",
2266 __func__, ifma);
2267 /* NOTREACHED */
2268 } else if (ifma->ifma_debug & IFD_TRASHED) {
2269 panic("%s: ifma %p is already in trash list", __func__, ifma);
2270 /* NOTREACHED */
2271 }
2272
2273 /*
2274 * NOTE: Caller calls IFMA_REMREF
2275 */
2276 ifma->ifma_debug &= ~IFD_ATTACHED;
2277 LIST_REMOVE(ifma, ifma_link);
2278 if (LIST_EMPTY(&ifp->if_multiaddrs))
2279 ifp->if_updatemcasts = 0;
2280
2281 if (ifma->ifma_debug & IFD_DEBUG) {
2282 /* Become a regular mutex, just in case */
2283 IFMA_CONVERT_LOCK(ifma);
2284 lck_mtx_lock(&ifma_trash_lock);
2285 TAILQ_INSERT_TAIL(&ifma_trash_head,
2286 (struct ifmultiaddr_dbg *)ifma, ifma_trash_link);
2287 lck_mtx_unlock(&ifma_trash_lock);
2288 ifma->ifma_debug |= IFD_TRASHED;
2289 }
2290
2291 return (1);
2292}
2293
2294/*
2295 * Find an ifmultiaddr that matches a socket address on an interface.
2296 *
2297 * Caller is responsible for holding the ifnet_lock while calling
2298 * this function.
2299 */
2300static int
2301if_addmulti_doesexist(struct ifnet *ifp, const struct sockaddr *sa,
2302 struct ifmultiaddr **retifma, int anon)
91447636
A
2303{
2304 struct ifmultiaddr *ifma;
6d2010ae
A
2305
2306 for (ifma = LIST_FIRST(&ifp->if_multiaddrs); ifma != NULL;
2307 ifma = LIST_NEXT(ifma, ifma_link)) {
2308 IFMA_LOCK_SPIN(ifma);
2309 if (!equal(sa, ifma->ifma_addr)) {
2310 IFMA_UNLOCK(ifma);
2311 continue;
2312 }
2313 if (anon) {
2314 VERIFY(!(ifma->ifma_flags & IFMAF_ANONYMOUS) ||
2315 ifma->ifma_anoncnt != 0);
2316 VERIFY((ifma->ifma_flags & IFMAF_ANONYMOUS) ||
2317 ifma->ifma_anoncnt == 0);
2318 ifma->ifma_anoncnt++;
2319 if (!(ifma->ifma_flags & IFMAF_ANONYMOUS)) {
2320 VERIFY(ifma->ifma_anoncnt == 1);
2321 ifma->ifma_flags |= IFMAF_ANONYMOUS;
91447636 2322 }
1c79356b 2323 }
6d2010ae
A
2324 if (!anon || ifma->ifma_anoncnt == 1) {
2325 ifma->ifma_reqcnt++;
2326 VERIFY(ifma->ifma_reqcnt > 1);
2327 }
2328 if (retifma != NULL) {
2329 *retifma = ifma;
2330 IFMA_ADDREF_LOCKED(ifma);
2331 }
2332 IFMA_UNLOCK(ifma);
2333 return (0);
1c79356b 2334 }
6d2010ae 2335 return (ENOENT);
91447636
A
2336}
2337
2d21ac55
A
2338/*
2339 * Radar 3642395, make sure all multicasts are in a standard format.
2340 */
2341static struct sockaddr*
2342copy_and_normalize(
2343 const struct sockaddr *original)
2344{
2345 int alen = 0;
2346 const u_char *aptr = NULL;
2347 struct sockaddr *copy = NULL;
2348 struct sockaddr_dl *sdl_new = NULL;
2349 int len = 0;
2350
2351 if (original->sa_family != AF_LINK &&
2352 original->sa_family != AF_UNSPEC) {
2353 /* Just make a copy */
2354 MALLOC(copy, struct sockaddr*, original->sa_len, M_IFADDR, M_WAITOK);
2355 if (copy != NULL)
2356 bcopy(original, copy, original->sa_len);
2357 return copy;
2358 }
2359
2360 switch (original->sa_family) {
2361 case AF_LINK: {
2362 const struct sockaddr_dl *sdl_original =
2363 (const struct sockaddr_dl*)original;
2364
2365 if (sdl_original->sdl_nlen + sdl_original->sdl_alen + sdl_original->sdl_slen +
2366 offsetof(struct sockaddr_dl, sdl_data) > sdl_original->sdl_len)
2367 return NULL;
2368
2369 alen = sdl_original->sdl_alen;
2370 aptr = CONST_LLADDR(sdl_original);
2371 }
2372 break;
2373
2374 case AF_UNSPEC: {
2375 if (original->sa_len < ETHER_ADDR_LEN +
2376 offsetof(struct sockaddr, sa_data)) {
2377 return NULL;
2378 }
2379
2380 alen = ETHER_ADDR_LEN;
2381 aptr = (const u_char*)original->sa_data;
2382 }
2383 break;
2384 }
2385
2386 if (alen == 0 || aptr == NULL)
2387 return NULL;
2388
2389 len = alen + offsetof(struct sockaddr_dl, sdl_data);
2390 MALLOC(sdl_new, struct sockaddr_dl*, len, M_IFADDR, M_WAITOK);
2391
2392 if (sdl_new != NULL) {
2393 bzero(sdl_new, len);
2394 sdl_new->sdl_len = len;
2395 sdl_new->sdl_family = AF_LINK;
2396 sdl_new->sdl_alen = alen;
2397 bcopy(aptr, LLADDR(sdl_new), alen);
2398 }
2399
2400 return (struct sockaddr*)sdl_new;
2401}
2402
91447636 2403/*
6d2010ae
A
2404 * Network-layer protocol domains which hold references to the underlying
2405 * link-layer record must use this routine.
91447636
A
2406 */
2407int
6d2010ae
A
2408if_addmulti(struct ifnet *ifp, const struct sockaddr *sa,
2409 struct ifmultiaddr **retifma)
2410{
2411 return (if_addmulti_common(ifp, sa, retifma, 0));
2412}
2413
2414/*
2415 * Anything other than network-layer protocol domains which hold references
2416 * to the underlying link-layer record must use this routine: SIOCADDMULTI
2417 * ioctl, ifnet_add_multicast(), AppleTalk, if_bond.
2418 */
2419int
2420if_addmulti_anon(struct ifnet *ifp, const struct sockaddr *sa,
2421 struct ifmultiaddr **retifma)
2422{
2423 return (if_addmulti_common(ifp, sa, retifma, 1));
2424}
2425
2426/*
2427 * Register an additional multicast address with a network interface.
2428 *
2429 * - If the address is already present, bump the reference count on the
2430 * address and return.
2431 * - If the address is not link-layer, look up a link layer address.
2432 * - Allocate address structures for one or both addresses, and attach to the
2433 * multicast address list on the interface. If automatically adding a link
2434 * layer address, the protocol address will own a reference to the link
2435 * layer address, to be freed when it is freed.
2436 * - Notify the network device driver of an addition to the multicast address
2437 * list.
2438 *
2439 * 'sa' points to caller-owned memory with the desired multicast address.
2440 *
2441 * 'retifma' will be used to return a pointer to the resulting multicast
2442 * address reference, if desired.
2443 *
2444 * 'anon' indicates a link-layer address with no protocol address reference
2445 * made to it. Anything other than network-layer protocol domain requests
2446 * are considered as anonymous.
2447 */
2448static int
2449if_addmulti_common(struct ifnet *ifp, const struct sockaddr *sa,
2450 struct ifmultiaddr **retifma, int anon)
91447636
A
2451{
2452 struct sockaddr_storage storage;
2453 struct sockaddr *llsa = NULL;
2d21ac55 2454 struct sockaddr *dupsa = NULL;
6d2010ae 2455 int error = 0, ll_firstref = 0, lladdr;
2d21ac55 2456 struct ifmultiaddr *ifma = NULL;
91447636 2457 struct ifmultiaddr *llifma = NULL;
6d2010ae
A
2458
2459 /* Only AF_UNSPEC/AF_LINK is allowed for an "anonymous" address */
2460 VERIFY(!anon || sa->sa_family == AF_UNSPEC ||
2461 sa->sa_family == AF_LINK);
2462
2d21ac55
A
2463 /* If sa is a AF_LINK or AF_UNSPEC, duplicate and normalize it */
2464 if (sa->sa_family == AF_LINK || sa->sa_family == AF_UNSPEC) {
2465 dupsa = copy_and_normalize(sa);
2466 if (dupsa == NULL) {
6d2010ae
A
2467 error = ENOMEM;
2468 goto cleanup;
2d21ac55
A
2469 }
2470 sa = dupsa;
2471 }
6d2010ae 2472
91447636 2473 ifnet_lock_exclusive(ifp);
6d2010ae
A
2474 if (!(ifp->if_flags & IFF_MULTICAST)) {
2475 error = EADDRNOTAVAIL;
2476 ifnet_lock_done(ifp);
2d21ac55
A
2477 goto cleanup;
2478 }
1c79356b 2479
6d2010ae
A
2480 /* If the address is already present, return a new reference to it */
2481 error = if_addmulti_doesexist(ifp, sa, retifma, anon);
2482 ifnet_lock_done(ifp);
2483 if (error == 0)
2484 goto cleanup;
2485
1c79356b 2486 /*
6d2010ae
A
2487 * The address isn't already present; give the link layer a chance
2488 * to accept/reject it, and also find out which AF_LINK address this
2489 * maps to, if it isn't one already.
1c79356b 2490 */
6d2010ae
A
2491 error = dlil_resolve_multi(ifp, sa, (struct sockaddr *)&storage,
2492 sizeof (storage));
91447636 2493 if (error == 0 && storage.ss_len != 0) {
6d2010ae 2494 llsa = copy_and_normalize((struct sockaddr *)&storage);
2d21ac55
A
2495 if (llsa == NULL) {
2496 error = ENOMEM;
2497 goto cleanup;
2498 }
6d2010ae
A
2499
2500 llifma = ifma_alloc(M_WAITOK);
2d21ac55
A
2501 if (llifma == NULL) {
2502 error = ENOMEM;
2503 goto cleanup;
2504 }
91447636 2505 }
6d2010ae 2506
9bccf70c 2507 /* to be similar to FreeBSD */
6d2010ae 2508 if (error == EOPNOTSUPP)
9bccf70c 2509 error = 0;
6d2010ae 2510 else if (error != 0)
2d21ac55 2511 goto cleanup;
1c79356b 2512
91447636 2513 /* Allocate while we aren't holding any locks */
2d21ac55
A
2514 if (dupsa == NULL) {
2515 dupsa = copy_and_normalize(sa);
2516 if (dupsa == NULL) {
2517 error = ENOMEM;
2518 goto cleanup;
2519 }
2520 }
6d2010ae 2521 ifma = ifma_alloc(M_WAITOK);
2d21ac55
A
2522 if (ifma == NULL) {
2523 error = ENOMEM;
2524 goto cleanup;
2525 }
6d2010ae 2526
91447636
A
2527 ifnet_lock_exclusive(ifp);
2528 /*
2529 * Check again for the matching multicast.
2530 */
6d2010ae
A
2531 error = if_addmulti_doesexist(ifp, sa, retifma, anon);
2532 if (error == 0) {
91447636 2533 ifnet_lock_done(ifp);
2d21ac55 2534 goto cleanup;
91447636 2535 }
1c79356b 2536
6d2010ae
A
2537 if (llifma != NULL) {
2538 VERIFY(!anon); /* must not get here if "anonymous" */
2539 if (if_addmulti_doesexist(ifp, llsa, &ifma->ifma_ll, 0) == 0) {
2540 FREE(llsa, M_IFADDR);
2541 llsa = NULL;
2542 ifma_free(llifma);
2543 llifma = NULL;
2544 VERIFY(ifma->ifma_ll->ifma_ifp == ifp);
1c79356b 2545 } else {
6d2010ae 2546 ll_firstref = 1;
91447636
A
2547 llifma->ifma_addr = llsa;
2548 llifma->ifma_ifp = ifp;
6d2010ae
A
2549 IFMA_LOCK(llifma);
2550 if_attach_ifma(ifp, llifma, 0);
2551 /* add extra refcnt for ifma */
2552 IFMA_ADDREF_LOCKED(llifma);
2553 IFMA_UNLOCK(llifma);
91447636 2554 ifma->ifma_ll = llifma;
1c79356b
A
2555 }
2556 }
6d2010ae
A
2557
2558 /* "anonymous" request should not result in network address */
2559 VERIFY(!anon || ifma->ifma_ll == NULL);
2560
2561 ifma->ifma_addr = dupsa;
2562 ifma->ifma_ifp = ifp;
2563 IFMA_LOCK(ifma);
2564 if_attach_ifma(ifp, ifma, anon);
2565 IFMA_ADDREF_LOCKED(ifma); /* for this routine */
2566 if (retifma != NULL) {
91447636 2567 *retifma = ifma;
6d2010ae 2568 IFMA_ADDREF_LOCKED(*retifma); /* for caller */
91447636 2569 }
6d2010ae
A
2570 lladdr = (ifma->ifma_addr->sa_family == AF_UNSPEC ||
2571 ifma->ifma_addr->sa_family == AF_LINK);
2572 IFMA_UNLOCK(ifma);
91447636 2573 ifnet_lock_done(ifp);
6d2010ae
A
2574
2575 rt_newmaddrmsg(RTM_NEWMADDR, ifma);
2576 IFMA_REMREF(ifma); /* for this routine */
91447636 2577
1c79356b
A
2578 /*
2579 * We are certain we have added something, so call down to the
6d2010ae
A
2580 * interface to let them know about it. Do this only for newly-
2581 * added AF_LINK/AF_UNSPEC address in the if_multiaddrs set.
1c79356b 2582 */
6d2010ae
A
2583 if (lladdr || ll_firstref)
2584 (void) ifnet_ioctl(ifp, 0, SIOCADDMULTI, NULL);
2585
2586 if (ifp->if_updatemcasts > 0)
2587 ifp->if_updatemcasts = 0;
2588
2589 return (0);
2590
2d21ac55 2591cleanup:
6d2010ae
A
2592 if (ifma != NULL)
2593 ifma_free(ifma);
2594 if (dupsa != NULL)
2d21ac55 2595 FREE(dupsa, M_IFADDR);
6d2010ae
A
2596 if (llifma != NULL)
2597 ifma_free(llifma);
2598 if (llsa != NULL)
2d21ac55 2599 FREE(llsa, M_IFADDR);
6d2010ae
A
2600
2601 return (error);
1c79356b
A
2602}
2603
6d2010ae
A
2604/*
2605 * Delete a multicast group membership by network-layer group address.
2606 * This routine is deprecated.
2607 */
1c79356b 2608int
6d2010ae 2609if_delmulti(struct ifnet *ifp, const struct sockaddr *sa)
1c79356b 2610{
6d2010ae 2611 return (if_delmulti_common(NULL, ifp, sa, 0));
55e303ae 2612}
1c79356b 2613
55e303ae 2614/*
6d2010ae
A
2615 * Delete a multicast group membership by group membership pointer.
2616 * Network-layer protocol domains must use this routine.
55e303ae
A
2617 */
2618int
6d2010ae
A
2619if_delmulti_ifma(struct ifmultiaddr *ifma)
2620{
2621 return (if_delmulti_common(ifma, NULL, NULL, 0));
2622}
2623
2624/*
2625 * Anything other than network-layer protocol domains which hold references
2626 * to the underlying link-layer record must use this routine: SIOCDELMULTI
2627 * ioctl, ifnet_remove_multicast(), AppleTalk, if_bond.
2628 */
2629int
2630if_delmulti_anon(struct ifnet *ifp, const struct sockaddr *sa)
2631{
2632 return (if_delmulti_common(NULL, ifp, sa, 1));
2633}
2634
2635/*
2636 * Delete a multicast group membership by network-layer group address.
2637 *
2638 * Returns ENOENT if the entry could not be found.
2639 */
2640static int
2641if_delmulti_common(struct ifmultiaddr *ifma, struct ifnet *ifp,
2642 const struct sockaddr *sa, int anon)
55e303ae 2643{
2d21ac55 2644 struct sockaddr *dupsa = NULL;
6d2010ae
A
2645 int lastref, ll_lastref = 0, lladdr;
2646 struct ifmultiaddr *ll = NULL;
55e303ae 2647
6d2010ae
A
2648 /* sanity check for callers */
2649 VERIFY(ifma != NULL || (ifp != NULL && sa != NULL));
2650
2651 if (ifma != NULL)
2652 ifp = ifma->ifma_ifp;
2653
2654 if (sa != NULL &&
2655 (sa->sa_family == AF_LINK || sa->sa_family == AF_UNSPEC)) {
2d21ac55 2656 dupsa = copy_and_normalize(sa);
6d2010ae
A
2657 if (dupsa == NULL)
2658 return (ENOMEM);
2d21ac55
A
2659 sa = dupsa;
2660 }
6d2010ae 2661
91447636 2662 ifnet_lock_exclusive(ifp);
6d2010ae
A
2663 if (ifma == NULL) {
2664 for (ifma = LIST_FIRST(&ifp->if_multiaddrs); ifma != NULL;
2665 ifma = LIST_NEXT(ifma, ifma_link)) {
2666 IFMA_LOCK(ifma);
2667 if (!equal(sa, ifma->ifma_addr) ||
2668 (anon && !(ifma->ifma_flags & IFMAF_ANONYMOUS))) {
2669 VERIFY(!(ifma->ifma_flags & IFMAF_ANONYMOUS) ||
2670 ifma->ifma_anoncnt != 0);
2671 IFMA_UNLOCK(ifma);
2672 continue;
2673 }
2674 /* found; keep it locked */
55e303ae 2675 break;
6d2010ae
A
2676 }
2677 if (ifma == NULL) {
2678 if (dupsa != NULL)
2679 FREE(dupsa, M_IFADDR);
2680 ifnet_lock_done(ifp);
2681 return (ENOENT);
2682 }
2683 } else {
2684 IFMA_LOCK(ifma);
2685 }
2686 IFMA_LOCK_ASSERT_HELD(ifma);
2687 IFMA_ADDREF_LOCKED(ifma); /* for this routine */
2688 lastref = if_detach_ifma(ifp, ifma, anon);
2689 VERIFY(!lastref || (!(ifma->ifma_debug & IFD_ATTACHED) &&
2690 ifma->ifma_reqcnt == 0));
2691 VERIFY(!anon || ifma->ifma_ll == NULL);
2692 ll = ifma->ifma_ll;
2693 lladdr = (ifma->ifma_addr->sa_family == AF_UNSPEC ||
2694 ifma->ifma_addr->sa_family == AF_LINK);
2695 IFMA_UNLOCK(ifma);
2696 if (lastref && ll != NULL) {
2697 IFMA_LOCK(ll);
2698 ll_lastref = if_detach_ifma(ifp, ll, 0);
2699 IFMA_UNLOCK(ll);
91447636 2700 }
91447636 2701 ifnet_lock_done(ifp);
6d2010ae
A
2702
2703 if (lastref)
2704 rt_newmaddrmsg(RTM_DELMADDR, ifma);
2705
2706 if ((ll == NULL && lastref && lladdr) || ll_lastref) {
2707 /*
2708 * Make sure the interface driver is notified in the
2709 * case of a link layer mcast group being left. Do
2710 * this only for a AF_LINK/AF_UNSPEC address that has
2711 * been removed from the if_multiaddrs set.
2712 */
2713 ifnet_ioctl(ifp, 0, SIOCDELMULTI, NULL);
2714 }
2715
2716 if (lastref)
2717 IFMA_REMREF(ifma); /* for if_multiaddrs list */
2718 if (ll_lastref)
2719 IFMA_REMREF(ll); /* for if_multiaddrs list */
2720
2721 IFMA_REMREF(ifma); /* for this routine */
2722 if (dupsa != NULL)
2d21ac55 2723 FREE(dupsa, M_IFADDR);
1c79356b 2724
6d2010ae
A
2725 return (0);
2726}
9bccf70c
A
2727
2728/*
2729 * We don't use if_setlladdr, our interfaces are responsible for
2730 * handling the SIOCSIFLLADDR ioctl.
2731 */
2732#ifndef __APPLE__
2733int
2734if_setlladdr(struct ifnet *ifp, const u_char *lladdr, int len)
2735{
2736 ...
2737}
2738#endif
2739
2d21ac55
A
2740SYSCTL_NODE(_net, PF_LINK, link, CTLFLAG_RW|CTLFLAG_LOCKED, 0, "Link layers");
2741SYSCTL_NODE(_net_link, 0, generic, CTLFLAG_RW|CTLFLAG_LOCKED, 0, "Generic link-management");
1c79356b
A
2742
2743
2744/*
2745 * Shutdown all network activity. Used boot() when halting
2746 * system.
2747 */
2d21ac55
A
2748int
2749if_down_all(void)
1c79356b 2750{
91447636
A
2751 struct ifnet **ifp;
2752 u_int32_t count;
2753 u_int32_t i;
1c79356b 2754
4a3eedf9 2755 if (ifnet_list_get_all(IFNET_FAMILY_ANY, &ifp, &count) == 0) {
91447636
A
2756 for (i = 0; i < count; i++) {
2757 if_down(ifp[i]);
4a3eedf9 2758 dlil_proto_unplumb_all(ifp[i]);
91447636
A
2759 }
2760 ifnet_list_free(ifp);
2761 }
4a3eedf9 2762
91447636 2763 return 0;
1c79356b 2764}
9bccf70c
A
2765
2766/*
2767 * Delete Routes for a Network Interface
2768 *
2769 * Called for each routing entry via the rnh->rnh_walktree() call above
2770 * to delete all route entries referencing a detaching network interface.
2771 *
2772 * Arguments:
2773 * rn pointer to node in the routing table
2774 * arg argument passed to rnh->rnh_walktree() - detaching interface
2775 *
2776 * Returns:
2777 * 0 successful
2778 * errno failed - reason indicated
2779 *
2780 */
2781static int
b0d623f7 2782if_rtdel(struct radix_node *rn, void *arg)
9bccf70c
A
2783{
2784 struct rtentry *rt = (struct rtentry *)rn;
2785 struct ifnet *ifp = arg;
2786 int err;
2787
b0d623f7
A
2788 if (rt == NULL)
2789 return (0);
2790 /*
2791 * Checking against RTF_UP protects against walktree
2792 * recursion problems with cloned routes.
2793 */
2794 RT_LOCK(rt);
2795 if (rt->rt_ifp == ifp && (rt->rt_flags & RTF_UP)) {
9bccf70c 2796 /*
b0d623f7
A
2797 * Safe to drop rt_lock and use rt_key, rt_gateway,
2798 * since holding rnh_lock here prevents another thread
2799 * from calling rt_setgate() on this route.
9bccf70c 2800 */
b0d623f7 2801 RT_UNLOCK(rt);
91447636 2802 err = rtrequest_locked(RTM_DELETE, rt_key(rt), rt->rt_gateway,
b0d623f7 2803 rt_mask(rt), rt->rt_flags, NULL);
9bccf70c
A
2804 if (err) {
2805 log(LOG_WARNING, "if_rtdel: error %d\n", err);
2806 }
b0d623f7
A
2807 } else {
2808 RT_UNLOCK(rt);
9bccf70c 2809 }
9bccf70c
A
2810 return (0);
2811}
2812
2813/*
b0d623f7 2814 * Removes routing table reference to a given interface
9bccf70c
A
2815 * for a given protocol family
2816 */
b0d623f7
A
2817void
2818if_rtproto_del(struct ifnet *ifp, int protocol)
9bccf70c 2819{
3a60a9f5 2820 struct radix_node_head *rnh;
b0d623f7
A
2821
2822 if (use_routegenid)
2823 routegenid_update();
3a60a9f5
A
2824 if ((protocol <= AF_MAX) && (protocol >= 0) &&
2825 ((rnh = rt_tables[protocol]) != NULL) && (ifp != NULL)) {
b0d623f7 2826 lck_mtx_lock(rnh_lock);
9bccf70c 2827 (void) rnh->rnh_walktree(rnh, if_rtdel, ifp);
b0d623f7 2828 lck_mtx_unlock(rnh_lock);
91447636
A
2829 }
2830}
2831
2d21ac55
A
2832static int
2833if_rtmtu(struct radix_node *rn, void *arg)
2834{
2835 struct rtentry *rt = (struct rtentry *)rn;
2836 struct ifnet *ifp = arg;
2837
b0d623f7 2838 RT_LOCK(rt);
2d21ac55
A
2839 if (rt->rt_ifp == ifp) {
2840 /*
2841 * Update the MTU of this entry only if the MTU
2842 * has not been locked (RTV_MTU is not set) and
2843 * if it was non-zero to begin with.
2844 */
2845 if (!(rt->rt_rmx.rmx_locks & RTV_MTU) && rt->rt_rmx.rmx_mtu)
2846 rt->rt_rmx.rmx_mtu = ifp->if_mtu;
2847 }
b0d623f7 2848 RT_UNLOCK(rt);
2d21ac55
A
2849
2850 return (0);
2851}
2852
2853/*
2854 * Update the MTU metric of all route entries in all protocol tables
2855 * associated with a particular interface; this is called when the
2856 * MTU of that interface has changed.
2857 */
2858static
2859void if_rtmtu_update(struct ifnet *ifp)
2860{
2861 struct radix_node_head *rnh;
2862 int p;
2863
2864 for (p = 0; p < AF_MAX + 1; p++) {
2865 if ((rnh = rt_tables[p]) == NULL)
2866 continue;
2867
b0d623f7 2868 lck_mtx_lock(rnh_lock);
2d21ac55 2869 (void) rnh->rnh_walktree(rnh, if_rtmtu, ifp);
b0d623f7 2870 lck_mtx_unlock(rnh_lock);
2d21ac55
A
2871 }
2872
2873 if (use_routegenid)
b0d623f7 2874 routegenid_update();
2d21ac55 2875}
91447636
A
2876
2877__private_extern__ void
6d2010ae
A
2878if_data_internal_to_if_data(struct ifnet *ifp,
2879 const struct if_data_internal *if_data_int, struct if_data *if_data)
91447636 2880{
6d2010ae
A
2881#pragma unused(ifp)
2882#define COPYFIELD(fld) if_data->fld = if_data_int->fld
91447636 2883#define COPYFIELD32(fld) if_data->fld = (u_int32_t)(if_data_int->fld)
6d2010ae
A
2884/* compiler will cast down to 32-bit */
2885#define COPYFIELD32_ATOMIC(fld) do { \
2886 atomic_get_64(if_data->fld, \
2887 (u_int64_t *)(void *)(uintptr_t)&if_data_int->fld); \
2888} while (0)
2889
91447636
A
2890 COPYFIELD(ifi_type);
2891 COPYFIELD(ifi_typelen);
2892 COPYFIELD(ifi_physical);
2893 COPYFIELD(ifi_addrlen);
2894 COPYFIELD(ifi_hdrlen);
2895 COPYFIELD(ifi_recvquota);
2896 COPYFIELD(ifi_xmitquota);
2897 if_data->ifi_unused1 = 0;
2898 COPYFIELD(ifi_mtu);
2899 COPYFIELD(ifi_metric);
2900 if (if_data_int->ifi_baudrate & 0xFFFFFFFF00000000LL) {
2901 if_data->ifi_baudrate = 0xFFFFFFFF;
6d2010ae 2902 } else {
91447636
A
2903 COPYFIELD32(ifi_baudrate);
2904 }
6d2010ae
A
2905
2906 COPYFIELD32_ATOMIC(ifi_ipackets);
2907 COPYFIELD32_ATOMIC(ifi_ierrors);
2908 COPYFIELD32_ATOMIC(ifi_opackets);
2909 COPYFIELD32_ATOMIC(ifi_oerrors);
2910 COPYFIELD32_ATOMIC(ifi_collisions);
2911 COPYFIELD32_ATOMIC(ifi_ibytes);
2912 COPYFIELD32_ATOMIC(ifi_obytes);
2913 COPYFIELD32_ATOMIC(ifi_imcasts);
2914 COPYFIELD32_ATOMIC(ifi_omcasts);
2915 COPYFIELD32_ATOMIC(ifi_iqdrops);
2916 COPYFIELD32_ATOMIC(ifi_noproto);
2917
2918 COPYFIELD(ifi_recvtiming);
2919 COPYFIELD(ifi_xmittiming);
91447636 2920
b0d623f7
A
2921 if_data->ifi_lastchange.tv_sec = if_data_int->ifi_lastchange.tv_sec;
2922 if_data->ifi_lastchange.tv_usec = if_data_int->ifi_lastchange.tv_usec;
6d2010ae 2923
91447636
A
2924#if IF_LASTCHANGEUPTIME
2925 if_data->ifi_lastchange.tv_sec += boottime_sec();
2926#endif
2927
2928 if_data->ifi_unused2 = 0;
2929 COPYFIELD(ifi_hwassist);
2930 if_data->ifi_reserved1 = 0;
2931 if_data->ifi_reserved2 = 0;
6d2010ae 2932#undef COPYFIELD32_ATOMIC
91447636
A
2933#undef COPYFIELD32
2934#undef COPYFIELD
2935}
2936
2937__private_extern__ void
6d2010ae
A
2938if_data_internal_to_if_data64(struct ifnet *ifp,
2939 const struct if_data_internal *if_data_int,
2940 struct if_data64 *if_data64)
91447636 2941{
6d2010ae
A
2942#pragma unused(ifp)
2943#define COPYFIELD64(fld) if_data64->fld = if_data_int->fld
2944#define COPYFIELD64_ATOMIC(fld) do { \
2945 atomic_get_64(if_data64->fld, \
2946 (u_int64_t *)(void *)(uintptr_t)&if_data_int->fld); \
2947} while (0)
2948
2949 COPYFIELD64(ifi_type);
2950 COPYFIELD64(ifi_typelen);
2951 COPYFIELD64(ifi_physical);
2952 COPYFIELD64(ifi_addrlen);
2953 COPYFIELD64(ifi_hdrlen);
2954 COPYFIELD64(ifi_recvquota);
2955 COPYFIELD64(ifi_xmitquota);
91447636 2956 if_data64->ifi_unused1 = 0;
6d2010ae
A
2957 COPYFIELD64(ifi_mtu);
2958 COPYFIELD64(ifi_metric);
2959 COPYFIELD64(ifi_baudrate);
2960
2961 COPYFIELD64_ATOMIC(ifi_ipackets);
2962 COPYFIELD64_ATOMIC(ifi_ierrors);
2963 COPYFIELD64_ATOMIC(ifi_opackets);
2964 COPYFIELD64_ATOMIC(ifi_oerrors);
2965 COPYFIELD64_ATOMIC(ifi_collisions);
2966 COPYFIELD64_ATOMIC(ifi_ibytes);
2967 COPYFIELD64_ATOMIC(ifi_obytes);
2968 COPYFIELD64_ATOMIC(ifi_imcasts);
2969 COPYFIELD64_ATOMIC(ifi_omcasts);
2970 COPYFIELD64_ATOMIC(ifi_iqdrops);
2971 COPYFIELD64_ATOMIC(ifi_noproto);
2972
2973 /* Note these two fields are actually 32 bit, so doing COPYFIELD64_ATOMIC will
2974 * cause them to be misaligned
2975 */
2976 COPYFIELD64(ifi_recvtiming);
2977 COPYFIELD64(ifi_xmittiming);
2978
b0d623f7
A
2979 if_data64->ifi_lastchange.tv_sec = if_data_int->ifi_lastchange.tv_sec;
2980 if_data64->ifi_lastchange.tv_usec = if_data_int->ifi_lastchange.tv_usec;
6d2010ae 2981
91447636
A
2982#if IF_LASTCHANGEUPTIME
2983 if_data64->ifi_lastchange.tv_sec += boottime_sec();
2984#endif
2985
6d2010ae 2986#undef COPYFIELD64
9bccf70c 2987}
b0d623f7 2988
6d2010ae
A
2989__private_extern__ void
2990if_copy_traffic_class(struct ifnet *ifp,
2991 struct if_traffic_class *if_tc)
b0d623f7 2992{
6d2010ae
A
2993#define COPY_IF_TC_FIELD64_ATOMIC(fld) do { \
2994 atomic_get_64(if_tc->fld, \
2995 (u_int64_t *)(void *)(uintptr_t)&ifp->if_tc.fld); \
2996} while (0)
2997
2998 COPY_IF_TC_FIELD64_ATOMIC(ifi_ibkpackets);
2999 COPY_IF_TC_FIELD64_ATOMIC(ifi_ibkbytes);
3000 COPY_IF_TC_FIELD64_ATOMIC(ifi_obkpackets);
3001 COPY_IF_TC_FIELD64_ATOMIC(ifi_obkbytes);
3002 COPY_IF_TC_FIELD64_ATOMIC(ifi_ivipackets);
3003 COPY_IF_TC_FIELD64_ATOMIC(ifi_ivibytes);
3004 COPY_IF_TC_FIELD64_ATOMIC(ifi_ovipackets);
3005 COPY_IF_TC_FIELD64_ATOMIC(ifi_ovibytes);
3006 COPY_IF_TC_FIELD64_ATOMIC(ifi_ivopackets);
3007 COPY_IF_TC_FIELD64_ATOMIC(ifi_ivobytes);
3008 COPY_IF_TC_FIELD64_ATOMIC(ifi_ovopackets);
3009 COPY_IF_TC_FIELD64_ATOMIC(ifi_ovobytes);
3010
3011#undef COPY_IF_TC_FIELD64_ATOMIC
3012}
b0d623f7 3013
6d2010ae
A
3014
3015struct ifaddr *
3016ifa_remref(struct ifaddr *ifa, int locked)
3017{
3018 if (!locked)
3019 IFA_LOCK_SPIN(ifa);
3020 else
3021 IFA_LOCK_ASSERT_HELD(ifa);
3022
3023 if (ifa->ifa_refcnt == 0)
b0d623f7 3024 panic("%s: ifa %p negative refcnt\n", __func__, ifa);
6d2010ae
A
3025 else if (ifa->ifa_trace != NULL)
3026 (*ifa->ifa_trace)(ifa, FALSE);
3027 if (--ifa->ifa_refcnt == 0) {
3028 if (ifa->ifa_debug & IFD_ATTACHED)
b0d623f7
A
3029 panic("ifa %p attached to ifp is being freed\n", ifa);
3030 /*
3031 * Some interface addresses are allocated either statically
3032 * or carved out of a larger block; e.g. AppleTalk addresses.
3033 * Only free it if it was allocated via MALLOC or via the
3034 * corresponding per-address family allocator. Otherwise,
3035 * leave it alone.
3036 */
3037 if (ifa->ifa_debug & IFD_ALLOC) {
6d2010ae
A
3038 if (ifa->ifa_free == NULL) {
3039 IFA_UNLOCK(ifa);
b0d623f7 3040 FREE(ifa, M_IFADDR);
6d2010ae
A
3041 } else {
3042 /* Become a regular mutex */
3043 IFA_CONVERT_LOCK(ifa);
3044 /* callee will unlock */
b0d623f7 3045 (*ifa->ifa_free)(ifa);
6d2010ae
A
3046 }
3047 } else {
3048 IFA_UNLOCK(ifa);
b0d623f7 3049 }
6d2010ae 3050 ifa = NULL;
b0d623f7 3051 }
6d2010ae
A
3052
3053 if (!locked && ifa != NULL)
3054 IFA_UNLOCK(ifa);
3055
3056 return (ifa);
b0d623f7
A
3057}
3058
3059void
6d2010ae 3060ifa_addref(struct ifaddr *ifa, int locked)
b0d623f7 3061{
6d2010ae
A
3062 if (!locked)
3063 IFA_LOCK_SPIN(ifa);
3064 else
3065 IFA_LOCK_ASSERT_HELD(ifa);
b0d623f7 3066
6d2010ae
A
3067 if (++ifa->ifa_refcnt == 0) {
3068 panic("%s: ifa %p wraparound refcnt\n", __func__, ifa);
3069 /* NOTREACHED */
3070 } else if (ifa->ifa_trace != NULL) {
b0d623f7 3071 (*ifa->ifa_trace)(ifa, TRUE);
6d2010ae
A
3072 }
3073 if (!locked)
3074 IFA_UNLOCK(ifa);
3075}
3076
3077void
3078ifa_lock_init(struct ifaddr *ifa)
3079{
3080 lck_mtx_init(&ifa->ifa_lock, ifa_mtx_grp, ifa_mtx_attr);
3081}
3082
3083void
3084ifa_lock_destroy(struct ifaddr *ifa)
3085{
3086 IFA_LOCK_ASSERT_NOTHELD(ifa);
3087 lck_mtx_destroy(&ifa->ifa_lock, ifa_mtx_grp);
b0d623f7 3088}