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