1/*
2 * Copyright (c) 2000-2018 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
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
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
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
61 * $FreeBSD: src/sys/net/if.c,v 1.85.2.9 2001/07/24 19:10:17 brooks Exp $
62 */
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 */
69
70#include <kern/locks.h>
71
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>
84#include <sys/mcache.h>
85#include <sys/kauth.h>
86#include <sys/priv.h>
87#include <kern/zalloc.h>
88#include <mach/boolean.h>
89
90#include <machine/endian.h>
91
92#include <pexpert/pexpert.h>
93
94#include <net/if.h>
95#include <net/if_arp.h>
96#include <net/if_dl.h>
97#include <net/if_types.h>
98#include <net/if_var.h>
99#include <net/if_ppp.h>
100#include <net/ethernet.h>
101#include <net/network_agent.h>
102#include <net/radix.h>
103#include <net/route.h>
104#include <net/dlil.h>
105#include <net/nwk_wq.h>
106
107#include <sys/domain.h>
108#include <libkern/OSAtomic.h>
109
110#if INET || INET6
111#include <netinet/in.h>
112#include <netinet/in_var.h>
113#include <netinet/in_tclass.h>
114#include <netinet/ip_var.h>
115#include <netinet/ip.h>
116#include <netinet/ip6.h>
117#include <netinet/ip_var.h>
118#include <netinet/tcp.h>
119#include <netinet/tcp_var.h>
120#include <netinet/udp.h>
121#include <netinet/udp_var.h>
122#if INET6
123#include <netinet6/in6_var.h>
124#include <netinet6/in6_ifattach.h>
125#include <netinet6/ip6_var.h>
126#include <netinet6/nd6.h>
127#endif /* INET6 */
128#endif /* INET || INET6 */
129
130#if CONFIG_MACF_NET
131#include <security/mac_framework.h>
132#endif
133
134/*
135 * System initialization
136 */
137
138extern char *proc_name_address(void *);
139
140/* Lock group and attribute for ifaddr lock */
141lck_attr_t *ifa_mtx_attr;
142lck_grp_t *ifa_mtx_grp;
143static lck_grp_attr_t *ifa_mtx_grp_attr;
144
145static int ifioctl_ifreq(struct socket *, u_long, struct ifreq *,
146 struct proc *);
147static int ifioctl_ifconf(u_long, caddr_t);
148static int ifioctl_ifclone(u_long, caddr_t);
149static int ifioctl_iforder(u_long, caddr_t);
150static int ifioctl_ifdesc(struct ifnet *, u_long, caddr_t, struct proc *);
151static int ifioctl_linkparams(struct ifnet *, u_long, caddr_t, struct proc *);
152static int ifioctl_qstats(struct ifnet *, u_long, caddr_t);
153static int ifioctl_throttle(struct ifnet *, u_long, caddr_t, struct proc *);
154static int ifioctl_netsignature(struct ifnet *, u_long, caddr_t);
155static int ifconf(u_long cmd, user_addr_t ifrp, int * ret_space);
156__private_extern__ void link_rtrequest(int, struct rtentry *, struct sockaddr *);
157void if_rtproto_del(struct ifnet *ifp, int protocol);
158
159static int if_addmulti_common(struct ifnet *, const struct sockaddr *,
160 struct ifmultiaddr **, int);
161static int if_delmulti_common(struct ifmultiaddr *, struct ifnet *,
162 const struct sockaddr *, int);
163static struct ifnet *ifunit_common(const char *, boolean_t);
164
165static int if_rtmtu(struct radix_node *, void *);
166static void if_rtmtu_update(struct ifnet *);
167
168static int if_clone_list(int, int *, user_addr_t);
169
170MALLOC_DEFINE(M_IFADDR, "ifaddr", "interface address");
171
172struct ifnethead ifnet_head = TAILQ_HEAD_INITIALIZER(ifnet_head);
173
174/* ifnet_ordered_head and if_ordered_count are protected by the ifnet_head lock */
175struct ifnethead ifnet_ordered_head = TAILQ_HEAD_INITIALIZER(ifnet_ordered_head);
176static u_int32_t if_ordered_count = 0;
177
178static int if_cloners_count;
179LIST_HEAD(, if_clone) if_cloners = LIST_HEAD_INITIALIZER(if_cloners);
180
181static struct ifaddr *ifa_ifwithnet_common(const struct sockaddr *,
182 unsigned int);
183static void if_attach_ifa_common(struct ifnet *, struct ifaddr *, int);
184static void if_detach_ifa_common(struct ifnet *, struct ifaddr *, int);
185
186static void if_attach_ifma(struct ifnet *, struct ifmultiaddr *, int);
187static int if_detach_ifma(struct ifnet *, struct ifmultiaddr *, int);
188
189static struct ifmultiaddr *ifma_alloc(int);
190static void ifma_free(struct ifmultiaddr *);
191static void ifma_trace(struct ifmultiaddr *, int);
192
193#if DEBUG
194static unsigned int ifma_debug = 1; /* debugging (enabled) */
195#else
196static unsigned int ifma_debug; /* debugging (disabled) */
197#endif /* !DEBUG */
198static unsigned int ifma_size; /* size of zone element */
199static struct zone *ifma_zone; /* zone for ifmultiaddr */
200
201#define IFMA_TRACE_HIST_SIZE 32 /* size of trace history */
202
203/* For gdb */
204__private_extern__ unsigned int ifma_trace_hist_size = IFMA_TRACE_HIST_SIZE;
205
206struct ifmultiaddr_dbg {
207 struct ifmultiaddr ifma; /* ifmultiaddr */
208 u_int16_t ifma_refhold_cnt; /* # of ref */
209 u_int16_t ifma_refrele_cnt; /* # of rele */
210 /*
211 * Circular lists of IFA_ADDREF and IFA_REMREF callers.
212 */
213 ctrace_t ifma_refhold[IFMA_TRACE_HIST_SIZE];
214 ctrace_t ifma_refrele[IFMA_TRACE_HIST_SIZE];
215 /*
216 * Trash list linkage
217 */
218 TAILQ_ENTRY(ifmultiaddr_dbg) ifma_trash_link;
219};
220
221/* List of trash ifmultiaddr entries protected by ifma_trash_lock */
222static TAILQ_HEAD(, ifmultiaddr_dbg) ifma_trash_head;
223static decl_lck_mtx_data(, ifma_trash_lock);
224
225#define IFMA_ZONE_MAX 64 /* maximum elements in zone */
226#define IFMA_ZONE_NAME "ifmultiaddr" /* zone name */
227
228#if INET6
229/*
230 * XXX: declare here to avoid to include many inet6 related files..
231 * should be more generalized?
232 */
233extern void nd6_setmtu(struct ifnet *);
234extern lck_mtx_t *nd6_mutex;
235#endif
236
237SYSCTL_NODE(_net, PF_LINK, link, CTLFLAG_RW|CTLFLAG_LOCKED, 0, "Link layers");
238SYSCTL_NODE(_net_link, 0, generic, CTLFLAG_RW|CTLFLAG_LOCKED, 0,
239 "Generic link-management");
240
241SYSCTL_DECL(_net_link_generic_system);
242
243static uint32_t if_verbose = 0;
244SYSCTL_INT(_net_link_generic_system, OID_AUTO, if_verbose,
245 CTLFLAG_RW | CTLFLAG_LOCKED, &if_verbose, 0, "");
246
247boolean_t intcoproc_unrestricted;
248
249/* Eventhandler context for interface events */
250struct eventhandler_lists_ctxt ifnet_evhdlr_ctxt;
251
252void
253ifa_init(void)
254{
255 /* Setup lock group and attribute for ifaddr */
256 ifa_mtx_grp_attr = lck_grp_attr_alloc_init();
257 ifa_mtx_grp = lck_grp_alloc_init("ifaddr", ifa_mtx_grp_attr);
258 ifa_mtx_attr = lck_attr_alloc_init();
259
260 PE_parse_boot_argn("ifa_debug", &ifma_debug, sizeof (ifma_debug));
261
262 ifma_size = (ifma_debug == 0) ? sizeof (struct ifmultiaddr) :
263 sizeof (struct ifmultiaddr_dbg);
264
265 ifma_zone = zinit(ifma_size, IFMA_ZONE_MAX * ifma_size, 0,
266 IFMA_ZONE_NAME);
267 if (ifma_zone == NULL) {
268 panic("%s: failed allocating %s", __func__, IFMA_ZONE_NAME);
269 /* NOTREACHED */
270 }
271 zone_change(ifma_zone, Z_EXPAND, TRUE);
272 zone_change(ifma_zone, Z_CALLERACCT, FALSE);
273
274 lck_mtx_init(&ifma_trash_lock, ifa_mtx_grp, ifa_mtx_attr);
275 TAILQ_INIT(&ifma_trash_head);
276
277 PE_parse_boot_argn("intcoproc_unrestricted", &intcoproc_unrestricted,
278 sizeof (intcoproc_unrestricted));
279}
280
281/*
282 * Network interface utility routines.
283 *
284 * Routines with ifa_ifwith* names take sockaddr *'s as
285 * parameters.
286 */
287
288int if_index;
289struct ifaddr **ifnet_addrs;
290struct ifnet **ifindex2ifnet;
291
292__private_extern__ void
293if_attach_ifa(struct ifnet *ifp, struct ifaddr *ifa)
294{
295 if_attach_ifa_common(ifp, ifa, 0);
296}
297
298__private_extern__ void
299if_attach_link_ifa(struct ifnet *ifp, struct ifaddr *ifa)
300{
301 if_attach_ifa_common(ifp, ifa, 1);
302}
303
304static void
305if_attach_ifa_common(struct ifnet *ifp, struct ifaddr *ifa, int link)
306{
307 ifnet_lock_assert(ifp, IFNET_LCK_ASSERT_EXCLUSIVE);
308 IFA_LOCK_ASSERT_HELD(ifa);
309
310 if (ifa->ifa_ifp != ifp) {
311 panic("%s: Mismatch ifa_ifp=%p != ifp=%p", __func__,
312 ifa->ifa_ifp, ifp);
313 /* NOTREACHED */
314 } else if (ifa->ifa_debug & IFD_ATTACHED) {
315 panic("%s: Attempt to attach an already attached ifa=%p",
316 __func__, ifa);
317 /* NOTREACHED */
318 } else if (link && !(ifa->ifa_debug & IFD_LINK)) {
319 panic("%s: Unexpected non-link address ifa=%p", __func__, ifa);
320 /* NOTREACHED */
321 } else if (!link && (ifa->ifa_debug & IFD_LINK)) {
322 panic("%s: Unexpected link address ifa=%p", __func__, ifa);
323 /* NOTREACHED */
324 }
325 IFA_ADDREF_LOCKED(ifa);
326 ifa->ifa_debug |= IFD_ATTACHED;
327 if (link)
328 TAILQ_INSERT_HEAD(&ifp->if_addrhead, ifa, ifa_link);
329 else
330 TAILQ_INSERT_TAIL(&ifp->if_addrhead, ifa, ifa_link);
331
332 if (ifa->ifa_attached != NULL)
333 (*ifa->ifa_attached)(ifa);
334
335}
336
337__private_extern__ void
338if_detach_ifa(struct ifnet *ifp, struct ifaddr *ifa)
339{
340 if_detach_ifa_common(ifp, ifa, 0);
341}
342
343__private_extern__ void
344if_detach_link_ifa(struct ifnet *ifp, struct ifaddr *ifa)
345{
346 if_detach_ifa_common(ifp, ifa, 1);
347}
348
349static void
350if_detach_ifa_common(struct ifnet *ifp, struct ifaddr *ifa, int link)
351{
352 ifnet_lock_assert(ifp, IFNET_LCK_ASSERT_EXCLUSIVE);
353 IFA_LOCK_ASSERT_HELD(ifa);
354
355 if (link && !(ifa->ifa_debug & IFD_LINK)) {
356 panic("%s: Unexpected non-link address ifa=%p", __func__, ifa);
357 /* NOTREACHED */
358 } else if (link && ifa != TAILQ_FIRST(&ifp->if_addrhead)) {
359 panic("%s: Link address ifa=%p not first", __func__, ifa);
360 /* NOTREACHED */
361 } else if (!link && (ifa->ifa_debug & IFD_LINK)) {
362 panic("%s: Unexpected link address ifa=%p", __func__, ifa);
363 /* NOTREACHED */
364 } else if (!(ifa->ifa_debug & IFD_ATTACHED)) {
365 panic("%s: Attempt to detach an unattached address ifa=%p",
366 __func__, ifa);
367 /* NOTREACHED */
368 } else if (ifa->ifa_ifp != ifp) {
369 panic("%s: Mismatch ifa_ifp=%p, ifp=%p", __func__,
370 ifa->ifa_ifp, ifp);
371 /* NOTREACHED */
372 } else if (ifa->ifa_debug & IFD_DEBUG) {
373 struct ifaddr *ifa2;
374 TAILQ_FOREACH(ifa2, &ifp->if_addrhead, ifa_link) {
375 if (ifa2 == ifa)
376 break;
377 }
378 if (ifa2 != ifa) {
379 panic("%s: Attempt to detach a stray address ifa=%p",
380 __func__, ifa);
381 /* NOTREACHED */
382 }
383 }
384 TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link);
385 /* This must not be the last reference to the ifaddr */
386 if (IFA_REMREF_LOCKED(ifa) == NULL) {
387 panic("%s: unexpected (missing) refcnt ifa=%p", __func__, ifa);
388 /* NOTREACHED */
389 }
390 ifa->ifa_debug &= ~(IFD_ATTACHED | IFD_DETACHING);
391
392 if (ifa->ifa_detached != NULL)
393 (*ifa->ifa_detached)(ifa);
394
395}
396
397#define INITIAL_IF_INDEXLIM 8
398
399/*
400 * Function: if_next_index
401 * Purpose:
402 * Return the next available interface index.
403 * Grow the ifnet_addrs[] and ifindex2ifnet[] arrays to accomodate the
404 * added entry when necessary.
405 *
406 * Note:
407 * ifnet_addrs[] is indexed by (if_index - 1), whereas
408 * ifindex2ifnet[] is indexed by ifp->if_index. That requires us to
409 * always allocate one extra element to hold ifindex2ifnet[0], which
410 * is unused.
411 */
412int if_next_index(void);
413
414__private_extern__ int
415if_next_index(void)
416{
417 static int if_indexlim = 0;
418 int new_index;
419
420 new_index = ++if_index;
421 if (if_index > if_indexlim) {
422 unsigned n;
423 int new_if_indexlim;
424 caddr_t new_ifnet_addrs;
425 caddr_t new_ifindex2ifnet;
426 caddr_t old_ifnet_addrs;
427
428 old_ifnet_addrs = (caddr_t)ifnet_addrs;
429 if (ifnet_addrs == NULL) {
430 new_if_indexlim = INITIAL_IF_INDEXLIM;
431 } else {
432 new_if_indexlim = if_indexlim << 1;
433 }
434
435 /* allocate space for the larger arrays */
436 n = (2 * new_if_indexlim + 1) * sizeof(caddr_t);
437 new_ifnet_addrs = _MALLOC(n, M_IFADDR, M_WAITOK | M_ZERO);
438 if (new_ifnet_addrs == NULL) {
439 --if_index;
440 return (-1);
441 }
442
443 new_ifindex2ifnet = new_ifnet_addrs
444 + new_if_indexlim * sizeof(caddr_t);
445 if (ifnet_addrs != NULL) {
446 /* copy the existing data */
447 bcopy((caddr_t)ifnet_addrs, new_ifnet_addrs,
448 if_indexlim * sizeof(caddr_t));
449 bcopy((caddr_t)ifindex2ifnet,
450 new_ifindex2ifnet,
451 (if_indexlim + 1) * sizeof(caddr_t));
452 }
453
454 /* switch to the new tables and size */
455 ifnet_addrs = (struct ifaddr **)(void *)new_ifnet_addrs;
456 ifindex2ifnet = (struct ifnet **)(void *)new_ifindex2ifnet;
457 if_indexlim = new_if_indexlim;
458
459 /* release the old data */
460 if (old_ifnet_addrs != NULL) {
461 _FREE((caddr_t)old_ifnet_addrs, M_IFADDR);
462 }
463 }
464 return (new_index);
465}
466
467/*
468 * Create a clone network interface.
469 */
470static int
471if_clone_create(char *name, int len, void *params)
472{
473 struct if_clone *ifc;
474 char *dp;
475 int wildcard;
476 u_int32_t bytoff, bitoff;
477 u_int32_t unit;
478 int err;
479
480 ifc = if_clone_lookup(name, &unit);
481 if (ifc == NULL)
482 return (EINVAL);
483
484 if (ifunit(name) != NULL)
485 return (EEXIST);
486
487 bytoff = bitoff = 0;
488 wildcard = (unit == UINT32_MAX);
489 /*
490 * Find a free unit if none was given.
491 */
492 if (wildcard) {
493 while ((bytoff < ifc->ifc_bmlen) &&
494 (ifc->ifc_units[bytoff] == 0xff))
495 bytoff++;
496 if (bytoff >= ifc->ifc_bmlen)
497 return (ENOSPC);
498 while ((ifc->ifc_units[bytoff] & (1 << bitoff)) != 0)
499 bitoff++;
500 unit = (bytoff << 3) + bitoff;
501 }
502
503 if (unit > ifc->ifc_maxunit)
504 return (ENXIO);
505
506 lck_mtx_lock(&ifc->ifc_mutex);
507 err = (*ifc->ifc_create)(ifc, unit, params);
508 if (err != 0) {
509 lck_mtx_unlock(&ifc->ifc_mutex);
510 return (err);
511 }
512
513 if (!wildcard) {
514 bytoff = unit >> 3;
515 bitoff = unit - (bytoff << 3);
516 }
517
518 /*
519 * Allocate the unit in the bitmap.
520 */
521 KASSERT((ifc->ifc_units[bytoff] & (1 << bitoff)) == 0,
522 ("%s: bit is already set", __func__));
523 ifc->ifc_units[bytoff] |= (1 << bitoff);
524
525 /* In the wildcard case, we need to update the name. */
526 if (wildcard) {
527 for (dp = name; *dp != '\0'; dp++);
528 if (snprintf(dp, len - (dp-name), "%d", unit) >
529 len - (dp-name) - 1) {
530 /*
531 * This can only be a programmer error and
532 * there's no straightforward way to recover if
533 * it happens.
534 */
535 panic("%s: interface name too long", __func__);
536 /* NOTREACHED */
537 }
538
539 }
540 lck_mtx_unlock(&ifc->ifc_mutex);
541
542 return (0);
543}
544
545/*
546 * Destroy a clone network interface.
547 */
548static int
549if_clone_destroy(const char *name)
550{
551 struct if_clone *ifc = NULL;
552 struct ifnet *ifp = NULL;
553 int bytoff, bitoff;
554 u_int32_t unit;
555 int error = 0;
556
557 ifc = if_clone_lookup(name, &unit);
558
559 if (ifc == NULL) {
560 error = EINVAL;
561 goto done;
562 }
563
564 if (unit < ifc->ifc_minifs) {
565 error = EINVAL;
566 goto done;
567 }
568
569 ifp = ifunit_ref(name);
570 if (ifp == NULL) {
571 error = ENXIO;
572 goto done;
573 }
574
575 if (ifc->ifc_destroy == NULL) {
576 error = EOPNOTSUPP;
577 goto done;
578 }
579
580 lck_mtx_lock(&ifc->ifc_mutex);
581 error = (*ifc->ifc_destroy)(ifp);
582
583 if (error) {
584 lck_mtx_unlock(&ifc->ifc_mutex);
585 goto done;
586 }
587
588 /* Compute offset in the bitmap and deallocate the unit. */
589 bytoff = unit >> 3;
590 bitoff = unit - (bytoff << 3);
591 KASSERT((ifc->ifc_units[bytoff] & (1 << bitoff)) != 0,
592 ("%s: bit is already cleared", __func__));
593 ifc->ifc_units[bytoff] &= ~(1 << bitoff);
594 lck_mtx_unlock(&ifc->ifc_mutex);
595
596done:
597 if (ifp != NULL)
598 ifnet_decr_iorefcnt(ifp);
599 return (error);
600}
601
602/*
603 * Look up a network interface cloner.
604 */
605
606__private_extern__ struct if_clone *
607if_clone_lookup(const char *name, u_int32_t *unitp)
608{
609 struct if_clone *ifc;
610 const char *cp;
611 u_int32_t i;
612
613 for (ifc = LIST_FIRST(&if_cloners); ifc != NULL; ) {
614 for (cp = name, i = 0; i < ifc->ifc_namelen; i++, cp++) {
615 if (ifc->ifc_name[i] != *cp)
616 goto next_ifc;
617 }
618 goto found_name;
619next_ifc:
620 ifc = LIST_NEXT(ifc, ifc_list);
621 }
622
623 /* No match. */
624 return ((struct if_clone *)NULL);
625
626found_name:
627 if (*cp == '\0') {
628 i = UINT32_MAX;
629 } else {
630 for (i = 0; *cp != '\0'; cp++) {
631 if (*cp < '0' || *cp > '9') {
632 /* Bogus unit number. */
633 return (NULL);
634 }
635 i = (i * 10) + (*cp - '0');
636 }
637 }
638
639 if (unitp != NULL)
640 *unitp = i;
641 return (ifc);
642}
643
644void *
645if_clone_softc_allocate(const struct if_clone *ifc)
646{
647 void *p_clone = NULL;
648
649 VERIFY(ifc != NULL);
650
651 p_clone = zalloc(ifc->ifc_zone);
652 if (p_clone != NULL)
653 bzero(p_clone, ifc->ifc_softc_size);
654
655 return (p_clone);
656}
657
658void
659if_clone_softc_deallocate(const struct if_clone *ifc, void *p_softc)
660{
661 VERIFY(ifc != NULL && p_softc != NULL);
662 bzero(p_softc, ifc->ifc_softc_size);
663 zfree(ifc->ifc_zone, p_softc);
664}
665
666/*
667 * Register a network interface cloner.
668 */
669int
670if_clone_attach(struct if_clone *ifc)
671{
672 int bytoff, bitoff;
673 int err;
674 int len, maxclone;
675 u_int32_t unit;
676
677 KASSERT(ifc->ifc_minifs - 1 <= ifc->ifc_maxunit,
678 ("%s: %s requested more units then allowed (%d > %d)",
679 __func__, ifc->ifc_name, ifc->ifc_minifs,
680 ifc->ifc_maxunit + 1));
681 /*
682 * Compute bitmap size and allocate it.
683 */
684 maxclone = ifc->ifc_maxunit + 1;
685 len = maxclone >> 3;
686 if ((len << 3) < maxclone)
687 len++;
688 ifc->ifc_units = _MALLOC(len, M_CLONE, M_WAITOK | M_ZERO);
689 if (ifc->ifc_units == NULL)
690 return (ENOBUFS);
691 ifc->ifc_bmlen = len;
692 lck_mtx_init(&ifc->ifc_mutex, ifnet_lock_group, ifnet_lock_attr);
693
694 if (ifc->ifc_softc_size != 0) {
695 ifc->ifc_zone = zinit(ifc->ifc_softc_size,
696 ifc->ifc_zone_max_elem * ifc->ifc_softc_size, 0, ifc->ifc_name);
697 if (ifc->ifc_zone == NULL) {
698 FREE(ifc->ifc_units, M_CLONE);
699 return (ENOBUFS);
700 }
701 zone_change(ifc->ifc_zone, Z_EXPAND, TRUE);
702 zone_change(ifc->ifc_zone, Z_CALLERACCT, FALSE);
703 }
704
705 LIST_INSERT_HEAD(&if_cloners, ifc, ifc_list);
706 if_cloners_count++;
707
708 for (unit = 0; unit < ifc->ifc_minifs; unit++) {
709 err = (*ifc->ifc_create)(ifc, unit, NULL);
710 KASSERT(err == 0,
711 ("%s: failed to create required interface %s%d",
712 __func__, ifc->ifc_name, unit));
713
714 /* Allocate the unit in the bitmap. */
715 bytoff = unit >> 3;
716 bitoff = unit - (bytoff << 3);
717 ifc->ifc_units[bytoff] |= (1 << bitoff);
718 }
719
720 return (0);
721}
722
723/*
724 * Unregister a network interface cloner.
725 */
726void
727if_clone_detach(struct if_clone *ifc)
728{
729 LIST_REMOVE(ifc, ifc_list);
730 FREE(ifc->ifc_units, M_CLONE);
731 if (ifc->ifc_softc_size != 0)
732 zdestroy(ifc->ifc_zone);
733
734 lck_mtx_destroy(&ifc->ifc_mutex, ifnet_lock_group);
735 if_cloners_count--;
736}
737
738/*
739 * Provide list of interface cloners to userspace.
740 */
741static int
742if_clone_list(int count, int *ret_total, user_addr_t dst)
743{
744 char outbuf[IFNAMSIZ];
745 struct if_clone *ifc;
746 int error = 0;
747
748 *ret_total = if_cloners_count;
749 if (dst == USER_ADDR_NULL) {
750 /* Just asking how many there are. */
751 return (0);
752 }
753
754 if (count < 0)
755 return (EINVAL);
756
757 count = (if_cloners_count < count) ? if_cloners_count : count;
758
759 for (ifc = LIST_FIRST(&if_cloners); ifc != NULL && count != 0;
760 ifc = LIST_NEXT(ifc, ifc_list), count--, dst += IFNAMSIZ) {
761 bzero(outbuf, sizeof(outbuf));
762 strlcpy(outbuf, ifc->ifc_name, IFNAMSIZ);
763 error = copyout(outbuf, dst, IFNAMSIZ);
764 if (error)
765 break;
766 }
767
768 return (error);
769}
770
771u_int32_t
772if_functional_type(struct ifnet *ifp, bool exclude_delegate)
773{
774 u_int32_t ret = IFRTYPE_FUNCTIONAL_UNKNOWN;
775 if (ifp != NULL) {
776 if (ifp->if_flags & IFF_LOOPBACK) {
777 ret = IFRTYPE_FUNCTIONAL_LOOPBACK;
778 } else if ((exclude_delegate &&
779 (ifp->if_subfamily == IFNET_SUBFAMILY_WIFI)) ||
780 (!exclude_delegate && IFNET_IS_WIFI(ifp))) {
781 if (ifp->if_eflags & IFEF_AWDL)
782 ret = IFRTYPE_FUNCTIONAL_WIFI_AWDL;
783 else
784 ret = IFRTYPE_FUNCTIONAL_WIFI_INFRA;
785 } else if ((exclude_delegate &&
786 (ifp->if_type == IFT_CELLULAR)) ||
787 (!exclude_delegate && IFNET_IS_CELLULAR(ifp))) {
788 ret = IFRTYPE_FUNCTIONAL_CELLULAR;
789 } else if (IFNET_IS_INTCOPROC(ifp)) {
790 ret = IFRTYPE_FUNCTIONAL_INTCOPROC;
791 } else if ((exclude_delegate &&
792 (ifp->if_family == IFNET_FAMILY_ETHERNET ||
793 ifp->if_family == IFNET_FAMILY_BOND ||
794 ifp->if_family == IFNET_FAMILY_VLAN ||
795 ifp->if_family == IFNET_FAMILY_FIREWIRE)) ||
796 (!exclude_delegate && IFNET_IS_WIRED(ifp))) {
797 ret = IFRTYPE_FUNCTIONAL_WIRED;
798 }
799 }
800
801 return (ret);
802}
803
804/*
805 * Similar to ifa_ifwithaddr, except that this is IPv4 specific
806 * and that it matches only the local (not broadcast) address.
807 */
808__private_extern__ struct in_ifaddr *
809ifa_foraddr(unsigned int addr)
810{
811 return (ifa_foraddr_scoped(addr, IFSCOPE_NONE));
812}
813
814/*
815 * Similar to ifa_foraddr, except with the added interface scope
816 * constraint (unless the caller passes in IFSCOPE_NONE in which
817 * case there is no scope restriction).
818 */
819__private_extern__ struct in_ifaddr *
820ifa_foraddr_scoped(unsigned int addr, unsigned int scope)
821{
822 struct in_ifaddr *ia = NULL;
823
824 lck_rw_lock_shared(in_ifaddr_rwlock);
825 TAILQ_FOREACH(ia, INADDR_HASH(addr), ia_hash) {
826 IFA_LOCK_SPIN(&ia->ia_ifa);
827 if (ia->ia_addr.sin_addr.s_addr == addr &&
828 (scope == IFSCOPE_NONE || ia->ia_ifp->if_index == scope)) {
829 IFA_ADDREF_LOCKED(&ia->ia_ifa); /* for caller */
830 IFA_UNLOCK(&ia->ia_ifa);
831 break;
832 }
833 IFA_UNLOCK(&ia->ia_ifa);
834 }
835 lck_rw_done(in_ifaddr_rwlock);
836 return (ia);
837}
838
839#if INET6
840/*
841 * Similar to ifa_foraddr, except that this for IPv6.
842 */
843__private_extern__ struct in6_ifaddr *
844ifa_foraddr6(struct in6_addr *addr6)
845{
846 return (ifa_foraddr6_scoped(addr6, IFSCOPE_NONE));
847}
848
849__private_extern__ struct in6_ifaddr *
850ifa_foraddr6_scoped(struct in6_addr *addr6, unsigned int scope)
851{
852 struct in6_ifaddr *ia = NULL;
853
854 lck_rw_lock_shared(&in6_ifaddr_rwlock);
855 for (ia = in6_ifaddrs; ia; ia = ia->ia_next) {
856 IFA_LOCK(&ia->ia_ifa);
857 if (IN6_ARE_ADDR_EQUAL(&ia->ia_addr.sin6_addr, addr6) &&
858 (scope == IFSCOPE_NONE || ia->ia_ifp->if_index == scope)) {
859 IFA_ADDREF_LOCKED(&ia->ia_ifa); /* for caller */
860 IFA_UNLOCK(&ia->ia_ifa);
861 break;
862 }
863 IFA_UNLOCK(&ia->ia_ifa);
864 }
865 lck_rw_done(&in6_ifaddr_rwlock);
866
867 return (ia);
868}
869#endif /* INET6 */
870
871/*
872 * Return the first (primary) address of a given family on an interface.
873 */
874__private_extern__ struct ifaddr *
875ifa_ifpgetprimary(struct ifnet *ifp, int family)
876{
877 struct ifaddr *ifa;
878
879 ifnet_lock_shared(ifp);
880 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
881 IFA_LOCK_SPIN(ifa);
882 if (ifa->ifa_addr->sa_family == family) {
883 IFA_ADDREF_LOCKED(ifa); /* for caller */
884 IFA_UNLOCK(ifa);
885 break;
886 }
887 IFA_UNLOCK(ifa);
888 }
889 ifnet_lock_done(ifp);
890
891 return (ifa);
892}
893
894static inline int
895ifa_equal(const struct sockaddr *sa1, const struct sockaddr *sa2)
896{
897
898 if (!sa1 || !sa2)
899 return 0;
900 if (sa1->sa_len != sa2->sa_len)
901 return 0;
902
903 return (bcmp(sa1, sa2, sa1->sa_len) == 0);
904}
905
906/*
907 * Locate an interface based on a complete address.
908 */
909struct ifaddr *
910ifa_ifwithaddr_locked(const struct sockaddr *addr)
911{
912 struct ifnet *ifp;
913 struct ifaddr *ifa;
914 struct ifaddr *result = NULL;
915
916 for (ifp = ifnet_head.tqh_first; ifp && !result;
917 ifp = ifp->if_link.tqe_next) {
918 ifnet_lock_shared(ifp);
919 for (ifa = ifp->if_addrhead.tqh_first; ifa;
920 ifa = ifa->ifa_link.tqe_next) {
921 IFA_LOCK_SPIN(ifa);
922 if (ifa->ifa_addr->sa_family != addr->sa_family) {
923 IFA_UNLOCK(ifa);
924 continue;
925 }
926 if (ifa_equal(addr, ifa->ifa_addr)) {
927 result = ifa;
928 IFA_ADDREF_LOCKED(ifa); /* for caller */
929 IFA_UNLOCK(ifa);
930 break;
931 }
932 if ((ifp->if_flags & IFF_BROADCAST) &&
933 ifa->ifa_broadaddr != NULL &&
934 /* IP6 doesn't have broadcast */
935 ifa->ifa_broadaddr->sa_len != 0 &&
936 ifa_equal(ifa->ifa_broadaddr, addr)) {
937 result = ifa;
938 IFA_ADDREF_LOCKED(ifa); /* for caller */
939 IFA_UNLOCK(ifa);
940 break;
941 }
942 IFA_UNLOCK(ifa);
943 }
944 ifnet_lock_done(ifp);
945 }
946
947 return (result);
948}
949
950struct ifaddr *
951ifa_ifwithaddr(const struct sockaddr *addr)
952{
953 struct ifaddr *result = NULL;
954
955 ifnet_head_lock_shared();
956
957 result = ifa_ifwithaddr_locked(addr);
958
959 ifnet_head_done();
960
961 return (result);
962}
963/*
964 * Locate the point to point interface with a given destination address.
965 */
966/*ARGSUSED*/
967struct ifaddr *
968ifa_ifwithdstaddr(const struct sockaddr *addr)
969{
970 struct ifnet *ifp;
971 struct ifaddr *ifa;
972 struct ifaddr *result = NULL;
973
974 ifnet_head_lock_shared();
975 for (ifp = ifnet_head.tqh_first; ifp && !result;
976 ifp = ifp->if_link.tqe_next) {
977 if ((ifp->if_flags & IFF_POINTOPOINT)) {
978 ifnet_lock_shared(ifp);
979 for (ifa = ifp->if_addrhead.tqh_first; ifa;
980 ifa = ifa->ifa_link.tqe_next) {
981 IFA_LOCK_SPIN(ifa);
982 if (ifa->ifa_addr->sa_family !=
983 addr->sa_family) {
984 IFA_UNLOCK(ifa);
985 continue;
986 }
987 if (ifa_equal(addr, ifa->ifa_dstaddr)) {
988 result = ifa;
989 IFA_ADDREF_LOCKED(ifa); /* for caller */
990 IFA_UNLOCK(ifa);
991 break;
992 }
993 IFA_UNLOCK(ifa);
994 }
995 ifnet_lock_done(ifp);
996 }
997 }
998 ifnet_head_done();
999 return (result);
1000}
1001
1002/*
1003 * Locate the source address of an interface based on a complete address.
1004 */
1005struct ifaddr *
1006ifa_ifwithaddr_scoped_locked(const struct sockaddr *addr, unsigned int ifscope)
1007{
1008 struct ifaddr *result = NULL;
1009 struct ifnet *ifp;
1010
1011 if (ifscope == IFSCOPE_NONE)
1012 return (ifa_ifwithaddr_locked(addr));
1013
1014 if (ifscope > (unsigned int)if_index) {
1015 return (NULL);
1016 }
1017
1018 ifp = ifindex2ifnet[ifscope];
1019 if (ifp != NULL) {
1020 struct ifaddr *ifa = NULL;
1021
1022 /*
1023 * This is suboptimal; there should be a better way
1024 * to search for a given address of an interface
1025 * for any given address family.
1026 */
1027 ifnet_lock_shared(ifp);
1028 for (ifa = ifp->if_addrhead.tqh_first; ifa != NULL;
1029 ifa = ifa->ifa_link.tqe_next) {
1030 IFA_LOCK_SPIN(ifa);
1031 if (ifa->ifa_addr->sa_family != addr->sa_family) {
1032 IFA_UNLOCK(ifa);
1033 continue;
1034 }
1035 if (ifa_equal(addr, ifa->ifa_addr)) {
1036 result = ifa;
1037 IFA_ADDREF_LOCKED(ifa); /* for caller */
1038 IFA_UNLOCK(ifa);
1039 break;
1040 }
1041 if ((ifp->if_flags & IFF_BROADCAST) &&
1042 ifa->ifa_broadaddr != NULL &&
1043 /* IP6 doesn't have broadcast */
1044 ifa->ifa_broadaddr->sa_len != 0 &&
1045 ifa_equal(ifa->ifa_broadaddr, addr)) {
1046 result = ifa;
1047 IFA_ADDREF_LOCKED(ifa); /* for caller */
1048 IFA_UNLOCK(ifa);
1049 break;
1050 }
1051 IFA_UNLOCK(ifa);
1052 }
1053 ifnet_lock_done(ifp);
1054 }
1055
1056 return (result);
1057}
1058
1059struct ifaddr *
1060ifa_ifwithaddr_scoped(const struct sockaddr *addr, unsigned int ifscope)
1061{
1062 struct ifaddr *result = NULL;
1063
1064 ifnet_head_lock_shared();
1065
1066 result = ifa_ifwithaddr_scoped_locked(addr, ifscope);
1067
1068 ifnet_head_done();
1069
1070 return (result);
1071}
1072
1073struct ifaddr *
1074ifa_ifwithnet(const struct sockaddr *addr)
1075{
1076 return (ifa_ifwithnet_common(addr, IFSCOPE_NONE));
1077}
1078
1079struct ifaddr *
1080ifa_ifwithnet_scoped(const struct sockaddr *addr, unsigned int ifscope)
1081{
1082 return (ifa_ifwithnet_common(addr, ifscope));
1083}
1084
1085/*
1086 * Find an interface on a specific network. If many, choice
1087 * is most specific found.
1088 */
1089static struct ifaddr *
1090ifa_ifwithnet_common(const struct sockaddr *addr, unsigned int ifscope)
1091{
1092 struct ifnet *ifp;
1093 struct ifaddr *ifa = NULL;
1094 struct ifaddr *ifa_maybe = NULL;
1095 u_int af = addr->sa_family;
1096 const char *addr_data = addr->sa_data, *cplim;
1097
1098#if INET6
1099 if (af != AF_INET && af != AF_INET6)
1100#else
1101 if (af != AF_INET)
1102#endif /* !INET6 */
1103 ifscope = IFSCOPE_NONE;
1104
1105 ifnet_head_lock_shared();
1106 /*
1107 * AF_LINK addresses can be looked up directly by their index number,
1108 * so do that if we can.
1109 */
1110 if (af == AF_LINK) {
1111 const struct sockaddr_dl *sdl =
1112 (const struct sockaddr_dl *)(uintptr_t)(size_t)addr;
1113 if (sdl->sdl_index && sdl->sdl_index <= if_index) {
1114 ifa = ifnet_addrs[sdl->sdl_index - 1];
1115 if (ifa != NULL)
1116 IFA_ADDREF(ifa);
1117
1118 ifnet_head_done();
1119 return (ifa);
1120 }
1121 }
1122
1123 /*
1124 * Scan though each interface, looking for ones that have
1125 * addresses in this address family.
1126 */
1127 for (ifp = ifnet_head.tqh_first; ifp; ifp = ifp->if_link.tqe_next) {
1128 ifnet_lock_shared(ifp);
1129 for (ifa = ifp->if_addrhead.tqh_first; ifa;
1130 ifa = ifa->ifa_link.tqe_next) {
1131 const char *cp, *cp2, *cp3;
1132
1133 IFA_LOCK(ifa);
1134 if (ifa->ifa_addr == NULL ||
1135 ifa->ifa_addr->sa_family != af) {
1136next:
1137 IFA_UNLOCK(ifa);
1138 continue;
1139 }
1140 /*
1141 * If we're looking up with a scope,
1142 * find using a matching interface.
1143 */
1144 if (ifscope != IFSCOPE_NONE &&
1145 ifp->if_index != ifscope) {
1146 IFA_UNLOCK(ifa);
1147 continue;
1148 }
1149
1150 /*
1151 * Scan all the bits in the ifa's address.
1152 * If a bit dissagrees with what we are
1153 * looking for, mask it with the netmask
1154 * to see if it really matters.
1155 * (A byte at a time)
1156 */
1157 if (ifa->ifa_netmask == 0) {
1158 IFA_UNLOCK(ifa);
1159 continue;
1160 }
1161 cp = addr_data;
1162 cp2 = ifa->ifa_addr->sa_data;
1163 cp3 = ifa->ifa_netmask->sa_data;
1164 cplim = ifa->ifa_netmask->sa_len +
1165 (char *)ifa->ifa_netmask;
1166 while (cp3 < cplim)
1167 if ((*cp++ ^ *cp2++) & *cp3++)
1168 goto next; /* next address! */
1169 /*
1170 * If the netmask of what we just found
1171 * is more specific than what we had before
1172 * (if we had one) then remember the new one
1173 * before continuing to search
1174 * for an even better one.
1175 */
1176 if (ifa_maybe == NULL ||
1177 rn_refines((caddr_t)ifa->ifa_netmask,
1178 (caddr_t)ifa_maybe->ifa_netmask)) {
1179 IFA_ADDREF_LOCKED(ifa); /* ifa_maybe */
1180 IFA_UNLOCK(ifa);
1181 if (ifa_maybe != NULL)
1182 IFA_REMREF(ifa_maybe);
1183 ifa_maybe = ifa;
1184 } else {
1185 IFA_UNLOCK(ifa);
1186 }
1187 IFA_LOCK_ASSERT_NOTHELD(ifa);
1188 }
1189 ifnet_lock_done(ifp);
1190
1191 if (ifa != NULL)
1192 break;
1193 }
1194 ifnet_head_done();
1195
1196 if (ifa == NULL)
1197 ifa = ifa_maybe;
1198 else if (ifa_maybe != NULL)
1199 IFA_REMREF(ifa_maybe);
1200
1201 return (ifa);
1202}
1203
1204/*
1205 * Find an interface address specific to an interface best matching
1206 * a given address applying same source address selection rules
1207 * as done in the kernel for implicit source address binding
1208 */
1209struct ifaddr *
1210ifaof_ifpforaddr_select(const struct sockaddr *addr, struct ifnet *ifp)
1211{
1212 u_int af = addr->sa_family;
1213
1214 if (af == AF_INET6)
1215 return (in6_selectsrc_core_ifa(__DECONST(struct sockaddr_in6 *, addr), ifp, 0));
1216
1217 return (ifaof_ifpforaddr(addr, ifp));
1218}
1219
1220/*
1221 * Find an interface address specific to an interface best matching
1222 * a given address without regards to source address selection.
1223 *
1224 * This is appropriate for use-cases where we just want to update/init
1225 * some data structure like routing table entries.
1226 */
1227struct ifaddr *
1228ifaof_ifpforaddr(const struct sockaddr *addr, struct ifnet *ifp)
1229{
1230 struct ifaddr *ifa = NULL;
1231 const char *cp, *cp2, *cp3;
1232 char *cplim;
1233 struct ifaddr *ifa_maybe = NULL;
1234 struct ifaddr *better_ifa_maybe = NULL;
1235 u_int af = addr->sa_family;
1236
1237 if (af >= AF_MAX)
1238 return (NULL);
1239
1240 ifnet_lock_shared(ifp);
1241 for (ifa = ifp->if_addrhead.tqh_first; ifa;
1242 ifa = ifa->ifa_link.tqe_next) {
1243 IFA_LOCK(ifa);
1244 if (ifa->ifa_addr->sa_family != af) {
1245 IFA_UNLOCK(ifa);
1246 continue;
1247 }
1248 if (ifa_maybe == NULL) {
1249 IFA_ADDREF_LOCKED(ifa); /* for ifa_maybe */
1250 ifa_maybe = ifa;
1251 }
1252 if (ifa->ifa_netmask == 0) {
1253 if (ifa_equal(addr, ifa->ifa_addr) ||
1254 ifa_equal(addr, ifa->ifa_dstaddr)) {
1255 IFA_ADDREF_LOCKED(ifa); /* for caller */
1256 IFA_UNLOCK(ifa);
1257 break;
1258 }
1259 IFA_UNLOCK(ifa);
1260 continue;
1261 }
1262 if (ifp->if_flags & IFF_POINTOPOINT) {
1263 if (ifa_equal(addr, ifa->ifa_dstaddr)) {
1264 IFA_ADDREF_LOCKED(ifa); /* for caller */
1265 IFA_UNLOCK(ifa);
1266 break;
1267 }
1268 } else {
1269 if (ifa_equal(addr, ifa->ifa_addr)) {
1270 /* exact match */
1271 IFA_ADDREF_LOCKED(ifa); /* for caller */
1272 IFA_UNLOCK(ifa);
1273 break;
1274 }
1275 cp = addr->sa_data;
1276 cp2 = ifa->ifa_addr->sa_data;
1277 cp3 = ifa->ifa_netmask->sa_data;
1278 cplim = ifa->ifa_netmask->sa_len +
1279 (char *)ifa->ifa_netmask;
1280 for (; cp3 < cplim; cp3++)
1281 if ((*cp++ ^ *cp2++) & *cp3)
1282 break;
1283 if (cp3 == cplim) {
1284 /* subnet match */
1285 if (better_ifa_maybe == NULL) {
1286 /* for better_ifa_maybe */
1287 IFA_ADDREF_LOCKED(ifa);
1288 better_ifa_maybe = ifa;
1289 }
1290 }
1291 }
1292 IFA_UNLOCK(ifa);
1293 }
1294
1295 if (ifa == NULL) {
1296 if (better_ifa_maybe != NULL) {
1297 ifa = better_ifa_maybe;
1298 better_ifa_maybe = NULL;
1299 } else {
1300 ifa = ifa_maybe;
1301 ifa_maybe = NULL;
1302 }
1303 }
1304
1305 ifnet_lock_done(ifp);
1306
1307 if (better_ifa_maybe != NULL)
1308 IFA_REMREF(better_ifa_maybe);
1309 if (ifa_maybe != NULL)
1310 IFA_REMREF(ifa_maybe);
1311
1312 return (ifa);
1313}
1314
1315#include <net/route.h>
1316
1317/*
1318 * Default action when installing a route with a Link Level gateway.
1319 * Lookup an appropriate real ifa to point to.
1320 * This should be moved to /sys/net/link.c eventually.
1321 */
1322void
1323link_rtrequest(int cmd, struct rtentry *rt, struct sockaddr *sa)
1324{
1325 struct ifaddr *ifa;
1326 struct sockaddr *dst;
1327 struct ifnet *ifp;
1328 void (*ifa_rtrequest)(int, struct rtentry *, struct sockaddr *);
1329
1330 LCK_MTX_ASSERT(rnh_lock, LCK_MTX_ASSERT_OWNED);
1331 RT_LOCK_ASSERT_HELD(rt);
1332
1333 if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) ||
1334 ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0))
1335 return;
1336
1337 /* Become a regular mutex, just in case */
1338 RT_CONVERT_LOCK(rt);
1339
1340 ifa = ifaof_ifpforaddr(dst, ifp);
1341 if (ifa) {
1342 rtsetifa(rt, ifa);
1343 IFA_LOCK_SPIN(ifa);
1344 ifa_rtrequest = ifa->ifa_rtrequest;
1345 IFA_UNLOCK(ifa);
1346 if (ifa_rtrequest != NULL && ifa_rtrequest != link_rtrequest)
1347 ifa_rtrequest(cmd, rt, sa);
1348 IFA_REMREF(ifa);
1349 }
1350}
1351
1352/*
1353 * if_updown will set the interface up or down. It will
1354 * prevent other up/down events from occurring until this
1355 * up/down event has completed.
1356 *
1357 * Caller must lock ifnet. This function will drop the
1358 * lock. This allows ifnet_set_flags to set the rest of
1359 * the flags after we change the up/down state without
1360 * dropping the interface lock between setting the
1361 * up/down state and updating the rest of the flags.
1362 */
1363__private_extern__ void
1364if_updown( struct ifnet *ifp, int up)
1365{
1366 int i;
1367 struct ifaddr **ifa;
1368 struct timespec tv;
1369 struct ifclassq *ifq = &ifp->if_snd;
1370
1371 /* Wait until no one else is changing the up/down state */
1372 while ((ifp->if_eflags & IFEF_UPDOWNCHANGE) != 0) {
1373 tv.tv_sec = 0;
1374 tv.tv_nsec = NSEC_PER_SEC / 10;
1375 ifnet_lock_done(ifp);
1376 msleep(&ifp->if_eflags, NULL, 0, "if_updown", &tv);
1377 ifnet_lock_exclusive(ifp);
1378 }
1379
1380 /* Verify that the interface isn't already in the right state */
1381 if ((!up && (ifp->if_flags & IFF_UP) == 0) ||
1382 (up && (ifp->if_flags & IFF_UP) == IFF_UP)) {
1383 return;
1384 }
1385
1386 /* Indicate that the up/down state is changing */
1387 ifp->if_eflags |= IFEF_UPDOWNCHANGE;
1388
1389 /* Mark interface up or down */
1390 if (up) {
1391 ifp->if_flags |= IFF_UP;
1392 } else {
1393 ifp->if_flags &= ~IFF_UP;
1394 }
1395
1396 ifnet_touch_lastchange(ifp);
1397 ifnet_touch_lastupdown(ifp);
1398
1399 /* Drop the lock to notify addresses and route */
1400 ifnet_lock_done(ifp);
1401
1402 IFCQ_LOCK(ifq);
1403 if_qflush(ifp, 1);
1404
1405 /* Inform all transmit queues about the new link state */
1406 ifnet_update_sndq(ifq, up ? CLASSQ_EV_LINK_UP : CLASSQ_EV_LINK_DOWN);
1407 IFCQ_UNLOCK(ifq);
1408
1409 if (ifnet_get_address_list(ifp, &ifa) == 0) {
1410 for (i = 0; ifa[i] != 0; i++) {
1411 pfctlinput(up ? PRC_IFUP : PRC_IFDOWN, ifa[i]->ifa_addr);
1412 }
1413 ifnet_free_address_list(ifa);
1414 }
1415 rt_ifmsg(ifp);
1416
1417 /* Aquire the lock to clear the changing flag */
1418 ifnet_lock_exclusive(ifp);
1419 ifp->if_eflags &= ~IFEF_UPDOWNCHANGE;
1420 wakeup(&ifp->if_eflags);
1421}
1422
1423/*
1424 * Mark an interface down and notify protocols of
1425 * the transition.
1426 */
1427void
1428if_down(
1429 struct ifnet *ifp)
1430{
1431 ifnet_lock_exclusive(ifp);
1432 if_updown(ifp, 0);
1433 ifnet_lock_done(ifp);
1434}
1435
1436/*
1437 * Mark an interface up and notify protocols of
1438 * the transition.
1439 */
1440void
1441if_up(
1442 struct ifnet *ifp)
1443{
1444 ifnet_lock_exclusive(ifp);
1445 if_updown(ifp, 1);
1446 ifnet_lock_done(ifp);
1447}
1448
1449/*
1450 * Flush an interface queue.
1451 */
1452void
1453if_qflush(struct ifnet *ifp, int ifq_locked)
1454{
1455 struct ifclassq *ifq = &ifp->if_snd;
1456
1457 if (!ifq_locked)
1458 IFCQ_LOCK(ifq);
1459
1460 if (IFCQ_IS_ENABLED(ifq))
1461 IFCQ_PURGE(ifq);
1462
1463 VERIFY(IFCQ_IS_EMPTY(ifq));
1464
1465 if (!ifq_locked)
1466 IFCQ_UNLOCK(ifq);
1467}
1468
1469void
1470if_qflush_sc(struct ifnet *ifp, mbuf_svc_class_t sc, u_int32_t flow,
1471 u_int32_t *packets, u_int32_t *bytes, int ifq_locked)
1472{
1473 struct ifclassq *ifq = &ifp->if_snd;
1474 u_int32_t cnt = 0, len = 0;
1475 u_int32_t a_cnt = 0, a_len = 0;
1476
1477 VERIFY(sc == MBUF_SC_UNSPEC || MBUF_VALID_SC(sc));
1478 VERIFY(flow != 0);
1479
1480 if (!ifq_locked)
1481 IFCQ_LOCK(ifq);
1482
1483 if (IFCQ_IS_ENABLED(ifq))
1484 IFCQ_PURGE_SC(ifq, sc, flow, cnt, len);
1485
1486 if (!ifq_locked)
1487 IFCQ_UNLOCK(ifq);
1488
1489 if (packets != NULL)
1490 *packets = cnt + a_cnt;
1491 if (bytes != NULL)
1492 *bytes = len + a_len;
1493}
1494
1495/*
1496 * Extracts interface unit number and name from string, returns -1 upon failure.
1497 * Upon success, returns extracted unit number, and interface name in dst.
1498 */
1499int
1500ifunit_extract(const char *src, char *dst, size_t dstlen, int *unit)
1501{
1502 const char *cp;
1503 size_t len, m;
1504 char c;
1505 int u;
1506
1507 if (src == NULL || dst == NULL || dstlen == 0 || unit == NULL)
1508 return (-1);
1509
1510 len = strlen(src);
1511 if (len < 2 || len > dstlen)
1512 return (-1);
1513 cp = src + len - 1;
1514 c = *cp;
1515 if (c < '0' || c > '9')
1516 return (-1); /* trailing garbage */
1517 u = 0;
1518 m = 1;
1519 do {
1520 if (cp == src)
1521 return (-1); /* no interface name */
1522 u += (c - '0') * m;
1523 if (u > 1000000)
1524 return (-1); /* number is unreasonable */
1525 m *= 10;
1526 c = *--cp;
1527 } while (c >= '0' && c <= '9');
1528 len = cp - src + 1;
1529 bcopy(src, dst, len);
1530 dst[len] = '\0';
1531 *unit = u;
1532
1533 return (0);
1534}
1535
1536/*
1537 * Map interface name to
1538 * interface structure pointer.
1539 */
1540static struct ifnet *
1541ifunit_common(const char *name, boolean_t hold)
1542{
1543 char namebuf[IFNAMSIZ + 1];
1544 struct ifnet *ifp;
1545 int unit;
1546
1547 if (ifunit_extract(name, namebuf, sizeof (namebuf), &unit) < 0)
1548 return (NULL);
1549
1550 /* for safety, since we use strcmp() below */
1551 namebuf[sizeof (namebuf) - 1] = '\0';
1552
1553 /*
1554 * Now search all the interfaces for this name/number
1555 */
1556 ifnet_head_lock_shared();
1557 TAILQ_FOREACH(ifp, &ifnet_head, if_link) {
1558 /*
1559 * Use strcmp() rather than strncmp() here,
1560 * since we want to match the entire string.
1561 */
1562 if (strcmp(ifp->if_name, namebuf))
1563 continue;
1564 if (unit == ifp->if_unit)
1565 break;
1566 }
1567
1568 /* if called from ifunit_ref() and ifnet is not attached, bail */
1569 if (hold && ifp != NULL && !ifnet_is_attached(ifp, 1))
1570 ifp = NULL;
1571
1572 ifnet_head_done();
1573 return (ifp);
1574}
1575
1576struct ifnet *
1577ifunit(const char *name)
1578{
1579 return (ifunit_common(name, FALSE));
1580}
1581
1582/*
1583 * Similar to ifunit(), except that we hold an I/O reference count on an
1584 * attached interface, which must later be released via ifnet_decr_iorefcnt().
1585 * Will return NULL unless interface exists and is fully attached.
1586 */
1587struct ifnet *
1588ifunit_ref(const char *name)
1589{
1590 return (ifunit_common(name, TRUE));
1591}
1592
1593/*
1594 * Map interface name in a sockaddr_dl to
1595 * interface structure pointer.
1596 */
1597struct ifnet *
1598if_withname(struct sockaddr *sa)
1599{
1600 char ifname[IFNAMSIZ+1];
1601 struct sockaddr_dl *sdl = (struct sockaddr_dl *)(void *)sa;
1602
1603 if ((sa->sa_family != AF_LINK) || (sdl->sdl_nlen == 0) ||
1604 (sdl->sdl_nlen > IFNAMSIZ))
1605 return (NULL);
1606
1607 /*
1608 * ifunit wants a null-terminated name. It may not be null-terminated
1609 * in the sockaddr. We don't want to change the caller's sockaddr,
1610 * and there might not be room to put the trailing null anyway, so we
1611 * make a local copy that we know we can null terminate safely.
1612 */
1613
1614 bcopy(sdl->sdl_data, ifname, sdl->sdl_nlen);
1615 ifname[sdl->sdl_nlen] = '\0';
1616 return (ifunit(ifname));
1617}
1618
1619static __attribute__((noinline)) int
1620ifioctl_ifconf(u_long cmd, caddr_t data)
1621{
1622 int error = 0;
1623
1624 switch (cmd) {
1625 case OSIOCGIFCONF32: /* struct ifconf32 */
1626 case SIOCGIFCONF32: { /* struct ifconf32 */
1627 struct ifconf32 ifc;
1628 bcopy(data, &ifc, sizeof (ifc));
1629 error = ifconf(cmd, CAST_USER_ADDR_T(ifc.ifc_req),
1630 &ifc.ifc_len);
1631 bcopy(&ifc, data, sizeof (ifc));
1632 break;
1633 }
1634
1635 case SIOCGIFCONF64: /* struct ifconf64 */
1636 case OSIOCGIFCONF64: { /* struct ifconf64 */
1637 struct ifconf64 ifc;
1638 bcopy(data, &ifc, sizeof (ifc));
1639 error = ifconf(cmd, ifc.ifc_req, &ifc.ifc_len);
1640 bcopy(&ifc, data, sizeof (ifc));
1641 break;
1642 }
1643
1644 default:
1645 VERIFY(0);
1646 /* NOTREACHED */
1647 }
1648
1649 return (error);
1650}
1651
1652static __attribute__((noinline)) int
1653ifioctl_ifclone(u_long cmd, caddr_t data)
1654{
1655 int error = 0;
1656
1657 switch (cmd) {
1658 case SIOCIFGCLONERS32: { /* struct if_clonereq32 */
1659 struct if_clonereq32 ifcr;
1660 bcopy(data, &ifcr, sizeof (ifcr));
1661 error = if_clone_list(ifcr.ifcr_count, &ifcr.ifcr_total,
1662 CAST_USER_ADDR_T(ifcr.ifcru_buffer));
1663 bcopy(&ifcr, data, sizeof (ifcr));
1664 break;
1665 }
1666
1667 case SIOCIFGCLONERS64: { /* struct if_clonereq64 */
1668 struct if_clonereq64 ifcr;
1669 bcopy(data, &ifcr, sizeof (ifcr));
1670 error = if_clone_list(ifcr.ifcr_count, &ifcr.ifcr_total,
1671 ifcr.ifcru_buffer);
1672 bcopy(&ifcr, data, sizeof (ifcr));
1673 break;
1674 }
1675
1676 default:
1677 VERIFY(0);
1678 /* NOTREACHED */
1679 }
1680
1681 return (error);
1682}
1683
1684static __attribute__((noinline)) int
1685ifioctl_ifdesc(struct ifnet *ifp, u_long cmd, caddr_t data, struct proc *p)
1686{
1687 struct if_descreq *ifdr = (struct if_descreq *)(void *)data;
1688 u_int32_t ifdr_len;
1689 int error = 0;
1690
1691 VERIFY(ifp != NULL);
1692
1693 switch (cmd) {
1694 case SIOCSIFDESC: { /* struct if_descreq */
1695 if ((error = proc_suser(p)) != 0)
1696 break;
1697
1698 ifnet_lock_exclusive(ifp);
1699 bcopy(&ifdr->ifdr_len, &ifdr_len, sizeof (ifdr_len));
1700 if (ifdr_len > sizeof (ifdr->ifdr_desc) ||
1701 ifdr_len > ifp->if_desc.ifd_maxlen) {
1702 error = EINVAL;
1703 ifnet_lock_done(ifp);
1704 break;
1705 }
1706
1707 bzero(ifp->if_desc.ifd_desc, ifp->if_desc.ifd_maxlen);
1708 if ((ifp->if_desc.ifd_len = ifdr_len) > 0) {
1709 bcopy(ifdr->ifdr_desc, ifp->if_desc.ifd_desc,
1710 MIN(ifdr_len, ifp->if_desc.ifd_maxlen));
1711 }
1712 ifnet_lock_done(ifp);
1713 break;
1714 }
1715
1716 case SIOCGIFDESC: { /* struct if_descreq */
1717 ifnet_lock_shared(ifp);
1718 ifdr_len = MIN(ifp->if_desc.ifd_len, sizeof (ifdr->ifdr_desc));
1719 bcopy(&ifdr_len, &ifdr->ifdr_len, sizeof (ifdr_len));
1720 bzero(&ifdr->ifdr_desc, sizeof (ifdr->ifdr_desc));
1721 if (ifdr_len > 0) {
1722 bcopy(ifp->if_desc.ifd_desc, ifdr->ifdr_desc, ifdr_len);
1723 }
1724 ifnet_lock_done(ifp);
1725 break;
1726 }
1727
1728 default:
1729 VERIFY(0);
1730 /* NOTREACHED */
1731 }
1732
1733 return (error);
1734}
1735
1736static __attribute__((noinline)) int
1737ifioctl_linkparams(struct ifnet *ifp, u_long cmd, caddr_t data, struct proc *p)
1738{
1739 struct if_linkparamsreq *iflpr =
1740 (struct if_linkparamsreq *)(void *)data;
1741 struct ifclassq *ifq;
1742 int error = 0;
1743
1744 VERIFY(ifp != NULL);
1745 ifq = &ifp->if_snd;
1746
1747 switch (cmd) {
1748 case SIOCSIFLINKPARAMS: { /* struct if_linkparamsreq */
1749 struct tb_profile tb = { 0, 0, 0 };
1750
1751 if ((error = proc_suser(p)) != 0)
1752 break;
1753
1754
1755 IFCQ_LOCK(ifq);
1756 if (!IFCQ_IS_READY(ifq)) {
1757 error = ENXIO;
1758 IFCQ_UNLOCK(ifq);
1759 break;
1760 }
1761 bcopy(&iflpr->iflpr_output_tbr_rate, &tb.rate,
1762 sizeof (tb.rate));
1763 bcopy(&iflpr->iflpr_output_tbr_percent, &tb.percent,
1764 sizeof (tb.percent));
1765 error = ifclassq_tbr_set(ifq, &tb, TRUE);
1766 IFCQ_UNLOCK(ifq);
1767 break;
1768 }
1769
1770 case SIOCGIFLINKPARAMS: { /* struct if_linkparamsreq */
1771 u_int32_t sched_type = PKTSCHEDT_NONE, flags = 0;
1772 u_int64_t tbr_bw = 0, tbr_pct = 0;
1773
1774 IFCQ_LOCK(ifq);
1775
1776 if (IFCQ_IS_ENABLED(ifq))
1777 sched_type = ifq->ifcq_type;
1778
1779 bcopy(&sched_type, &iflpr->iflpr_output_sched,
1780 sizeof (iflpr->iflpr_output_sched));
1781
1782 if (IFCQ_TBR_IS_ENABLED(ifq)) {
1783 tbr_bw = ifq->ifcq_tbr.tbr_rate_raw;
1784 tbr_pct = ifq->ifcq_tbr.tbr_percent;
1785 }
1786 bcopy(&tbr_bw, &iflpr->iflpr_output_tbr_rate,
1787 sizeof (iflpr->iflpr_output_tbr_rate));
1788 bcopy(&tbr_pct, &iflpr->iflpr_output_tbr_percent,
1789 sizeof (iflpr->iflpr_output_tbr_percent));
1790 IFCQ_UNLOCK(ifq);
1791
1792 if (ifp->if_output_sched_model ==
1793 IFNET_SCHED_MODEL_DRIVER_MANAGED)
1794 flags |= IFLPRF_DRVMANAGED;
1795 bcopy(&flags, &iflpr->iflpr_flags, sizeof (iflpr->iflpr_flags));
1796 bcopy(&ifp->if_output_bw, &iflpr->iflpr_output_bw,
1797 sizeof (iflpr->iflpr_output_bw));
1798 bcopy(&ifp->if_input_bw, &iflpr->iflpr_input_bw,
1799 sizeof (iflpr->iflpr_input_bw));
1800 bcopy(&ifp->if_output_lt, &iflpr->iflpr_output_lt,
1801 sizeof (iflpr->iflpr_output_lt));
1802 bcopy(&ifp->if_input_lt, &iflpr->iflpr_input_lt,
1803 sizeof (iflpr->iflpr_input_lt));
1804 break;
1805 }
1806
1807 default:
1808 VERIFY(0);
1809 /* NOTREACHED */
1810 }
1811
1812 return (error);
1813}
1814
1815static __attribute__((noinline)) int
1816ifioctl_qstats(struct ifnet *ifp, u_long cmd, caddr_t data)
1817{
1818 struct if_qstatsreq *ifqr = (struct if_qstatsreq *)(void *)data;
1819 u_int32_t ifqr_len, ifqr_slot;
1820 int error = 0;
1821
1822 VERIFY(ifp != NULL);
1823
1824 switch (cmd) {
1825 case SIOCGIFQUEUESTATS: { /* struct if_qstatsreq */
1826 bcopy(&ifqr->ifqr_slot, &ifqr_slot, sizeof (ifqr_slot));
1827 bcopy(&ifqr->ifqr_len, &ifqr_len, sizeof (ifqr_len));
1828 error = ifclassq_getqstats(&ifp->if_snd, ifqr_slot,
1829 ifqr->ifqr_buf, &ifqr_len);
1830 if (error != 0)
1831 ifqr_len = 0;
1832 bcopy(&ifqr_len, &ifqr->ifqr_len, sizeof (ifqr_len));
1833 break;
1834 }
1835
1836 default:
1837 VERIFY(0);
1838 /* NOTREACHED */
1839 }
1840
1841 return (error);
1842}
1843
1844static __attribute__((noinline)) int
1845ifioctl_throttle(struct ifnet *ifp, u_long cmd, caddr_t data, struct proc *p)
1846{
1847 struct if_throttlereq *ifthr = (struct if_throttlereq *)(void *)data;
1848 u_int32_t ifthr_level;
1849 int error = 0;
1850
1851 VERIFY(ifp != NULL);
1852
1853 switch (cmd) {
1854 case SIOCSIFTHROTTLE: { /* struct if_throttlereq */
1855 /*
1856 * XXX: Use priv_check_cred() instead of root check?
1857 */
1858 if ((error = proc_suser(p)) != 0)
1859 break;
1860
1861 bcopy(&ifthr->ifthr_level, &ifthr_level, sizeof (ifthr_level));
1862 error = ifnet_set_throttle(ifp, ifthr_level);
1863 if (error == EALREADY)
1864 error = 0;
1865 break;
1866 }
1867
1868 case SIOCGIFTHROTTLE: { /* struct if_throttlereq */
1869 if ((error = ifnet_get_throttle(ifp, &ifthr_level)) == 0) {
1870 bcopy(&ifthr_level, &ifthr->ifthr_level,
1871 sizeof (ifthr_level));
1872 }
1873 break;
1874 }
1875
1876 default:
1877 VERIFY(0);
1878 /* NOTREACHED */
1879 }
1880
1881 return (error);
1882}
1883
1884static int
1885ifioctl_getnetagents(struct ifnet *ifp, u_int32_t *count, user_addr_t uuid_p)
1886{
1887 int error = 0;
1888 u_int32_t index = 0;
1889 u_int32_t valid_netagent_count = 0;
1890 *count = 0;
1891
1892 ifnet_lock_assert(ifp, IFNET_LCK_ASSERT_SHARED);
1893
1894 if (ifp->if_agentids != NULL) {
1895 for (index = 0; index < ifp->if_agentcount; index++) {
1896 uuid_t *netagent_uuid = &(ifp->if_agentids[index]);
1897 if (!uuid_is_null(*netagent_uuid)) {
1898 if (uuid_p != USER_ADDR_NULL) {
1899 error = copyout(netagent_uuid,
1900 uuid_p + sizeof(uuid_t) * valid_netagent_count,
1901 sizeof(uuid_t));
1902 if (error != 0) {
1903 return (error);
1904 }
1905 }
1906 valid_netagent_count++;
1907 }
1908 }
1909 }
1910 *count = valid_netagent_count;
1911
1912 return (0);
1913}
1914
1915#define IF_MAXAGENTS 64
1916#define IF_AGENT_INCREMENT 8
1917static int
1918if_add_netagent_locked(struct ifnet *ifp, uuid_t new_agent_uuid)
1919{
1920 uuid_t *first_empty_slot = NULL;
1921 u_int32_t index = 0;
1922 bool already_added = FALSE;
1923
1924 if (ifp->if_agentids != NULL) {
1925 for (index = 0; index < ifp->if_agentcount; index++) {
1926 uuid_t *netagent_uuid = &(ifp->if_agentids[index]);
1927 if (uuid_compare(*netagent_uuid, new_agent_uuid) == 0) {
1928 /* Already present, ignore */
1929 already_added = TRUE;
1930 break;
1931 }
1932 if (first_empty_slot == NULL &&
1933 uuid_is_null(*netagent_uuid)) {
1934 first_empty_slot = netagent_uuid;
1935 }
1936 }
1937 }
1938 if (already_added) {
1939 /* Already added agent, don't return an error */
1940 return (0);
1941 }
1942 if (first_empty_slot == NULL) {
1943 if (ifp->if_agentcount >= IF_MAXAGENTS) {
1944 /* No room for another netagent UUID, bail */
1945 return (ENOMEM);
1946 } else {
1947 /* Calculate new array size */
1948 u_int32_t new_agent_count =
1949 MIN(ifp->if_agentcount + IF_AGENT_INCREMENT,
1950 IF_MAXAGENTS);
1951
1952 /* Reallocate array */
1953 uuid_t *new_agent_array = _REALLOC(ifp->if_agentids,
1954 sizeof(uuid_t) * new_agent_count, M_NETAGENT,
1955 M_WAITOK | M_ZERO);
1956 if (new_agent_array == NULL) {
1957 return (ENOMEM);
1958 }
1959
1960 /* Save new array */
1961 ifp->if_agentids = new_agent_array;
1962
1963 /* Set first empty slot */
1964 first_empty_slot =
1965 &(ifp->if_agentids[ifp->if_agentcount]);
1966
1967 /* Save new array length */
1968 ifp->if_agentcount = new_agent_count;
1969 }
1970 }
1971 uuid_copy(*first_empty_slot, new_agent_uuid);
1972 netagent_post_updated_interfaces(new_agent_uuid);
1973 return (0);
1974}
1975
1976int
1977if_add_netagent(struct ifnet *ifp, uuid_t new_agent_uuid)
1978{
1979 VERIFY(ifp != NULL);
1980
1981 ifnet_lock_exclusive(ifp);
1982
1983 int error = if_add_netagent_locked(ifp, new_agent_uuid);
1984
1985 ifnet_lock_done(ifp);
1986
1987 return (error);
1988}
1989
1990static int
1991if_delete_netagent_locked(struct ifnet *ifp, uuid_t remove_agent_uuid)
1992{
1993 u_int32_t index = 0;
1994 bool removed_agent_id = FALSE;
1995
1996 if (ifp->if_agentids != NULL) {
1997 for (index = 0; index < ifp->if_agentcount; index++) {
1998 uuid_t *netagent_uuid = &(ifp->if_agentids[index]);
1999 if (uuid_compare(*netagent_uuid,
2000 remove_agent_uuid) == 0) {
2001 uuid_clear(*netagent_uuid);
2002 removed_agent_id = TRUE;
2003 break;
2004 }
2005 }
2006 }
2007 if (removed_agent_id)
2008 netagent_post_updated_interfaces(remove_agent_uuid);
2009
2010 return (0);
2011}
2012
2013int
2014if_delete_netagent(struct ifnet *ifp, uuid_t remove_agent_uuid)
2015{
2016 VERIFY(ifp != NULL);
2017
2018 ifnet_lock_exclusive(ifp);
2019
2020 int error = if_delete_netagent_locked(ifp, remove_agent_uuid);
2021
2022 ifnet_lock_done(ifp);
2023
2024 return (error);
2025}
2026
2027boolean_t
2028if_check_netagent(struct ifnet *ifp, uuid_t find_agent_uuid)
2029{
2030 boolean_t found = FALSE;
2031
2032 if (!ifp || uuid_is_null(find_agent_uuid))
2033 return FALSE;
2034
2035 ifnet_lock_shared(ifp);
2036
2037 if (ifp->if_agentids != NULL) {
2038 for (uint32_t index = 0; index < ifp->if_agentcount; index++) {
2039 if (uuid_compare(ifp->if_agentids[index], find_agent_uuid) == 0) {
2040 found = TRUE;
2041 break;
2042 }
2043 }
2044 }
2045
2046 ifnet_lock_done(ifp);
2047
2048 return found;
2049}
2050
2051static __attribute__((noinline)) int
2052ifioctl_netagent(struct ifnet *ifp, u_long cmd, caddr_t data, struct proc *p)
2053{
2054 struct if_agentidreq *ifar = (struct if_agentidreq *)(void *)data;
2055 union {
2056 struct if_agentidsreq32 s32;
2057 struct if_agentidsreq64 s64;
2058 } u;
2059 int error = 0;
2060
2061 VERIFY(ifp != NULL);
2062
2063 /* Get an io ref count if the interface is attached */
2064 if (!ifnet_is_attached(ifp, 1)) {
2065 return (EOPNOTSUPP);
2066 }
2067
2068 if (cmd == SIOCAIFAGENTID ||
2069 cmd == SIOCDIFAGENTID) {
2070 ifnet_lock_exclusive(ifp);
2071 } else {
2072 ifnet_lock_shared(ifp);
2073 }
2074
2075 switch (cmd) {
2076 case SIOCAIFAGENTID: { /* struct if_agentidreq */
2077 // TODO: Use priv_check_cred() instead of root check
2078 if ((error = proc_suser(p)) != 0) {
2079 break;
2080 }
2081 error = if_add_netagent_locked(ifp, ifar->ifar_uuid);
2082 break;
2083 }
2084 case SIOCDIFAGENTID: { /* struct if_agentidreq */
2085 // TODO: Use priv_check_cred() instead of root check
2086 if ((error = proc_suser(p)) != 0) {
2087 break;
2088 }
2089 error = if_delete_netagent_locked(ifp, ifar->ifar_uuid);
2090 break;
2091 }
2092 case SIOCGIFAGENTIDS32: { /* struct if_agentidsreq32 */
2093 bcopy(data, &u.s32, sizeof(u.s32));
2094 error = ifioctl_getnetagents(ifp, &u.s32.ifar_count,
2095 u.s32.ifar_uuids);
2096 if (error == 0) {
2097 bcopy(&u.s32, data, sizeof(u.s32));
2098 }
2099 break;
2100 }
2101 case SIOCGIFAGENTIDS64: { /* struct if_agentidsreq64 */
2102 bcopy(data, &u.s64, sizeof(u.s64));
2103 error = ifioctl_getnetagents(ifp, &u.s64.ifar_count,
2104 u.s64.ifar_uuids);
2105 if (error == 0) {
2106 bcopy(&u.s64, data, sizeof(u.s64));
2107 }
2108 break;
2109 }
2110 default:
2111 VERIFY(0);
2112 /* NOTREACHED */
2113 }
2114
2115 ifnet_lock_done(ifp);
2116 ifnet_decr_iorefcnt(ifp);
2117
2118 return (error);
2119}
2120
2121void
2122ifnet_clear_netagent(uuid_t netagent_uuid)
2123{
2124 struct ifnet *ifp = NULL;
2125 u_int32_t index = 0;
2126
2127 ifnet_head_lock_shared();
2128
2129 TAILQ_FOREACH(ifp, &ifnet_head, if_link) {
2130 ifnet_lock_shared(ifp);
2131 if (ifp->if_agentids != NULL) {
2132 for (index = 0; index < ifp->if_agentcount; index++) {
2133 uuid_t *ifp_netagent_uuid = &(ifp->if_agentids[index]);
2134 if (uuid_compare(*ifp_netagent_uuid, netagent_uuid) == 0) {
2135 uuid_clear(*ifp_netagent_uuid);
2136 }
2137 }
2138 }
2139 ifnet_lock_done(ifp);
2140 }
2141
2142 ifnet_head_done();
2143}
2144
2145void
2146ifnet_increment_generation(ifnet_t interface)
2147{
2148 OSIncrementAtomic(&interface->if_generation);
2149}
2150
2151u_int32_t
2152ifnet_get_generation(ifnet_t interface)
2153{
2154 return (interface->if_generation);
2155}
2156
2157void
2158ifnet_remove_from_ordered_list(struct ifnet *ifp)
2159{
2160 ifnet_head_assert_exclusive();
2161
2162 // Remove from list
2163 TAILQ_REMOVE(&ifnet_ordered_head, ifp, if_ordered_link);
2164 ifp->if_ordered_link.tqe_next = NULL;
2165 ifp->if_ordered_link.tqe_prev = NULL;
2166
2167 // Update ordered count
2168 VERIFY(if_ordered_count > 0);
2169 if_ordered_count--;
2170}
2171
2172static int
2173ifnet_reset_order(u_int32_t *ordered_indices, u_int32_t count)
2174{
2175 struct ifnet *ifp = NULL;
2176 int error = 0;
2177
2178 ifnet_head_lock_exclusive();
2179 for (u_int32_t order_index = 0; order_index < count; order_index++) {
2180 if (ordered_indices[order_index] == IFSCOPE_NONE ||
2181 ordered_indices[order_index] > (uint32_t)if_index) {
2182 error = EINVAL;
2183 ifnet_head_done();
2184 return (error);
2185 }
2186 }
2187 // Flush current ordered list
2188 for (ifp = TAILQ_FIRST(&ifnet_ordered_head); ifp != NULL;
2189 ifp = TAILQ_FIRST(&ifnet_ordered_head)) {
2190 ifnet_lock_exclusive(ifp);
2191 ifnet_remove_from_ordered_list(ifp);
2192 ifnet_lock_done(ifp);
2193 }
2194
2195 VERIFY(if_ordered_count == 0);
2196
2197 for (u_int32_t order_index = 0; order_index < count; order_index++) {
2198 u_int32_t interface_index = ordered_indices[order_index];
2199 ifp = ifindex2ifnet[interface_index];
2200 if (ifp == NULL) {
2201 continue;
2202 }
2203 ifnet_lock_exclusive(ifp);
2204 TAILQ_INSERT_TAIL(&ifnet_ordered_head, ifp, if_ordered_link);
2205 ifnet_lock_done(ifp);
2206 if_ordered_count++;
2207 }
2208
2209 ifnet_head_done();
2210
2211 necp_update_all_clients();
2212
2213 return (error);
2214}
2215
2216int
2217if_set_qosmarking_mode(struct ifnet *ifp, u_int32_t mode)
2218{
2219 int error = 0;
2220 u_int32_t old_mode = ifp->if_qosmarking_mode;
2221
2222 switch (mode) {
2223 case IFRTYPE_QOSMARKING_MODE_NONE:
2224 ifp->if_qosmarking_mode = IFRTYPE_QOSMARKING_MODE_NONE;
2225 ifp->if_eflags &= ~IFEF_QOSMARKING_CAPABLE;
2226 break;
2227 case IFRTYPE_QOSMARKING_FASTLANE:
2228 ifp->if_qosmarking_mode = IFRTYPE_QOSMARKING_FASTLANE;
2229 ifp->if_eflags |= IFEF_QOSMARKING_CAPABLE;
2230 if (net_qos_policy_capable_enabled != 0)
2231 ifp->if_eflags |= IFEF_QOSMARKING_ENABLED;
2232 break;
2233 default:
2234 error = EINVAL;
2235 break;
2236 }
2237 if (error == 0 && old_mode != ifp->if_qosmarking_mode) {
2238 dlil_post_msg(ifp, KEV_DL_SUBCLASS, KEV_DL_QOS_MODE_CHANGED,
2239 NULL, sizeof(struct kev_dl_rrc_state));
2240
2241 }
2242 return (error);
2243}
2244
2245static __attribute__((noinline)) int
2246ifioctl_iforder(u_long cmd, caddr_t data)
2247{
2248 int error = 0;
2249 u_int32_t *ordered_indices = NULL;
2250 if (data == NULL) {
2251 return (EINVAL);
2252 }
2253
2254 switch (cmd) {
2255 case SIOCSIFORDER: { /* struct if_order */
2256 struct if_order *ifo = (struct if_order *)(void *)data;
2257
2258 if (ifo->ifo_count > (u_int32_t)if_index) {
2259 error = EINVAL;
2260 break;
2261 }
2262
2263 size_t length = (ifo->ifo_count * sizeof(u_int32_t));
2264 if (length > 0) {
2265 if (ifo->ifo_ordered_indices == USER_ADDR_NULL) {
2266 error = EINVAL;
2267 break;
2268 }
2269 ordered_indices = _MALLOC(length, M_NECP, M_WAITOK);
2270 if (ordered_indices == NULL) {
2271 error = ENOMEM;
2272 break;
2273 }
2274
2275 error = copyin(ifo->ifo_ordered_indices,
2276 ordered_indices, length);
2277 if (error != 0) {
2278 break;
2279 }
2280
2281 /* ordered_indices should not contain duplicates */
2282 bool found_duplicate = FALSE;
2283 for (uint32_t i = 0; i < (ifo->ifo_count - 1) && !found_duplicate ; i++){
2284 for (uint32_t j = i + 1; j < ifo->ifo_count && !found_duplicate ; j++){
2285 if (ordered_indices[j] == ordered_indices[i]){
2286 error = EINVAL;
2287 found_duplicate = TRUE;
2288 break;
2289 }
2290 }
2291 }
2292 if (found_duplicate) {
2293 break;
2294 }
2295 }
2296
2297 error = ifnet_reset_order(ordered_indices, ifo->ifo_count);
2298
2299 break;
2300 }
2301
2302 default: {
2303 VERIFY(0);
2304 /* NOTREACHED */
2305 }
2306 }
2307
2308 if (ordered_indices != NULL) {
2309 _FREE(ordered_indices, M_NECP);
2310 }
2311
2312 return (error);
2313}
2314
2315static __attribute__((noinline)) int
2316ifioctl_netsignature(struct ifnet *ifp, u_long cmd, caddr_t data)
2317{
2318 struct if_nsreq *ifnsr = (struct if_nsreq *)(void *)data;
2319 u_int16_t flags;
2320 int error = 0;
2321
2322 VERIFY(ifp != NULL);
2323
2324 switch (cmd) {
2325 case SIOCSIFNETSIGNATURE: /* struct if_nsreq */
2326 if (ifnsr->ifnsr_len > sizeof (ifnsr->ifnsr_data)) {
2327 error = EINVAL;
2328 break;
2329 }
2330 bcopy(&ifnsr->ifnsr_flags, &flags, sizeof (flags));
2331 error = ifnet_set_netsignature(ifp, ifnsr->ifnsr_family,
2332 ifnsr->ifnsr_len, flags, ifnsr->ifnsr_data);
2333 break;
2334
2335 case SIOCGIFNETSIGNATURE: /* struct if_nsreq */
2336 ifnsr->ifnsr_len = sizeof (ifnsr->ifnsr_data);
2337 error = ifnet_get_netsignature(ifp, ifnsr->ifnsr_family,
2338 &ifnsr->ifnsr_len, &flags, ifnsr->ifnsr_data);
2339 if (error == 0)
2340 bcopy(&flags, &ifnsr->ifnsr_flags, sizeof (flags));
2341 else
2342 ifnsr->ifnsr_len = 0;
2343 break;
2344
2345 default:
2346 VERIFY(0);
2347 /* NOTREACHED */
2348 }
2349
2350 return (error);
2351}
2352
2353#if INET6
2354static __attribute__((noinline)) int
2355ifioctl_nat64prefix(struct ifnet *ifp, u_long cmd, caddr_t data)
2356{
2357 struct if_nat64req *ifnat64 = (struct if_nat64req *)(void *)data;
2358 int error = 0;
2359
2360 VERIFY(ifp != NULL);
2361
2362 switch (cmd) {
2363 case SIOCSIFNAT64PREFIX: /* struct if_nat64req */
2364 error = ifnet_set_nat64prefix(ifp, ifnat64->ifnat64_prefixes);
2365 if (error != 0)
2366 ip6stat.ip6s_clat464_plat64_pfx_setfail++;
2367 break;
2368
2369 case SIOCGIFNAT64PREFIX: /* struct if_nat64req */
2370 error = ifnet_get_nat64prefix(ifp, ifnat64->ifnat64_prefixes);
2371 if (error != 0)
2372 ip6stat.ip6s_clat464_plat64_pfx_getfail++;
2373 break;
2374
2375 default:
2376 VERIFY(0);
2377 /* NOTREACHED */
2378 }
2379
2380 return (error);
2381}
2382
2383static __attribute__((noinline)) int
2384ifioctl_clat46addr(struct ifnet *ifp, u_long cmd, caddr_t data)
2385{
2386 struct if_clat46req *ifclat46 = (struct if_clat46req *)(void *)data;
2387 struct in6_ifaddr *ia6_clat = NULL;
2388 int error = 0;
2389
2390 VERIFY(ifp != NULL);
2391
2392 switch (cmd) {
2393 case SIOCGIFCLAT46ADDR:
2394 ia6_clat = in6ifa_ifpwithflag(ifp, IN6_IFF_CLAT46);
2395 if (ia6_clat == NULL) {
2396 error = ENOENT;
2397 break;
2398 }
2399
2400 bcopy(&ia6_clat->ia_addr.sin6_addr, &ifclat46->ifclat46_addr.v6_address,
2401 sizeof(ifclat46->ifclat46_addr.v6_address));
2402 ifclat46->ifclat46_addr.v6_prefixlen = ia6_clat->ia_plen;
2403 IFA_REMREF(&ia6_clat->ia_ifa);
2404 break;
2405 default:
2406 VERIFY(0);
2407 /* NOTREACHED */
2408 }
2409
2410 return (error);
2411}
2412#endif
2413
2414
2415static int
2416ifioctl_get_protolist(struct ifnet *ifp, u_int32_t * ret_count,
2417 user_addr_t ifpl)
2418{
2419 u_int32_t actual_count;
2420 u_int32_t count;
2421 int error = 0;
2422 u_int32_t *list = NULL;
2423
2424 /* find out how many */
2425 count = if_get_protolist(ifp, NULL, 0);
2426 if (ifpl == USER_ADDR_NULL) {
2427 goto done;
2428 }
2429
2430 /* copy out how many there's space for */
2431 if (*ret_count < count) {
2432 count = *ret_count;
2433 }
2434 if (count == 0) {
2435 goto done;
2436 }
2437 list = _MALLOC(count * sizeof(*list), M_TEMP, M_WAITOK | M_ZERO);
2438 if (list == NULL) {
2439 error = ENOMEM;
2440 goto done;
2441 }
2442 actual_count = if_get_protolist(ifp, list, count);
2443 if (actual_count < count) {
2444 count = actual_count;
2445 }
2446 if (count != 0) {
2447 error = copyout((caddr_t)list, ifpl, count * sizeof(*list));
2448 }
2449
2450 done:
2451 if (list != NULL) {
2452 if_free_protolist(list);
2453 }
2454 *ret_count = count;
2455 return (error);
2456}
2457
2458static __attribute__((noinline)) int
2459ifioctl_protolist(struct ifnet *ifp, u_long cmd, caddr_t data)
2460{
2461 int error = 0;
2462
2463 switch (cmd) {
2464 case SIOCGIFPROTOLIST32: { /* struct if_protolistreq32 */
2465 struct if_protolistreq32 ifpl;
2466
2467 bcopy(data, &ifpl, sizeof(ifpl));
2468 if (ifpl.ifpl_reserved != 0) {
2469 error = EINVAL;
2470 break;
2471 }
2472 error = ifioctl_get_protolist(ifp, &ifpl.ifpl_count,
2473 CAST_USER_ADDR_T(ifpl.ifpl_list));
2474 bcopy(&ifpl, data, sizeof(ifpl));
2475 break;
2476 }
2477 case SIOCGIFPROTOLIST64: { /* struct if_protolistreq64 */
2478 struct if_protolistreq64 ifpl;
2479
2480 bcopy(data, &ifpl, sizeof(ifpl));
2481 if (ifpl.ifpl_reserved != 0) {
2482 error = EINVAL;
2483 break;
2484 }
2485 error = ifioctl_get_protolist(ifp, &ifpl.ifpl_count,
2486 ifpl.ifpl_list);
2487 bcopy(&ifpl, data, sizeof(ifpl));
2488 break;
2489 }
2490 default:
2491 VERIFY(0);
2492 /* NOTREACHED */
2493 }
2494
2495 return (error);
2496}
2497
2498/*
2499 * List the ioctl()s we can perform on restricted INTCOPROC interfaces.
2500 */
2501static bool
2502ifioctl_restrict_intcoproc(unsigned long cmd, const char *ifname,
2503 struct ifnet *ifp, struct proc *p)
2504{
2505
2506 if (intcoproc_unrestricted == TRUE) {
2507 return (false);
2508 }
2509 if (proc_pid(p) == 0) {
2510 return (false);
2511 }
2512 if (ifname) {
2513 ifp = ifunit(ifname);
2514 }
2515 if (ifp == NULL) {
2516 return (false);
2517 }
2518 if (!IFNET_IS_INTCOPROC(ifp)) {
2519 return (false);
2520 }
2521 switch (cmd) {
2522 case SIOCGIFBRDADDR:
2523 case SIOCGIFCONF32:
2524 case SIOCGIFCONF64:
2525 case SIOCGIFFLAGS:
2526 case SIOCGIFEFLAGS:
2527 case SIOCGIFCAP:
2528 case SIOCGIFMAC:
2529 case SIOCGIFMETRIC:
2530 case SIOCGIFMTU:
2531 case SIOCGIFPHYS:
2532 case SIOCGIFTYPE:
2533 case SIOCGIFFUNCTIONALTYPE:
2534 case SIOCGIFPSRCADDR:
2535 case SIOCGIFPDSTADDR:
2536 case SIOCGIFGENERIC:
2537 case SIOCGIFDEVMTU:
2538 case SIOCGIFVLAN:
2539 case SIOCGIFBOND:
2540 case SIOCGIFWAKEFLAGS:
2541 case SIOCGIFGETRTREFCNT:
2542 case SIOCGIFOPPORTUNISTIC:
2543 case SIOCGIFLINKQUALITYMETRIC:
2544 case SIOCGIFLOG:
2545 case SIOCGIFDELEGATE:
2546 case SIOCGIFEXPENSIVE:
2547 case SIOCGIFINTERFACESTATE:
2548 case SIOCGIFPROBECONNECTIVITY:
2549 case SIOCGIFTIMESTAMPENABLED:
2550 case SIOCGECNMODE:
2551 case SIOCGQOSMARKINGMODE:
2552 case SIOCGQOSMARKINGENABLED:
2553 case SIOCGIFLOWINTERNET:
2554 case SIOCGIFSTATUS:
2555 case SIOCGIFMEDIA32:
2556 case SIOCGIFMEDIA64:
2557 case SIOCGIFDESC:
2558 case SIOCGIFLINKPARAMS:
2559 case SIOCGIFQUEUESTATS:
2560 case SIOCGIFTHROTTLE:
2561 case SIOCGIFAGENTIDS32:
2562 case SIOCGIFAGENTIDS64:
2563 case SIOCGIFNETSIGNATURE:
2564 case SIOCGIFINFO_IN6:
2565 case SIOCGIFAFLAG_IN6:
2566 case SIOCGNBRINFO_IN6:
2567 case SIOCGIFALIFETIME_IN6:
2568 case SIOCGIFNETMASK_IN6:
2569 case SIOCGIFPROTOLIST32:
2570 case SIOCGIFPROTOLIST64:
2571 return (false);
2572 default:
2573#if (DEBUG || DEVELOPMENT)
2574 printf("%s: cmd 0x%lx not allowed (pid %u)\n",
2575 __func__, cmd, proc_pid(p));
2576#endif
2577 return (true);
2578 }
2579 return (false);
2580}
2581
2582/*
2583 * Interface ioctls.
2584 *
2585 * Most of the routines called to handle the ioctls would end up being
2586 * tail-call optimized, which unfortunately causes this routine to
2587 * consume too much stack space; this is the reason for the "noinline"
2588 * attribute used on those routines.
2589 */
2590int
2591ifioctl(struct socket *so, u_long cmd, caddr_t data, struct proc *p)
2592{
2593 char ifname[IFNAMSIZ + 1];
2594 struct ifnet *ifp = NULL;
2595 struct ifstat *ifs = NULL;
2596 int error = 0;
2597
2598 bzero(ifname, sizeof (ifname));
2599
2600 /*
2601 * ioctls which don't require ifp, or ifreq ioctls
2602 */
2603 switch (cmd) {
2604 case OSIOCGIFCONF32: /* struct ifconf32 */
2605 case SIOCGIFCONF32: /* struct ifconf32 */
2606 case SIOCGIFCONF64: /* struct ifconf64 */
2607 case OSIOCGIFCONF64: /* struct ifconf64 */
2608 error = ifioctl_ifconf(cmd, data);
2609 goto done;
2610
2611 case SIOCIFGCLONERS32: /* struct if_clonereq32 */
2612 case SIOCIFGCLONERS64: /* struct if_clonereq64 */
2613 error = ifioctl_ifclone(cmd, data);
2614 goto done;
2615
2616 case SIOCGIFAGENTDATA32: /* struct netagent_req32 */
2617 case SIOCGIFAGENTDATA64: /* struct netagent_req64 */
2618 case SIOCGIFAGENTLIST32: /* struct netagentlist_req32 */
2619 case SIOCGIFAGENTLIST64: /* struct netagentlist_req64 */
2620 error = netagent_ioctl(cmd, data);
2621 goto done;
2622
2623 case SIOCSIFORDER: /* struct if_order */
2624 error = ifioctl_iforder(cmd, data);
2625 goto done;
2626
2627 case SIOCSIFDSTADDR: /* struct ifreq */
2628 case SIOCSIFADDR: /* struct ifreq */
2629 case SIOCSIFBRDADDR: /* struct ifreq */
2630 case SIOCSIFNETMASK: /* struct ifreq */
2631 case OSIOCGIFADDR: /* struct ifreq */
2632 case OSIOCGIFDSTADDR: /* struct ifreq */
2633 case OSIOCGIFBRDADDR: /* struct ifreq */
2634 case OSIOCGIFNETMASK: /* struct ifreq */
2635 case SIOCSIFKPI: /* struct ifreq */
2636 if (so->so_proto == NULL) {
2637 error = EOPNOTSUPP;
2638 goto done;
2639 }
2640 /* FALLTHRU */
2641 case SIOCIFCREATE: /* struct ifreq */
2642 case SIOCIFCREATE2: /* struct ifreq */
2643 case SIOCIFDESTROY: /* struct ifreq */
2644 case SIOCGIFFLAGS: /* struct ifreq */
2645 case SIOCGIFEFLAGS: /* struct ifreq */
2646 case SIOCGIFCAP: /* struct ifreq */
2647#if CONFIG_MACF_NET
2648 case SIOCGIFMAC: /* struct ifreq */
2649 case SIOCSIFMAC: /* struct ifreq */
2650#endif /* CONFIG_MACF_NET */
2651 case SIOCGIFMETRIC: /* struct ifreq */
2652 case SIOCGIFMTU: /* struct ifreq */
2653 case SIOCGIFPHYS: /* struct ifreq */
2654 case SIOCSIFFLAGS: /* struct ifreq */
2655 case SIOCSIFCAP: /* struct ifreq */
2656 case SIOCSIFMETRIC: /* struct ifreq */
2657 case SIOCSIFPHYS: /* struct ifreq */
2658 case SIOCSIFMTU: /* struct ifreq */
2659 case SIOCADDMULTI: /* struct ifreq */
2660 case SIOCDELMULTI: /* struct ifreq */
2661 case SIOCDIFPHYADDR: /* struct ifreq */
2662 case SIOCSIFMEDIA: /* struct ifreq */
2663 case SIOCSIFGENERIC: /* struct ifreq */
2664 case SIOCSIFLLADDR: /* struct ifreq */
2665 case SIOCSIFALTMTU: /* struct ifreq */
2666 case SIOCSIFVLAN: /* struct ifreq */
2667 case SIOCSIFBOND: /* struct ifreq */
2668 case SIOCGIFLLADDR: /* struct ifreq */
2669 case SIOCGIFTYPE: /* struct ifreq */
2670 case SIOCGIFFUNCTIONALTYPE: /* struct ifreq */
2671 case SIOCGIFPSRCADDR: /* struct ifreq */
2672 case SIOCGIFPDSTADDR: /* struct ifreq */
2673 case SIOCGIFGENERIC: /* struct ifreq */
2674 case SIOCGIFDEVMTU: /* struct ifreq */
2675 case SIOCGIFVLAN: /* struct ifreq */
2676 case SIOCGIFBOND: /* struct ifreq */
2677 case SIOCGIFWAKEFLAGS: /* struct ifreq */
2678 case SIOCGIFGETRTREFCNT: /* struct ifreq */
2679 case SIOCSIFOPPORTUNISTIC: /* struct ifreq */
2680 case SIOCGIFOPPORTUNISTIC: /* struct ifreq */
2681 case SIOCGIFLINKQUALITYMETRIC: /* struct ifreq */
2682 case SIOCSIFLOG: /* struct ifreq */
2683 case SIOCGIFLOG: /* struct ifreq */
2684 case SIOCGIFDELEGATE: /* struct ifreq */
2685 case SIOCGIFEXPENSIVE: /* struct ifreq */
2686 case SIOCSIFEXPENSIVE: /* struct ifreq */
2687 case SIOCSIF2KCL: /* struct ifreq */
2688 case SIOCGIF2KCL: /* struct ifreq */
2689 case SIOCSIFINTERFACESTATE: /* struct ifreq */
2690 case SIOCGIFINTERFACESTATE: /* struct ifreq */
2691 case SIOCSIFPROBECONNECTIVITY: /* struct ifreq */
2692 case SIOCGIFPROBECONNECTIVITY: /* struct ifreq */
2693 case SIOCGSTARTDELAY: /* struct ifreq */
2694 case SIOCSIFTIMESTAMPENABLE: /* struct ifreq */
2695 case SIOCSIFTIMESTAMPDISABLE: /* struct ifreq */
2696 case SIOCGIFTIMESTAMPENABLED: /* struct ifreq */
2697#if (DEBUG || DEVELOPMENT)
2698 case SIOCSIFDISABLEOUTPUT: /* struct ifreq */
2699#endif /* (DEBUG || DEVELOPMENT) */
2700 case SIOCGECNMODE: /* struct ifreq */
2701 case SIOCSECNMODE:
2702 case SIOCSQOSMARKINGMODE: /* struct ifreq */
2703 case SIOCSQOSMARKINGENABLED: /* struct ifreq */
2704 case SIOCGQOSMARKINGMODE: /* struct ifreq */
2705 case SIOCGQOSMARKINGENABLED: /* struct ifreq */
2706 case SIOCSIFLOWINTERNET: /* struct ifreq */
2707 case SIOCGIFLOWINTERNET: /* struct ifreq */
2708 case SIOCGIFLOWPOWER: /* struct ifreq */
2709 case SIOCSIFLOWPOWER: /* struct ifreq */
2710 { /* struct ifreq */
2711 struct ifreq ifr;
2712 bcopy(data, &ifr, sizeof (ifr));
2713 ifr.ifr_name[IFNAMSIZ - 1] = '\0';
2714 bcopy(&ifr.ifr_name, ifname, IFNAMSIZ);
2715 if (ifioctl_restrict_intcoproc(cmd, ifname, NULL, p) == true) {
2716 error = EPERM;
2717 goto done;
2718 }
2719 error = ifioctl_ifreq(so, cmd, &ifr, p);
2720 bcopy(&ifr, data, sizeof (ifr));
2721 goto done;
2722 }
2723 }
2724
2725 /*
2726 * ioctls which require ifp. Note that we acquire dlil_ifnet_lock
2727 * here to ensure that the ifnet, if found, has been fully attached.
2728 */
2729 dlil_if_lock();
2730 switch (cmd) {
2731 case SIOCSIFPHYADDR: /* struct {if,in_}aliasreq */
2732 bcopy(((struct in_aliasreq *)(void *)data)->ifra_name,
2733 ifname, IFNAMSIZ);
2734 ifp = ifunit(ifname);
2735 break;
2736
2737#if INET6
2738 case SIOCSIFPHYADDR_IN6_32: /* struct in6_aliasreq_32 */
2739 bcopy(((struct in6_aliasreq_32 *)(void *)data)->ifra_name,
2740 ifname, IFNAMSIZ);
2741 ifp = ifunit(ifname);
2742 break;
2743
2744 case SIOCSIFPHYADDR_IN6_64: /* struct in6_aliasreq_64 */
2745 bcopy(((struct in6_aliasreq_64 *)(void *)data)->ifra_name,
2746 ifname, IFNAMSIZ);
2747 ifp = ifunit(ifname);
2748 break;
2749#endif /* INET6 */
2750
2751 case SIOCGIFSTATUS: /* struct ifstat */
2752 ifs = _MALLOC(sizeof (*ifs), M_DEVBUF, M_WAITOK);
2753 if (ifs == NULL) {
2754 error = ENOMEM;
2755 dlil_if_unlock();
2756 goto done;
2757 }
2758 bcopy(data, ifs, sizeof (*ifs));
2759 ifs->ifs_name[IFNAMSIZ - 1] = '\0';
2760 bcopy(ifs->ifs_name, ifname, IFNAMSIZ);
2761 ifp = ifunit(ifname);
2762 break;
2763
2764 case SIOCGIFMEDIA32: /* struct ifmediareq32 */
2765 bcopy(((struct ifmediareq32 *)(void *)data)->ifm_name,
2766 ifname, IFNAMSIZ);
2767 ifp = ifunit(ifname);
2768 break;
2769
2770 case SIOCGIFMEDIA64: /* struct ifmediareq64 */
2771 bcopy(((struct ifmediareq64 *)(void *)data)->ifm_name,
2772 ifname, IFNAMSIZ);
2773 ifp = ifunit(ifname);
2774 break;
2775
2776 case SIOCSIFDESC: /* struct if_descreq */
2777 case SIOCGIFDESC: /* struct if_descreq */
2778 bcopy(((struct if_descreq *)(void *)data)->ifdr_name,
2779 ifname, IFNAMSIZ);
2780 ifp = ifunit(ifname);
2781 break;
2782
2783 case SIOCSIFLINKPARAMS: /* struct if_linkparamsreq */
2784 case SIOCGIFLINKPARAMS: /* struct if_linkparamsreq */
2785 bcopy(((struct if_linkparamsreq *)(void *)data)->iflpr_name,
2786 ifname, IFNAMSIZ);
2787 ifp = ifunit(ifname);
2788 break;
2789
2790 case SIOCGIFQUEUESTATS: /* struct if_qstatsreq */
2791 bcopy(((struct if_qstatsreq *)(void *)data)->ifqr_name,
2792 ifname, IFNAMSIZ);
2793 ifp = ifunit(ifname);
2794 break;
2795
2796 case SIOCSIFTHROTTLE: /* struct if_throttlereq */
2797 case SIOCGIFTHROTTLE: /* struct if_throttlereq */
2798 bcopy(((struct if_throttlereq *)(void *)data)->ifthr_name,
2799 ifname, IFNAMSIZ);
2800 ifp = ifunit(ifname);
2801 break;
2802
2803 case SIOCAIFAGENTID: /* struct if_agentidreq */
2804 case SIOCDIFAGENTID: /* struct if_agentidreq */
2805 case SIOCGIFAGENTIDS32: /* struct if_agentidsreq32 */
2806 case SIOCGIFAGENTIDS64: /* struct if_agentidsreq64 */
2807 bcopy(((struct if_agentidreq *)(void *)data)->ifar_name,
2808 ifname, IFNAMSIZ);
2809 ifp = ifunit(ifname);
2810 break;
2811
2812 case SIOCSIFNETSIGNATURE: /* struct if_nsreq */
2813 case SIOCGIFNETSIGNATURE: /* struct if_nsreq */
2814 bcopy(((struct if_nsreq *)(void *)data)->ifnsr_name,
2815 ifname, IFNAMSIZ);
2816 ifp = ifunit(ifname);
2817 break;
2818
2819 case SIOCGIFPROTOLIST32: /* struct if_protolistreq32 */
2820 case SIOCGIFPROTOLIST64: /* struct if_protolistreq64 */
2821 bcopy(((struct if_protolistreq *)(void *)data)->ifpl_name,
2822 ifname, IFNAMSIZ);
2823 ifp = ifunit(ifname);
2824 break;
2825 default:
2826 /*
2827 * This is a bad assumption, but the code seems to
2828 * have been doing this in the past; caveat emptor.
2829 */
2830 bcopy(((struct ifreq *)(void *)data)->ifr_name,
2831 ifname, IFNAMSIZ);
2832 ifp = ifunit(ifname);
2833 break;
2834 }
2835 dlil_if_unlock();
2836
2837 if (ifp == NULL) {
2838 error = ENXIO;
2839 goto done;
2840 }
2841
2842 if (ifioctl_restrict_intcoproc(cmd, NULL, ifp, p) == true) {
2843 error = EPERM;
2844 goto done;
2845 }
2846 switch (cmd) {
2847 case SIOCSIFPHYADDR: /* struct {if,in_}aliasreq */
2848#if INET6
2849 case SIOCSIFPHYADDR_IN6_32: /* struct in6_aliasreq_32 */
2850 case SIOCSIFPHYADDR_IN6_64: /* struct in6_aliasreq_64 */
2851#endif /* INET6 */
2852 error = proc_suser(p);
2853 if (error != 0)
2854 break;
2855
2856 error = ifnet_ioctl(ifp, SOCK_DOM(so), cmd, data);
2857 if (error != 0)
2858 break;
2859
2860 ifnet_touch_lastchange(ifp);
2861 break;
2862
2863 case SIOCGIFSTATUS: /* struct ifstat */
2864 VERIFY(ifs != NULL);
2865 ifs->ascii[0] = '\0';
2866
2867 error = ifnet_ioctl(ifp, SOCK_DOM(so), cmd, (caddr_t)ifs);
2868
2869 bcopy(ifs, data, sizeof (*ifs));
2870 break;
2871
2872 case SIOCGIFMEDIA32: /* struct ifmediareq32 */
2873 case SIOCGIFMEDIA64: /* struct ifmediareq64 */
2874 error = ifnet_ioctl(ifp, SOCK_DOM(so), cmd, data);
2875 break;
2876
2877 case SIOCSIFDESC: /* struct if_descreq */
2878 case SIOCGIFDESC: /* struct if_descreq */
2879 error = ifioctl_ifdesc(ifp, cmd, data, p);
2880 break;
2881
2882 case SIOCSIFLINKPARAMS: /* struct if_linkparamsreq */
2883 case SIOCGIFLINKPARAMS: /* struct if_linkparamsreq */
2884 error = ifioctl_linkparams(ifp, cmd, data, p);
2885 break;
2886
2887 case SIOCGIFQUEUESTATS: /* struct if_qstatsreq */
2888 error = ifioctl_qstats(ifp, cmd, data);
2889 break;
2890
2891 case SIOCSIFTHROTTLE: /* struct if_throttlereq */
2892 case SIOCGIFTHROTTLE: /* struct if_throttlereq */
2893 error = ifioctl_throttle(ifp, cmd, data, p);
2894 break;
2895
2896 case SIOCAIFAGENTID: /* struct if_agentidreq */
2897 case SIOCDIFAGENTID: /* struct if_agentidreq */
2898 case SIOCGIFAGENTIDS32: /* struct if_agentidsreq32 */
2899 case SIOCGIFAGENTIDS64: /* struct if_agentidsreq64 */
2900 error = ifioctl_netagent(ifp, cmd, data, p);
2901 break;
2902
2903 case SIOCSIFNETSIGNATURE: /* struct if_nsreq */
2904 case SIOCGIFNETSIGNATURE: /* struct if_nsreq */
2905 error = ifioctl_netsignature(ifp, cmd, data);
2906 break;
2907
2908#if INET6
2909 case SIOCSIFNAT64PREFIX: /* struct if_nat64req */
2910 case SIOCGIFNAT64PREFIX: /* struct if_nat64req */
2911 error = ifioctl_nat64prefix(ifp, cmd, data);
2912 break;
2913
2914 case SIOCGIFCLAT46ADDR: /* struct if_clat46req */
2915 error = ifioctl_clat46addr(ifp, cmd, data);
2916 break;
2917#endif
2918
2919 case SIOCGIFPROTOLIST32: /* struct if_protolistreq32 */
2920 case SIOCGIFPROTOLIST64: /* struct if_protolistreq64 */
2921 error = ifioctl_protolist(ifp, cmd, data);
2922 break;
2923
2924 default:
2925 if (so->so_proto == NULL) {
2926 error = EOPNOTSUPP;
2927 break;
2928 }
2929
2930 socket_lock(so, 1);
2931 error = ((*so->so_proto->pr_usrreqs->pru_control)(so, cmd,
2932 data, ifp, p));
2933 socket_unlock(so, 1);
2934
2935 if (error == EOPNOTSUPP || error == ENOTSUP) {
2936 error = ifnet_ioctl(ifp, SOCK_DOM(so), cmd, data);
2937 }
2938 break;
2939 }
2940
2941done:
2942 if (ifs != NULL)
2943 _FREE(ifs, M_DEVBUF);
2944
2945 if (if_verbose) {
2946 if (ifname[0] == '\0')
2947 (void) snprintf(ifname, sizeof (ifname), "%s",
2948 "NULL");
2949 else if (ifp != NULL)
2950 (void) snprintf(ifname, sizeof (ifname), "%s",
2951 if_name(ifp));
2952
2953 if (error != 0) {
2954 printf("%s[%s,%d]: ifp %s cmd 0x%08lx (%c%c [%lu] "
2955 "%c %lu) error %d\n", __func__,
2956 proc_name_address(p), proc_pid(p),
2957 ifname, cmd, (cmd & IOC_IN) ? 'I' : ' ',
2958 (cmd & IOC_OUT) ? 'O' : ' ', IOCPARM_LEN(cmd),
2959 (char)IOCGROUP(cmd), cmd & 0xff, error);
2960 } else if (if_verbose > 1) {
2961 printf("%s[%s,%d]: ifp %s cmd 0x%08lx (%c%c [%lu] "
2962 "%c %lu) OK\n", __func__,
2963 proc_name_address(p), proc_pid(p),
2964 ifname, cmd, (cmd & IOC_IN) ? 'I' : ' ',
2965 (cmd & IOC_OUT) ? 'O' : ' ', IOCPARM_LEN(cmd),
2966 (char)IOCGROUP(cmd), cmd & 0xff);
2967 }
2968 }
2969
2970 return (error);
2971}
2972
2973static __attribute__((noinline)) int
2974ifioctl_ifreq(struct socket *so, u_long cmd, struct ifreq *ifr, struct proc *p)
2975{
2976 struct ifnet *ifp;
2977 u_long ocmd = cmd;
2978 int error = 0;
2979 struct kev_msg ev_msg;
2980 struct net_event_data ev_data;
2981
2982 bzero(&ev_data, sizeof (struct net_event_data));
2983 bzero(&ev_msg, sizeof (struct kev_msg));
2984
2985 switch (cmd) {
2986 case SIOCIFCREATE:
2987 case SIOCIFCREATE2:
2988 error = proc_suser(p);
2989 if (error)
2990 return (error);
2991 return (if_clone_create(ifr->ifr_name, sizeof(ifr->ifr_name),
2992 cmd == SIOCIFCREATE2 ? ifr->ifr_data : NULL));
2993 case SIOCIFDESTROY:
2994 error = proc_suser(p);
2995 if (error)
2996 return (error);
2997 return (if_clone_destroy(ifr->ifr_name));
2998 }
2999
3000 /*
3001 * ioctls which require ifp. Note that we acquire dlil_ifnet_lock
3002 * here to ensure that the ifnet, if found, has been fully attached.
3003 */
3004 dlil_if_lock();
3005 ifp = ifunit(ifr->ifr_name);
3006 dlil_if_unlock();
3007
3008 if (ifp == NULL)
3009 return (ENXIO);
3010
3011 switch (cmd) {
3012 case SIOCGIFFLAGS:
3013 ifnet_lock_shared(ifp);
3014 ifr->ifr_flags = ifp->if_flags;
3015 ifnet_lock_done(ifp);
3016 break;
3017
3018 case SIOCGIFEFLAGS:
3019 ifnet_lock_shared(ifp);
3020 ifr->ifr_eflags = ifp->if_eflags;
3021 ifnet_lock_done(ifp);
3022 break;
3023
3024 case SIOCGIFCAP:
3025 ifnet_lock_shared(ifp);
3026 ifr->ifr_reqcap = ifp->if_capabilities;
3027 ifr->ifr_curcap = ifp->if_capenable;
3028 ifnet_lock_done(ifp);
3029 break;
3030
3031#if CONFIG_MACF_NET
3032 case SIOCGIFMAC:
3033 error = mac_ifnet_label_get(kauth_cred_get(), ifr, ifp);
3034 break;
3035
3036 case SIOCSIFMAC:
3037 error = mac_ifnet_label_set(kauth_cred_get(), ifr, ifp);
3038 break;
3039#endif /* CONFIG_MACF_NET */
3040
3041 case SIOCGIFMETRIC:
3042 ifnet_lock_shared(ifp);
3043 ifr->ifr_metric = ifp->if_metric;
3044 ifnet_lock_done(ifp);
3045 break;
3046
3047 case SIOCGIFMTU:
3048 ifnet_lock_shared(ifp);
3049 ifr->ifr_mtu = ifp->if_mtu;
3050 ifnet_lock_done(ifp);
3051 break;
3052
3053 case SIOCGIFPHYS:
3054 ifnet_lock_shared(ifp);
3055 ifr->ifr_phys = ifp->if_physical;
3056 ifnet_lock_done(ifp);
3057 break;
3058
3059 case SIOCSIFFLAGS:
3060 error = proc_suser(p);
3061 if (error != 0)
3062 break;
3063
3064 (void) ifnet_set_flags(ifp, ifr->ifr_flags,
3065 (u_int16_t)~IFF_CANTCHANGE);
3066
3067 /*
3068 * Note that we intentionally ignore any error from below
3069 * for the SIOCSIFFLAGS case.
3070 */
3071 (void) ifnet_ioctl(ifp, SOCK_DOM(so), cmd, (caddr_t)ifr);
3072
3073 /*
3074 * Send the event even upon error from the driver because
3075 * we changed the flags.
3076 */
3077 dlil_post_sifflags_msg(ifp);
3078
3079 ifnet_touch_lastchange(ifp);
3080 break;
3081
3082 case SIOCSIFCAP:
3083 error = proc_suser(p);
3084 if (error != 0)
3085 break;
3086
3087 if ((ifr->ifr_reqcap & ~ifp->if_capabilities)) {
3088 error = EINVAL;
3089 break;
3090 }
3091 error = ifnet_ioctl(ifp, SOCK_DOM(so), cmd, (caddr_t)ifr);
3092
3093 ifnet_touch_lastchange(ifp);
3094 break;
3095
3096 case SIOCSIFMETRIC:
3097 error = proc_suser(p);
3098 if (error != 0)
3099 break;
3100
3101 ifp->if_metric = ifr->ifr_metric;
3102
3103 ev_msg.vendor_code = KEV_VENDOR_APPLE;
3104 ev_msg.kev_class = KEV_NETWORK_CLASS;
3105 ev_msg.kev_subclass = KEV_DL_SUBCLASS;
3106
3107 ev_msg.event_code = KEV_DL_SIFMETRICS;
3108 strlcpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ);
3109 ev_data.if_family = ifp->if_family;
3110 ev_data.if_unit = (u_int32_t) ifp->if_unit;
3111 ev_msg.dv[0].data_length = sizeof(struct net_event_data);
3112 ev_msg.dv[0].data_ptr = &ev_data;
3113
3114 ev_msg.dv[1].data_length = 0;
3115 dlil_post_complete_msg(ifp, &ev_msg);
3116
3117 ifnet_touch_lastchange(ifp);
3118 break;
3119
3120 case SIOCSIFPHYS:
3121 error = proc_suser(p);
3122 if (error != 0)
3123 break;
3124
3125 error = ifnet_ioctl(ifp, SOCK_DOM(so), cmd, (caddr_t)ifr);
3126 if (error != 0)
3127 break;
3128
3129 ev_msg.vendor_code = KEV_VENDOR_APPLE;
3130 ev_msg.kev_class = KEV_NETWORK_CLASS;
3131 ev_msg.kev_subclass = KEV_DL_SUBCLASS;
3132
3133 ev_msg.event_code = KEV_DL_SIFPHYS;
3134 strlcpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ);
3135 ev_data.if_family = ifp->if_family;
3136 ev_data.if_unit = (u_int32_t) ifp->if_unit;
3137 ev_msg.dv[0].data_length = sizeof(struct net_event_data);
3138 ev_msg.dv[0].data_ptr = &ev_data;
3139 ev_msg.dv[1].data_length = 0;
3140 dlil_post_complete_msg(ifp, &ev_msg);
3141
3142 ifnet_touch_lastchange(ifp);
3143 break;
3144
3145 case SIOCSIFMTU: {
3146 u_int32_t oldmtu = ifp->if_mtu;
3147 struct ifclassq *ifq = &ifp->if_snd;
3148
3149 error = proc_suser(p);
3150 if (error != 0)
3151 break;
3152
3153 if (ifp->if_ioctl == NULL) {
3154 error = EOPNOTSUPP;
3155 break;
3156 }
3157 if (ifr->ifr_mtu < IF_MINMTU || ifr->ifr_mtu > IF_MAXMTU) {
3158 error = EINVAL;
3159 break;
3160 }
3161 error = ifnet_ioctl(ifp, SOCK_DOM(so), cmd, (caddr_t)ifr);
3162 if (error != 0)
3163 break;
3164
3165 ev_msg.vendor_code = KEV_VENDOR_APPLE;
3166 ev_msg.kev_class = KEV_NETWORK_CLASS;
3167 ev_msg.kev_subclass = KEV_DL_SUBCLASS;
3168
3169 ev_msg.event_code = KEV_DL_SIFMTU;
3170 strlcpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ);
3171 ev_data.if_family = ifp->if_family;
3172 ev_data.if_unit = (u_int32_t) ifp->if_unit;
3173 ev_msg.dv[0].data_length = sizeof(struct net_event_data);
3174 ev_msg.dv[0].data_ptr = &ev_data;
3175 ev_msg.dv[1].data_length = 0;
3176 dlil_post_complete_msg(ifp, &ev_msg);
3177
3178 ifnet_touch_lastchange(ifp);
3179 rt_ifmsg(ifp);
3180
3181 /*
3182 * If the link MTU changed, do network layer specific procedure
3183 * and update all route entries associated with the interface,
3184 * so that their MTU metric gets updated.
3185 */
3186 if (ifp->if_mtu != oldmtu) {
3187 if_rtmtu_update(ifp);
3188#if INET6
3189 nd6_setmtu(ifp);
3190#endif /* INET6 */
3191 /* Inform all transmit queues about the new MTU */
3192 IFCQ_LOCK(ifq);
3193 ifnet_update_sndq(ifq, CLASSQ_EV_LINK_MTU);
3194 IFCQ_UNLOCK(ifq);
3195 }
3196 break;
3197 }
3198
3199 case SIOCADDMULTI:
3200 case SIOCDELMULTI:
3201 error = proc_suser(p);
3202 if (error != 0)
3203 break;
3204
3205 /* Don't allow group membership on non-multicast interfaces. */
3206 if ((ifp->if_flags & IFF_MULTICAST) == 0) {
3207 error = EOPNOTSUPP;
3208 break;
3209 }
3210
3211 /* Don't let users screw up protocols' entries. */
3212 if (ifr->ifr_addr.sa_family != AF_UNSPEC &&
3213 ifr->ifr_addr.sa_family != AF_LINK) {
3214 error = EINVAL;
3215 break;
3216 }
3217
3218 /*
3219 * User is permitted to anonymously join a particular link
3220 * multicast group via SIOCADDMULTI. Subsequent join requested
3221 * for the same record which has an outstanding refcnt from a
3222 * past if_addmulti_anon() will not result in EADDRINUSE error
3223 * (unlike other BSDs.) Anonymously leaving a group is also
3224 * allowed only as long as there is an outstanding refcnt held
3225 * by a previous anonymous request, or else ENOENT (even if the
3226 * link-layer multicast membership exists for a network-layer
3227 * membership.)
3228 */
3229 if (cmd == SIOCADDMULTI) {
3230 error = if_addmulti_anon(ifp, &ifr->ifr_addr, NULL);
3231 ev_msg.event_code = KEV_DL_ADDMULTI;
3232 } else {
3233 error = if_delmulti_anon(ifp, &ifr->ifr_addr);
3234 ev_msg.event_code = KEV_DL_DELMULTI;
3235 }
3236 if (error != 0)
3237 break;
3238
3239 ev_msg.vendor_code = KEV_VENDOR_APPLE;
3240 ev_msg.kev_class = KEV_NETWORK_CLASS;
3241 ev_msg.kev_subclass = KEV_DL_SUBCLASS;
3242 strlcpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ);
3243
3244 ev_data.if_family = ifp->if_family;
3245 ev_data.if_unit = (u_int32_t) ifp->if_unit;
3246 ev_msg.dv[0].data_length = sizeof(struct net_event_data);
3247 ev_msg.dv[0].data_ptr = &ev_data;
3248 ev_msg.dv[1].data_length = 0;
3249 dlil_post_complete_msg(ifp, &ev_msg);
3250
3251 ifnet_touch_lastchange(ifp);
3252 break;
3253
3254 case SIOCDIFPHYADDR:
3255 case SIOCSIFMEDIA:
3256 case SIOCSIFGENERIC:
3257 case SIOCSIFLLADDR:
3258 case SIOCSIFALTMTU:
3259 case SIOCSIFVLAN:
3260 case SIOCSIFBOND:
3261 error = proc_suser(p);
3262 if (error != 0)
3263 break;
3264
3265 error = ifnet_ioctl(ifp, SOCK_DOM(so), cmd, (caddr_t)ifr);
3266 if (error != 0)
3267 break;
3268
3269 ifnet_touch_lastchange(ifp);
3270 break;
3271
3272 case SIOCGIFLLADDR: {
3273 struct sockaddr_dl *sdl = SDL(ifp->if_lladdr->ifa_addr);
3274
3275 if (sdl->sdl_alen == 0) {
3276 error = EADDRNOTAVAIL;
3277 break;
3278 }
3279 /* If larger than 14-bytes we'll need another mechanism */
3280 if (sdl->sdl_alen > sizeof (ifr->ifr_addr.sa_data)) {
3281 error = EMSGSIZE;
3282 break;
3283 }
3284 /* Follow the same convention used by SIOCSIFLLADDR */
3285 bzero(&ifr->ifr_addr, sizeof (ifr->ifr_addr));
3286 ifr->ifr_addr.sa_family = AF_LINK;
3287 ifr->ifr_addr.sa_len = sdl->sdl_alen;
3288 error = ifnet_guarded_lladdr_copy_bytes(ifp,
3289 &ifr->ifr_addr.sa_data, sdl->sdl_alen);
3290 break;
3291 }
3292
3293 case SIOCGIFTYPE:
3294 ifr->ifr_type.ift_type = ifp->if_type;
3295 ifr->ifr_type.ift_family = ifp->if_family;
3296 ifr->ifr_type.ift_subfamily = ifp->if_subfamily;
3297 break;
3298
3299 case SIOCGIFFUNCTIONALTYPE:
3300 ifr->ifr_functional_type = if_functional_type(ifp, FALSE);
3301 break;
3302
3303 case SIOCGIFPSRCADDR:
3304 case SIOCGIFPDSTADDR:
3305 case SIOCGIFGENERIC:
3306 case SIOCGIFDEVMTU:
3307 case SIOCGIFVLAN:
3308 case SIOCGIFBOND:
3309 error = ifnet_ioctl(ifp, SOCK_DOM(so), cmd, (caddr_t)ifr);
3310 break;
3311
3312 case SIOCGIFWAKEFLAGS:
3313 ifnet_lock_shared(ifp);
3314 ifr->ifr_wake_flags = ifnet_get_wake_flags(ifp);
3315 ifnet_lock_done(ifp);
3316 break;
3317
3318 case SIOCGIFGETRTREFCNT:
3319 ifnet_lock_shared(ifp);
3320 ifr->ifr_route_refcnt = ifp->if_route_refcnt;
3321 ifnet_lock_done(ifp);
3322 break;
3323
3324 case SIOCSIFOPPORTUNISTIC:
3325 case SIOCGIFOPPORTUNISTIC:
3326 error = ifnet_getset_opportunistic(ifp, cmd, ifr, p);
3327 break;
3328
3329 case SIOCGIFLINKQUALITYMETRIC:
3330 ifnet_lock_shared(ifp);
3331 if ((ifp->if_interface_state.valid_bitmask &
3332 IF_INTERFACE_STATE_LQM_STATE_VALID)) {
3333 ifr->ifr_link_quality_metric =
3334 ifp->if_interface_state.lqm_state;
3335 } else if (IF_FULLY_ATTACHED(ifp)) {
3336 ifr->ifr_link_quality_metric =
3337 IFNET_LQM_THRESH_UNKNOWN;
3338 } else {
3339 ifr->ifr_link_quality_metric =
3340 IFNET_LQM_THRESH_OFF;
3341 }
3342 ifnet_lock_done(ifp);
3343 break;
3344
3345 case SIOCSIFLOG:
3346 case SIOCGIFLOG:
3347 error = ifnet_getset_log(ifp, cmd, ifr, p);
3348 break;
3349
3350 case SIOCGIFDELEGATE:
3351 ifnet_lock_shared(ifp);
3352 ifr->ifr_delegated = ((ifp->if_delegated.ifp != NULL) ?
3353 ifp->if_delegated.ifp->if_index : 0);
3354 ifnet_lock_done(ifp);
3355 break;
3356
3357 case SIOCGIFEXPENSIVE:
3358 ifnet_lock_shared(ifp);
3359 if (ifp->if_eflags & IFEF_EXPENSIVE)
3360 ifr->ifr_expensive = 1;
3361 else
3362 ifr->ifr_expensive = 0;
3363 ifnet_lock_done(ifp);
3364 break;
3365
3366 case SIOCSIFEXPENSIVE:
3367 {
3368 struct ifnet *difp;
3369
3370 if ((error = priv_check_cred(kauth_cred_get(),
3371 PRIV_NET_INTERFACE_CONTROL, 0)) != 0)
3372 return (error);
3373 ifnet_lock_exclusive(ifp);
3374 if (ifr->ifr_expensive)
3375 ifp->if_eflags |= IFEF_EXPENSIVE;
3376 else
3377 ifp->if_eflags &= ~IFEF_EXPENSIVE;
3378 ifnet_lock_done(ifp);
3379 /*
3380 * Update the expensive bit in the delegated interface
3381 * structure.
3382 */
3383 ifnet_head_lock_shared();
3384 TAILQ_FOREACH(difp, &ifnet_head, if_link) {
3385 ifnet_lock_exclusive(difp);
3386 if (difp->if_delegated.ifp == ifp) {
3387 difp->if_delegated.expensive =
3388 ifp->if_eflags & IFEF_EXPENSIVE ? 1 : 0;
3389
3390 }
3391 ifnet_lock_done(difp);
3392 }
3393 ifnet_head_done();
3394 break;
3395 }
3396
3397 case SIOCGIF2KCL:
3398 ifnet_lock_shared(ifp);
3399 if (ifp->if_eflags & IFEF_2KCL)
3400 ifr->ifr_2kcl = 1;
3401 else
3402 ifr->ifr_2kcl = 0;
3403 ifnet_lock_done(ifp);
3404 break;
3405
3406 case SIOCSIF2KCL:
3407 if ((error = priv_check_cred(kauth_cred_get(),
3408 PRIV_NET_INTERFACE_CONTROL, 0)) != 0)
3409 return (error);
3410 ifnet_lock_exclusive(ifp);
3411 if (ifr->ifr_2kcl)
3412 ifp->if_eflags |= IFEF_2KCL;
3413 else
3414 ifp->if_eflags &= ~IFEF_2KCL;
3415 ifnet_lock_done(ifp);
3416 break;
3417 case SIOCGSTARTDELAY:
3418 ifnet_lock_shared(ifp);
3419 if (ifp->if_eflags & IFEF_ENQUEUE_MULTI) {
3420 ifr->ifr_start_delay_qlen =
3421 ifp->if_start_delay_qlen;
3422 ifr->ifr_start_delay_timeout =
3423 ifp->if_start_delay_timeout;
3424 } else {
3425 ifr->ifr_start_delay_qlen = 0;
3426 ifr->ifr_start_delay_timeout = 0;
3427 }
3428 ifnet_lock_done(ifp);
3429 break;
3430 case SIOCSIFDSTADDR:
3431 case SIOCSIFADDR:
3432 case SIOCSIFBRDADDR:
3433 case SIOCSIFNETMASK:
3434 case OSIOCGIFADDR:
3435 case OSIOCGIFDSTADDR:
3436 case OSIOCGIFBRDADDR:
3437 case OSIOCGIFNETMASK:
3438 case SIOCSIFKPI:
3439 VERIFY(so->so_proto != NULL);
3440
3441 if (cmd == SIOCSIFDSTADDR || cmd == SIOCSIFADDR ||
3442 cmd == SIOCSIFBRDADDR || cmd == SIOCSIFNETMASK) {
3443#if BYTE_ORDER != BIG_ENDIAN
3444 if (ifr->ifr_addr.sa_family == 0 &&
3445 ifr->ifr_addr.sa_len < 16) {
3446 ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len;
3447 ifr->ifr_addr.sa_len = 16;
3448 }
3449#else
3450 if (ifr->ifr_addr.sa_len == 0)
3451 ifr->ifr_addr.sa_len = 16;
3452#endif
3453 } else if (cmd == OSIOCGIFADDR) {
3454 cmd = SIOCGIFADDR; /* struct ifreq */
3455 } else if (cmd == OSIOCGIFDSTADDR) {
3456 cmd = SIOCGIFDSTADDR; /* struct ifreq */
3457 } else if (cmd == OSIOCGIFBRDADDR) {
3458 cmd = SIOCGIFBRDADDR; /* struct ifreq */
3459 } else if (cmd == OSIOCGIFNETMASK) {
3460 cmd = SIOCGIFNETMASK; /* struct ifreq */
3461 }
3462
3463 socket_lock(so, 1);
3464 error = ((*so->so_proto->pr_usrreqs->pru_control)(so, cmd,
3465 (caddr_t)ifr, ifp, p));
3466 socket_unlock(so, 1);
3467
3468 switch (ocmd) {
3469 case OSIOCGIFADDR:
3470 case OSIOCGIFDSTADDR:
3471 case OSIOCGIFBRDADDR:
3472 case OSIOCGIFNETMASK:
3473 bcopy(&ifr->ifr_addr.sa_family, &ifr->ifr_addr,
3474 sizeof (u_short));
3475 }
3476
3477 if (cmd == SIOCSIFKPI) {
3478 int temperr = proc_suser(p);
3479 if (temperr != 0)
3480 error = temperr;
3481 }
3482
3483 if (error == EOPNOTSUPP || error == ENOTSUP) {
3484 error = ifnet_ioctl(ifp, SOCK_DOM(so), cmd,
3485 (caddr_t)ifr);
3486 }
3487 break;
3488
3489 case SIOCGIFINTERFACESTATE:
3490 if_get_state(ifp, &ifr->ifr_interface_state);
3491
3492 break;
3493 case SIOCSIFINTERFACESTATE:
3494 if ((error = priv_check_cred(kauth_cred_get(),
3495 PRIV_NET_INTERFACE_CONTROL, 0)) != 0)
3496 return (error);
3497
3498 error = if_state_update(ifp, &ifr->ifr_interface_state);
3499
3500 break;
3501 case SIOCSIFPROBECONNECTIVITY:
3502 if ((error = priv_check_cred(kauth_cred_get(),
3503 PRIV_NET_INTERFACE_CONTROL, 0)) != 0)
3504 return (error);
3505 error = if_probe_connectivity(ifp,
3506 ifr->ifr_probe_connectivity);
3507 break;
3508 case SIOCGIFPROBECONNECTIVITY:
3509 if ((error = priv_check_cred(kauth_cred_get(),
3510 PRIV_NET_INTERFACE_CONTROL, 0)) != 0)
3511 return (error);
3512 if (ifp->if_eflags & IFEF_PROBE_CONNECTIVITY)
3513 ifr->ifr_probe_connectivity = 1;
3514 else
3515 ifr->ifr_probe_connectivity = 0;
3516 break;
3517 case SIOCGECNMODE:
3518 if ((ifp->if_eflags & (IFEF_ECN_ENABLE|IFEF_ECN_DISABLE)) ==
3519 IFEF_ECN_ENABLE)
3520 ifr->ifr_ecn_mode = IFRTYPE_ECN_ENABLE;
3521 else if ((ifp->if_eflags & (IFEF_ECN_ENABLE|IFEF_ECN_DISABLE)) ==
3522 IFEF_ECN_DISABLE)
3523 ifr->ifr_ecn_mode = IFRTYPE_ECN_DISABLE;
3524 else
3525 ifr->ifr_ecn_mode = IFRTYPE_ECN_DEFAULT;
3526 break;
3527 case SIOCSECNMODE:
3528 if ((error = priv_check_cred(kauth_cred_get(),
3529 PRIV_NET_INTERFACE_CONTROL, 0)) != 0)
3530 return (error);
3531 if (ifr->ifr_ecn_mode == IFRTYPE_ECN_DEFAULT) {
3532 ifp->if_eflags &= ~(IFEF_ECN_ENABLE|IFEF_ECN_DISABLE);
3533 } else if (ifr->ifr_ecn_mode == IFRTYPE_ECN_ENABLE) {
3534 ifp->if_eflags |= IFEF_ECN_ENABLE;
3535 ifp->if_eflags &= ~IFEF_ECN_DISABLE;
3536 } else if (ifr->ifr_ecn_mode == IFRTYPE_ECN_DISABLE) {
3537 ifp->if_eflags |= IFEF_ECN_DISABLE;
3538 ifp->if_eflags &= ~IFEF_ECN_ENABLE;
3539 } else
3540 error = EINVAL;
3541 break;
3542 case SIOCSIFTIMESTAMPENABLE:
3543 case SIOCSIFTIMESTAMPDISABLE:
3544 error = proc_suser(p);
3545 if (error != 0)
3546 break;
3547
3548 ifnet_lock_exclusive(ifp);
3549 if ((cmd == SIOCSIFTIMESTAMPENABLE &&
3550 (ifp->if_xflags & IFXF_TIMESTAMP_ENABLED) != 0) ||
3551 (cmd == SIOCSIFTIMESTAMPDISABLE &&
3552 (ifp->if_xflags & IFXF_TIMESTAMP_ENABLED) == 0)) {
3553 ifnet_lock_done(ifp);
3554 break;
3555 }
3556 if (cmd == SIOCSIFTIMESTAMPENABLE)
3557 ifp->if_xflags |= IFXF_TIMESTAMP_ENABLED;
3558 else
3559 ifp->if_xflags &= ~IFXF_TIMESTAMP_ENABLED;
3560 ifnet_lock_done(ifp);
3561 /*
3562 * Pass the setting to the interface if it supports either
3563 * software or hardware time stamping
3564 */
3565 if (ifp->if_capabilities & (IFCAP_HW_TIMESTAMP |
3566 IFCAP_SW_TIMESTAMP)) {
3567 error = ifnet_ioctl(ifp, SOCK_DOM(so), cmd,
3568 (caddr_t)ifr);
3569 }
3570 break;
3571 case SIOCGIFTIMESTAMPENABLED: {
3572 if ((ifp->if_xflags & IFXF_TIMESTAMP_ENABLED) != 0)
3573 ifr->ifr_intval = 1;
3574 else
3575 ifr->ifr_intval = 0;
3576 break;
3577 }
3578 case SIOCSQOSMARKINGMODE:
3579 if ((error = priv_check_cred(kauth_cred_get(),
3580 PRIV_NET_INTERFACE_CONTROL, 0)) != 0)
3581 return (error);
3582 error = if_set_qosmarking_mode(ifp, ifr->ifr_qosmarking_mode);
3583 break;
3584
3585 case SIOCGQOSMARKINGMODE:
3586 ifr->ifr_qosmarking_mode = ifp->if_qosmarking_mode;
3587 break;
3588
3589 case SIOCSQOSMARKINGENABLED:
3590 if ((error = priv_check_cred(kauth_cred_get(),
3591 PRIV_NET_INTERFACE_CONTROL, 0)) != 0)
3592 return (error);
3593 if (ifr->ifr_qosmarking_enabled != 0)
3594 ifp->if_eflags |= IFEF_QOSMARKING_ENABLED;
3595 else
3596 ifp->if_eflags &= ~IFEF_QOSMARKING_ENABLED;
3597 break;
3598
3599 case SIOCGQOSMARKINGENABLED:
3600 ifr->ifr_qosmarking_enabled =
3601 (ifp->if_eflags & IFEF_QOSMARKING_ENABLED) ? 1 : 0;
3602 break;
3603
3604 case SIOCSIFDISABLEOUTPUT:
3605#if (DEBUG || DEVELOPMENT)
3606 if (ifr->ifr_disable_output == 1) {
3607 error = ifnet_disable_output(ifp);
3608 } else if (ifr->ifr_disable_output == 0) {
3609 error = ifnet_enable_output(ifp);
3610 } else {
3611 error = EINVAL;
3612 }
3613#else
3614 error = EINVAL;
3615#endif /* (DEBUG || DEVELOPMENT) */
3616 break;
3617 case SIOCSIFLOWINTERNET:
3618 if ((error = priv_check_cred(kauth_cred_get(),
3619 PRIV_NET_INTERFACE_CONTROL, 0)) != 0)
3620 return (error);
3621
3622 ifnet_lock_exclusive(ifp);
3623 if (ifr->ifr_low_internet & IFRTYPE_LOW_INTERNET_ENABLE_UL)
3624 ifp->if_xflags |= IFXF_LOW_INTERNET_UL;
3625 else
3626 ifp->if_xflags &= ~(IFXF_LOW_INTERNET_UL);
3627 if (ifr->ifr_low_internet & IFRTYPE_LOW_INTERNET_ENABLE_DL)
3628 ifp->if_xflags |= IFXF_LOW_INTERNET_DL;
3629 else
3630 ifp->if_xflags &= ~(IFXF_LOW_INTERNET_DL);
3631 ifnet_lock_done(ifp);
3632 break;
3633 case SIOCGIFLOWINTERNET:
3634 ifnet_lock_shared(ifp);
3635 ifr->ifr_low_internet = 0;
3636 if (ifp->if_xflags & IFXF_LOW_INTERNET_UL)
3637 ifr->ifr_low_internet |=
3638 IFRTYPE_LOW_INTERNET_ENABLE_UL;
3639 if (ifp->if_xflags & IFXF_LOW_INTERNET_DL)
3640 ifr->ifr_low_internet |=
3641 IFRTYPE_LOW_INTERNET_ENABLE_DL;
3642 ifnet_lock_done(ifp);
3643 break;
3644 case SIOCGIFLOWPOWER:
3645 ifr->ifr_low_power_mode =
3646 !!(ifp->if_xflags & IFXF_LOW_POWER);
3647 break;
3648 case SIOCSIFLOWPOWER:
3649#if (DEVELOPMENT || DEBUG)
3650 error = if_set_low_power(ifp, !!(ifr->ifr_low_power_mode));
3651#else /* DEVELOPMENT || DEBUG */
3652 error = EOPNOTSUPP;
3653#endif /* DEVELOPMENT || DEBUG */
3654 break;
3655 default:
3656 VERIFY(0);
3657 /* NOTREACHED */
3658 }
3659
3660 return (error);
3661}
3662
3663int
3664ifioctllocked(struct socket *so, u_long cmd, caddr_t data, struct proc *p)
3665{
3666 int error;
3667
3668 socket_unlock(so, 0);
3669 error = ifioctl(so, cmd, data, p);
3670 socket_lock(so, 0);
3671 return (error);
3672}
3673
3674/*
3675 * Set/clear promiscuous mode on interface ifp based on the truth value
3676 * of pswitch. The calls are reference counted so that only the first
3677 * "on" request actually has an effect, as does the final "off" request.
3678 * Results are undefined if the "off" and "on" requests are not matched.
3679 */
3680errno_t
3681ifnet_set_promiscuous(
3682 ifnet_t ifp,
3683 int pswitch)
3684{
3685 int error = 0;
3686 int oldflags = 0;
3687 int newflags = 0;
3688
3689 ifnet_lock_exclusive(ifp);
3690 oldflags = ifp->if_flags;
3691 ifp->if_pcount += pswitch ? 1 : -1;
3692
3693 if (ifp->if_pcount > 0)
3694 ifp->if_flags |= IFF_PROMISC;
3695 else
3696 ifp->if_flags &= ~IFF_PROMISC;
3697
3698 newflags = ifp->if_flags;
3699 ifnet_lock_done(ifp);
3700
3701 if (newflags != oldflags && (newflags & IFF_UP) != 0) {
3702 error = ifnet_ioctl(ifp, 0, SIOCSIFFLAGS, NULL);
3703 if (error == 0) {
3704 rt_ifmsg(ifp);
3705 } else {
3706 ifnet_lock_exclusive(ifp);
3707 // revert the flags
3708 ifp->if_pcount -= pswitch ? 1 : -1;
3709 if (ifp->if_pcount > 0)
3710 ifp->if_flags |= IFF_PROMISC;
3711 else
3712 ifp->if_flags &= ~IFF_PROMISC;
3713 ifnet_lock_done(ifp);
3714 }
3715 }
3716
3717 if (newflags != oldflags) {
3718 log(LOG_INFO, "%s: promiscuous mode %s%s\n",
3719 if_name(ifp),
3720 (newflags & IFF_PROMISC) != 0 ? "enable" : "disable",
3721 error != 0 ? " failed" : " succeeded");
3722 }
3723 return (error);
3724}
3725
3726/*
3727 * Return interface configuration
3728 * of system. List may be used
3729 * in later ioctl's (above) to get
3730 * other information.
3731 */
3732/*ARGSUSED*/
3733static int
3734ifconf(u_long cmd, user_addr_t ifrp, int *ret_space)
3735{
3736 struct ifnet *ifp = NULL;
3737 struct ifaddr *ifa;
3738 struct ifreq ifr;
3739 int error = 0;
3740 size_t space;
3741 net_thread_marks_t marks;
3742
3743 marks = net_thread_marks_push(NET_THREAD_CKREQ_LLADDR);
3744
3745 /*
3746 * Zero the ifr buffer to make sure we don't
3747 * disclose the contents of the stack.
3748 */
3749 bzero(&ifr, sizeof (struct ifreq));
3750
3751 space = *ret_space;
3752 ifnet_head_lock_shared();
3753 for (ifp = ifnet_head.tqh_first; space > sizeof (ifr) &&
3754 ifp; ifp = ifp->if_link.tqe_next) {
3755 char workbuf[64];
3756 size_t ifnlen, addrs;
3757
3758 ifnlen = snprintf(workbuf, sizeof (workbuf),
3759 "%s", if_name(ifp));
3760 if (ifnlen + 1 > sizeof (ifr.ifr_name)) {
3761 error = ENAMETOOLONG;
3762 break;
3763 } else {
3764 strlcpy(ifr.ifr_name, workbuf, IFNAMSIZ);
3765 }
3766
3767 ifnet_lock_shared(ifp);
3768
3769 addrs = 0;
3770 ifa = ifp->if_addrhead.tqh_first;
3771 for (; space > sizeof (ifr) && ifa;
3772 ifa = ifa->ifa_link.tqe_next) {
3773 struct sockaddr *sa;
3774 union {
3775 struct sockaddr sa;
3776 struct sockaddr_dl sdl;
3777 uint8_t buf[SOCK_MAXADDRLEN + 1];
3778 } u;
3779
3780 /*
3781 * Make sure to accomodate the largest possible
3782 * size of SA(if_lladdr)->sa_len.
3783 */
3784 _CASSERT(sizeof (u) == (SOCK_MAXADDRLEN + 1));
3785
3786 IFA_LOCK(ifa);
3787 sa = ifa->ifa_addr;
3788 addrs++;
3789
3790 if (ifa == ifp->if_lladdr) {
3791 VERIFY(sa->sa_family == AF_LINK);
3792 bcopy(sa, &u, sa->sa_len);
3793 IFA_UNLOCK(ifa);
3794 ifnet_guarded_lladdr_copy_bytes(ifp,
3795 LLADDR(&u.sdl), u.sdl.sdl_alen);
3796 IFA_LOCK(ifa);
3797 sa = &u.sa;
3798 }
3799
3800 if (cmd == OSIOCGIFCONF32 || cmd == OSIOCGIFCONF64) {
3801 struct osockaddr *osa =
3802 (struct osockaddr *)(void *)&ifr.ifr_addr;
3803 ifr.ifr_addr = *sa;
3804 osa->sa_family = sa->sa_family;
3805 error = copyout((caddr_t)&ifr, ifrp,
3806 sizeof (ifr));
3807 ifrp += sizeof (struct ifreq);
3808 } else if (sa->sa_len <= sizeof (*sa)) {
3809 ifr.ifr_addr = *sa;
3810 error = copyout((caddr_t)&ifr, ifrp,
3811 sizeof (ifr));
3812 ifrp += sizeof (struct ifreq);
3813 } else {
3814 if (space <
3815 sizeof (ifr) + sa->sa_len - sizeof (*sa)) {
3816 IFA_UNLOCK(ifa);
3817 break;
3818 }
3819 space -= sa->sa_len - sizeof (*sa);
3820 error = copyout((caddr_t)&ifr, ifrp,
3821 sizeof (ifr.ifr_name));
3822 if (error == 0) {
3823 error = copyout((caddr_t)sa, (ifrp +
3824 offsetof(struct ifreq, ifr_addr)),
3825 sa->sa_len);
3826 }
3827 ifrp += (sa->sa_len + offsetof(struct ifreq,
3828 ifr_addr));
3829 }
3830 IFA_UNLOCK(ifa);
3831 if (error)
3832 break;
3833 space -= sizeof (ifr);
3834 }
3835 ifnet_lock_done(ifp);
3836
3837 if (error)
3838 break;
3839 if (!addrs) {
3840 bzero((caddr_t)&ifr.ifr_addr, sizeof (ifr.ifr_addr));
3841 error = copyout((caddr_t)&ifr, ifrp, sizeof (ifr));
3842 if (error)
3843 break;
3844 space -= sizeof (ifr);
3845 ifrp += sizeof (struct ifreq);
3846 }
3847 }
3848 ifnet_head_done();
3849 *ret_space -= space;
3850 net_thread_marks_pop(marks);
3851 return (error);
3852}
3853
3854/*
3855 * Just like if_promisc(), but for all-multicast-reception mode.
3856 */
3857int
3858if_allmulti(struct ifnet *ifp, int onswitch)
3859{
3860 int error = 0;
3861 int modified = 0;
3862
3863 ifnet_lock_exclusive(ifp);
3864
3865 if (onswitch) {
3866 if (ifp->if_amcount++ == 0) {
3867 ifp->if_flags |= IFF_ALLMULTI;
3868 modified = 1;
3869 }
3870 } else {
3871 if (ifp->if_amcount > 1) {
3872 ifp->if_amcount--;
3873 } else {
3874 ifp->if_amcount = 0;
3875 ifp->if_flags &= ~IFF_ALLMULTI;
3876 modified = 1;
3877 }
3878 }
3879 ifnet_lock_done(ifp);
3880
3881 if (modified)
3882 error = ifnet_ioctl(ifp, 0, SIOCSIFFLAGS, NULL);
3883
3884 if (error == 0)
3885 rt_ifmsg(ifp);
3886 return (error);
3887}
3888
3889static struct ifmultiaddr *
3890ifma_alloc(int how)
3891{
3892 struct ifmultiaddr *ifma;
3893
3894 ifma = (how == M_WAITOK) ? zalloc(ifma_zone) :
3895 zalloc_noblock(ifma_zone);
3896
3897 if (ifma != NULL) {
3898 bzero(ifma, ifma_size);
3899 lck_mtx_init(&ifma->ifma_lock, ifa_mtx_grp, ifa_mtx_attr);
3900 ifma->ifma_debug |= IFD_ALLOC;
3901 if (ifma_debug != 0) {
3902 ifma->ifma_debug |= IFD_DEBUG;
3903 ifma->ifma_trace = ifma_trace;
3904 }
3905 }
3906 return (ifma);
3907}
3908
3909static void
3910ifma_free(struct ifmultiaddr *ifma)
3911{
3912 IFMA_LOCK(ifma);
3913
3914 if (ifma->ifma_protospec != NULL) {
3915 panic("%s: Protospec not NULL for ifma=%p", __func__, ifma);
3916 /* NOTREACHED */
3917 } else if ((ifma->ifma_flags & IFMAF_ANONYMOUS) ||
3918 ifma->ifma_anoncnt != 0) {
3919 panic("%s: Freeing ifma=%p with outstanding anon req",
3920 __func__, ifma);
3921 /* NOTREACHED */
3922 } else if (ifma->ifma_debug & IFD_ATTACHED) {
3923 panic("%s: ifma=%p attached to ifma_ifp=%p is being freed",
3924 __func__, ifma, ifma->ifma_ifp);
3925 /* NOTREACHED */
3926 } else if (!(ifma->ifma_debug & IFD_ALLOC)) {
3927 panic("%s: ifma %p cannot be freed", __func__, ifma);
3928 /* NOTREACHED */
3929 } else if (ifma->ifma_refcount != 0) {
3930 panic("%s: non-zero refcount ifma=%p", __func__, ifma);
3931 /* NOTREACHED */
3932 } else if (ifma->ifma_reqcnt != 0) {
3933 panic("%s: non-zero reqcnt ifma=%p", __func__, ifma);
3934 /* NOTREACHED */
3935 } else if (ifma->ifma_ifp != NULL) {
3936 panic("%s: non-NULL ifma_ifp=%p for ifma=%p", __func__,
3937 ifma->ifma_ifp, ifma);
3938 /* NOTREACHED */
3939 } else if (ifma->ifma_ll != NULL) {
3940 panic("%s: non-NULL ifma_ll=%p for ifma=%p", __func__,
3941 ifma->ifma_ll, ifma);
3942 /* NOTREACHED */
3943 }
3944 ifma->ifma_debug &= ~IFD_ALLOC;
3945 if ((ifma->ifma_debug & (IFD_DEBUG | IFD_TRASHED)) ==
3946 (IFD_DEBUG | IFD_TRASHED)) {
3947 lck_mtx_lock(&ifma_trash_lock);
3948 TAILQ_REMOVE(&ifma_trash_head, (struct ifmultiaddr_dbg *)ifma,
3949 ifma_trash_link);
3950 lck_mtx_unlock(&ifma_trash_lock);
3951 ifma->ifma_debug &= ~IFD_TRASHED;
3952 }
3953 IFMA_UNLOCK(ifma);
3954
3955 if (ifma->ifma_addr != NULL) {
3956 FREE(ifma->ifma_addr, M_IFADDR);
3957 ifma->ifma_addr = NULL;
3958 }
3959 lck_mtx_destroy(&ifma->ifma_lock, ifa_mtx_grp);
3960 zfree(ifma_zone, ifma);
3961}
3962
3963static void
3964ifma_trace(struct ifmultiaddr *ifma, int refhold)
3965{
3966 struct ifmultiaddr_dbg *ifma_dbg = (struct ifmultiaddr_dbg *)ifma;
3967 ctrace_t *tr;
3968 u_int32_t idx;
3969 u_int16_t *cnt;
3970
3971 if (!(ifma->ifma_debug & IFD_DEBUG)) {
3972 panic("%s: ifma %p has no debug structure", __func__, ifma);
3973 /* NOTREACHED */
3974 }
3975 if (refhold) {
3976 cnt = &ifma_dbg->ifma_refhold_cnt;
3977 tr = ifma_dbg->ifma_refhold;
3978 } else {
3979 cnt = &ifma_dbg->ifma_refrele_cnt;
3980 tr = ifma_dbg->ifma_refrele;
3981 }
3982
3983 idx = atomic_add_16_ov(cnt, 1) % IFMA_TRACE_HIST_SIZE;
3984 ctrace_record(&tr[idx]);
3985}
3986
3987void
3988ifma_addref(struct ifmultiaddr *ifma, int locked)
3989{
3990 if (!locked)
3991 IFMA_LOCK(ifma);
3992 else
3993 IFMA_LOCK_ASSERT_HELD(ifma);
3994
3995 if (++ifma->ifma_refcount == 0) {
3996 panic("%s: ifma=%p wraparound refcnt", __func__, ifma);
3997 /* NOTREACHED */
3998 } else if (ifma->ifma_trace != NULL) {
3999 (*ifma->ifma_trace)(ifma, TRUE);
4000 }
4001 if (!locked)
4002 IFMA_UNLOCK(ifma);
4003}
4004
4005void
4006ifma_remref(struct ifmultiaddr *ifma)
4007{
4008 struct ifmultiaddr *ll;
4009
4010 IFMA_LOCK(ifma);
4011
4012 if (ifma->ifma_refcount == 0) {
4013 panic("%s: ifma=%p negative refcnt", __func__, ifma);
4014 /* NOTREACHED */
4015 } else if (ifma->ifma_trace != NULL) {
4016 (*ifma->ifma_trace)(ifma, FALSE);
4017 }
4018
4019 --ifma->ifma_refcount;
4020 if (ifma->ifma_refcount > 0) {
4021 IFMA_UNLOCK(ifma);
4022 return;
4023 }
4024
4025 ll = ifma->ifma_ll;
4026 ifma->ifma_ifp = NULL;
4027 ifma->ifma_ll = NULL;
4028 IFMA_UNLOCK(ifma);
4029 ifma_free(ifma); /* deallocate it */
4030
4031 if (ll != NULL)
4032 IFMA_REMREF(ll);
4033}
4034
4035static void
4036if_attach_ifma(struct ifnet *ifp, struct ifmultiaddr *ifma, int anon)
4037{
4038 ifnet_lock_assert(ifp, IFNET_LCK_ASSERT_EXCLUSIVE);
4039 IFMA_LOCK_ASSERT_HELD(ifma);
4040
4041 if (ifma->ifma_ifp != ifp) {
4042 panic("%s: Mismatch ifma_ifp=%p != ifp=%p", __func__,
4043 ifma->ifma_ifp, ifp);
4044 /* NOTREACHED */
4045 } else if (ifma->ifma_debug & IFD_ATTACHED) {
4046 panic("%s: Attempt to attach an already attached ifma=%p",
4047 __func__, ifma);
4048 /* NOTREACHED */
4049 } else if (anon && (ifma->ifma_flags & IFMAF_ANONYMOUS)) {
4050 panic("%s: ifma=%p unexpected IFMAF_ANONYMOUS", __func__, ifma);
4051 /* NOTREACHED */
4052 } else if (ifma->ifma_debug & IFD_TRASHED) {
4053 panic("%s: Attempt to reattach a detached ifma=%p",
4054 __func__, ifma);
4055 /* NOTREACHED */
4056 }
4057
4058 ifma->ifma_reqcnt++;
4059 VERIFY(ifma->ifma_reqcnt == 1);
4060 IFMA_ADDREF_LOCKED(ifma);
4061 ifma->ifma_debug |= IFD_ATTACHED;
4062 if (anon) {
4063 ifma->ifma_anoncnt++;
4064 VERIFY(ifma->ifma_anoncnt == 1);
4065 ifma->ifma_flags |= IFMAF_ANONYMOUS;
4066 }
4067
4068 LIST_INSERT_HEAD(&ifp->if_multiaddrs, ifma, ifma_link);
4069}
4070
4071static int
4072if_detach_ifma(struct ifnet *ifp, struct ifmultiaddr *ifma, int anon)
4073{
4074 ifnet_lock_assert(ifp, IFNET_LCK_ASSERT_EXCLUSIVE);
4075 IFMA_LOCK_ASSERT_HELD(ifma);
4076
4077 if (ifma->ifma_reqcnt == 0) {
4078 panic("%s: ifma=%p negative reqcnt", __func__, ifma);
4079 /* NOTREACHED */
4080 } else if (anon && !(ifma->ifma_flags & IFMAF_ANONYMOUS)) {
4081 panic("%s: ifma=%p missing IFMAF_ANONYMOUS", __func__, ifma);
4082 /* NOTREACHED */
4083 } else if (anon && ifma->ifma_anoncnt == 0) {
4084 panic("%s: ifma=%p negative anonreqcnt", __func__, ifma);
4085 /* NOTREACHED */
4086 } else if (ifma->ifma_ifp != ifp) {
4087 panic("%s: Mismatch ifma_ifp=%p, ifp=%p", __func__,
4088 ifma->ifma_ifp, ifp);
4089 /* NOTREACHED */
4090 }
4091
4092 if (anon) {
4093 --ifma->ifma_anoncnt;
4094 if (ifma->ifma_anoncnt > 0)
4095 return (0);
4096 ifma->ifma_flags &= ~IFMAF_ANONYMOUS;
4097 }
4098
4099 --ifma->ifma_reqcnt;
4100 if (ifma->ifma_reqcnt > 0)
4101 return (0);
4102
4103 if (ifma->ifma_protospec != NULL) {
4104 panic("%s: Protospec not NULL for ifma=%p", __func__, ifma);
4105 /* NOTREACHED */
4106 } else if ((ifma->ifma_flags & IFMAF_ANONYMOUS) ||
4107 ifma->ifma_anoncnt != 0) {
4108 panic("%s: Detaching ifma=%p with outstanding anon req",
4109 __func__, ifma);
4110 /* NOTREACHED */
4111 } else if (!(ifma->ifma_debug & IFD_ATTACHED)) {
4112 panic("%s: Attempt to detach an unattached address ifma=%p",
4113 __func__, ifma);
4114 /* NOTREACHED */
4115 } else if (ifma->ifma_debug & IFD_TRASHED) {
4116 panic("%s: ifma %p is already in trash list", __func__, ifma);
4117 /* NOTREACHED */
4118 }
4119
4120 /*
4121 * NOTE: Caller calls IFMA_REMREF
4122 */
4123 ifma->ifma_debug &= ~IFD_ATTACHED;
4124 LIST_REMOVE(ifma, ifma_link);
4125 if (LIST_EMPTY(&ifp->if_multiaddrs))
4126 ifp->if_updatemcasts = 0;
4127
4128 if (ifma->ifma_debug & IFD_DEBUG) {
4129 /* Become a regular mutex, just in case */
4130 IFMA_CONVERT_LOCK(ifma);
4131 lck_mtx_lock(&ifma_trash_lock);
4132 TAILQ_INSERT_TAIL(&ifma_trash_head,
4133 (struct ifmultiaddr_dbg *)ifma, ifma_trash_link);
4134 lck_mtx_unlock(&ifma_trash_lock);
4135 ifma->ifma_debug |= IFD_TRASHED;
4136 }
4137
4138 return (1);
4139}
4140
4141/*
4142 * Find an ifmultiaddr that matches a socket address on an interface.
4143 *
4144 * Caller is responsible for holding the ifnet_lock while calling
4145 * this function.
4146 */
4147static int
4148if_addmulti_doesexist(struct ifnet *ifp, const struct sockaddr *sa,
4149 struct ifmultiaddr **retifma, int anon)
4150{
4151 struct ifmultiaddr *ifma;
4152
4153 for (ifma = LIST_FIRST(&ifp->if_multiaddrs); ifma != NULL;
4154 ifma = LIST_NEXT(ifma, ifma_link)) {
4155 IFMA_LOCK_SPIN(ifma);
4156 if (!ifa_equal(sa, ifma->ifma_addr)) {
4157 IFMA_UNLOCK(ifma);
4158 continue;
4159 }
4160 if (anon) {
4161 VERIFY(!(ifma->ifma_flags & IFMAF_ANONYMOUS) ||
4162 ifma->ifma_anoncnt != 0);
4163 VERIFY((ifma->ifma_flags & IFMAF_ANONYMOUS) ||
4164 ifma->ifma_anoncnt == 0);
4165 ifma->ifma_anoncnt++;
4166 if (!(ifma->ifma_flags & IFMAF_ANONYMOUS)) {
4167 VERIFY(ifma->ifma_anoncnt == 1);
4168 ifma->ifma_flags |= IFMAF_ANONYMOUS;
4169 }
4170 }
4171 if (!anon || ifma->ifma_anoncnt == 1) {
4172 ifma->ifma_reqcnt++;
4173 VERIFY(ifma->ifma_reqcnt > 1);
4174 }
4175 if (retifma != NULL) {
4176 *retifma = ifma;
4177 IFMA_ADDREF_LOCKED(ifma);
4178 }
4179 IFMA_UNLOCK(ifma);
4180 return (0);
4181 }
4182 return (ENOENT);
4183}
4184
4185/*
4186 * Radar 3642395, make sure all multicasts are in a standard format.
4187 */
4188static struct sockaddr *
4189copy_and_normalize(const struct sockaddr *original)
4190{
4191 int alen = 0;
4192 const u_char *aptr = NULL;
4193 struct sockaddr *copy = NULL;
4194 struct sockaddr_dl *sdl_new = NULL;
4195 int len = 0;
4196
4197 if (original->sa_family != AF_LINK &&
4198 original->sa_family != AF_UNSPEC) {
4199 /* Just make a copy */
4200 MALLOC(copy, struct sockaddr *, original->sa_len,
4201 M_IFADDR, M_WAITOK);
4202 if (copy != NULL)
4203 bcopy(original, copy, original->sa_len);
4204 return (copy);
4205 }
4206
4207 switch (original->sa_family) {
4208 case AF_LINK: {
4209 const struct sockaddr_dl *sdl_original =
4210 (struct sockaddr_dl *)(uintptr_t)(size_t)original;
4211
4212 if (sdl_original->sdl_nlen + sdl_original->sdl_alen +
4213 sdl_original->sdl_slen +
4214 offsetof(struct sockaddr_dl, sdl_data) >
4215 sdl_original->sdl_len)
4216 return (NULL);
4217
4218 alen = sdl_original->sdl_alen;
4219 aptr = CONST_LLADDR(sdl_original);
4220 }
4221 break;
4222
4223 case AF_UNSPEC: {
4224 if (original->sa_len < ETHER_ADDR_LEN +
4225 offsetof(struct sockaddr, sa_data)) {
4226 return (NULL);
4227 }
4228
4229 alen = ETHER_ADDR_LEN;
4230 aptr = (const u_char *)original->sa_data;
4231 }
4232 break;
4233 }
4234
4235 if (alen == 0 || aptr == NULL)
4236 return (NULL);
4237
4238 len = alen + offsetof(struct sockaddr_dl, sdl_data);
4239 MALLOC(sdl_new, struct sockaddr_dl *, len, M_IFADDR, M_WAITOK);
4240
4241 if (sdl_new != NULL) {
4242 bzero(sdl_new, len);
4243 sdl_new->sdl_len = len;
4244 sdl_new->sdl_family = AF_LINK;
4245 sdl_new->sdl_alen = alen;
4246 bcopy(aptr, LLADDR(sdl_new), alen);
4247 }
4248
4249 return ((struct sockaddr *)sdl_new);
4250}
4251
4252/*
4253 * Network-layer protocol domains which hold references to the underlying
4254 * link-layer record must use this routine.
4255 */
4256int
4257if_addmulti(struct ifnet *ifp, const struct sockaddr *sa,
4258 struct ifmultiaddr **retifma)
4259{
4260 return (if_addmulti_common(ifp, sa, retifma, 0));
4261}
4262
4263/*
4264 * Anything other than network-layer protocol domains which hold references
4265 * to the underlying link-layer record must use this routine: SIOCADDMULTI
4266 * ioctl, ifnet_add_multicast(), if_bond.
4267 */
4268int
4269if_addmulti_anon(struct ifnet *ifp, const struct sockaddr *sa,
4270 struct ifmultiaddr **retifma)
4271{
4272 return (if_addmulti_common(ifp, sa, retifma, 1));
4273}
4274
4275/*
4276 * Register an additional multicast address with a network interface.
4277 *
4278 * - If the address is already present, bump the reference count on the
4279 * address and return.
4280 * - If the address is not link-layer, look up a link layer address.
4281 * - Allocate address structures for one or both addresses, and attach to the
4282 * multicast address list on the interface. If automatically adding a link
4283 * layer address, the protocol address will own a reference to the link
4284 * layer address, to be freed when it is freed.
4285 * - Notify the network device driver of an addition to the multicast address
4286 * list.
4287 *
4288 * 'sa' points to caller-owned memory with the desired multicast address.
4289 *
4290 * 'retifma' will be used to return a pointer to the resulting multicast
4291 * address reference, if desired.
4292 *
4293 * 'anon' indicates a link-layer address with no protocol address reference
4294 * made to it. Anything other than network-layer protocol domain requests
4295 * are considered as anonymous.
4296 */
4297static int
4298if_addmulti_common(struct ifnet *ifp, const struct sockaddr *sa,
4299 struct ifmultiaddr **retifma, int anon)
4300{
4301 struct sockaddr_storage storage;
4302 struct sockaddr *llsa = NULL;
4303 struct sockaddr *dupsa = NULL;
4304 int error = 0, ll_firstref = 0, lladdr;
4305 struct ifmultiaddr *ifma = NULL;
4306 struct ifmultiaddr *llifma = NULL;
4307
4308 /* Only AF_UNSPEC/AF_LINK is allowed for an "anonymous" address */
4309 VERIFY(!anon || sa->sa_family == AF_UNSPEC ||
4310 sa->sa_family == AF_LINK);
4311
4312 /* If sa is a AF_LINK or AF_UNSPEC, duplicate and normalize it */
4313 if (sa->sa_family == AF_LINK || sa->sa_family == AF_UNSPEC) {
4314 dupsa = copy_and_normalize(sa);
4315 if (dupsa == NULL) {
4316 error = ENOMEM;
4317 goto cleanup;
4318 }
4319 sa = dupsa;
4320 }
4321
4322 ifnet_lock_exclusive(ifp);
4323 if (!(ifp->if_flags & IFF_MULTICAST)) {
4324 error = EADDRNOTAVAIL;
4325 ifnet_lock_done(ifp);
4326 goto cleanup;
4327 }
4328
4329 /* If the address is already present, return a new reference to it */
4330 error = if_addmulti_doesexist(ifp, sa, retifma, anon);
4331 ifnet_lock_done(ifp);
4332 if (error == 0)
4333 goto cleanup;
4334
4335 /*
4336 * The address isn't already present; give the link layer a chance
4337 * to accept/reject it, and also find out which AF_LINK address this
4338 * maps to, if it isn't one already.
4339 */
4340 error = dlil_resolve_multi(ifp, sa, (struct sockaddr *)&storage,
4341 sizeof (storage));
4342 if (error == 0 && storage.ss_len != 0) {
4343 llsa = copy_and_normalize((struct sockaddr *)&storage);
4344 if (llsa == NULL) {
4345 error = ENOMEM;
4346 goto cleanup;
4347 }
4348
4349 llifma = ifma_alloc(M_WAITOK);
4350 if (llifma == NULL) {
4351 error = ENOMEM;
4352 goto cleanup;
4353 }
4354 }
4355
4356 /* to be similar to FreeBSD */
4357 if (error == EOPNOTSUPP)
4358 error = 0;
4359 else if (error != 0)
4360 goto cleanup;
4361
4362 /* Allocate while we aren't holding any locks */
4363 if (dupsa == NULL) {
4364 dupsa = copy_and_normalize(sa);
4365 if (dupsa == NULL) {
4366 error = ENOMEM;
4367 goto cleanup;
4368 }
4369 }
4370 ifma = ifma_alloc(M_WAITOK);
4371 if (ifma == NULL) {
4372 error = ENOMEM;
4373 goto cleanup;
4374 }
4375
4376 ifnet_lock_exclusive(ifp);
4377 /*
4378 * Check again for the matching multicast.
4379 */
4380 error = if_addmulti_doesexist(ifp, sa, retifma, anon);
4381 if (error == 0) {
4382 ifnet_lock_done(ifp);
4383 goto cleanup;
4384 }
4385
4386 if (llifma != NULL) {
4387 VERIFY(!anon); /* must not get here if "anonymous" */
4388 if (if_addmulti_doesexist(ifp, llsa, &ifma->ifma_ll, 0) == 0) {
4389 FREE(llsa, M_IFADDR);
4390 llsa = NULL;
4391 ifma_free(llifma);
4392 llifma = NULL;
4393 VERIFY(ifma->ifma_ll->ifma_ifp == ifp);
4394 } else {
4395 ll_firstref = 1;
4396 llifma->ifma_addr = llsa;
4397 llifma->ifma_ifp = ifp;
4398 IFMA_LOCK(llifma);
4399 if_attach_ifma(ifp, llifma, 0);
4400 /* add extra refcnt for ifma */
4401 IFMA_ADDREF_LOCKED(llifma);
4402 IFMA_UNLOCK(llifma);
4403 ifma->ifma_ll = llifma;
4404 }
4405 }
4406
4407 /* "anonymous" request should not result in network address */
4408 VERIFY(!anon || ifma->ifma_ll == NULL);
4409
4410 ifma->ifma_addr = dupsa;
4411 ifma->ifma_ifp = ifp;
4412 IFMA_LOCK(ifma);
4413 if_attach_ifma(ifp, ifma, anon);
4414 IFMA_ADDREF_LOCKED(ifma); /* for this routine */
4415 if (retifma != NULL) {
4416 *retifma = ifma;
4417 IFMA_ADDREF_LOCKED(*retifma); /* for caller */
4418 }
4419 lladdr = (ifma->ifma_addr->sa_family == AF_UNSPEC ||
4420 ifma->ifma_addr->sa_family == AF_LINK);
4421 IFMA_UNLOCK(ifma);
4422 ifnet_lock_done(ifp);
4423
4424 rt_newmaddrmsg(RTM_NEWMADDR, ifma);
4425 IFMA_REMREF(ifma); /* for this routine */
4426
4427 /*
4428 * We are certain we have added something, so call down to the
4429 * interface to let them know about it. Do this only for newly-
4430 * added AF_LINK/AF_UNSPEC address in the if_multiaddrs set.
4431 */
4432 if (lladdr || ll_firstref)
4433 (void) ifnet_ioctl(ifp, 0, SIOCADDMULTI, NULL);
4434
4435 if (ifp->if_updatemcasts > 0)
4436 ifp->if_updatemcasts = 0;
4437
4438 return (0);
4439
4440cleanup:
4441 if (ifma != NULL)
4442 ifma_free(ifma);
4443 if (dupsa != NULL)
4444 FREE(dupsa, M_IFADDR);
4445 if (llifma != NULL)
4446 ifma_free(llifma);
4447 if (llsa != NULL)
4448 FREE(llsa, M_IFADDR);
4449
4450 return (error);
4451}
4452
4453/*
4454 * Delete a multicast group membership by network-layer group address.
4455 * This routine is deprecated.
4456 */
4457int
4458if_delmulti(struct ifnet *ifp, const struct sockaddr *sa)
4459{
4460 return (if_delmulti_common(NULL, ifp, sa, 0));
4461}
4462
4463/*
4464 * Delete a multicast group membership by group membership pointer.
4465 * Network-layer protocol domains must use this routine.
4466 */
4467int
4468if_delmulti_ifma(struct ifmultiaddr *ifma)
4469{
4470 return (if_delmulti_common(ifma, NULL, NULL, 0));
4471}
4472
4473/*
4474 * Anything other than network-layer protocol domains which hold references
4475 * to the underlying link-layer record must use this routine: SIOCDELMULTI
4476 * ioctl, ifnet_remove_multicast(), if_bond.
4477 */
4478int
4479if_delmulti_anon(struct ifnet *ifp, const struct sockaddr *sa)
4480{
4481 return (if_delmulti_common(NULL, ifp, sa, 1));
4482}
4483
4484/*
4485 * Delete a multicast group membership by network-layer group address.
4486 *
4487 * Returns ENOENT if the entry could not be found.
4488 */
4489static int
4490if_delmulti_common(struct ifmultiaddr *ifma, struct ifnet *ifp,
4491 const struct sockaddr *sa, int anon)
4492{
4493 struct sockaddr *dupsa = NULL;
4494 int lastref, ll_lastref = 0, lladdr;
4495 struct ifmultiaddr *ll = NULL;
4496
4497 /* sanity check for callers */
4498 VERIFY(ifma != NULL || (ifp != NULL && sa != NULL));
4499
4500 if (ifma != NULL)
4501 ifp = ifma->ifma_ifp;
4502
4503 if (sa != NULL &&
4504 (sa->sa_family == AF_LINK || sa->sa_family == AF_UNSPEC)) {
4505 dupsa = copy_and_normalize(sa);
4506 if (dupsa == NULL)
4507 return (ENOMEM);
4508 sa = dupsa;
4509 }
4510
4511 ifnet_lock_exclusive(ifp);
4512 if (ifma == NULL) {
4513 for (ifma = LIST_FIRST(&ifp->if_multiaddrs); ifma != NULL;
4514 ifma = LIST_NEXT(ifma, ifma_link)) {
4515 IFMA_LOCK(ifma);
4516 if (!ifa_equal(sa, ifma->ifma_addr) ||
4517 (anon && !(ifma->ifma_flags & IFMAF_ANONYMOUS))) {
4518 VERIFY(!(ifma->ifma_flags & IFMAF_ANONYMOUS) ||
4519 ifma->ifma_anoncnt != 0);
4520 IFMA_UNLOCK(ifma);
4521 continue;
4522 }
4523 /* found; keep it locked */
4524 break;
4525 }
4526 if (ifma == NULL) {
4527 if (dupsa != NULL)
4528 FREE(dupsa, M_IFADDR);
4529 ifnet_lock_done(ifp);
4530 return (ENOENT);
4531 }
4532 } else {
4533 IFMA_LOCK(ifma);
4534 }
4535 IFMA_LOCK_ASSERT_HELD(ifma);
4536 IFMA_ADDREF_LOCKED(ifma); /* for this routine */
4537 lastref = if_detach_ifma(ifp, ifma, anon);
4538 VERIFY(!lastref || (!(ifma->ifma_debug & IFD_ATTACHED) &&
4539 ifma->ifma_reqcnt == 0));
4540 VERIFY(!anon || ifma->ifma_ll == NULL);
4541 ll = ifma->ifma_ll;
4542 lladdr = (ifma->ifma_addr->sa_family == AF_UNSPEC ||
4543 ifma->ifma_addr->sa_family == AF_LINK);
4544 IFMA_UNLOCK(ifma);
4545 if (lastref && ll != NULL) {
4546 IFMA_LOCK(ll);
4547 ll_lastref = if_detach_ifma(ifp, ll, 0);
4548 IFMA_UNLOCK(ll);
4549 }
4550 ifnet_lock_done(ifp);
4551
4552 if (lastref)
4553 rt_newmaddrmsg(RTM_DELMADDR, ifma);
4554
4555 if ((ll == NULL && lastref && lladdr) || ll_lastref) {
4556 /*
4557 * Make sure the interface driver is notified in the
4558 * case of a link layer mcast group being left. Do
4559 * this only for a AF_LINK/AF_UNSPEC address that has
4560 * been removed from the if_multiaddrs set.
4561 */
4562 ifnet_ioctl(ifp, 0, SIOCDELMULTI, NULL);
4563 }
4564
4565 if (lastref)
4566 IFMA_REMREF(ifma); /* for if_multiaddrs list */
4567 if (ll_lastref)
4568 IFMA_REMREF(ll); /* for if_multiaddrs list */
4569
4570 IFMA_REMREF(ifma); /* for this routine */
4571 if (dupsa != NULL)
4572 FREE(dupsa, M_IFADDR);
4573
4574 return (0);
4575}
4576
4577/*
4578 * Shutdown all network activity. Used boot() when halting
4579 * system.
4580 */
4581int
4582if_down_all(void)
4583{
4584 struct ifnet **ifp;
4585 u_int32_t count;
4586 u_int32_t i;
4587
4588 if (ifnet_list_get_all(IFNET_FAMILY_ANY, &ifp, &count) == 0) {
4589 for (i = 0; i < count; i++) {
4590 if_down(ifp[i]);
4591 dlil_proto_unplumb_all(ifp[i]);
4592 }
4593 ifnet_list_free(ifp);
4594 }
4595
4596 return (0);
4597}
4598
4599/*
4600 * Delete Routes for a Network Interface
4601 *
4602 * Called for each routing entry via the rnh->rnh_walktree() call above
4603 * to delete all route entries referencing a detaching network interface.
4604 *
4605 * Arguments:
4606 * rn pointer to node in the routing table
4607 * arg argument passed to rnh->rnh_walktree() - detaching interface
4608 *
4609 * Returns:
4610 * 0 successful
4611 * errno failed - reason indicated
4612 *
4613 */
4614static int
4615if_rtdel(struct radix_node *rn, void *arg)
4616{
4617 struct rtentry *rt = (struct rtentry *)rn;
4618 struct ifnet *ifp = arg;
4619 int err;
4620
4621 if (rt == NULL)
4622 return (0);
4623 /*
4624 * Checking against RTF_UP protects against walktree
4625 * recursion problems with cloned routes.
4626 */
4627 RT_LOCK(rt);
4628 if (rt->rt_ifp == ifp && (rt->rt_flags & RTF_UP)) {
4629 /*
4630 * Safe to drop rt_lock and use rt_key, rt_gateway,
4631 * since holding rnh_lock here prevents another thread
4632 * from calling rt_setgate() on this route.
4633 */
4634 RT_UNLOCK(rt);
4635 err = rtrequest_locked(RTM_DELETE, rt_key(rt), rt->rt_gateway,
4636 rt_mask(rt), rt->rt_flags, NULL);
4637 if (err) {
4638 log(LOG_WARNING, "if_rtdel: error %d\n", err);
4639 }
4640 } else {
4641 RT_UNLOCK(rt);
4642 }
4643 return (0);
4644}
4645
4646/*
4647 * Removes routing table reference to a given interface
4648 * for a given protocol family
4649 */
4650void
4651if_rtproto_del(struct ifnet *ifp, int protocol)
4652{
4653 struct radix_node_head *rnh;
4654
4655 if ((protocol <= AF_MAX) && (protocol >= 0) &&
4656 ((rnh = rt_tables[protocol]) != NULL) && (ifp != NULL)) {
4657 lck_mtx_lock(rnh_lock);
4658 (void) rnh->rnh_walktree(rnh, if_rtdel, ifp);
4659 lck_mtx_unlock(rnh_lock);
4660 }
4661}
4662
4663static int
4664if_rtmtu(struct radix_node *rn, void *arg)
4665{
4666 struct rtentry *rt = (struct rtentry *)rn;
4667 struct ifnet *ifp = arg;
4668
4669 RT_LOCK(rt);
4670 if (rt->rt_ifp == ifp) {
4671 /*
4672 * Update the MTU of this entry only if the MTU
4673 * has not been locked (RTV_MTU is not set) and
4674 * if it was non-zero to begin with.
4675 */
4676 if (!(rt->rt_rmx.rmx_locks & RTV_MTU) && rt->rt_rmx.rmx_mtu) {
4677 rt->rt_rmx.rmx_mtu = ifp->if_mtu;
4678 if (rt_key(rt)->sa_family == AF_INET &&
4679 INTF_ADJUST_MTU_FOR_CLAT46(ifp)) {
4680 rt->rt_rmx.rmx_mtu = IN6_LINKMTU(ifp);
4681 /* Further adjust the size for CLAT46 expansion */
4682 rt->rt_rmx.rmx_mtu -= CLAT46_HDR_EXPANSION_OVERHD;
4683 }
4684 }
4685 }
4686 RT_UNLOCK(rt);
4687
4688 return (0);
4689}
4690
4691/*
4692 * Update the MTU metric of all route entries in all protocol tables
4693 * associated with a particular interface; this is called when the
4694 * MTU of that interface has changed.
4695 */
4696static void
4697if_rtmtu_update(struct ifnet *ifp)
4698{
4699 struct radix_node_head *rnh;
4700 int p;
4701
4702 for (p = 0; p < AF_MAX + 1; p++) {
4703 if ((rnh = rt_tables[p]) == NULL)
4704 continue;
4705
4706 lck_mtx_lock(rnh_lock);
4707 (void) rnh->rnh_walktree(rnh, if_rtmtu, ifp);
4708 lck_mtx_unlock(rnh_lock);
4709 }
4710 routegenid_update();
4711}
4712
4713__private_extern__ void
4714if_data_internal_to_if_data(struct ifnet *ifp,
4715 const struct if_data_internal *if_data_int, struct if_data *if_data)
4716{
4717#pragma unused(ifp)
4718#define COPYFIELD(fld) if_data->fld = if_data_int->fld
4719#define COPYFIELD32(fld) if_data->fld = (u_int32_t)(if_data_int->fld)
4720/* compiler will cast down to 32-bit */
4721#define COPYFIELD32_ATOMIC(fld) do { \
4722 atomic_get_64(if_data->fld, \
4723 (u_int64_t *)(void *)(uintptr_t)&if_data_int->fld); \
4724} while (0)
4725
4726 COPYFIELD(ifi_type);
4727 COPYFIELD(ifi_typelen);
4728 COPYFIELD(ifi_physical);
4729 COPYFIELD(ifi_addrlen);
4730 COPYFIELD(ifi_hdrlen);
4731 COPYFIELD(ifi_recvquota);
4732 COPYFIELD(ifi_xmitquota);
4733 if_data->ifi_unused1 = 0;
4734 COPYFIELD(ifi_mtu);
4735 COPYFIELD(ifi_metric);
4736 if (if_data_int->ifi_baudrate & 0xFFFFFFFF00000000LL) {
4737 if_data->ifi_baudrate = 0xFFFFFFFF;
4738 } else {
4739 COPYFIELD32(ifi_baudrate);
4740 }
4741
4742 COPYFIELD32_ATOMIC(ifi_ipackets);
4743 COPYFIELD32_ATOMIC(ifi_ierrors);
4744 COPYFIELD32_ATOMIC(ifi_opackets);
4745 COPYFIELD32_ATOMIC(ifi_oerrors);
4746 COPYFIELD32_ATOMIC(ifi_collisions);
4747 COPYFIELD32_ATOMIC(ifi_ibytes);
4748 COPYFIELD32_ATOMIC(ifi_obytes);
4749 COPYFIELD32_ATOMIC(ifi_imcasts);
4750 COPYFIELD32_ATOMIC(ifi_omcasts);
4751 COPYFIELD32_ATOMIC(ifi_iqdrops);
4752 COPYFIELD32_ATOMIC(ifi_noproto);
4753
4754 COPYFIELD(ifi_recvtiming);
4755 COPYFIELD(ifi_xmittiming);
4756
4757 if_data->ifi_lastchange.tv_sec = if_data_int->ifi_lastchange.tv_sec;
4758 if_data->ifi_lastchange.tv_usec = if_data_int->ifi_lastchange.tv_usec;
4759
4760 if_data->ifi_lastchange.tv_sec += boottime_sec();
4761
4762 if_data->ifi_unused2 = 0;
4763 COPYFIELD(ifi_hwassist);
4764 if_data->ifi_reserved1 = 0;
4765 if_data->ifi_reserved2 = 0;
4766#undef COPYFIELD32_ATOMIC
4767#undef COPYFIELD32
4768#undef COPYFIELD
4769}
4770
4771__private_extern__ void
4772if_data_internal_to_if_data64(struct ifnet *ifp,
4773 const struct if_data_internal *if_data_int,
4774 struct if_data64 *if_data64)
4775{
4776#pragma unused(ifp)
4777#define COPYFIELD64(fld) if_data64->fld = if_data_int->fld
4778#define COPYFIELD64_ATOMIC(fld) do { \
4779 atomic_get_64(if_data64->fld, \
4780 (u_int64_t *)(void *)(uintptr_t)&if_data_int->fld); \
4781} while (0)
4782
4783 COPYFIELD64(ifi_type);
4784 COPYFIELD64(ifi_typelen);
4785 COPYFIELD64(ifi_physical);
4786 COPYFIELD64(ifi_addrlen);
4787 COPYFIELD64(ifi_hdrlen);
4788 COPYFIELD64(ifi_recvquota);
4789 COPYFIELD64(ifi_xmitquota);
4790 if_data64->ifi_unused1 = 0;
4791 COPYFIELD64(ifi_mtu);
4792 COPYFIELD64(ifi_metric);
4793 COPYFIELD64(ifi_baudrate);
4794
4795 COPYFIELD64_ATOMIC(ifi_ipackets);
4796 COPYFIELD64_ATOMIC(ifi_ierrors);
4797 COPYFIELD64_ATOMIC(ifi_opackets);
4798 COPYFIELD64_ATOMIC(ifi_oerrors);
4799 COPYFIELD64_ATOMIC(ifi_collisions);
4800 COPYFIELD64_ATOMIC(ifi_ibytes);
4801 COPYFIELD64_ATOMIC(ifi_obytes);
4802 COPYFIELD64_ATOMIC(ifi_imcasts);
4803 COPYFIELD64_ATOMIC(ifi_omcasts);
4804 COPYFIELD64_ATOMIC(ifi_iqdrops);
4805 COPYFIELD64_ATOMIC(ifi_noproto);
4806
4807 /*
4808 * Note these two fields are actually 32 bit, so doing
4809 * COPYFIELD64_ATOMIC will cause them to be misaligned
4810 */
4811 COPYFIELD64(ifi_recvtiming);
4812 COPYFIELD64(ifi_xmittiming);
4813
4814 if_data64->ifi_lastchange.tv_sec = if_data_int->ifi_lastchange.tv_sec;
4815 if_data64->ifi_lastchange.tv_usec = if_data_int->ifi_lastchange.tv_usec;
4816
4817 if_data64->ifi_lastchange.tv_sec += boottime_sec();
4818
4819#undef COPYFIELD64
4820}
4821
4822__private_extern__ void
4823if_copy_traffic_class(struct ifnet *ifp,
4824 struct if_traffic_class *if_tc)
4825{
4826#define COPY_IF_TC_FIELD64_ATOMIC(fld) do { \
4827 atomic_get_64(if_tc->fld, \
4828 (u_int64_t *)(void *)(uintptr_t)&ifp->if_tc.fld); \
4829} while (0)
4830
4831 bzero(if_tc, sizeof (*if_tc));
4832 COPY_IF_TC_FIELD64_ATOMIC(ifi_ibepackets);
4833 COPY_IF_TC_FIELD64_ATOMIC(ifi_ibebytes);
4834 COPY_IF_TC_FIELD64_ATOMIC(ifi_obepackets);
4835 COPY_IF_TC_FIELD64_ATOMIC(ifi_obebytes);
4836 COPY_IF_TC_FIELD64_ATOMIC(ifi_ibkpackets);
4837 COPY_IF_TC_FIELD64_ATOMIC(ifi_ibkbytes);
4838 COPY_IF_TC_FIELD64_ATOMIC(ifi_obkpackets);
4839 COPY_IF_TC_FIELD64_ATOMIC(ifi_obkbytes);
4840 COPY_IF_TC_FIELD64_ATOMIC(ifi_ivipackets);
4841 COPY_IF_TC_FIELD64_ATOMIC(ifi_ivibytes);
4842 COPY_IF_TC_FIELD64_ATOMIC(ifi_ovipackets);
4843 COPY_IF_TC_FIELD64_ATOMIC(ifi_ovibytes);
4844 COPY_IF_TC_FIELD64_ATOMIC(ifi_ivopackets);
4845 COPY_IF_TC_FIELD64_ATOMIC(ifi_ivobytes);
4846 COPY_IF_TC_FIELD64_ATOMIC(ifi_ovopackets);
4847 COPY_IF_TC_FIELD64_ATOMIC(ifi_ovobytes);
4848 COPY_IF_TC_FIELD64_ATOMIC(ifi_ipvpackets);
4849 COPY_IF_TC_FIELD64_ATOMIC(ifi_ipvbytes);
4850 COPY_IF_TC_FIELD64_ATOMIC(ifi_opvpackets);
4851 COPY_IF_TC_FIELD64_ATOMIC(ifi_opvbytes);
4852
4853#undef COPY_IF_TC_FIELD64_ATOMIC
4854}
4855
4856void
4857if_copy_data_extended(struct ifnet *ifp, struct if_data_extended *if_de)
4858{
4859#define COPY_IF_DE_FIELD64_ATOMIC(fld) do { \
4860 atomic_get_64(if_de->fld, \
4861 (u_int64_t *)(void *)(uintptr_t)&ifp->if_data.fld); \
4862} while (0)
4863
4864 bzero(if_de, sizeof (*if_de));
4865 COPY_IF_DE_FIELD64_ATOMIC(ifi_alignerrs);
4866 COPY_IF_DE_FIELD64_ATOMIC(ifi_dt_bytes);
4867 COPY_IF_DE_FIELD64_ATOMIC(ifi_fpackets);
4868 COPY_IF_DE_FIELD64_ATOMIC(ifi_fbytes);
4869
4870#undef COPY_IF_DE_FIELD64_ATOMIC
4871}
4872
4873void
4874if_copy_packet_stats(struct ifnet *ifp, struct if_packet_stats *if_ps)
4875{
4876#define COPY_IF_PS_TCP_FIELD64_ATOMIC(fld) do { \
4877 atomic_get_64(if_ps->ifi_tcp_##fld, \
4878 (u_int64_t *)(void *)(uintptr_t)&ifp->if_tcp_stat->fld); \
4879} while (0)
4880
4881#define COPY_IF_PS_UDP_FIELD64_ATOMIC(fld) do { \
4882 atomic_get_64(if_ps->ifi_udp_##fld, \
4883 (u_int64_t *)(void *)(uintptr_t)&ifp->if_udp_stat->fld); \
4884} while (0)
4885
4886 COPY_IF_PS_TCP_FIELD64_ATOMIC(badformat);
4887 COPY_IF_PS_TCP_FIELD64_ATOMIC(unspecv6);
4888 COPY_IF_PS_TCP_FIELD64_ATOMIC(synfin);
4889 COPY_IF_PS_TCP_FIELD64_ATOMIC(badformatipsec);
4890 COPY_IF_PS_TCP_FIELD64_ATOMIC(noconnnolist);
4891 COPY_IF_PS_TCP_FIELD64_ATOMIC(noconnlist);
4892 COPY_IF_PS_TCP_FIELD64_ATOMIC(listbadsyn);
4893 COPY_IF_PS_TCP_FIELD64_ATOMIC(icmp6unreach);
4894 COPY_IF_PS_TCP_FIELD64_ATOMIC(deprecate6);
4895 COPY_IF_PS_TCP_FIELD64_ATOMIC(ooopacket);
4896 COPY_IF_PS_TCP_FIELD64_ATOMIC(rstinsynrcv);
4897 COPY_IF_PS_TCP_FIELD64_ATOMIC(dospacket);
4898 COPY_IF_PS_TCP_FIELD64_ATOMIC(cleanup);
4899 COPY_IF_PS_TCP_FIELD64_ATOMIC(synwindow);
4900
4901 COPY_IF_PS_UDP_FIELD64_ATOMIC(port_unreach);
4902 COPY_IF_PS_UDP_FIELD64_ATOMIC(faithprefix);
4903 COPY_IF_PS_UDP_FIELD64_ATOMIC(port0);
4904 COPY_IF_PS_UDP_FIELD64_ATOMIC(badlength);
4905 COPY_IF_PS_UDP_FIELD64_ATOMIC(badchksum);
4906 COPY_IF_PS_UDP_FIELD64_ATOMIC(badmcast);
4907 COPY_IF_PS_UDP_FIELD64_ATOMIC(cleanup);
4908 COPY_IF_PS_UDP_FIELD64_ATOMIC(badipsec);
4909
4910#undef COPY_IF_PS_TCP_FIELD64_ATOMIC
4911#undef COPY_IF_PS_UDP_FIELD64_ATOMIC
4912}
4913
4914void
4915if_copy_rxpoll_stats(struct ifnet *ifp, struct if_rxpoll_stats *if_rs)
4916{
4917 bzero(if_rs, sizeof (*if_rs));
4918 if (!(ifp->if_eflags & IFEF_RXPOLL) || !ifnet_is_attached(ifp, 1))
4919 return;
4920
4921 /* by now, ifnet will stay attached so if_inp must be valid */
4922 VERIFY(ifp->if_inp != NULL);
4923 bcopy(&ifp->if_inp->pstats, if_rs, sizeof (*if_rs));
4924
4925 /* Release the IO refcnt */
4926 ifnet_decr_iorefcnt(ifp);
4927}
4928
4929struct ifaddr *
4930ifa_remref(struct ifaddr *ifa, int locked)
4931{
4932 if (!locked)
4933 IFA_LOCK_SPIN(ifa);
4934 else
4935 IFA_LOCK_ASSERT_HELD(ifa);
4936
4937 if (ifa->ifa_refcnt == 0)
4938 panic("%s: ifa %p negative refcnt\n", __func__, ifa);
4939 else if (ifa->ifa_trace != NULL)
4940 (*ifa->ifa_trace)(ifa, FALSE);
4941 if (--ifa->ifa_refcnt == 0) {
4942 if (ifa->ifa_debug & IFD_ATTACHED)
4943 panic("ifa %p attached to ifp is being freed\n", ifa);
4944 /*
4945 * Some interface addresses are allocated either statically
4946 * or carved out of a larger block. Only free it if it was
4947 * allocated via MALLOC or via the corresponding per-address
4948 * family allocator. Otherwise, leave it alone.
4949 */
4950 if (ifa->ifa_debug & IFD_ALLOC) {
4951 if (ifa->ifa_free == NULL) {
4952 IFA_UNLOCK(ifa);
4953 FREE(ifa, M_IFADDR);
4954 } else {
4955 /* Become a regular mutex */
4956 IFA_CONVERT_LOCK(ifa);
4957 /* callee will unlock */
4958 (*ifa->ifa_free)(ifa);
4959 }
4960 } else {
4961 IFA_UNLOCK(ifa);
4962 }
4963 ifa = NULL;
4964 }
4965
4966 if (!locked && ifa != NULL)
4967 IFA_UNLOCK(ifa);
4968
4969 return (ifa);
4970}
4971
4972void
4973ifa_addref(struct ifaddr *ifa, int locked)
4974{
4975 if (!locked)
4976 IFA_LOCK_SPIN(ifa);
4977 else
4978 IFA_LOCK_ASSERT_HELD(ifa);
4979
4980 if (++ifa->ifa_refcnt == 0) {
4981 panic("%s: ifa %p wraparound refcnt\n", __func__, ifa);
4982 /* NOTREACHED */
4983 } else if (ifa->ifa_trace != NULL) {
4984 (*ifa->ifa_trace)(ifa, TRUE);
4985 }
4986 if (!locked)
4987 IFA_UNLOCK(ifa);
4988}
4989
4990void
4991ifa_lock_init(struct ifaddr *ifa)
4992{
4993 lck_mtx_init(&ifa->ifa_lock, ifa_mtx_grp, ifa_mtx_attr);
4994}
4995
4996void
4997ifa_lock_destroy(struct ifaddr *ifa)
4998{
4999 IFA_LOCK_ASSERT_NOTHELD(ifa);
5000 lck_mtx_destroy(&ifa->ifa_lock, ifa_mtx_grp);
5001}
5002
5003/*
5004 * 'i' group ioctls.
5005 *
5006 * The switch statement below does nothing at runtime, as it serves as a
5007 * compile time check to ensure that all of the socket 'i' ioctls (those
5008 * in the 'i' group going thru soo_ioctl) that are made available by the
5009 * networking stack is unique. This works as long as this routine gets
5010 * updated each time a new interface ioctl gets added.
5011 *
5012 * Any failures at compile time indicates duplicated ioctl values.
5013 */
5014static __attribute__((unused)) void
5015ifioctl_cassert(void)
5016{
5017 /*
5018 * This is equivalent to _CASSERT() and the compiler wouldn't
5019 * generate any instructions, thus for compile time only.
5020 */
5021 switch ((u_long)0) {
5022 case 0:
5023
5024 /* bsd/net/if_ppp.h */
5025 case SIOCGPPPSTATS:
5026 case SIOCGPPPCSTATS:
5027
5028#if INET6
5029 /* bsd/netinet6/in6_var.h */
5030 case SIOCSIFADDR_IN6:
5031 case SIOCGIFADDR_IN6:
5032 case SIOCSIFDSTADDR_IN6:
5033 case SIOCSIFNETMASK_IN6:
5034 case SIOCGIFDSTADDR_IN6:
5035 case SIOCGIFNETMASK_IN6:
5036 case SIOCDIFADDR_IN6:
5037 case SIOCAIFADDR_IN6_32:
5038 case SIOCAIFADDR_IN6_64:
5039 case SIOCSIFPHYADDR_IN6_32:
5040 case SIOCSIFPHYADDR_IN6_64:
5041 case SIOCGIFPSRCADDR_IN6:
5042 case SIOCGIFPDSTADDR_IN6:
5043 case SIOCGIFAFLAG_IN6:
5044 case SIOCGDRLST_IN6_32:
5045 case SIOCGDRLST_IN6_64:
5046 case SIOCGPRLST_IN6_32:
5047 case SIOCGPRLST_IN6_64:
5048 case OSIOCGIFINFO_IN6:
5049 case SIOCGIFINFO_IN6:
5050 case SIOCSNDFLUSH_IN6:
5051 case SIOCGNBRINFO_IN6_32:
5052 case SIOCGNBRINFO_IN6_64:
5053 case SIOCSPFXFLUSH_IN6:
5054 case SIOCSRTRFLUSH_IN6:
5055 case SIOCGIFALIFETIME_IN6:
5056 case SIOCSIFALIFETIME_IN6:
5057 case SIOCGIFSTAT_IN6:
5058 case SIOCGIFSTAT_ICMP6:
5059 case SIOCSDEFIFACE_IN6_32:
5060 case SIOCSDEFIFACE_IN6_64:
5061 case SIOCGDEFIFACE_IN6_32:
5062 case SIOCGDEFIFACE_IN6_64:
5063 case SIOCSIFINFO_FLAGS:
5064 case SIOCSSCOPE6:
5065 case SIOCGSCOPE6:
5066 case SIOCGSCOPE6DEF:
5067 case SIOCSIFPREFIX_IN6:
5068 case SIOCGIFPREFIX_IN6:
5069 case SIOCDIFPREFIX_IN6:
5070 case SIOCAIFPREFIX_IN6:
5071 case SIOCCIFPREFIX_IN6:
5072 case SIOCSGIFPREFIX_IN6:
5073 case SIOCPROTOATTACH_IN6_32:
5074 case SIOCPROTOATTACH_IN6_64:
5075 case SIOCPROTODETACH_IN6:
5076 case SIOCLL_START_32:
5077 case SIOCLL_START_64:
5078 case SIOCLL_STOP:
5079 case SIOCAUTOCONF_START:
5080 case SIOCAUTOCONF_STOP:
5081 case SIOCSETROUTERMODE_IN6:
5082 case SIOCLL_CGASTART_32:
5083 case SIOCLL_CGASTART_64:
5084 case SIOCGIFCGAPREP_IN6:
5085 case SIOCSIFCGAPREP_IN6:
5086#endif /* INET6 */
5087
5088 /* bsd/sys/sockio.h */
5089 case SIOCSIFADDR:
5090 case OSIOCGIFADDR:
5091 case SIOCSIFDSTADDR:
5092 case OSIOCGIFDSTADDR:
5093 case SIOCSIFFLAGS:
5094 case SIOCGIFFLAGS:
5095 case OSIOCGIFBRDADDR:
5096 case SIOCSIFBRDADDR:
5097 case OSIOCGIFCONF32:
5098 case OSIOCGIFCONF64:
5099 case OSIOCGIFNETMASK:
5100 case SIOCSIFNETMASK:
5101 case SIOCGIFMETRIC:
5102 case SIOCSIFMETRIC:
5103 case SIOCDIFADDR:
5104 case SIOCAIFADDR:
5105
5106 case SIOCGIFADDR:
5107 case SIOCGIFDSTADDR:
5108 case SIOCGIFBRDADDR:
5109 case SIOCGIFCONF32:
5110 case SIOCGIFCONF64:
5111 case SIOCGIFNETMASK:
5112 case SIOCAUTOADDR:
5113 case SIOCAUTONETMASK:
5114 case SIOCARPIPLL:
5115
5116 case SIOCADDMULTI:
5117 case SIOCDELMULTI:
5118 case SIOCGIFMTU:
5119 case SIOCSIFMTU:
5120 case SIOCGIFPHYS:
5121 case SIOCSIFPHYS:
5122 case SIOCSIFMEDIA:
5123 case SIOCGIFMEDIA32:
5124 case SIOCGIFMEDIA64:
5125 case SIOCSIFGENERIC:
5126 case SIOCGIFGENERIC:
5127 case SIOCRSLVMULTI:
5128
5129 case SIOCSIFLLADDR:
5130 case SIOCGIFSTATUS:
5131 case SIOCSIFPHYADDR:
5132 case SIOCGIFPSRCADDR:
5133 case SIOCGIFPDSTADDR:
5134 case SIOCDIFPHYADDR:
5135
5136 case SIOCGIFDEVMTU:
5137 case SIOCSIFALTMTU:
5138 case SIOCGIFALTMTU:
5139 case SIOCSIFBOND:
5140 case SIOCGIFBOND:
5141
5142 case SIOCPROTOATTACH:
5143 case SIOCPROTODETACH:
5144
5145 case SIOCSIFCAP:
5146 case SIOCGIFCAP:
5147
5148 case SIOCIFCREATE:
5149 case SIOCIFDESTROY:
5150 case SIOCIFCREATE2:
5151
5152 case SIOCSDRVSPEC32:
5153 case SIOCGDRVSPEC32:
5154 case SIOCSDRVSPEC64:
5155 case SIOCGDRVSPEC64:
5156
5157 case SIOCSIFVLAN:
5158 case SIOCGIFVLAN:
5159
5160 case SIOCIFGCLONERS32:
5161 case SIOCIFGCLONERS64:
5162
5163 case SIOCGIFASYNCMAP:
5164 case SIOCSIFASYNCMAP:
5165#if CONFIG_MACF_NET
5166 case SIOCGIFMAC:
5167 case SIOCSIFMAC:
5168#endif /* CONFIG_MACF_NET */
5169 case SIOCSIFKPI:
5170 case SIOCGIFKPI:
5171
5172 case SIOCGIFWAKEFLAGS:
5173
5174 case SIOCGIFGETRTREFCNT:
5175 case SIOCGIFLINKQUALITYMETRIC:
5176 case SIOCSIFOPPORTUNISTIC:
5177 case SIOCGIFOPPORTUNISTIC:
5178 case SIOCSETROUTERMODE:
5179 case SIOCGIFEFLAGS:
5180 case SIOCSIFDESC:
5181 case SIOCGIFDESC:
5182 case SIOCSIFLINKPARAMS:
5183 case SIOCGIFLINKPARAMS:
5184 case SIOCGIFQUEUESTATS:
5185 case SIOCSIFTHROTTLE:
5186 case SIOCGIFTHROTTLE:
5187
5188 case SIOCGASSOCIDS32:
5189 case SIOCGASSOCIDS64:
5190 case SIOCGCONNIDS32:
5191 case SIOCGCONNIDS64:
5192 case SIOCGCONNINFO32:
5193 case SIOCGCONNINFO64:
5194 case SIOCSCONNORDER:
5195 case SIOCGCONNORDER:
5196
5197 case SIOCSIFLOG:
5198 case SIOCGIFLOG:
5199 case SIOCGIFDELEGATE:
5200 case SIOCGIFLLADDR:
5201 case SIOCGIFTYPE:
5202 case SIOCGIFEXPENSIVE:
5203 case SIOCSIFEXPENSIVE:
5204 case SIOCGIF2KCL:
5205 case SIOCSIF2KCL:
5206 case SIOCGSTARTDELAY:
5207
5208 case SIOCAIFAGENTID:
5209 case SIOCDIFAGENTID:
5210 case SIOCGIFAGENTIDS32:
5211 case SIOCGIFAGENTIDS64:
5212 case SIOCGIFAGENTDATA32:
5213 case SIOCGIFAGENTDATA64:
5214
5215 case SIOCSIFINTERFACESTATE:
5216 case SIOCGIFINTERFACESTATE:
5217 case SIOCSIFPROBECONNECTIVITY:
5218 case SIOCGIFPROBECONNECTIVITY:
5219
5220 case SIOCGIFFUNCTIONALTYPE:
5221 case SIOCSIFNETSIGNATURE:
5222 case SIOCGIFNETSIGNATURE:
5223
5224 case SIOCGECNMODE:
5225 case SIOCSECNMODE:
5226
5227 case SIOCSIFORDER:
5228
5229 case SIOCSQOSMARKINGMODE:
5230 case SIOCSQOSMARKINGENABLED:
5231 case SIOCGQOSMARKINGMODE:
5232 case SIOCGQOSMARKINGENABLED:
5233
5234 case SIOCSIFTIMESTAMPENABLE:
5235 case SIOCSIFTIMESTAMPDISABLE:
5236 case SIOCGIFTIMESTAMPENABLED:
5237
5238 case SIOCSIFDISABLEOUTPUT:
5239
5240 case SIOCGIFAGENTLIST32:
5241 case SIOCGIFAGENTLIST64:
5242
5243 case SIOCSIFLOWINTERNET:
5244 case SIOCGIFLOWINTERNET:
5245
5246#if INET6
5247 case SIOCGIFNAT64PREFIX:
5248 case SIOCSIFNAT64PREFIX:
5249
5250 case SIOCGIFCLAT46ADDR:
5251#endif /* INET6 */
5252
5253 case SIOCGIFPROTOLIST32:
5254 case SIOCGIFPROTOLIST64:
5255
5256 case SIOCGIFLOWPOWER:
5257 case SIOCSIFLOWPOWER:
5258 ;
5259 }
5260}
5261
5262uint32_t
5263ifnet_mbuf_packetpreamblelen(struct ifnet *ifp)
5264{
5265#pragma unused(ifp)
5266 return (0);
5267}
5268
5269/* The following is used to enqueue work items for interface events */
5270struct intf_event {
5271 struct ifnet *ifp;
5272 union sockaddr_in_4_6 addr;
5273 uint32_t intf_event_code;
5274};
5275
5276static void
5277intf_event_callback(void *arg)
5278{
5279 struct intf_event *p_intf_ev = (struct intf_event *)arg;
5280
5281 /* Call this before we walk the tree */
5282 EVENTHANDLER_INVOKE(&ifnet_evhdlr_ctxt, ifnet_event, p_intf_ev->ifp,
5283 (struct sockaddr *)&(p_intf_ev->addr), p_intf_ev->intf_event_code);
5284}
5285
5286struct intf_event_nwk_wq_entry {
5287 struct nwk_wq_entry nwk_wqe;
5288 struct intf_event intf_ev_arg;
5289};
5290
5291void
5292intf_event_enqueue_nwk_wq_entry(struct ifnet *ifp, struct sockaddr *addrp,
5293 uint32_t intf_event_code)
5294{
5295#pragma unused(addrp)
5296 struct intf_event_nwk_wq_entry *p_intf_ev = NULL;
5297
5298 MALLOC(p_intf_ev, struct intf_event_nwk_wq_entry *,
5299 sizeof(struct intf_event_nwk_wq_entry),
5300 M_NWKWQ, M_WAITOK | M_ZERO);
5301
5302 p_intf_ev->intf_ev_arg.ifp = ifp;
5303 /*
5304 * XXX Not using addr in the arg. This will be used
5305 * once we need IP address add/delete events
5306 */
5307 p_intf_ev->intf_ev_arg.intf_event_code = intf_event_code;
5308 p_intf_ev->nwk_wqe.func = intf_event_callback;
5309 p_intf_ev->nwk_wqe.is_arg_managed = TRUE;
5310 p_intf_ev->nwk_wqe.arg = &p_intf_ev->intf_ev_arg;
5311 nwk_wq_enqueue((struct nwk_wq_entry*)p_intf_ev);
5312}
5313