]> git.saurik.com Git - apple/xnu.git/blob - bsd/net/if.c
xnu-2422.115.4.tar.gz
[apple/xnu.git] / bsd / net / if.c
1 /*
2 * Copyright (c) 2000-2013 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 <kern/zalloc.h>
86
87 #include <machine/endian.h>
88
89 #include <pexpert/pexpert.h>
90
91 #include <net/if.h>
92 #include <net/if_arp.h>
93 #include <net/if_dl.h>
94 #include <net/if_types.h>
95 #include <net/if_var.h>
96 #include <net/if_ppp.h>
97 #include <net/ethernet.h>
98
99 #include <net/radix.h>
100 #include <net/route.h>
101 #include <net/dlil.h>
102 #include <sys/domain.h>
103 #include <libkern/OSAtomic.h>
104
105 #if INET || INET6
106 /*XXX*/
107 #include <netinet/in.h>
108 #include <netinet/in_var.h>
109 #include <netinet/ip_var.h>
110 #include <netinet/ip6.h>
111 #include <netinet/ip_var.h>
112 #include <netinet/tcp.h>
113 #include <netinet/tcp_var.h>
114 #include <netinet/udp.h>
115 #include <netinet/udp_var.h>
116 #if INET6
117 #include <netinet6/in6_var.h>
118 #include <netinet6/in6_ifattach.h>
119 #include <netinet6/ip6_var.h>
120 #include <netinet6/nd6.h>
121 #endif /* INET6 */
122 #endif /* INET || INET6 */
123
124 #if CONFIG_MACF_NET
125 #include <security/mac_framework.h>
126 #endif
127
128 #if PF_ALTQ
129 #include <net/altq/if_altq.h>
130 #endif /* !PF_ALTQ */
131
132 /*
133 * System initialization
134 */
135
136 extern char *proc_name_address(void *);
137
138 /* Lock group and attribute for ifaddr lock */
139 lck_attr_t *ifa_mtx_attr;
140 lck_grp_t *ifa_mtx_grp;
141 static lck_grp_attr_t *ifa_mtx_grp_attr;
142
143 static int ifioctl_ifreq(struct socket *, u_long, struct ifreq *,
144 struct proc *);
145 static int ifioctl_ifconf(u_long, caddr_t);
146 static int ifioctl_ifclone(u_long, caddr_t);
147 static int ifioctl_ifdesc(struct ifnet *, u_long, caddr_t, struct proc *);
148 static int ifioctl_linkparams(struct ifnet *, u_long, caddr_t, struct proc *);
149 static int ifioctl_qstats(struct ifnet *, u_long, caddr_t);
150 static int ifioctl_throttle(struct ifnet *, u_long, caddr_t, struct proc *);
151 static int ifconf(u_long cmd, user_addr_t ifrp, int * ret_space);
152 __private_extern__ void link_rtrequest(int, struct rtentry *, struct sockaddr *);
153 void if_rtproto_del(struct ifnet *ifp, int protocol);
154
155 static int if_addmulti_common(struct ifnet *, const struct sockaddr *,
156 struct ifmultiaddr **, int);
157 static int if_delmulti_common(struct ifmultiaddr *, struct ifnet *,
158 const struct sockaddr *, int);
159
160 static int if_rtmtu(struct radix_node *, void *);
161 static void if_rtmtu_update(struct ifnet *);
162
163 static int if_clone_list(int, int *, user_addr_t);
164
165 MALLOC_DEFINE(M_IFADDR, "ifaddr", "interface address");
166
167 struct ifnethead ifnet_head = TAILQ_HEAD_INITIALIZER(ifnet_head);
168
169 static int if_cloners_count;
170 LIST_HEAD(, if_clone) if_cloners = LIST_HEAD_INITIALIZER(if_cloners);
171
172 static struct ifaddr *ifa_ifwithnet_common(const struct sockaddr *,
173 unsigned int);
174 static void if_attach_ifa_common(struct ifnet *, struct ifaddr *, int);
175 static void if_detach_ifa_common(struct ifnet *, struct ifaddr *, int);
176
177 static void if_attach_ifma(struct ifnet *, struct ifmultiaddr *, int);
178 static int if_detach_ifma(struct ifnet *, struct ifmultiaddr *, int);
179
180 static struct ifmultiaddr *ifma_alloc(int);
181 static void ifma_free(struct ifmultiaddr *);
182 static void ifma_trace(struct ifmultiaddr *, int);
183
184 #if DEBUG
185 static unsigned int ifma_debug = 1; /* debugging (enabled) */
186 #else
187 static unsigned int ifma_debug; /* debugging (disabled) */
188 #endif /* !DEBUG */
189 static unsigned int ifma_size; /* size of zone element */
190 static struct zone *ifma_zone; /* zone for ifmultiaddr */
191
192 #define IFMA_TRACE_HIST_SIZE 32 /* size of trace history */
193
194 /* For gdb */
195 __private_extern__ unsigned int ifma_trace_hist_size = IFMA_TRACE_HIST_SIZE;
196
197 struct ifmultiaddr_dbg {
198 struct ifmultiaddr ifma; /* ifmultiaddr */
199 u_int16_t ifma_refhold_cnt; /* # of ref */
200 u_int16_t ifma_refrele_cnt; /* # of rele */
201 /*
202 * Circular lists of IFA_ADDREF and IFA_REMREF callers.
203 */
204 ctrace_t ifma_refhold[IFMA_TRACE_HIST_SIZE];
205 ctrace_t ifma_refrele[IFMA_TRACE_HIST_SIZE];
206 /*
207 * Trash list linkage
208 */
209 TAILQ_ENTRY(ifmultiaddr_dbg) ifma_trash_link;
210 };
211
212 /* List of trash ifmultiaddr entries protected by ifma_trash_lock */
213 static TAILQ_HEAD(, ifmultiaddr_dbg) ifma_trash_head;
214 static decl_lck_mtx_data(, ifma_trash_lock);
215
216 #define IFMA_ZONE_MAX 64 /* maximum elements in zone */
217 #define IFMA_ZONE_NAME "ifmultiaddr" /* zone name */
218
219 #if INET6
220 /*
221 * XXX: declare here to avoid to include many inet6 related files..
222 * should be more generalized?
223 */
224 extern void nd6_setmtu(struct ifnet *);
225 extern lck_mtx_t *nd6_mutex;
226 #endif
227
228 SYSCTL_NODE(_net, PF_LINK, link, CTLFLAG_RW|CTLFLAG_LOCKED, 0, "Link layers");
229 SYSCTL_NODE(_net_link, 0, generic, CTLFLAG_RW|CTLFLAG_LOCKED, 0,
230 "Generic link-management");
231
232 SYSCTL_DECL(_net_link_generic_system);
233
234 static uint32_t if_verbose = 0;
235 SYSCTL_INT(_net_link_generic_system, OID_AUTO, if_verbose,
236 CTLFLAG_RW | CTLFLAG_LOCKED, &if_verbose, 0, "");
237
238 void
239 ifa_init(void)
240 {
241 /* Setup lock group and attribute for ifaddr */
242 ifa_mtx_grp_attr = lck_grp_attr_alloc_init();
243 ifa_mtx_grp = lck_grp_alloc_init("ifaddr", ifa_mtx_grp_attr);
244 ifa_mtx_attr = lck_attr_alloc_init();
245
246 PE_parse_boot_argn("ifa_debug", &ifma_debug, sizeof (ifma_debug));
247
248 ifma_size = (ifma_debug == 0) ? sizeof (struct ifmultiaddr) :
249 sizeof (struct ifmultiaddr_dbg);
250
251 ifma_zone = zinit(ifma_size, IFMA_ZONE_MAX * ifma_size, 0,
252 IFMA_ZONE_NAME);
253 if (ifma_zone == NULL) {
254 panic("%s: failed allocating %s", __func__, IFMA_ZONE_NAME);
255 /* NOTREACHED */
256 }
257 zone_change(ifma_zone, Z_EXPAND, TRUE);
258 zone_change(ifma_zone, Z_CALLERACCT, FALSE);
259
260 lck_mtx_init(&ifma_trash_lock, ifa_mtx_grp, ifa_mtx_attr);
261 TAILQ_INIT(&ifma_trash_head);
262 }
263
264 /*
265 * Network interface utility routines.
266 *
267 * Routines with ifa_ifwith* names take sockaddr *'s as
268 * parameters.
269 */
270
271 int if_index;
272 struct ifaddr **ifnet_addrs;
273 struct ifnet **ifindex2ifnet;
274
275 __private_extern__ void
276 if_attach_ifa(struct ifnet *ifp, struct ifaddr *ifa)
277 {
278 if_attach_ifa_common(ifp, ifa, 0);
279 }
280
281 __private_extern__ void
282 if_attach_link_ifa(struct ifnet *ifp, struct ifaddr *ifa)
283 {
284 if_attach_ifa_common(ifp, ifa, 1);
285 }
286
287 static void
288 if_attach_ifa_common(struct ifnet *ifp, struct ifaddr *ifa, int link)
289 {
290 ifnet_lock_assert(ifp, IFNET_LCK_ASSERT_EXCLUSIVE);
291 IFA_LOCK_ASSERT_HELD(ifa);
292
293 if (ifa->ifa_ifp != ifp) {
294 panic("%s: Mismatch ifa_ifp=%p != ifp=%p", __func__,
295 ifa->ifa_ifp, ifp);
296 /* NOTREACHED */
297 } else if (ifa->ifa_debug & IFD_ATTACHED) {
298 panic("%s: Attempt to attach an already attached ifa=%p",
299 __func__, ifa);
300 /* NOTREACHED */
301 } else if (link && !(ifa->ifa_debug & IFD_LINK)) {
302 panic("%s: Unexpected non-link address ifa=%p", __func__, ifa);
303 /* NOTREACHED */
304 } else if (!link && (ifa->ifa_debug & IFD_LINK)) {
305 panic("%s: Unexpected link address ifa=%p", __func__, ifa);
306 /* NOTREACHED */
307 }
308 IFA_ADDREF_LOCKED(ifa);
309 ifa->ifa_debug |= IFD_ATTACHED;
310 if (link)
311 TAILQ_INSERT_HEAD(&ifp->if_addrhead, ifa, ifa_link);
312 else
313 TAILQ_INSERT_TAIL(&ifp->if_addrhead, ifa, ifa_link);
314
315 if (ifa->ifa_attached != NULL)
316 (*ifa->ifa_attached)(ifa);
317 }
318
319 __private_extern__ void
320 if_detach_ifa(struct ifnet *ifp, struct ifaddr *ifa)
321 {
322 if_detach_ifa_common(ifp, ifa, 0);
323 }
324
325 __private_extern__ void
326 if_detach_link_ifa(struct ifnet *ifp, struct ifaddr *ifa)
327 {
328 if_detach_ifa_common(ifp, ifa, 1);
329 }
330
331 static void
332 if_detach_ifa_common(struct ifnet *ifp, struct ifaddr *ifa, int link)
333 {
334 ifnet_lock_assert(ifp, IFNET_LCK_ASSERT_EXCLUSIVE);
335 IFA_LOCK_ASSERT_HELD(ifa);
336
337 if (link && !(ifa->ifa_debug & IFD_LINK)) {
338 panic("%s: Unexpected non-link address ifa=%p", __func__, ifa);
339 /* NOTREACHED */
340 } else if (link && ifa != TAILQ_FIRST(&ifp->if_addrhead)) {
341 panic("%s: Link address ifa=%p not first", __func__, ifa);
342 /* NOTREACHED */
343 } else if (!link && (ifa->ifa_debug & IFD_LINK)) {
344 panic("%s: Unexpected link address ifa=%p", __func__, ifa);
345 /* NOTREACHED */
346 } else if (!(ifa->ifa_debug & IFD_ATTACHED)) {
347 panic("%s: Attempt to detach an unattached address ifa=%p",
348 __func__, ifa);
349 /* NOTREACHED */
350 } else if (ifa->ifa_ifp != ifp) {
351 panic("%s: Mismatch ifa_ifp=%p, ifp=%p", __func__,
352 ifa->ifa_ifp, ifp);
353 /* NOTREACHED */
354 } else if (ifa->ifa_debug & IFD_DEBUG) {
355 struct ifaddr *ifa2;
356 TAILQ_FOREACH(ifa2, &ifp->if_addrhead, ifa_link) {
357 if (ifa2 == ifa)
358 break;
359 }
360 if (ifa2 != ifa) {
361 panic("%s: Attempt to detach a stray address ifa=%p",
362 __func__, ifa);
363 /* NOTREACHED */
364 }
365 }
366 TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link);
367 /* This must not be the last reference to the ifaddr */
368 if (IFA_REMREF_LOCKED(ifa) == NULL) {
369 panic("%s: unexpected (missing) refcnt ifa=%p", __func__, ifa);
370 /* NOTREACHED */
371 }
372 ifa->ifa_debug &= ~IFD_ATTACHED;
373
374 if (ifa->ifa_detached != NULL)
375 (*ifa->ifa_detached)(ifa);
376 }
377
378 #define INITIAL_IF_INDEXLIM 8
379
380 /*
381 * Function: if_next_index
382 * Purpose:
383 * Return the next available interface index.
384 * Grow the ifnet_addrs[] and ifindex2ifnet[] arrays to accomodate the
385 * added entry when necessary.
386 *
387 * Note:
388 * ifnet_addrs[] is indexed by (if_index - 1), whereas
389 * ifindex2ifnet[] is indexed by ifp->if_index. That requires us to
390 * always allocate one extra element to hold ifindex2ifnet[0], which
391 * is unused.
392 */
393 int if_next_index(void);
394
395 __private_extern__ int
396 if_next_index(void)
397 {
398 static int if_indexlim = 0;
399 int new_index;
400
401 new_index = ++if_index;
402 if (if_index > if_indexlim) {
403 unsigned n;
404 int new_if_indexlim;
405 caddr_t new_ifnet_addrs;
406 caddr_t new_ifindex2ifnet;
407 caddr_t old_ifnet_addrs;
408
409 old_ifnet_addrs = (caddr_t)ifnet_addrs;
410 if (ifnet_addrs == NULL) {
411 new_if_indexlim = INITIAL_IF_INDEXLIM;
412 } else {
413 new_if_indexlim = if_indexlim << 1;
414 }
415
416 /* allocate space for the larger arrays */
417 n = (2 * new_if_indexlim + 1) * sizeof(caddr_t);
418 new_ifnet_addrs = _MALLOC(n, M_IFADDR, M_WAITOK);
419 if (new_ifnet_addrs == NULL) {
420 --if_index;
421 return -1;
422 }
423
424 new_ifindex2ifnet = new_ifnet_addrs
425 + new_if_indexlim * sizeof(caddr_t);
426 bzero(new_ifnet_addrs, n);
427 if (ifnet_addrs != NULL) {
428 /* copy the existing data */
429 bcopy((caddr_t)ifnet_addrs, new_ifnet_addrs,
430 if_indexlim * sizeof(caddr_t));
431 bcopy((caddr_t)ifindex2ifnet,
432 new_ifindex2ifnet,
433 (if_indexlim + 1) * sizeof(caddr_t));
434 }
435
436 /* switch to the new tables and size */
437 ifnet_addrs = (struct ifaddr **)(void *)new_ifnet_addrs;
438 ifindex2ifnet = (struct ifnet **)(void *)new_ifindex2ifnet;
439 if_indexlim = new_if_indexlim;
440
441 /* release the old data */
442 if (old_ifnet_addrs != NULL) {
443 _FREE((caddr_t)old_ifnet_addrs, M_IFADDR);
444 }
445 }
446 return (new_index);
447 }
448
449 /*
450 * Create a clone network interface.
451 */
452 static int
453 if_clone_create(char *name, int len, void *params)
454 {
455 struct if_clone *ifc;
456 char *dp;
457 int wildcard;
458 u_int32_t bytoff, bitoff;
459 u_int32_t unit;
460 int err;
461
462 ifc = if_clone_lookup(name, &unit);
463 if (ifc == NULL)
464 return (EINVAL);
465
466 if (ifunit(name) != NULL)
467 return (EEXIST);
468
469 bytoff = bitoff = 0;
470 wildcard = (unit == UINT32_MAX);
471 /*
472 * Find a free unit if none was given.
473 */
474 if (wildcard) {
475 while ((bytoff < ifc->ifc_bmlen)
476 && (ifc->ifc_units[bytoff] == 0xff))
477 bytoff++;
478 if (bytoff >= ifc->ifc_bmlen)
479 return (ENOSPC);
480 while ((ifc->ifc_units[bytoff] & (1 << bitoff)) != 0)
481 bitoff++;
482 unit = (bytoff << 3) + bitoff;
483 }
484
485 if (unit > ifc->ifc_maxunit)
486 return (ENXIO);
487
488 err = (*ifc->ifc_create)(ifc, unit, params);
489 if (err != 0)
490 return (err);
491
492 if (!wildcard) {
493 bytoff = unit >> 3;
494 bitoff = unit - (bytoff << 3);
495 }
496
497 /*
498 * Allocate the unit in the bitmap.
499 */
500 KASSERT((ifc->ifc_units[bytoff] & (1 << bitoff)) == 0,
501 ("%s: bit is already set", __func__));
502 ifc->ifc_units[bytoff] |= (1 << bitoff);
503
504 /* In the wildcard case, we need to update the name. */
505 if (wildcard) {
506 for (dp = name; *dp != '\0'; dp++);
507 if (snprintf(dp, len - (dp-name), "%d", unit) >
508 len - (dp-name) - 1) {
509 /*
510 * This can only be a programmer error and
511 * there's no straightforward way to recover if
512 * it happens.
513 */
514 panic("%s: interface name too long", __func__);
515 /* NOTREACHED */
516 }
517
518 }
519
520 return (0);
521 }
522
523 /*
524 * Destroy a clone network interface.
525 */
526 static int
527 if_clone_destroy(const char *name)
528 {
529 struct if_clone *ifc;
530 struct ifnet *ifp;
531 int bytoff, bitoff;
532 u_int32_t unit;
533
534 ifc = if_clone_lookup(name, &unit);
535 if (ifc == NULL)
536 return (EINVAL);
537
538 if (unit < ifc->ifc_minifs)
539 return (EINVAL);
540
541 ifp = ifunit(name);
542 if (ifp == NULL)
543 return (ENXIO);
544
545 if (ifc->ifc_destroy == NULL)
546 return (EOPNOTSUPP);
547
548 (*ifc->ifc_destroy)(ifp);
549
550 /*
551 * Compute offset in the bitmap and deallocate the unit.
552 */
553 bytoff = unit >> 3;
554 bitoff = unit - (bytoff << 3);
555 KASSERT((ifc->ifc_units[bytoff] & (1 << bitoff)) != 0,
556 ("%s: bit is already cleared", __func__));
557 ifc->ifc_units[bytoff] &= ~(1 << bitoff);
558 return (0);
559 }
560
561 /*
562 * Look up a network interface cloner.
563 */
564
565 __private_extern__ struct if_clone *
566 if_clone_lookup(const char *name, u_int32_t *unitp)
567 {
568 struct if_clone *ifc;
569 const char *cp;
570 u_int32_t i;
571
572 for (ifc = LIST_FIRST(&if_cloners); ifc != NULL;) {
573 for (cp = name, i = 0; i < ifc->ifc_namelen; i++, cp++) {
574 if (ifc->ifc_name[i] != *cp)
575 goto next_ifc;
576 }
577 goto found_name;
578 next_ifc:
579 ifc = LIST_NEXT(ifc, ifc_list);
580 }
581
582 /* No match. */
583 return ((struct if_clone *)NULL);
584
585 found_name:
586 if (*cp == '\0') {
587 i = UINT32_MAX;
588 } else {
589 for (i = 0; *cp != '\0'; cp++) {
590 if (*cp < '0' || *cp > '9') {
591 /* Bogus unit number. */
592 return (NULL);
593 }
594 i = (i * 10) + (*cp - '0');
595 }
596 }
597
598 if (unitp != NULL)
599 *unitp = i;
600 return (ifc);
601 }
602
603 /*
604 * Register a network interface cloner.
605 */
606 int
607 if_clone_attach(struct if_clone *ifc)
608 {
609 int bytoff, bitoff;
610 int err;
611 int len, maxclone;
612 u_int32_t unit;
613
614 KASSERT(ifc->ifc_minifs - 1 <= ifc->ifc_maxunit,
615 ("%s: %s requested more units then allowed (%d > %d)",
616 __func__, ifc->ifc_name, ifc->ifc_minifs,
617 ifc->ifc_maxunit + 1));
618 /*
619 * Compute bitmap size and allocate it.
620 */
621 maxclone = ifc->ifc_maxunit + 1;
622 len = maxclone >> 3;
623 if ((len << 3) < maxclone)
624 len++;
625 ifc->ifc_units = _MALLOC(len, M_CLONE, M_WAITOK | M_ZERO);
626 if (ifc->ifc_units == NULL)
627 return ENOBUFS;
628 bzero(ifc->ifc_units, len);
629 ifc->ifc_bmlen = len;
630
631 LIST_INSERT_HEAD(&if_cloners, ifc, ifc_list);
632 if_cloners_count++;
633
634 for (unit = 0; unit < ifc->ifc_minifs; unit++) {
635 err = (*ifc->ifc_create)(ifc, unit, NULL);
636 KASSERT(err == 0,
637 ("%s: failed to create required interface %s%d",
638 __func__, ifc->ifc_name, unit));
639
640 /* Allocate the unit in the bitmap. */
641 bytoff = unit >> 3;
642 bitoff = unit - (bytoff << 3);
643 ifc->ifc_units[bytoff] |= (1 << bitoff);
644 }
645
646 return 0;
647 }
648
649 /*
650 * Unregister a network interface cloner.
651 */
652 void
653 if_clone_detach(struct if_clone *ifc)
654 {
655 LIST_REMOVE(ifc, ifc_list);
656 FREE(ifc->ifc_units, M_CLONE);
657 if_cloners_count--;
658 }
659
660 /*
661 * Provide list of interface cloners to userspace.
662 */
663 static int
664 if_clone_list(int count, int *ret_total, user_addr_t dst)
665 {
666 char outbuf[IFNAMSIZ];
667 struct if_clone *ifc;
668 int error = 0;
669
670 *ret_total = if_cloners_count;
671 if (dst == USER_ADDR_NULL) {
672 /* Just asking how many there are. */
673 return (0);
674 }
675
676 if (count < 0)
677 return (EINVAL);
678
679 count = (if_cloners_count < count) ? if_cloners_count : count;
680
681 for (ifc = LIST_FIRST(&if_cloners); ifc != NULL && count != 0;
682 ifc = LIST_NEXT(ifc, ifc_list), count--, dst += IFNAMSIZ) {
683 strlcpy(outbuf, ifc->ifc_name, IFNAMSIZ);
684 error = copyout(outbuf, dst, IFNAMSIZ);
685 if (error)
686 break;
687 }
688
689 return (error);
690 }
691
692 /*
693 * Similar to ifa_ifwithaddr, except that this is IPv4 specific
694 * and that it matches only the local (not broadcast) address.
695 */
696 __private_extern__ struct in_ifaddr *
697 ifa_foraddr(unsigned int addr)
698 {
699 return (ifa_foraddr_scoped(addr, IFSCOPE_NONE));
700 }
701
702 /*
703 * Similar to ifa_foraddr, except with the added interface scope
704 * constraint (unless the caller passes in IFSCOPE_NONE in which
705 * case there is no scope restriction).
706 */
707 __private_extern__ struct in_ifaddr *
708 ifa_foraddr_scoped(unsigned int addr, unsigned int scope)
709 {
710 struct in_ifaddr *ia = NULL;
711
712 lck_rw_lock_shared(in_ifaddr_rwlock);
713 TAILQ_FOREACH(ia, INADDR_HASH(addr), ia_hash) {
714 IFA_LOCK_SPIN(&ia->ia_ifa);
715 if (ia->ia_addr.sin_addr.s_addr == addr &&
716 (scope == IFSCOPE_NONE || ia->ia_ifp->if_index == scope)) {
717 IFA_ADDREF_LOCKED(&ia->ia_ifa); /* for caller */
718 IFA_UNLOCK(&ia->ia_ifa);
719 break;
720 }
721 IFA_UNLOCK(&ia->ia_ifa);
722 }
723 lck_rw_done(in_ifaddr_rwlock);
724 return (ia);
725 }
726
727 #if INET6
728 /*
729 * Similar to ifa_foraddr, except that this for IPv6.
730 */
731 __private_extern__ struct in6_ifaddr *
732 ifa_foraddr6(struct in6_addr *addr6)
733 {
734 return (ifa_foraddr6_scoped(addr6, IFSCOPE_NONE));
735 }
736
737 __private_extern__ struct in6_ifaddr *
738 ifa_foraddr6_scoped(struct in6_addr *addr6, unsigned int scope)
739 {
740 struct in6_ifaddr *ia = NULL;
741
742 lck_rw_lock_shared(&in6_ifaddr_rwlock);
743 for (ia = in6_ifaddrs; ia; ia = ia->ia_next) {
744 IFA_LOCK(&ia->ia_ifa);
745 if (IN6_ARE_ADDR_EQUAL(&ia->ia_addr.sin6_addr, addr6) &&
746 (scope == IFSCOPE_NONE || ia->ia_ifp->if_index == scope)) {
747 IFA_ADDREF_LOCKED(&ia->ia_ifa); /* for caller */
748 IFA_UNLOCK(&ia->ia_ifa);
749 break;
750 }
751 IFA_UNLOCK(&ia->ia_ifa);
752 }
753 lck_rw_done(&in6_ifaddr_rwlock);
754
755 return (ia);
756 }
757 #endif /* INET6 */
758
759 /*
760 * Return the first (primary) address of a given family on an interface.
761 */
762 __private_extern__ struct ifaddr *
763 ifa_ifpgetprimary(struct ifnet *ifp, int family)
764 {
765 struct ifaddr *ifa;
766
767 ifnet_lock_shared(ifp);
768 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
769 IFA_LOCK_SPIN(ifa);
770 if (ifa->ifa_addr->sa_family == family) {
771 IFA_ADDREF_LOCKED(ifa); /* for caller */
772 IFA_UNLOCK(ifa);
773 break;
774 }
775 IFA_UNLOCK(ifa);
776 }
777 ifnet_lock_done(ifp);
778
779 return (ifa);
780 }
781
782 /*
783 * Locate an interface based on a complete address.
784 */
785 /*ARGSUSED*/
786 struct ifaddr *
787 ifa_ifwithaddr(const struct sockaddr *addr)
788 {
789 struct ifnet *ifp;
790 struct ifaddr *ifa;
791 struct ifaddr *result = NULL;
792
793 #define equal(a1, a2) \
794 (bcmp((const void*)(a1), (const void*)(a2), \
795 ((const struct sockaddr *)(a1))->sa_len) == 0)
796
797 ifnet_head_lock_shared();
798 for (ifp = ifnet_head.tqh_first; ifp && !result;
799 ifp = ifp->if_link.tqe_next) {
800 ifnet_lock_shared(ifp);
801 for (ifa = ifp->if_addrhead.tqh_first; ifa;
802 ifa = ifa->ifa_link.tqe_next) {
803 IFA_LOCK_SPIN(ifa);
804 if (ifa->ifa_addr->sa_family != addr->sa_family) {
805 IFA_UNLOCK(ifa);
806 continue;
807 }
808 if (equal(addr, ifa->ifa_addr)) {
809 result = ifa;
810 IFA_ADDREF_LOCKED(ifa); /* for caller */
811 IFA_UNLOCK(ifa);
812 break;
813 }
814 if ((ifp->if_flags & IFF_BROADCAST) &&
815 ifa->ifa_broadaddr != NULL &&
816 /* IP6 doesn't have broadcast */
817 ifa->ifa_broadaddr->sa_len != 0 &&
818 equal(ifa->ifa_broadaddr, addr)) {
819 result = ifa;
820 IFA_ADDREF_LOCKED(ifa); /* for caller */
821 IFA_UNLOCK(ifa);
822 break;
823 }
824 IFA_UNLOCK(ifa);
825 }
826 ifnet_lock_done(ifp);
827 }
828 ifnet_head_done();
829
830 return (result);
831 }
832 /*
833 * Locate the point to point interface with a given destination address.
834 */
835 /*ARGSUSED*/
836 struct ifaddr *
837 ifa_ifwithdstaddr(const struct sockaddr *addr)
838 {
839 struct ifnet *ifp;
840 struct ifaddr *ifa;
841 struct ifaddr *result = NULL;
842
843 ifnet_head_lock_shared();
844 for (ifp = ifnet_head.tqh_first; ifp && !result;
845 ifp = ifp->if_link.tqe_next) {
846 if ((ifp->if_flags & IFF_POINTOPOINT)) {
847 ifnet_lock_shared(ifp);
848 for (ifa = ifp->if_addrhead.tqh_first; ifa;
849 ifa = ifa->ifa_link.tqe_next) {
850 IFA_LOCK_SPIN(ifa);
851 if (ifa->ifa_addr->sa_family !=
852 addr->sa_family) {
853 IFA_UNLOCK(ifa);
854 continue;
855 }
856 if (ifa->ifa_dstaddr &&
857 equal(addr, ifa->ifa_dstaddr)) {
858 result = ifa;
859 IFA_ADDREF_LOCKED(ifa); /* for caller */
860 IFA_UNLOCK(ifa);
861 break;
862 }
863 IFA_UNLOCK(ifa);
864 }
865 ifnet_lock_done(ifp);
866 }
867 }
868 ifnet_head_done();
869 return (result);
870 }
871
872 /*
873 * Locate the source address of an interface based on a complete address.
874 */
875 struct ifaddr *
876 ifa_ifwithaddr_scoped(const struct sockaddr *addr, unsigned int ifscope)
877 {
878 struct ifaddr *result = NULL;
879 struct ifnet *ifp;
880
881 if (ifscope == IFSCOPE_NONE)
882 return (ifa_ifwithaddr(addr));
883
884 ifnet_head_lock_shared();
885 if (ifscope > (unsigned int)if_index) {
886 ifnet_head_done();
887 return (NULL);
888 }
889
890 ifp = ifindex2ifnet[ifscope];
891 if (ifp != NULL) {
892 struct ifaddr *ifa = NULL;
893
894 /*
895 * This is suboptimal; there should be a better way
896 * to search for a given address of an interface
897 * for any given address family.
898 */
899 ifnet_lock_shared(ifp);
900 for (ifa = ifp->if_addrhead.tqh_first; ifa != NULL;
901 ifa = ifa->ifa_link.tqe_next) {
902 IFA_LOCK_SPIN(ifa);
903 if (ifa->ifa_addr->sa_family != addr->sa_family) {
904 IFA_UNLOCK(ifa);
905 continue;
906 }
907 if (equal(addr, ifa->ifa_addr)) {
908 result = ifa;
909 IFA_ADDREF_LOCKED(ifa); /* for caller */
910 IFA_UNLOCK(ifa);
911 break;
912 }
913 if ((ifp->if_flags & IFF_BROADCAST) &&
914 ifa->ifa_broadaddr != NULL &&
915 /* IP6 doesn't have broadcast */
916 ifa->ifa_broadaddr->sa_len != 0 &&
917 equal(ifa->ifa_broadaddr, addr)) {
918 result = ifa;
919 IFA_ADDREF_LOCKED(ifa); /* for caller */
920 IFA_UNLOCK(ifa);
921 break;
922 }
923 IFA_UNLOCK(ifa);
924 }
925 ifnet_lock_done(ifp);
926 }
927 ifnet_head_done();
928
929 return (result);
930 }
931
932 struct ifaddr *
933 ifa_ifwithnet(const struct sockaddr *addr)
934 {
935 return (ifa_ifwithnet_common(addr, IFSCOPE_NONE));
936 }
937
938 struct ifaddr *
939 ifa_ifwithnet_scoped(const struct sockaddr *addr, unsigned int ifscope)
940 {
941 return (ifa_ifwithnet_common(addr, ifscope));
942 }
943
944 /*
945 * Find an interface on a specific network. If many, choice
946 * is most specific found.
947 */
948 static struct ifaddr *
949 ifa_ifwithnet_common(const struct sockaddr *addr, unsigned int ifscope)
950 {
951 struct ifnet *ifp;
952 struct ifaddr *ifa = NULL;
953 struct ifaddr *ifa_maybe = NULL;
954 u_int af = addr->sa_family;
955 const char *addr_data = addr->sa_data, *cplim;
956
957 #if INET6
958 if ((af != AF_INET && af != AF_INET6) ||
959 (af == AF_INET && !ip_doscopedroute) ||
960 (af == AF_INET6 && !ip6_doscopedroute))
961 #else
962 if (af != AF_INET || !ip_doscopedroute)
963 #endif /* !INET6 */
964 ifscope = IFSCOPE_NONE;
965
966 ifnet_head_lock_shared();
967 /*
968 * AF_LINK addresses can be looked up directly by their index number,
969 * so do that if we can.
970 */
971 if (af == AF_LINK) {
972 const struct sockaddr_dl *sdl =
973 (const struct sockaddr_dl *)(uintptr_t)(size_t)addr;
974 if (sdl->sdl_index && sdl->sdl_index <= if_index) {
975 ifa = ifnet_addrs[sdl->sdl_index - 1];
976 if (ifa != NULL)
977 IFA_ADDREF(ifa);
978
979 ifnet_head_done();
980 return (ifa);
981 }
982 }
983
984 /*
985 * Scan though each interface, looking for ones that have
986 * addresses in this address family.
987 */
988 for (ifp = ifnet_head.tqh_first; ifp; ifp = ifp->if_link.tqe_next) {
989 ifnet_lock_shared(ifp);
990 for (ifa = ifp->if_addrhead.tqh_first; ifa;
991 ifa = ifa->ifa_link.tqe_next) {
992 const char *cp, *cp2, *cp3;
993
994 IFA_LOCK(ifa);
995 if (ifa->ifa_addr == NULL ||
996 ifa->ifa_addr->sa_family != af) {
997 next:
998 IFA_UNLOCK(ifa);
999 continue;
1000 }
1001 /*
1002 * If we're looking up with a scope,
1003 * find using a matching interface.
1004 */
1005 if (ifscope != IFSCOPE_NONE &&
1006 ifp->if_index != ifscope) {
1007 IFA_UNLOCK(ifa);
1008 continue;
1009 }
1010
1011 /*
1012 * Scan all the bits in the ifa's address.
1013 * If a bit dissagrees with what we are
1014 * looking for, mask it with the netmask
1015 * to see if it really matters.
1016 * (A byte at a time)
1017 */
1018 if (ifa->ifa_netmask == 0) {
1019 IFA_UNLOCK(ifa);
1020 continue;
1021 }
1022 cp = addr_data;
1023 cp2 = ifa->ifa_addr->sa_data;
1024 cp3 = ifa->ifa_netmask->sa_data;
1025 cplim = ifa->ifa_netmask->sa_len +
1026 (char *)ifa->ifa_netmask;
1027 while (cp3 < cplim)
1028 if ((*cp++ ^ *cp2++) & *cp3++)
1029 goto next; /* next address! */
1030 /*
1031 * If the netmask of what we just found
1032 * is more specific than what we had before
1033 * (if we had one) then remember the new one
1034 * before continuing to search
1035 * for an even better one.
1036 */
1037 if (ifa_maybe == NULL ||
1038 rn_refines((caddr_t)ifa->ifa_netmask,
1039 (caddr_t)ifa_maybe->ifa_netmask)) {
1040 IFA_ADDREF_LOCKED(ifa); /* ifa_maybe */
1041 IFA_UNLOCK(ifa);
1042 if (ifa_maybe != NULL)
1043 IFA_REMREF(ifa_maybe);
1044 ifa_maybe = ifa;
1045 } else {
1046 IFA_UNLOCK(ifa);
1047 }
1048 IFA_LOCK_ASSERT_NOTHELD(ifa);
1049 }
1050 ifnet_lock_done(ifp);
1051
1052 if (ifa != NULL)
1053 break;
1054 }
1055 ifnet_head_done();
1056
1057 if (ifa == NULL)
1058 ifa = ifa_maybe;
1059 else if (ifa_maybe != NULL)
1060 IFA_REMREF(ifa_maybe);
1061
1062 return (ifa);
1063 }
1064
1065 /*
1066 * Find an interface address specific to an interface best matching
1067 * a given address.
1068 */
1069 struct ifaddr *
1070 ifaof_ifpforaddr(const struct sockaddr *addr, struct ifnet *ifp)
1071 {
1072 struct ifaddr *ifa = NULL;
1073 const char *cp, *cp2, *cp3;
1074 char *cplim;
1075 struct ifaddr *ifa_maybe = NULL;
1076 struct ifaddr *better_ifa_maybe = NULL;
1077 u_int af = addr->sa_family;
1078
1079 if (af >= AF_MAX)
1080 return (NULL);
1081
1082 ifnet_lock_shared(ifp);
1083 for (ifa = ifp->if_addrhead.tqh_first; ifa;
1084 ifa = ifa->ifa_link.tqe_next) {
1085 IFA_LOCK(ifa);
1086 if (ifa->ifa_addr->sa_family != af) {
1087 IFA_UNLOCK(ifa);
1088 continue;
1089 }
1090 if (ifa_maybe == NULL) {
1091 IFA_ADDREF_LOCKED(ifa); /* for ifa_maybe */
1092 ifa_maybe = ifa;
1093 }
1094 if (ifa->ifa_netmask == 0) {
1095 if (equal(addr, ifa->ifa_addr) || (ifa->ifa_dstaddr &&
1096 equal(addr, ifa->ifa_dstaddr))) {
1097 IFA_ADDREF_LOCKED(ifa); /* for caller */
1098 IFA_UNLOCK(ifa);
1099 break;
1100 }
1101 IFA_UNLOCK(ifa);
1102 continue;
1103 }
1104 if (ifp->if_flags & IFF_POINTOPOINT) {
1105 if (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)) {
1106 IFA_ADDREF_LOCKED(ifa); /* for caller */
1107 IFA_UNLOCK(ifa);
1108 break;
1109 }
1110 } else {
1111 if (equal(addr, ifa->ifa_addr)) {
1112 /* exact match */
1113 IFA_ADDREF_LOCKED(ifa); /* for caller */
1114 IFA_UNLOCK(ifa);
1115 break;
1116 }
1117 cp = addr->sa_data;
1118 cp2 = ifa->ifa_addr->sa_data;
1119 cp3 = ifa->ifa_netmask->sa_data;
1120 cplim = ifa->ifa_netmask->sa_len +
1121 (char *)ifa->ifa_netmask;
1122 for (; cp3 < cplim; cp3++)
1123 if ((*cp++ ^ *cp2++) & *cp3)
1124 break;
1125 if (cp3 == cplim) {
1126 /* subnet match */
1127 if (better_ifa_maybe == NULL) {
1128 /* for better_ifa_maybe */
1129 IFA_ADDREF_LOCKED(ifa);
1130 better_ifa_maybe = ifa;
1131 }
1132 }
1133 }
1134 IFA_UNLOCK(ifa);
1135 }
1136
1137 if (ifa == NULL) {
1138 if (better_ifa_maybe != NULL) {
1139 ifa = better_ifa_maybe;
1140 better_ifa_maybe = NULL;
1141 } else {
1142 ifa = ifa_maybe;
1143 ifa_maybe = NULL;
1144 }
1145 }
1146
1147 ifnet_lock_done(ifp);
1148
1149 if (better_ifa_maybe != NULL)
1150 IFA_REMREF(better_ifa_maybe);
1151 if (ifa_maybe != NULL)
1152 IFA_REMREF(ifa_maybe);
1153
1154 return (ifa);
1155 }
1156
1157 #include <net/route.h>
1158
1159 /*
1160 * Default action when installing a route with a Link Level gateway.
1161 * Lookup an appropriate real ifa to point to.
1162 * This should be moved to /sys/net/link.c eventually.
1163 */
1164 void
1165 link_rtrequest(int cmd, struct rtentry *rt, struct sockaddr *sa)
1166 {
1167 struct ifaddr *ifa;
1168 struct sockaddr *dst;
1169 struct ifnet *ifp;
1170 void (*ifa_rtrequest)(int, struct rtentry *, struct sockaddr *);
1171
1172 lck_mtx_assert(rnh_lock, LCK_MTX_ASSERT_OWNED);
1173 RT_LOCK_ASSERT_HELD(rt);
1174
1175 if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) ||
1176 ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0))
1177 return;
1178
1179 /* Become a regular mutex, just in case */
1180 RT_CONVERT_LOCK(rt);
1181
1182 ifa = ifaof_ifpforaddr(dst, ifp);
1183 if (ifa) {
1184 rtsetifa(rt, ifa);
1185 IFA_LOCK_SPIN(ifa);
1186 ifa_rtrequest = ifa->ifa_rtrequest;
1187 IFA_UNLOCK(ifa);
1188 if (ifa_rtrequest != NULL && ifa_rtrequest != link_rtrequest)
1189 ifa_rtrequest(cmd, rt, sa);
1190 IFA_REMREF(ifa);
1191 }
1192 }
1193
1194 /*
1195 * if_updown will set the interface up or down. It will
1196 * prevent other up/down events from occurring until this
1197 * up/down event has completed.
1198 *
1199 * Caller must lock ifnet. This function will drop the
1200 * lock. This allows ifnet_set_flags to set the rest of
1201 * the flags after we change the up/down state without
1202 * dropping the interface lock between setting the
1203 * up/down state and updating the rest of the flags.
1204 */
1205 __private_extern__ void
1206 if_updown(
1207 struct ifnet *ifp,
1208 int up)
1209 {
1210 int i;
1211 struct ifaddr **ifa;
1212 struct timespec tv;
1213 struct ifclassq *ifq = &ifp->if_snd;
1214
1215 /* Wait until no one else is changing the up/down state */
1216 while ((ifp->if_eflags & IFEF_UPDOWNCHANGE) != 0) {
1217 tv.tv_sec = 0;
1218 tv.tv_nsec = NSEC_PER_SEC / 10;
1219 ifnet_lock_done(ifp);
1220 msleep(&ifp->if_eflags, NULL, 0, "if_updown", &tv);
1221 ifnet_lock_exclusive(ifp);
1222 }
1223
1224 /* Verify that the interface isn't already in the right state */
1225 if ((!up && (ifp->if_flags & IFF_UP) == 0) ||
1226 (up && (ifp->if_flags & IFF_UP) == IFF_UP)) {
1227 return;
1228 }
1229
1230 /* Indicate that the up/down state is changing */
1231 ifp->if_eflags |= IFEF_UPDOWNCHANGE;
1232
1233 /* Mark interface up or down */
1234 if (up) {
1235 ifp->if_flags |= IFF_UP;
1236 }
1237 else {
1238 ifp->if_flags &= ~IFF_UP;
1239 }
1240
1241 ifnet_touch_lastchange(ifp);
1242
1243 /* Drop the lock to notify addresses and route */
1244 ifnet_lock_done(ifp);
1245 if (ifnet_get_address_list(ifp, &ifa) == 0) {
1246 for (i = 0; ifa[i] != 0; i++) {
1247 pfctlinput(up ? PRC_IFUP : PRC_IFDOWN, ifa[i]->ifa_addr);
1248 }
1249 ifnet_free_address_list(ifa);
1250 }
1251 rt_ifmsg(ifp);
1252
1253 if (!up)
1254 if_qflush(ifp, 0);
1255
1256 /* Inform all transmit queues about the new link state */
1257 IFCQ_LOCK(ifq);
1258 ifnet_update_sndq(ifq, up ? CLASSQ_EV_LINK_UP : CLASSQ_EV_LINK_DOWN);
1259 IFCQ_UNLOCK(ifq);
1260
1261 /* Aquire the lock to clear the changing flag */
1262 ifnet_lock_exclusive(ifp);
1263 ifp->if_eflags &= ~IFEF_UPDOWNCHANGE;
1264 wakeup(&ifp->if_eflags);
1265 }
1266
1267 /*
1268 * Mark an interface down and notify protocols of
1269 * the transition.
1270 */
1271 void
1272 if_down(
1273 struct ifnet *ifp)
1274 {
1275 ifnet_lock_exclusive(ifp);
1276 if_updown(ifp, 0);
1277 ifnet_lock_done(ifp);
1278 }
1279
1280 /*
1281 * Mark an interface up and notify protocols of
1282 * the transition.
1283 */
1284 void
1285 if_up(
1286 struct ifnet *ifp)
1287 {
1288 ifnet_lock_exclusive(ifp);
1289 if_updown(ifp, 1);
1290 ifnet_lock_done(ifp);
1291 }
1292
1293 /*
1294 * Flush an interface queue.
1295 */
1296 void
1297 if_qflush(struct ifnet *ifp, int ifq_locked)
1298 {
1299 struct ifclassq *ifq = &ifp->if_snd;
1300
1301 if (!ifq_locked)
1302 IFCQ_LOCK(ifq);
1303
1304 if (IFCQ_IS_ENABLED(ifq))
1305 IFCQ_PURGE(ifq);
1306 #if PF_ALTQ
1307 if (IFCQ_IS_DRAINING(ifq))
1308 ifq->ifcq_drain = 0;
1309 if (ALTQ_IS_ENABLED(IFCQ_ALTQ(ifq)))
1310 ALTQ_PURGE(IFCQ_ALTQ(ifq));
1311 #endif /* PF_ALTQ */
1312
1313 VERIFY(IFCQ_IS_EMPTY(ifq));
1314
1315 if (!ifq_locked)
1316 IFCQ_UNLOCK(ifq);
1317 }
1318
1319 void
1320 if_qflush_sc(struct ifnet *ifp, mbuf_svc_class_t sc, u_int32_t flow,
1321 u_int32_t *packets, u_int32_t *bytes, int ifq_locked)
1322 {
1323 struct ifclassq *ifq = &ifp->if_snd;
1324 u_int32_t cnt = 0, len = 0;
1325 u_int32_t a_cnt = 0, a_len = 0;
1326
1327 VERIFY(sc == MBUF_SC_UNSPEC || MBUF_VALID_SC(sc));
1328 VERIFY(flow != 0);
1329
1330 if (!ifq_locked)
1331 IFCQ_LOCK(ifq);
1332
1333 if (IFCQ_IS_ENABLED(ifq))
1334 IFCQ_PURGE_SC(ifq, sc, flow, cnt, len);
1335 #if PF_ALTQ
1336 if (IFCQ_IS_DRAINING(ifq)) {
1337 VERIFY((signed)(ifq->ifcq_drain - cnt) >= 0);
1338 ifq->ifcq_drain -= cnt;
1339 }
1340 if (ALTQ_IS_ENABLED(IFCQ_ALTQ(ifq)))
1341 ALTQ_PURGE_SC(IFCQ_ALTQ(ifq), sc, flow, a_cnt, a_len);
1342 #endif /* PF_ALTQ */
1343
1344 if (!ifq_locked)
1345 IFCQ_UNLOCK(ifq);
1346
1347 if (packets != NULL)
1348 *packets = cnt + a_cnt;
1349 if (bytes != NULL)
1350 *bytes = len + a_len;
1351 }
1352
1353 /*
1354 * Map interface name to
1355 * interface structure pointer.
1356 */
1357 struct ifnet *
1358 ifunit(const char *name)
1359 {
1360 char namebuf[IFNAMSIZ + 1];
1361 const char *cp;
1362 struct ifnet *ifp;
1363 int unit;
1364 unsigned len, m;
1365 char c;
1366
1367 len = strlen(name);
1368 if (len < 2 || len > IFNAMSIZ)
1369 return (NULL);
1370 cp = name + len - 1;
1371 c = *cp;
1372 if (c < '0' || c > '9')
1373 return (NULL); /* trailing garbage */
1374 unit = 0;
1375 m = 1;
1376 do {
1377 if (cp == name)
1378 return (NULL); /* no interface name */
1379 unit += (c - '0') * m;
1380 if (unit > 1000000)
1381 return (NULL); /* number is unreasonable */
1382 m *= 10;
1383 c = *--cp;
1384 } while (c >= '0' && c <= '9');
1385 len = cp - name + 1;
1386 bcopy(name, namebuf, len);
1387 namebuf[len] = '\0';
1388 /*
1389 * Now search all the interfaces for this name/number
1390 */
1391 ifnet_head_lock_shared();
1392 TAILQ_FOREACH(ifp, &ifnet_head, if_link) {
1393 if (strncmp(ifp->if_name, namebuf, len))
1394 continue;
1395 if (unit == ifp->if_unit)
1396 break;
1397 }
1398 ifnet_head_done();
1399 return (ifp);
1400 }
1401
1402
1403 /*
1404 * Map interface name in a sockaddr_dl to
1405 * interface structure pointer.
1406 */
1407 struct ifnet *
1408 if_withname(struct sockaddr *sa)
1409 {
1410 char ifname[IFNAMSIZ+1];
1411 struct sockaddr_dl *sdl = (struct sockaddr_dl *)(void *)sa;
1412
1413 if ( (sa->sa_family != AF_LINK) || (sdl->sdl_nlen == 0) ||
1414 (sdl->sdl_nlen > IFNAMSIZ) )
1415 return (NULL);
1416
1417 /*
1418 * ifunit wants a null-terminated name. It may not be null-terminated
1419 * in the sockaddr. We don't want to change the caller's sockaddr,
1420 * and there might not be room to put the trailing null anyway, so we
1421 * make a local copy that we know we can null terminate safely.
1422 */
1423
1424 bcopy(sdl->sdl_data, ifname, sdl->sdl_nlen);
1425 ifname[sdl->sdl_nlen] = '\0';
1426 return (ifunit(ifname));
1427 }
1428
1429 static __attribute__((noinline)) int
1430 ifioctl_ifconf(u_long cmd, caddr_t data)
1431 {
1432 int error = 0;
1433
1434 switch (cmd) {
1435 case OSIOCGIFCONF32: /* struct ifconf32 */
1436 case SIOCGIFCONF32: { /* struct ifconf32 */
1437 struct ifconf32 ifc;
1438 bcopy(data, &ifc, sizeof (ifc));
1439 error = ifconf(cmd, CAST_USER_ADDR_T(ifc.ifc_req),
1440 &ifc.ifc_len);
1441 bcopy(&ifc, data, sizeof (ifc));
1442 break;
1443 }
1444
1445 case SIOCGIFCONF64: /* struct ifconf64 */
1446 case OSIOCGIFCONF64: { /* struct ifconf64 */
1447 struct ifconf64 ifc;
1448 bcopy(data, &ifc, sizeof (ifc));
1449 error = ifconf(cmd, ifc.ifc_req, &ifc.ifc_len);
1450 bcopy(&ifc, data, sizeof (ifc));
1451 break;
1452 }
1453
1454 default:
1455 VERIFY(0);
1456 /* NOTREACHED */
1457 }
1458
1459 return (error);
1460 }
1461
1462 static __attribute__((noinline)) int
1463 ifioctl_ifclone(u_long cmd, caddr_t data)
1464 {
1465 int error = 0;
1466
1467 switch (cmd) {
1468 case SIOCIFGCLONERS32: { /* struct if_clonereq32 */
1469 struct if_clonereq32 ifcr;
1470 bcopy(data, &ifcr, sizeof (ifcr));
1471 error = if_clone_list(ifcr.ifcr_count, &ifcr.ifcr_total,
1472 CAST_USER_ADDR_T(ifcr.ifcru_buffer));
1473 bcopy(&ifcr, data, sizeof (ifcr));
1474 break;
1475 }
1476
1477 case SIOCIFGCLONERS64: { /* struct if_clonereq64 */
1478 struct if_clonereq64 ifcr;
1479 bcopy(data, &ifcr, sizeof (ifcr));
1480 error = if_clone_list(ifcr.ifcr_count, &ifcr.ifcr_total,
1481 ifcr.ifcru_buffer);
1482 bcopy(&ifcr, data, sizeof (ifcr));
1483 break;
1484 }
1485
1486 default:
1487 VERIFY(0);
1488 /* NOTREACHED */
1489 }
1490
1491 return (error);
1492 }
1493
1494 static __attribute__((noinline)) int
1495 ifioctl_ifdesc(struct ifnet *ifp, u_long cmd, caddr_t data, struct proc *p)
1496 {
1497 struct if_descreq *ifdr = (struct if_descreq *)(void *)data;
1498 u_int32_t ifdr_len;
1499 int error = 0;
1500
1501 VERIFY(ifp != NULL);
1502
1503 switch (cmd) {
1504 case SIOCSIFDESC: { /* struct if_descreq */
1505 if ((error = proc_suser(p)) != 0)
1506 break;
1507
1508 ifnet_lock_exclusive(ifp);
1509 bcopy(&ifdr->ifdr_len, &ifdr_len, sizeof (ifdr_len));
1510 if (ifdr_len > sizeof (ifdr->ifdr_desc) ||
1511 ifdr_len > ifp->if_desc.ifd_maxlen) {
1512 error = EINVAL;
1513 ifnet_lock_done(ifp);
1514 break;
1515 }
1516
1517 bzero(ifp->if_desc.ifd_desc, ifp->if_desc.ifd_maxlen);
1518 if ((ifp->if_desc.ifd_len = ifdr_len) > 0) {
1519 bcopy(ifdr->ifdr_desc, ifp->if_desc.ifd_desc,
1520 MIN(ifdr_len, ifp->if_desc.ifd_maxlen));
1521 }
1522 ifnet_lock_done(ifp);
1523 break;
1524 }
1525
1526 case SIOCGIFDESC: { /* struct if_descreq */
1527 ifnet_lock_shared(ifp);
1528 ifdr_len = MIN(ifp->if_desc.ifd_len, sizeof (ifdr->ifdr_desc));
1529 bcopy(&ifdr_len, &ifdr->ifdr_len, sizeof (ifdr_len));
1530 bzero(&ifdr->ifdr_desc, sizeof (ifdr->ifdr_desc));
1531 if (ifdr_len > 0) {
1532 bcopy(ifp->if_desc.ifd_desc, ifdr->ifdr_desc, ifdr_len);
1533 }
1534 ifnet_lock_done(ifp);
1535 break;
1536 }
1537
1538 default:
1539 VERIFY(0);
1540 /* NOTREACHED */
1541 }
1542
1543 return (error);
1544 }
1545
1546 static __attribute__((noinline)) int
1547 ifioctl_linkparams(struct ifnet *ifp, u_long cmd, caddr_t data, struct proc *p)
1548 {
1549 struct if_linkparamsreq *iflpr =
1550 (struct if_linkparamsreq *)(void *)data;
1551 struct ifclassq *ifq;
1552 int error = 0;
1553
1554 VERIFY(ifp != NULL);
1555 ifq = &ifp->if_snd;
1556
1557 switch (cmd) {
1558 case SIOCSIFLINKPARAMS: { /* struct if_linkparamsreq */
1559 struct tb_profile tb = { 0, 0, 0 };
1560
1561 if ((error = proc_suser(p)) != 0)
1562 break;
1563
1564 IFCQ_LOCK(ifq);
1565 if (!IFCQ_IS_READY(ifq)) {
1566 error = ENXIO;
1567 IFCQ_UNLOCK(ifq);
1568 break;
1569 }
1570 bcopy(&iflpr->iflpr_output_tbr_rate, &tb.rate,
1571 sizeof (tb.rate));
1572 bcopy(&iflpr->iflpr_output_tbr_percent, &tb.percent,
1573 sizeof (tb.percent));
1574 error = ifclassq_tbr_set(ifq, &tb, TRUE);
1575 IFCQ_UNLOCK(ifq);
1576 break;
1577 }
1578
1579 case SIOCGIFLINKPARAMS: { /* struct if_linkparamsreq */
1580 u_int32_t sched_type = PKTSCHEDT_NONE, flags = 0;
1581 u_int64_t tbr_bw = 0, tbr_pct = 0;
1582
1583 IFCQ_LOCK(ifq);
1584 #if PF_ALTQ
1585 if (ALTQ_IS_ENABLED(IFCQ_ALTQ(ifq))) {
1586 sched_type = IFCQ_ALTQ(ifq)->altq_type;
1587 flags |= IFLPRF_ALTQ;
1588 } else
1589 #endif /* PF_ALTQ */
1590 {
1591 if (IFCQ_IS_ENABLED(ifq))
1592 sched_type = ifq->ifcq_type;
1593 }
1594 bcopy(&sched_type, &iflpr->iflpr_output_sched,
1595 sizeof (iflpr->iflpr_output_sched));
1596
1597 if (IFCQ_TBR_IS_ENABLED(ifq)) {
1598 tbr_bw = ifq->ifcq_tbr.tbr_rate_raw;
1599 tbr_pct = ifq->ifcq_tbr.tbr_percent;
1600 }
1601 bcopy(&tbr_bw, &iflpr->iflpr_output_tbr_rate,
1602 sizeof (iflpr->iflpr_output_tbr_rate));
1603 bcopy(&tbr_pct, &iflpr->iflpr_output_tbr_percent,
1604 sizeof (iflpr->iflpr_output_tbr_percent));
1605 IFCQ_UNLOCK(ifq);
1606
1607 if (ifp->if_output_sched_model ==
1608 IFNET_SCHED_MODEL_DRIVER_MANAGED)
1609 flags |= IFLPRF_DRVMANAGED;
1610 bcopy(&flags, &iflpr->iflpr_flags, sizeof (iflpr->iflpr_flags));
1611 bcopy(&ifp->if_output_bw, &iflpr->iflpr_output_bw,
1612 sizeof (iflpr->iflpr_output_bw));
1613 bcopy(&ifp->if_input_bw, &iflpr->iflpr_input_bw,
1614 sizeof (iflpr->iflpr_input_bw));
1615 bcopy(&ifp->if_output_lt, &iflpr->iflpr_output_lt,
1616 sizeof (iflpr->iflpr_output_lt));
1617 bcopy(&ifp->if_input_lt, &iflpr->iflpr_input_lt,
1618 sizeof (iflpr->iflpr_input_lt));
1619 break;
1620 }
1621
1622 default:
1623 VERIFY(0);
1624 /* NOTREACHED */
1625 }
1626
1627 return (error);
1628 }
1629
1630 static __attribute__((noinline)) int
1631 ifioctl_qstats(struct ifnet *ifp, u_long cmd, caddr_t data)
1632 {
1633 struct if_qstatsreq *ifqr = (struct if_qstatsreq *)(void *)data;
1634 u_int32_t ifqr_len, ifqr_slot;
1635 int error = 0;
1636
1637 VERIFY(ifp != NULL);
1638
1639 switch (cmd) {
1640 case SIOCGIFQUEUESTATS: { /* struct if_qstatsreq */
1641 bcopy(&ifqr->ifqr_slot, &ifqr_slot, sizeof (ifqr_slot));
1642 bcopy(&ifqr->ifqr_len, &ifqr_len, sizeof (ifqr_len));
1643 error = ifclassq_getqstats(&ifp->if_snd, ifqr_slot,
1644 ifqr->ifqr_buf, &ifqr_len);
1645 if (error != 0)
1646 ifqr_len = 0;
1647 bcopy(&ifqr_len, &ifqr->ifqr_len, sizeof (ifqr_len));
1648 break;
1649 }
1650
1651 default:
1652 VERIFY(0);
1653 /* NOTREACHED */
1654 }
1655
1656 return (error);
1657 }
1658
1659 static __attribute__((noinline)) int
1660 ifioctl_throttle(struct ifnet *ifp, u_long cmd, caddr_t data, struct proc *p)
1661 {
1662 struct if_throttlereq *ifthr = (struct if_throttlereq *)(void *)data;
1663 u_int32_t ifthr_level;
1664 int error = 0;
1665
1666 VERIFY(ifp != NULL);
1667
1668 switch (cmd) {
1669 case SIOCSIFTHROTTLE: { /* struct if_throttlereq */
1670 /*
1671 * XXX: Use priv_check_cred() instead of root check?
1672 */
1673 if ((error = proc_suser(p)) != 0)
1674 break;
1675
1676 bcopy(&ifthr->ifthr_level, &ifthr_level, sizeof (ifthr_level));
1677 error = ifnet_set_throttle(ifp, ifthr_level);
1678 if (error == EALREADY)
1679 error = 0;
1680 break;
1681 }
1682
1683 case SIOCGIFTHROTTLE: { /* struct if_throttlereq */
1684 if ((error = ifnet_get_throttle(ifp, &ifthr_level)) == 0) {
1685 bcopy(&ifthr_level, &ifthr->ifthr_level,
1686 sizeof (ifthr_level));
1687 }
1688 break;
1689 }
1690
1691 default:
1692 VERIFY(0);
1693 /* NOTREACHED */
1694 }
1695
1696 return (error);
1697 }
1698
1699 /*
1700 * Interface ioctls.
1701 *
1702 * Most of the routines called to handle the ioctls would end up being
1703 * tail-call optimized, which unfortunately causes this routine to
1704 * consume too much stack space; this is the reason for the "noinline"
1705 * attribute used on those routines.
1706 */
1707 int
1708 ifioctl(struct socket *so, u_long cmd, caddr_t data, struct proc *p)
1709 {
1710 char ifname[IFNAMSIZ + 1];
1711 struct ifnet *ifp = NULL;
1712 struct ifstat *ifs = NULL;
1713 int error = 0;
1714
1715 bzero(ifname, sizeof (ifname));
1716
1717 /*
1718 * ioctls which don't require ifp, or ifreq ioctls
1719 */
1720 switch (cmd) {
1721 case OSIOCGIFCONF32: /* struct ifconf32 */
1722 case SIOCGIFCONF32: /* struct ifconf32 */
1723 case SIOCGIFCONF64: /* struct ifconf64 */
1724 case OSIOCGIFCONF64: /* struct ifconf64 */
1725 error = ifioctl_ifconf(cmd, data);
1726 goto done;
1727
1728 case SIOCIFGCLONERS32: /* struct if_clonereq32 */
1729 case SIOCIFGCLONERS64: /* struct if_clonereq64 */
1730 error = ifioctl_ifclone(cmd, data);
1731 goto done;
1732
1733 case SIOCSIFDSTADDR: /* struct ifreq */
1734 case SIOCSIFADDR: /* struct ifreq */
1735 case SIOCSIFBRDADDR: /* struct ifreq */
1736 case SIOCSIFNETMASK: /* struct ifreq */
1737 case OSIOCGIFADDR: /* struct ifreq */
1738 case OSIOCGIFDSTADDR: /* struct ifreq */
1739 case OSIOCGIFBRDADDR: /* struct ifreq */
1740 case OSIOCGIFNETMASK: /* struct ifreq */
1741 case SIOCSIFKPI: /* struct ifreq */
1742 if (so->so_proto == NULL) {
1743 error = EOPNOTSUPP;
1744 goto done;
1745 }
1746 /* FALLTHRU */
1747 case SIOCIFCREATE: /* struct ifreq */
1748 case SIOCIFCREATE2: /* struct ifreq */
1749 case SIOCIFDESTROY: /* struct ifreq */
1750 case SIOCGIFFLAGS: /* struct ifreq */
1751 case SIOCGIFEFLAGS: /* struct ifreq */
1752 case SIOCGIFCAP: /* struct ifreq */
1753 #if CONFIG_MACF_NET
1754 case SIOCGIFMAC: /* struct ifreq */
1755 case SIOCSIFMAC: /* struct ifreq */
1756 #endif /* CONFIG_MACF_NET */
1757 case SIOCGIFMETRIC: /* struct ifreq */
1758 case SIOCGIFMTU: /* struct ifreq */
1759 case SIOCGIFPHYS: /* struct ifreq */
1760 case SIOCSIFFLAGS: /* struct ifreq */
1761 case SIOCSIFCAP: /* struct ifreq */
1762 case SIOCSIFMETRIC: /* struct ifreq */
1763 case SIOCSIFPHYS: /* struct ifreq */
1764 case SIOCSIFMTU: /* struct ifreq */
1765 case SIOCADDMULTI: /* struct ifreq */
1766 case SIOCDELMULTI: /* struct ifreq */
1767 case SIOCDIFPHYADDR: /* struct ifreq */
1768 case SIOCSIFMEDIA: /* struct ifreq */
1769 case SIOCSIFGENERIC: /* struct ifreq */
1770 case SIOCSIFLLADDR: /* struct ifreq */
1771 case SIOCSIFALTMTU: /* struct ifreq */
1772 case SIOCSIFVLAN: /* struct ifreq */
1773 case SIOCSIFBOND: /* struct ifreq */
1774 case SIOCGIFLLADDR: /* struct ifreq */
1775 case SIOCGIFTYPE: /* struct ifreq */
1776 case SIOCGIFPSRCADDR: /* struct ifreq */
1777 case SIOCGIFPDSTADDR: /* struct ifreq */
1778 case SIOCGIFGENERIC: /* struct ifreq */
1779 case SIOCGIFDEVMTU: /* struct ifreq */
1780 case SIOCGIFVLAN: /* struct ifreq */
1781 case SIOCGIFBOND: /* struct ifreq */
1782 case SIOCGIFWAKEFLAGS: /* struct ifreq */
1783 case SIOCGIFGETRTREFCNT: /* struct ifreq */
1784 case SIOCSIFOPPORTUNISTIC: /* struct ifreq */
1785 case SIOCGIFOPPORTUNISTIC: /* struct ifreq */
1786 case SIOCGIFLINKQUALITYMETRIC: /* struct ifreq */
1787 case SIOCSIFLOG: /* struct ifreq */
1788 case SIOCGIFLOG: /* struct ifreq */
1789 case SIOCGIFDELEGATE: { /* struct ifreq */
1790 struct ifreq ifr;
1791 bcopy(data, &ifr, sizeof (ifr));
1792 ifr.ifr_name[IFNAMSIZ - 1] = '\0';
1793 bcopy(&ifr.ifr_name, ifname, IFNAMSIZ);
1794 error = ifioctl_ifreq(so, cmd, &ifr, p);
1795 bcopy(&ifr, data, sizeof (ifr));
1796 goto done;
1797 }
1798 }
1799
1800 /*
1801 * ioctls which require ifp. Note that we acquire dlil_ifnet_lock
1802 * here to ensure that the ifnet, if found, has been fully attached.
1803 */
1804 dlil_if_lock();
1805 switch (cmd) {
1806 case SIOCSIFPHYADDR: /* struct {if,in_}aliasreq */
1807 bcopy(((struct in_aliasreq *)(void *)data)->ifra_name,
1808 ifname, IFNAMSIZ);
1809 ifp = ifunit(ifname);
1810 break;
1811
1812 #if INET6
1813 case SIOCSIFPHYADDR_IN6_32: /* struct in6_aliasreq_32 */
1814 bcopy(((struct in6_aliasreq_32 *)(void *)data)->ifra_name,
1815 ifname, IFNAMSIZ);
1816 ifp = ifunit(ifname);
1817 break;
1818
1819 case SIOCSIFPHYADDR_IN6_64: /* struct in6_aliasreq_64 */
1820 bcopy(((struct in6_aliasreq_64 *)(void *)data)->ifra_name,
1821 ifname, IFNAMSIZ);
1822 ifp = ifunit(ifname);
1823 break;
1824 #endif /* INET6 */
1825
1826 case SIOCSLIFPHYADDR: /* struct if_laddrreq */
1827 case SIOCGLIFPHYADDR: /* struct if_laddrreq */
1828 bcopy(((struct if_laddrreq *)(void *)data)->iflr_name,
1829 ifname, IFNAMSIZ);
1830 ifp = ifunit(ifname);
1831 break;
1832
1833 case SIOCGIFSTATUS: /* struct ifstat */
1834 ifs = _MALLOC(sizeof (*ifs), M_DEVBUF, M_WAITOK);
1835 if (ifs == NULL) {
1836 error = ENOMEM;
1837 dlil_if_unlock();
1838 goto done;
1839 }
1840 bcopy(data, ifs, sizeof (*ifs));
1841 ifs->ifs_name[IFNAMSIZ - 1] = '\0';
1842 bcopy(ifs->ifs_name, ifname, IFNAMSIZ);
1843 ifp = ifunit(ifname);
1844 break;
1845
1846 case SIOCGIFMEDIA32: /* struct ifmediareq32 */
1847 bcopy(((struct ifmediareq32 *)(void *)data)->ifm_name,
1848 ifname, IFNAMSIZ);
1849 ifp = ifunit(ifname);
1850 break;
1851
1852 case SIOCGIFMEDIA64: /* struct ifmediareq64 */
1853 bcopy(((struct ifmediareq64 *)(void *)data)->ifm_name,
1854 ifname, IFNAMSIZ);
1855 ifp = ifunit(ifname);
1856 break;
1857
1858 case SIOCSIFDESC: /* struct if_descreq */
1859 case SIOCGIFDESC: /* struct if_descreq */
1860 bcopy(((struct if_descreq *)(void *)data)->ifdr_name,
1861 ifname, IFNAMSIZ);
1862 ifp = ifunit(ifname);
1863 break;
1864
1865 case SIOCSIFLINKPARAMS: /* struct if_linkparamsreq */
1866 case SIOCGIFLINKPARAMS: /* struct if_linkparamsreq */
1867 bcopy(((struct if_linkparamsreq *)(void *)data)->iflpr_name,
1868 ifname, IFNAMSIZ);
1869 ifp = ifunit(ifname);
1870 break;
1871
1872 case SIOCGIFQUEUESTATS: /* struct if_qstatsreq */
1873 bcopy(((struct if_qstatsreq *)(void *)data)->ifqr_name,
1874 ifname, IFNAMSIZ);
1875 ifp = ifunit(ifname);
1876 break;
1877
1878 case SIOCSIFTHROTTLE: /* struct if_throttlereq */
1879 case SIOCGIFTHROTTLE: /* struct if_throttlereq */
1880 bcopy(((struct if_throttlereq *)(void *)data)->ifthr_name,
1881 ifname, IFNAMSIZ);
1882 ifp = ifunit(ifname);
1883 break;
1884
1885 default:
1886 /*
1887 * This is a bad assumption, but the code seems to
1888 * have been doing this in the past; caveat emptor.
1889 */
1890 bcopy(((struct ifreq *)(void *)data)->ifr_name,
1891 ifname, IFNAMSIZ);
1892 ifp = ifunit(ifname);
1893 break;
1894 }
1895 dlil_if_unlock();
1896
1897 if (ifp == NULL) {
1898 error = ENXIO;
1899 goto done;
1900 }
1901
1902 switch (cmd) {
1903 case SIOCSIFPHYADDR: /* struct {if,in_}aliasreq */
1904 #if INET6
1905 case SIOCSIFPHYADDR_IN6_32: /* struct in6_aliasreq_32 */
1906 case SIOCSIFPHYADDR_IN6_64: /* struct in6_aliasreq_64 */
1907 #endif /* INET6 */
1908 case SIOCSLIFPHYADDR: /* struct if_laddrreq */
1909 error = proc_suser(p);
1910 if (error != 0)
1911 break;
1912
1913 error = ifnet_ioctl(ifp, SOCK_DOM(so), cmd, data);
1914 if (error != 0)
1915 break;
1916
1917 ifnet_touch_lastchange(ifp);
1918 break;
1919
1920 case SIOCGIFSTATUS: /* struct ifstat */
1921 VERIFY(ifs != NULL);
1922 ifs->ascii[0] = '\0';
1923
1924 error = ifnet_ioctl(ifp, SOCK_DOM(so), cmd, (caddr_t)ifs);
1925
1926 bcopy(ifs, data, sizeof (*ifs));
1927 break;
1928
1929 case SIOCGLIFPHYADDR: /* struct if_laddrreq */
1930 case SIOCGIFMEDIA32: /* struct ifmediareq32 */
1931 case SIOCGIFMEDIA64: /* struct ifmediareq64 */
1932 error = ifnet_ioctl(ifp, SOCK_DOM(so), cmd, data);
1933 break;
1934
1935 case SIOCSIFDESC: /* struct if_descreq */
1936 case SIOCGIFDESC: /* struct if_descreq */
1937 error = ifioctl_ifdesc(ifp, cmd, data, p);
1938 break;
1939
1940 case SIOCSIFLINKPARAMS: /* struct if_linkparamsreq */
1941 case SIOCGIFLINKPARAMS: /* struct if_linkparamsreq */
1942 error = ifioctl_linkparams(ifp, cmd, data, p);
1943 break;
1944
1945 case SIOCGIFQUEUESTATS: /* struct if_qstatsreq */
1946 error = ifioctl_qstats(ifp, cmd, data);
1947 break;
1948
1949 case SIOCSIFTHROTTLE: /* struct if_throttlereq */
1950 case SIOCGIFTHROTTLE: /* struct if_throttlereq */
1951 error = ifioctl_throttle(ifp, cmd, data, p);
1952 break;
1953
1954 default:
1955 if (so->so_proto == NULL) {
1956 error = EOPNOTSUPP;
1957 break;
1958 }
1959
1960 socket_lock(so, 1);
1961 error = ((*so->so_proto->pr_usrreqs->pru_control)(so, cmd,
1962 data, ifp, p));
1963 socket_unlock(so, 1);
1964
1965 if (error == EOPNOTSUPP || error == ENOTSUP) {
1966 error = ifnet_ioctl(ifp, SOCK_DOM(so), cmd, data);
1967 }
1968 break;
1969 }
1970
1971 done:
1972 if (ifs != NULL)
1973 _FREE(ifs, M_DEVBUF);
1974
1975 if (if_verbose) {
1976 if (ifname[0] == '\0')
1977 (void) snprintf(ifname, sizeof (ifname), "%s",
1978 "NULL");
1979 else if (ifp != NULL)
1980 (void) snprintf(ifname, sizeof (ifname), "%s",
1981 if_name(ifp));
1982
1983 if (error != 0) {
1984 printf("%s[%s,%d]: ifp %s cmd 0x%08lx (%c%c [%lu] "
1985 "%c %lu) error %d\n", __func__,
1986 proc_name_address(p), proc_pid(p),
1987 ifname, cmd, (cmd & IOC_IN) ? 'I' : ' ',
1988 (cmd & IOC_OUT) ? 'O' : ' ', IOCPARM_LEN(cmd),
1989 (char)IOCGROUP(cmd), cmd & 0xff, error);
1990 } else if (if_verbose > 1) {
1991 printf("%s[%s,%d]: ifp %s cmd 0x%08lx (%c%c [%lu] "
1992 "%c %lu) OK\n", __func__,
1993 proc_name_address(p), proc_pid(p),
1994 ifname, cmd, (cmd & IOC_IN) ? 'I' : ' ',
1995 (cmd & IOC_OUT) ? 'O' : ' ', IOCPARM_LEN(cmd),
1996 (char)IOCGROUP(cmd), cmd & 0xff);
1997 }
1998 }
1999
2000 return (error);
2001 }
2002
2003 static __attribute__((noinline)) int
2004 ifioctl_ifreq(struct socket *so, u_long cmd, struct ifreq *ifr, struct proc *p)
2005 {
2006 struct ifnet *ifp;
2007 u_long ocmd = cmd;
2008 int error = 0;
2009 struct kev_msg ev_msg;
2010 struct net_event_data ev_data;
2011
2012 bzero(&ev_data, sizeof (struct net_event_data));
2013 bzero(&ev_msg, sizeof (struct kev_msg));
2014
2015 switch (cmd) {
2016 case SIOCIFCREATE:
2017 case SIOCIFCREATE2:
2018 error = proc_suser(p);
2019 if (error)
2020 return (error);
2021 return (if_clone_create(ifr->ifr_name, sizeof(ifr->ifr_name),
2022 cmd == SIOCIFCREATE2 ? ifr->ifr_data : NULL));
2023 case SIOCIFDESTROY:
2024 error = proc_suser(p);
2025 if (error)
2026 return (error);
2027 return (if_clone_destroy(ifr->ifr_name));
2028 }
2029
2030 /*
2031 * ioctls which require ifp. Note that we acquire dlil_ifnet_lock
2032 * here to ensure that the ifnet, if found, has been fully attached.
2033 */
2034 dlil_if_lock();
2035 ifp = ifunit(ifr->ifr_name);
2036 dlil_if_unlock();
2037
2038 if (ifp == NULL)
2039 return (ENXIO);
2040
2041 switch (cmd) {
2042 case SIOCGIFFLAGS:
2043 ifnet_lock_shared(ifp);
2044 ifr->ifr_flags = ifp->if_flags;
2045 ifnet_lock_done(ifp);
2046 break;
2047
2048 case SIOCGIFEFLAGS:
2049 ifnet_lock_shared(ifp);
2050 ifr->ifr_eflags = ifp->if_eflags;
2051 ifnet_lock_done(ifp);
2052 break;
2053
2054 case SIOCGIFCAP:
2055 ifnet_lock_shared(ifp);
2056 ifr->ifr_reqcap = ifp->if_capabilities;
2057 ifr->ifr_curcap = ifp->if_capenable;
2058 ifnet_lock_done(ifp);
2059 break;
2060
2061 #if CONFIG_MACF_NET
2062 case SIOCGIFMAC:
2063 error = mac_ifnet_label_get(kauth_cred_get(), ifr, ifp);
2064 break;
2065
2066 case SIOCSIFMAC:
2067 error = mac_ifnet_label_set(kauth_cred_get(), ifr, ifp);
2068 break;
2069 #endif /* CONFIG_MACF_NET */
2070
2071 case SIOCGIFMETRIC:
2072 ifnet_lock_shared(ifp);
2073 ifr->ifr_metric = ifp->if_metric;
2074 ifnet_lock_done(ifp);
2075 break;
2076
2077 case SIOCGIFMTU:
2078 ifnet_lock_shared(ifp);
2079 ifr->ifr_mtu = ifp->if_mtu;
2080 ifnet_lock_done(ifp);
2081 break;
2082
2083 case SIOCGIFPHYS:
2084 ifnet_lock_shared(ifp);
2085 ifr->ifr_phys = ifp->if_physical;
2086 ifnet_lock_done(ifp);
2087 break;
2088
2089 case SIOCSIFFLAGS:
2090 error = proc_suser(p);
2091 if (error != 0)
2092 break;
2093
2094 (void) ifnet_set_flags(ifp, ifr->ifr_flags,
2095 (u_int16_t)~IFF_CANTCHANGE);
2096
2097 /*
2098 * Note that we intentionally ignore any error from below
2099 * for the SIOCSIFFLAGS case.
2100 */
2101 (void) ifnet_ioctl(ifp, SOCK_DOM(so), cmd, (caddr_t)ifr);
2102
2103 /*
2104 * Send the event even upon error from the driver because
2105 * we changed the flags.
2106 */
2107 ev_msg.vendor_code = KEV_VENDOR_APPLE;
2108 ev_msg.kev_class = KEV_NETWORK_CLASS;
2109 ev_msg.kev_subclass = KEV_DL_SUBCLASS;
2110
2111 ev_msg.event_code = KEV_DL_SIFFLAGS;
2112 strlcpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ);
2113 ev_data.if_family = ifp->if_family;
2114 ev_data.if_unit = (u_int32_t) ifp->if_unit;
2115 ev_msg.dv[0].data_length = sizeof(struct net_event_data);
2116 ev_msg.dv[0].data_ptr = &ev_data;
2117 ev_msg.dv[1].data_length = 0;
2118 kev_post_msg(&ev_msg);
2119
2120 ifnet_touch_lastchange(ifp);
2121 break;
2122
2123 case SIOCSIFCAP:
2124 error = proc_suser(p);
2125 if (error != 0)
2126 break;
2127
2128 if ((ifr->ifr_reqcap & ~ifp->if_capabilities)) {
2129 error = EINVAL;
2130 break;
2131 }
2132 error = ifnet_ioctl(ifp, SOCK_DOM(so), cmd, (caddr_t)ifr);
2133
2134 ifnet_touch_lastchange(ifp);
2135 break;
2136
2137 case SIOCSIFMETRIC:
2138 error = proc_suser(p);
2139 if (error != 0)
2140 break;
2141
2142 ifp->if_metric = ifr->ifr_metric;
2143
2144 ev_msg.vendor_code = KEV_VENDOR_APPLE;
2145 ev_msg.kev_class = KEV_NETWORK_CLASS;
2146 ev_msg.kev_subclass = KEV_DL_SUBCLASS;
2147
2148 ev_msg.event_code = KEV_DL_SIFMETRICS;
2149 strlcpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ);
2150 ev_data.if_family = ifp->if_family;
2151 ev_data.if_unit = (u_int32_t) ifp->if_unit;
2152 ev_msg.dv[0].data_length = sizeof(struct net_event_data);
2153 ev_msg.dv[0].data_ptr = &ev_data;
2154
2155 ev_msg.dv[1].data_length = 0;
2156 kev_post_msg(&ev_msg);
2157
2158 ifnet_touch_lastchange(ifp);
2159 break;
2160
2161 case SIOCSIFPHYS:
2162 error = proc_suser(p);
2163 if (error != 0)
2164 break;
2165
2166 error = ifnet_ioctl(ifp, SOCK_DOM(so), cmd, (caddr_t)ifr);
2167 if (error != 0)
2168 break;
2169
2170 ev_msg.vendor_code = KEV_VENDOR_APPLE;
2171 ev_msg.kev_class = KEV_NETWORK_CLASS;
2172 ev_msg.kev_subclass = KEV_DL_SUBCLASS;
2173
2174 ev_msg.event_code = KEV_DL_SIFPHYS;
2175 strlcpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ);
2176 ev_data.if_family = ifp->if_family;
2177 ev_data.if_unit = (u_int32_t) ifp->if_unit;
2178 ev_msg.dv[0].data_length = sizeof(struct net_event_data);
2179 ev_msg.dv[0].data_ptr = &ev_data;
2180 ev_msg.dv[1].data_length = 0;
2181 kev_post_msg(&ev_msg);
2182
2183 ifnet_touch_lastchange(ifp);
2184 break;
2185
2186 case SIOCSIFMTU: {
2187 u_int32_t oldmtu = ifp->if_mtu;
2188 struct ifclassq *ifq = &ifp->if_snd;
2189
2190 error = proc_suser(p);
2191 if (error != 0)
2192 break;
2193
2194 if (ifp->if_ioctl == NULL) {
2195 error = EOPNOTSUPP;
2196 break;
2197 }
2198 if (ifr->ifr_mtu < IF_MINMTU || ifr->ifr_mtu > IF_MAXMTU) {
2199 error = EINVAL;
2200 break;
2201 }
2202 error = ifnet_ioctl(ifp, SOCK_DOM(so), cmd, (caddr_t)ifr);
2203 if (error != 0)
2204 break;
2205
2206 ev_msg.vendor_code = KEV_VENDOR_APPLE;
2207 ev_msg.kev_class = KEV_NETWORK_CLASS;
2208 ev_msg.kev_subclass = KEV_DL_SUBCLASS;
2209
2210 ev_msg.event_code = KEV_DL_SIFMTU;
2211 strlcpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ);
2212 ev_data.if_family = ifp->if_family;
2213 ev_data.if_unit = (u_int32_t) ifp->if_unit;
2214 ev_msg.dv[0].data_length = sizeof(struct net_event_data);
2215 ev_msg.dv[0].data_ptr = &ev_data;
2216 ev_msg.dv[1].data_length = 0;
2217 kev_post_msg(&ev_msg);
2218
2219 ifnet_touch_lastchange(ifp);
2220 rt_ifmsg(ifp);
2221
2222 /*
2223 * If the link MTU changed, do network layer specific procedure
2224 * and update all route entries associated with the interface,
2225 * so that their MTU metric gets updated.
2226 */
2227 if (ifp->if_mtu != oldmtu) {
2228 if_rtmtu_update(ifp);
2229 #if INET6
2230 nd6_setmtu(ifp);
2231 #endif /* INET6 */
2232 /* Inform all transmit queues about the new MTU */
2233 IFCQ_LOCK(ifq);
2234 ifnet_update_sndq(ifq, CLASSQ_EV_LINK_MTU);
2235 IFCQ_UNLOCK(ifq);
2236 }
2237 break;
2238 }
2239
2240 case SIOCADDMULTI:
2241 case SIOCDELMULTI:
2242 error = proc_suser(p);
2243 if (error != 0)
2244 break;
2245
2246 /* Don't allow group membership on non-multicast interfaces. */
2247 if ((ifp->if_flags & IFF_MULTICAST) == 0) {
2248 error = EOPNOTSUPP;
2249 break;
2250 }
2251
2252 /* Don't let users screw up protocols' entries. */
2253 if (ifr->ifr_addr.sa_family != AF_UNSPEC &&
2254 ifr->ifr_addr.sa_family != AF_LINK) {
2255 error = EINVAL;
2256 break;
2257 }
2258
2259 /*
2260 * User is permitted to anonymously join a particular link
2261 * multicast group via SIOCADDMULTI. Subsequent join requested
2262 * for the same record which has an outstanding refcnt from a
2263 * past if_addmulti_anon() will not result in EADDRINUSE error
2264 * (unlike other BSDs.) Anonymously leaving a group is also
2265 * allowed only as long as there is an outstanding refcnt held
2266 * by a previous anonymous request, or else ENOENT (even if the
2267 * link-layer multicast membership exists for a network-layer
2268 * membership.)
2269 */
2270 if (cmd == SIOCADDMULTI) {
2271 error = if_addmulti_anon(ifp, &ifr->ifr_addr, NULL);
2272 ev_msg.event_code = KEV_DL_ADDMULTI;
2273 } else {
2274 error = if_delmulti_anon(ifp, &ifr->ifr_addr);
2275 ev_msg.event_code = KEV_DL_DELMULTI;
2276 }
2277 if (error != 0)
2278 break;
2279
2280 ev_msg.vendor_code = KEV_VENDOR_APPLE;
2281 ev_msg.kev_class = KEV_NETWORK_CLASS;
2282 ev_msg.kev_subclass = KEV_DL_SUBCLASS;
2283 strlcpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ);
2284
2285 ev_data.if_family = ifp->if_family;
2286 ev_data.if_unit = (u_int32_t) ifp->if_unit;
2287 ev_msg.dv[0].data_length = sizeof(struct net_event_data);
2288 ev_msg.dv[0].data_ptr = &ev_data;
2289 ev_msg.dv[1].data_length = 0;
2290 kev_post_msg(&ev_msg);
2291
2292 ifnet_touch_lastchange(ifp);
2293 break;
2294
2295 case SIOCDIFPHYADDR:
2296 case SIOCSIFMEDIA:
2297 case SIOCSIFGENERIC:
2298 case SIOCSIFLLADDR:
2299 case SIOCSIFALTMTU:
2300 case SIOCSIFVLAN:
2301 case SIOCSIFBOND:
2302 error = proc_suser(p);
2303 if (error != 0)
2304 break;
2305
2306 error = ifnet_ioctl(ifp, SOCK_DOM(so), cmd, (caddr_t)ifr);
2307 if (error != 0)
2308 break;
2309
2310 ifnet_touch_lastchange(ifp);
2311 break;
2312
2313 case SIOCGIFLLADDR: {
2314 struct sockaddr_dl *sdl = SDL(ifp->if_lladdr->ifa_addr);
2315
2316 if (sdl->sdl_alen == 0) {
2317 error = EADDRNOTAVAIL;
2318 break;
2319 }
2320 /* If larger than 14-bytes we'll need another mechanism */
2321 if (sdl->sdl_alen > sizeof (ifr->ifr_addr.sa_data)) {
2322 error = EMSGSIZE;
2323 break;
2324 }
2325 /* Follow the same convention used by SIOCSIFLLADDR */
2326 bzero(&ifr->ifr_addr, sizeof (ifr->ifr_addr));
2327 ifr->ifr_addr.sa_family = AF_LINK;
2328 ifr->ifr_addr.sa_len = sdl->sdl_alen;
2329 error = ifnet_guarded_lladdr_copy_bytes(ifp,
2330 &ifr->ifr_addr.sa_data, sdl->sdl_alen);
2331 break;
2332 }
2333
2334 case SIOCGIFTYPE:
2335 ifr->ifr_type.ift_type = ifp->if_type;
2336 ifr->ifr_type.ift_family = ifp->if_family;
2337 ifr->ifr_type.ift_subfamily = ifp->if_subfamily;
2338 break;
2339
2340 case SIOCGIFPSRCADDR:
2341 case SIOCGIFPDSTADDR:
2342 case SIOCGIFGENERIC:
2343 case SIOCGIFDEVMTU:
2344 case SIOCGIFVLAN:
2345 case SIOCGIFBOND:
2346 error = ifnet_ioctl(ifp, SOCK_DOM(so), cmd, (caddr_t)ifr);
2347 break;
2348
2349 case SIOCGIFWAKEFLAGS:
2350 ifnet_lock_shared(ifp);
2351 ifr->ifr_wake_flags = ifnet_get_wake_flags(ifp);
2352 ifnet_lock_done(ifp);
2353 break;
2354
2355 case SIOCGIFGETRTREFCNT:
2356 ifnet_lock_shared(ifp);
2357 ifr->ifr_route_refcnt = ifp->if_route_refcnt;
2358 ifnet_lock_done(ifp);
2359 break;
2360
2361 case SIOCSIFOPPORTUNISTIC:
2362 case SIOCGIFOPPORTUNISTIC:
2363 error = ifnet_getset_opportunistic(ifp, cmd, ifr, p);
2364 break;
2365
2366 case SIOCGIFLINKQUALITYMETRIC:
2367 ifnet_lock_shared(ifp);
2368 ifr->ifr_link_quality_metric = ifp->if_lqm;
2369 ifnet_lock_done(ifp);
2370 break;
2371
2372 case SIOCSIFLOG:
2373 case SIOCGIFLOG:
2374 error = ifnet_getset_log(ifp, cmd, ifr, p);
2375 break;
2376
2377 case SIOCGIFDELEGATE:
2378 ifnet_lock_shared(ifp);
2379 ifr->ifr_delegated = ((ifp->if_delegated.ifp != NULL) ?
2380 ifp->if_delegated.ifp->if_index : 0);
2381 ifnet_lock_done(ifp);
2382 break;
2383
2384 case SIOCSIFDSTADDR:
2385 case SIOCSIFADDR:
2386 case SIOCSIFBRDADDR:
2387 case SIOCSIFNETMASK:
2388 case OSIOCGIFADDR:
2389 case OSIOCGIFDSTADDR:
2390 case OSIOCGIFBRDADDR:
2391 case OSIOCGIFNETMASK:
2392 case SIOCSIFKPI:
2393 VERIFY(so->so_proto != NULL);
2394
2395 if (cmd == SIOCSIFDSTADDR || cmd == SIOCSIFADDR ||
2396 cmd == SIOCSIFBRDADDR || cmd == SIOCSIFNETMASK) {
2397 #if BYTE_ORDER != BIG_ENDIAN
2398 if (ifr->ifr_addr.sa_family == 0 &&
2399 ifr->ifr_addr.sa_len < 16) {
2400 ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len;
2401 ifr->ifr_addr.sa_len = 16;
2402 }
2403 #else
2404 if (ifr->ifr_addr.sa_len == 0)
2405 ifr->ifr_addr.sa_len = 16;
2406 #endif
2407 } else if (cmd == OSIOCGIFADDR) {
2408 cmd = SIOCGIFADDR; /* struct ifreq */
2409 } else if (cmd == OSIOCGIFDSTADDR) {
2410 cmd = SIOCGIFDSTADDR; /* struct ifreq */
2411 } else if (cmd == OSIOCGIFBRDADDR) {
2412 cmd = SIOCGIFBRDADDR; /* struct ifreq */
2413 } else if (cmd == OSIOCGIFNETMASK) {
2414 cmd = SIOCGIFNETMASK; /* struct ifreq */
2415 }
2416
2417 socket_lock(so, 1);
2418 error = ((*so->so_proto->pr_usrreqs->pru_control)(so, cmd,
2419 (caddr_t)ifr, ifp, p));
2420 socket_unlock(so, 1);
2421
2422 switch (ocmd) {
2423 case OSIOCGIFADDR:
2424 case OSIOCGIFDSTADDR:
2425 case OSIOCGIFBRDADDR:
2426 case OSIOCGIFNETMASK:
2427 bcopy(&ifr->ifr_addr.sa_family, &ifr->ifr_addr,
2428 sizeof (u_short));
2429 }
2430
2431 if (cmd == SIOCSIFKPI) {
2432 int temperr = proc_suser(p);
2433 if (temperr != 0)
2434 error = temperr;
2435 }
2436
2437 if (error == EOPNOTSUPP || error == ENOTSUP) {
2438 error = ifnet_ioctl(ifp, SOCK_DOM(so), cmd,
2439 (caddr_t)ifr);
2440 }
2441 break;
2442
2443 default:
2444 VERIFY(0);
2445 /* NOTREACHED */
2446 }
2447
2448 return (error);
2449 }
2450
2451 int
2452 ifioctllocked(struct socket *so, u_long cmd, caddr_t data, struct proc *p)
2453 {
2454 int error;
2455
2456 socket_unlock(so, 0);
2457 error = ifioctl(so, cmd, data, p);
2458 socket_lock(so, 0);
2459 return(error);
2460 }
2461
2462 /*
2463 * Set/clear promiscuous mode on interface ifp based on the truth value
2464 * of pswitch. The calls are reference counted so that only the first
2465 * "on" request actually has an effect, as does the final "off" request.
2466 * Results are undefined if the "off" and "on" requests are not matched.
2467 */
2468 errno_t
2469 ifnet_set_promiscuous(
2470 ifnet_t ifp,
2471 int pswitch)
2472 {
2473 int error = 0;
2474 int oldflags = 0;
2475 int newflags = 0;
2476
2477 ifnet_lock_exclusive(ifp);
2478 oldflags = ifp->if_flags;
2479 ifp->if_pcount += pswitch ? 1 : -1;
2480
2481 if (ifp->if_pcount > 0)
2482 ifp->if_flags |= IFF_PROMISC;
2483 else
2484 ifp->if_flags &= ~IFF_PROMISC;
2485
2486 newflags = ifp->if_flags;
2487 ifnet_lock_done(ifp);
2488
2489 if (newflags != oldflags && (newflags & IFF_UP) != 0) {
2490 error = ifnet_ioctl(ifp, 0, SIOCSIFFLAGS, NULL);
2491 if (error == 0) {
2492 rt_ifmsg(ifp);
2493 } else {
2494 ifnet_lock_exclusive(ifp);
2495 // revert the flags
2496 ifp->if_pcount -= pswitch ? 1 : -1;
2497 if (ifp->if_pcount > 0)
2498 ifp->if_flags |= IFF_PROMISC;
2499 else
2500 ifp->if_flags &= ~IFF_PROMISC;
2501 ifnet_lock_done(ifp);
2502 }
2503 }
2504
2505 if (newflags != oldflags) {
2506 log(LOG_INFO, "%s: promiscuous mode %s%s\n",
2507 if_name(ifp),
2508 (newflags & IFF_PROMISC) != 0 ? "enable" : "disable",
2509 error != 0 ? " failed" : " succeeded");
2510 }
2511 return error;
2512 }
2513
2514 /*
2515 * Return interface configuration
2516 * of system. List may be used
2517 * in later ioctl's (above) to get
2518 * other information.
2519 */
2520 /*ARGSUSED*/
2521 static int
2522 ifconf(u_long cmd, user_addr_t ifrp, int *ret_space)
2523 {
2524 struct ifnet *ifp = NULL;
2525 struct ifaddr *ifa;
2526 struct ifreq ifr;
2527 int error = 0;
2528 size_t space;
2529 net_thread_marks_t marks;
2530
2531 marks = net_thread_marks_push(NET_THREAD_CKREQ_LLADDR);
2532
2533 /*
2534 * Zero the ifr buffer to make sure we don't
2535 * disclose the contents of the stack.
2536 */
2537 bzero(&ifr, sizeof (struct ifreq));
2538
2539 space = *ret_space;
2540 ifnet_head_lock_shared();
2541 for (ifp = ifnet_head.tqh_first; space > sizeof (ifr) &&
2542 ifp; ifp = ifp->if_link.tqe_next) {
2543 char workbuf[64];
2544 size_t ifnlen, addrs;
2545
2546 ifnlen = snprintf(workbuf, sizeof (workbuf),
2547 "%s", if_name(ifp));
2548 if (ifnlen + 1 > sizeof (ifr.ifr_name)) {
2549 error = ENAMETOOLONG;
2550 break;
2551 } else {
2552 strlcpy(ifr.ifr_name, workbuf, IFNAMSIZ);
2553 }
2554
2555 ifnet_lock_shared(ifp);
2556
2557 addrs = 0;
2558 ifa = ifp->if_addrhead.tqh_first;
2559 for (; space > sizeof (ifr) && ifa;
2560 ifa = ifa->ifa_link.tqe_next) {
2561 struct sockaddr *sa;
2562 union {
2563 struct sockaddr sa;
2564 struct sockaddr_dl sdl;
2565 uint8_t buf[SOCK_MAXADDRLEN + 1];
2566 } u;
2567
2568 /*
2569 * Make sure to accomodate the largest possible
2570 * size of SA(if_lladdr)->sa_len.
2571 */
2572 _CASSERT(sizeof (u) == (SOCK_MAXADDRLEN + 1));
2573
2574 IFA_LOCK(ifa);
2575 sa = ifa->ifa_addr;
2576 addrs++;
2577
2578 if (ifa == ifp->if_lladdr) {
2579 VERIFY(sa->sa_family == AF_LINK);
2580 bcopy(sa, &u, sa->sa_len);
2581 IFA_UNLOCK(ifa);
2582 ifnet_guarded_lladdr_copy_bytes(ifp,
2583 LLADDR(&u.sdl), u.sdl.sdl_alen);
2584 IFA_LOCK(ifa);
2585 sa = &u.sa;
2586 }
2587
2588 if (cmd == OSIOCGIFCONF32 || cmd == OSIOCGIFCONF64) {
2589 struct osockaddr *osa =
2590 (struct osockaddr *)(void *)&ifr.ifr_addr;
2591 ifr.ifr_addr = *sa;
2592 osa->sa_family = sa->sa_family;
2593 error = copyout((caddr_t)&ifr, ifrp,
2594 sizeof (ifr));
2595 ifrp += sizeof (struct ifreq);
2596 } else if (sa->sa_len <= sizeof (*sa)) {
2597 ifr.ifr_addr = *sa;
2598 error = copyout((caddr_t)&ifr, ifrp,
2599 sizeof (ifr));
2600 ifrp += sizeof (struct ifreq);
2601 } else {
2602 if (space <
2603 sizeof (ifr) + sa->sa_len - sizeof (*sa)) {
2604 IFA_UNLOCK(ifa);
2605 break;
2606 }
2607 space -= sa->sa_len - sizeof (*sa);
2608 error = copyout((caddr_t)&ifr, ifrp,
2609 sizeof (ifr.ifr_name));
2610 if (error == 0) {
2611 error = copyout((caddr_t)sa, (ifrp +
2612 offsetof(struct ifreq, ifr_addr)),
2613 sa->sa_len);
2614 }
2615 ifrp += (sa->sa_len + offsetof(struct ifreq,
2616 ifr_addr));
2617 }
2618 IFA_UNLOCK(ifa);
2619 if (error)
2620 break;
2621 space -= sizeof (ifr);
2622 }
2623 ifnet_lock_done(ifp);
2624
2625 if (error)
2626 break;
2627 if (!addrs) {
2628 bzero((caddr_t)&ifr.ifr_addr, sizeof (ifr.ifr_addr));
2629 error = copyout((caddr_t)&ifr, ifrp, sizeof (ifr));
2630 if (error)
2631 break;
2632 space -= sizeof (ifr);
2633 ifrp += sizeof (struct ifreq);
2634 }
2635 }
2636 ifnet_head_done();
2637 *ret_space -= space;
2638 net_thread_marks_pop(marks);
2639 return (error);
2640 }
2641
2642 /*
2643 * Just like if_promisc(), but for all-multicast-reception mode.
2644 */
2645 int
2646 if_allmulti(struct ifnet *ifp, int onswitch)
2647 {
2648 int error = 0;
2649 int modified = 0;
2650
2651 ifnet_lock_exclusive(ifp);
2652
2653 if (onswitch) {
2654 if (ifp->if_amcount++ == 0) {
2655 ifp->if_flags |= IFF_ALLMULTI;
2656 modified = 1;
2657 }
2658 } else {
2659 if (ifp->if_amcount > 1) {
2660 ifp->if_amcount--;
2661 } else {
2662 ifp->if_amcount = 0;
2663 ifp->if_flags &= ~IFF_ALLMULTI;
2664 modified = 1;
2665 }
2666 }
2667 ifnet_lock_done(ifp);
2668
2669 if (modified)
2670 error = ifnet_ioctl(ifp, 0, SIOCSIFFLAGS, NULL);
2671
2672 if (error == 0)
2673 rt_ifmsg(ifp);
2674 return error;
2675 }
2676
2677 static struct ifmultiaddr *
2678 ifma_alloc(int how)
2679 {
2680 struct ifmultiaddr *ifma;
2681
2682 ifma = (how == M_WAITOK) ? zalloc(ifma_zone) :
2683 zalloc_noblock(ifma_zone);
2684
2685 if (ifma != NULL) {
2686 bzero(ifma, ifma_size);
2687 lck_mtx_init(&ifma->ifma_lock, ifa_mtx_grp, ifa_mtx_attr);
2688 ifma->ifma_debug |= IFD_ALLOC;
2689 if (ifma_debug != 0) {
2690 ifma->ifma_debug |= IFD_DEBUG;
2691 ifma->ifma_trace = ifma_trace;
2692 }
2693 }
2694 return (ifma);
2695 }
2696
2697 static void
2698 ifma_free(struct ifmultiaddr *ifma)
2699 {
2700 IFMA_LOCK(ifma);
2701
2702 if (ifma->ifma_protospec != NULL) {
2703 panic("%s: Protospec not NULL for ifma=%p", __func__, ifma);
2704 /* NOTREACHED */
2705 } else if ((ifma->ifma_flags & IFMAF_ANONYMOUS) ||
2706 ifma->ifma_anoncnt != 0) {
2707 panic("%s: Freeing ifma=%p with outstanding anon req",
2708 __func__, ifma);
2709 /* NOTREACHED */
2710 } else if (ifma->ifma_debug & IFD_ATTACHED) {
2711 panic("%s: ifma=%p attached to ifma_ifp=%p is being freed",
2712 __func__, ifma, ifma->ifma_ifp);
2713 /* NOTREACHED */
2714 } else if (!(ifma->ifma_debug & IFD_ALLOC)) {
2715 panic("%s: ifma %p cannot be freed", __func__, ifma);
2716 /* NOTREACHED */
2717 } else if (ifma->ifma_refcount != 0) {
2718 panic("%s: non-zero refcount ifma=%p", __func__, ifma);
2719 /* NOTREACHED */
2720 } else if (ifma->ifma_reqcnt != 0) {
2721 panic("%s: non-zero reqcnt ifma=%p", __func__, ifma);
2722 /* NOTREACHED */
2723 } else if (ifma->ifma_ifp != NULL) {
2724 panic("%s: non-NULL ifma_ifp=%p for ifma=%p", __func__,
2725 ifma->ifma_ifp, ifma);
2726 /* NOTREACHED */
2727 } else if (ifma->ifma_ll != NULL) {
2728 panic("%s: non-NULL ifma_ll=%p for ifma=%p", __func__,
2729 ifma->ifma_ll, ifma);
2730 /* NOTREACHED */
2731 }
2732 ifma->ifma_debug &= ~IFD_ALLOC;
2733 if ((ifma->ifma_debug & (IFD_DEBUG | IFD_TRASHED)) ==
2734 (IFD_DEBUG | IFD_TRASHED)) {
2735 lck_mtx_lock(&ifma_trash_lock);
2736 TAILQ_REMOVE(&ifma_trash_head, (struct ifmultiaddr_dbg *)ifma,
2737 ifma_trash_link);
2738 lck_mtx_unlock(&ifma_trash_lock);
2739 ifma->ifma_debug &= ~IFD_TRASHED;
2740 }
2741 IFMA_UNLOCK(ifma);
2742
2743 if (ifma->ifma_addr != NULL) {
2744 FREE(ifma->ifma_addr, M_IFADDR);
2745 ifma->ifma_addr = NULL;
2746 }
2747 lck_mtx_destroy(&ifma->ifma_lock, ifa_mtx_grp);
2748 zfree(ifma_zone, ifma);
2749 }
2750
2751 static void
2752 ifma_trace(struct ifmultiaddr *ifma, int refhold)
2753 {
2754 struct ifmultiaddr_dbg *ifma_dbg = (struct ifmultiaddr_dbg *)ifma;
2755 ctrace_t *tr;
2756 u_int32_t idx;
2757 u_int16_t *cnt;
2758
2759 if (!(ifma->ifma_debug & IFD_DEBUG)) {
2760 panic("%s: ifma %p has no debug structure", __func__, ifma);
2761 /* NOTREACHED */
2762 }
2763 if (refhold) {
2764 cnt = &ifma_dbg->ifma_refhold_cnt;
2765 tr = ifma_dbg->ifma_refhold;
2766 } else {
2767 cnt = &ifma_dbg->ifma_refrele_cnt;
2768 tr = ifma_dbg->ifma_refrele;
2769 }
2770
2771 idx = atomic_add_16_ov(cnt, 1) % IFMA_TRACE_HIST_SIZE;
2772 ctrace_record(&tr[idx]);
2773 }
2774
2775 void
2776 ifma_addref(struct ifmultiaddr *ifma, int locked)
2777 {
2778 if (!locked)
2779 IFMA_LOCK(ifma);
2780 else
2781 IFMA_LOCK_ASSERT_HELD(ifma);
2782
2783 if (++ifma->ifma_refcount == 0) {
2784 panic("%s: ifma=%p wraparound refcnt", __func__, ifma);
2785 /* NOTREACHED */
2786 } else if (ifma->ifma_trace != NULL) {
2787 (*ifma->ifma_trace)(ifma, TRUE);
2788 }
2789 if (!locked)
2790 IFMA_UNLOCK(ifma);
2791 }
2792
2793 void
2794 ifma_remref(struct ifmultiaddr *ifma)
2795 {
2796 struct ifmultiaddr *ll;
2797
2798 IFMA_LOCK(ifma);
2799
2800 if (ifma->ifma_refcount == 0) {
2801 panic("%s: ifma=%p negative refcnt", __func__, ifma);
2802 /* NOTREACHED */
2803 } else if (ifma->ifma_trace != NULL) {
2804 (*ifma->ifma_trace)(ifma, FALSE);
2805 }
2806
2807 --ifma->ifma_refcount;
2808 if (ifma->ifma_refcount > 0) {
2809 IFMA_UNLOCK(ifma);
2810 return;
2811 }
2812
2813 ll = ifma->ifma_ll;
2814 ifma->ifma_ifp = NULL;
2815 ifma->ifma_ll = NULL;
2816 IFMA_UNLOCK(ifma);
2817 ifma_free(ifma); /* deallocate it */
2818
2819 if (ll != NULL)
2820 IFMA_REMREF(ll);
2821 }
2822
2823 static void
2824 if_attach_ifma(struct ifnet *ifp, struct ifmultiaddr *ifma, int anon)
2825 {
2826 ifnet_lock_assert(ifp, IFNET_LCK_ASSERT_EXCLUSIVE);
2827 IFMA_LOCK_ASSERT_HELD(ifma);
2828
2829 if (ifma->ifma_ifp != ifp) {
2830 panic("%s: Mismatch ifma_ifp=%p != ifp=%p", __func__,
2831 ifma->ifma_ifp, ifp);
2832 /* NOTREACHED */
2833 } else if (ifma->ifma_debug & IFD_ATTACHED) {
2834 panic("%s: Attempt to attach an already attached ifma=%p",
2835 __func__, ifma);
2836 /* NOTREACHED */
2837 } else if (anon && (ifma->ifma_flags & IFMAF_ANONYMOUS)) {
2838 panic("%s: ifma=%p unexpected IFMAF_ANONYMOUS", __func__, ifma);
2839 /* NOTREACHED */
2840 } else if (ifma->ifma_debug & IFD_TRASHED) {
2841 panic("%s: Attempt to reattach a detached ifma=%p",
2842 __func__, ifma);
2843 /* NOTREACHED */
2844 }
2845
2846 ifma->ifma_reqcnt++;
2847 VERIFY(ifma->ifma_reqcnt == 1);
2848 IFMA_ADDREF_LOCKED(ifma);
2849 ifma->ifma_debug |= IFD_ATTACHED;
2850 if (anon) {
2851 ifma->ifma_anoncnt++;
2852 VERIFY(ifma->ifma_anoncnt == 1);
2853 ifma->ifma_flags |= IFMAF_ANONYMOUS;
2854 }
2855
2856 LIST_INSERT_HEAD(&ifp->if_multiaddrs, ifma, ifma_link);
2857 }
2858
2859 static int
2860 if_detach_ifma(struct ifnet *ifp, struct ifmultiaddr *ifma, int anon)
2861 {
2862 ifnet_lock_assert(ifp, IFNET_LCK_ASSERT_EXCLUSIVE);
2863 IFMA_LOCK_ASSERT_HELD(ifma);
2864
2865 if (ifma->ifma_reqcnt == 0) {
2866 panic("%s: ifma=%p negative reqcnt", __func__, ifma);
2867 /* NOTREACHED */
2868 } else if (anon && !(ifma->ifma_flags & IFMAF_ANONYMOUS)) {
2869 panic("%s: ifma=%p missing IFMAF_ANONYMOUS", __func__, ifma);
2870 /* NOTREACHED */
2871 } else if (anon && ifma->ifma_anoncnt == 0) {
2872 panic("%s: ifma=%p negative anonreqcnt", __func__, ifma);
2873 /* NOTREACHED */
2874 } else if (ifma->ifma_ifp != ifp) {
2875 panic("%s: Mismatch ifma_ifp=%p, ifp=%p", __func__,
2876 ifma->ifma_ifp, ifp);
2877 /* NOTREACHED */
2878 }
2879
2880 if (anon) {
2881 --ifma->ifma_anoncnt;
2882 if (ifma->ifma_anoncnt > 0)
2883 return (0);
2884 ifma->ifma_flags &= ~IFMAF_ANONYMOUS;
2885 }
2886
2887 --ifma->ifma_reqcnt;
2888 if (ifma->ifma_reqcnt > 0)
2889 return (0);
2890
2891 if (ifma->ifma_protospec != NULL) {
2892 panic("%s: Protospec not NULL for ifma=%p", __func__, ifma);
2893 /* NOTREACHED */
2894 } else if ((ifma->ifma_flags & IFMAF_ANONYMOUS) ||
2895 ifma->ifma_anoncnt != 0) {
2896 panic("%s: Detaching ifma=%p with outstanding anon req",
2897 __func__, ifma);
2898 /* NOTREACHED */
2899 } else if (!(ifma->ifma_debug & IFD_ATTACHED)) {
2900 panic("%s: Attempt to detach an unattached address ifma=%p",
2901 __func__, ifma);
2902 /* NOTREACHED */
2903 } else if (ifma->ifma_debug & IFD_TRASHED) {
2904 panic("%s: ifma %p is already in trash list", __func__, ifma);
2905 /* NOTREACHED */
2906 }
2907
2908 /*
2909 * NOTE: Caller calls IFMA_REMREF
2910 */
2911 ifma->ifma_debug &= ~IFD_ATTACHED;
2912 LIST_REMOVE(ifma, ifma_link);
2913 if (LIST_EMPTY(&ifp->if_multiaddrs))
2914 ifp->if_updatemcasts = 0;
2915
2916 if (ifma->ifma_debug & IFD_DEBUG) {
2917 /* Become a regular mutex, just in case */
2918 IFMA_CONVERT_LOCK(ifma);
2919 lck_mtx_lock(&ifma_trash_lock);
2920 TAILQ_INSERT_TAIL(&ifma_trash_head,
2921 (struct ifmultiaddr_dbg *)ifma, ifma_trash_link);
2922 lck_mtx_unlock(&ifma_trash_lock);
2923 ifma->ifma_debug |= IFD_TRASHED;
2924 }
2925
2926 return (1);
2927 }
2928
2929 /*
2930 * Find an ifmultiaddr that matches a socket address on an interface.
2931 *
2932 * Caller is responsible for holding the ifnet_lock while calling
2933 * this function.
2934 */
2935 static int
2936 if_addmulti_doesexist(struct ifnet *ifp, const struct sockaddr *sa,
2937 struct ifmultiaddr **retifma, int anon)
2938 {
2939 struct ifmultiaddr *ifma;
2940
2941 for (ifma = LIST_FIRST(&ifp->if_multiaddrs); ifma != NULL;
2942 ifma = LIST_NEXT(ifma, ifma_link)) {
2943 IFMA_LOCK_SPIN(ifma);
2944 if (!equal(sa, ifma->ifma_addr)) {
2945 IFMA_UNLOCK(ifma);
2946 continue;
2947 }
2948 if (anon) {
2949 VERIFY(!(ifma->ifma_flags & IFMAF_ANONYMOUS) ||
2950 ifma->ifma_anoncnt != 0);
2951 VERIFY((ifma->ifma_flags & IFMAF_ANONYMOUS) ||
2952 ifma->ifma_anoncnt == 0);
2953 ifma->ifma_anoncnt++;
2954 if (!(ifma->ifma_flags & IFMAF_ANONYMOUS)) {
2955 VERIFY(ifma->ifma_anoncnt == 1);
2956 ifma->ifma_flags |= IFMAF_ANONYMOUS;
2957 }
2958 }
2959 if (!anon || ifma->ifma_anoncnt == 1) {
2960 ifma->ifma_reqcnt++;
2961 VERIFY(ifma->ifma_reqcnt > 1);
2962 }
2963 if (retifma != NULL) {
2964 *retifma = ifma;
2965 IFMA_ADDREF_LOCKED(ifma);
2966 }
2967 IFMA_UNLOCK(ifma);
2968 return (0);
2969 }
2970 return (ENOENT);
2971 }
2972
2973 /*
2974 * Radar 3642395, make sure all multicasts are in a standard format.
2975 */
2976 static struct sockaddr*
2977 copy_and_normalize(const struct sockaddr *original)
2978 {
2979 int alen = 0;
2980 const u_char *aptr = NULL;
2981 struct sockaddr *copy = NULL;
2982 struct sockaddr_dl *sdl_new = NULL;
2983 int len = 0;
2984
2985 if (original->sa_family != AF_LINK &&
2986 original->sa_family != AF_UNSPEC) {
2987 /* Just make a copy */
2988 MALLOC(copy, struct sockaddr*, original->sa_len,
2989 M_IFADDR, M_WAITOK);
2990 if (copy != NULL)
2991 bcopy(original, copy, original->sa_len);
2992 return (copy);
2993 }
2994
2995 switch (original->sa_family) {
2996 case AF_LINK: {
2997 const struct sockaddr_dl *sdl_original =
2998 (struct sockaddr_dl*)(uintptr_t)(size_t)original;
2999
3000 if (sdl_original->sdl_nlen + sdl_original->sdl_alen +
3001 sdl_original->sdl_slen +
3002 offsetof(struct sockaddr_dl, sdl_data) >
3003 sdl_original->sdl_len)
3004 return (NULL);
3005
3006 alen = sdl_original->sdl_alen;
3007 aptr = CONST_LLADDR(sdl_original);
3008 }
3009 break;
3010
3011 case AF_UNSPEC: {
3012 if (original->sa_len < ETHER_ADDR_LEN +
3013 offsetof(struct sockaddr, sa_data)) {
3014 return (NULL);
3015 }
3016
3017 alen = ETHER_ADDR_LEN;
3018 aptr = (const u_char*)original->sa_data;
3019 }
3020 break;
3021 }
3022
3023 if (alen == 0 || aptr == NULL)
3024 return (NULL);
3025
3026 len = alen + offsetof(struct sockaddr_dl, sdl_data);
3027 MALLOC(sdl_new, struct sockaddr_dl*, len, M_IFADDR, M_WAITOK);
3028
3029 if (sdl_new != NULL) {
3030 bzero(sdl_new, len);
3031 sdl_new->sdl_len = len;
3032 sdl_new->sdl_family = AF_LINK;
3033 sdl_new->sdl_alen = alen;
3034 bcopy(aptr, LLADDR(sdl_new), alen);
3035 }
3036
3037 return ((struct sockaddr*)sdl_new);
3038 }
3039
3040 /*
3041 * Network-layer protocol domains which hold references to the underlying
3042 * link-layer record must use this routine.
3043 */
3044 int
3045 if_addmulti(struct ifnet *ifp, const struct sockaddr *sa,
3046 struct ifmultiaddr **retifma)
3047 {
3048 return (if_addmulti_common(ifp, sa, retifma, 0));
3049 }
3050
3051 /*
3052 * Anything other than network-layer protocol domains which hold references
3053 * to the underlying link-layer record must use this routine: SIOCADDMULTI
3054 * ioctl, ifnet_add_multicast(), if_bond.
3055 */
3056 int
3057 if_addmulti_anon(struct ifnet *ifp, const struct sockaddr *sa,
3058 struct ifmultiaddr **retifma)
3059 {
3060 return (if_addmulti_common(ifp, sa, retifma, 1));
3061 }
3062
3063 /*
3064 * Register an additional multicast address with a network interface.
3065 *
3066 * - If the address is already present, bump the reference count on the
3067 * address and return.
3068 * - If the address is not link-layer, look up a link layer address.
3069 * - Allocate address structures for one or both addresses, and attach to the
3070 * multicast address list on the interface. If automatically adding a link
3071 * layer address, the protocol address will own a reference to the link
3072 * layer address, to be freed when it is freed.
3073 * - Notify the network device driver of an addition to the multicast address
3074 * list.
3075 *
3076 * 'sa' points to caller-owned memory with the desired multicast address.
3077 *
3078 * 'retifma' will be used to return a pointer to the resulting multicast
3079 * address reference, if desired.
3080 *
3081 * 'anon' indicates a link-layer address with no protocol address reference
3082 * made to it. Anything other than network-layer protocol domain requests
3083 * are considered as anonymous.
3084 */
3085 static int
3086 if_addmulti_common(struct ifnet *ifp, const struct sockaddr *sa,
3087 struct ifmultiaddr **retifma, int anon)
3088 {
3089 struct sockaddr_storage storage;
3090 struct sockaddr *llsa = NULL;
3091 struct sockaddr *dupsa = NULL;
3092 int error = 0, ll_firstref = 0, lladdr;
3093 struct ifmultiaddr *ifma = NULL;
3094 struct ifmultiaddr *llifma = NULL;
3095
3096 /* Only AF_UNSPEC/AF_LINK is allowed for an "anonymous" address */
3097 VERIFY(!anon || sa->sa_family == AF_UNSPEC ||
3098 sa->sa_family == AF_LINK);
3099
3100 /* If sa is a AF_LINK or AF_UNSPEC, duplicate and normalize it */
3101 if (sa->sa_family == AF_LINK || sa->sa_family == AF_UNSPEC) {
3102 dupsa = copy_and_normalize(sa);
3103 if (dupsa == NULL) {
3104 error = ENOMEM;
3105 goto cleanup;
3106 }
3107 sa = dupsa;
3108 }
3109
3110 ifnet_lock_exclusive(ifp);
3111 if (!(ifp->if_flags & IFF_MULTICAST)) {
3112 error = EADDRNOTAVAIL;
3113 ifnet_lock_done(ifp);
3114 goto cleanup;
3115 }
3116
3117 /* If the address is already present, return a new reference to it */
3118 error = if_addmulti_doesexist(ifp, sa, retifma, anon);
3119 ifnet_lock_done(ifp);
3120 if (error == 0)
3121 goto cleanup;
3122
3123 /*
3124 * The address isn't already present; give the link layer a chance
3125 * to accept/reject it, and also find out which AF_LINK address this
3126 * maps to, if it isn't one already.
3127 */
3128 error = dlil_resolve_multi(ifp, sa, (struct sockaddr *)&storage,
3129 sizeof (storage));
3130 if (error == 0 && storage.ss_len != 0) {
3131 llsa = copy_and_normalize((struct sockaddr *)&storage);
3132 if (llsa == NULL) {
3133 error = ENOMEM;
3134 goto cleanup;
3135 }
3136
3137 llifma = ifma_alloc(M_WAITOK);
3138 if (llifma == NULL) {
3139 error = ENOMEM;
3140 goto cleanup;
3141 }
3142 }
3143
3144 /* to be similar to FreeBSD */
3145 if (error == EOPNOTSUPP)
3146 error = 0;
3147 else if (error != 0)
3148 goto cleanup;
3149
3150 /* Allocate while we aren't holding any locks */
3151 if (dupsa == NULL) {
3152 dupsa = copy_and_normalize(sa);
3153 if (dupsa == NULL) {
3154 error = ENOMEM;
3155 goto cleanup;
3156 }
3157 }
3158 ifma = ifma_alloc(M_WAITOK);
3159 if (ifma == NULL) {
3160 error = ENOMEM;
3161 goto cleanup;
3162 }
3163
3164 ifnet_lock_exclusive(ifp);
3165 /*
3166 * Check again for the matching multicast.
3167 */
3168 error = if_addmulti_doesexist(ifp, sa, retifma, anon);
3169 if (error == 0) {
3170 ifnet_lock_done(ifp);
3171 goto cleanup;
3172 }
3173
3174 if (llifma != NULL) {
3175 VERIFY(!anon); /* must not get here if "anonymous" */
3176 if (if_addmulti_doesexist(ifp, llsa, &ifma->ifma_ll, 0) == 0) {
3177 FREE(llsa, M_IFADDR);
3178 llsa = NULL;
3179 ifma_free(llifma);
3180 llifma = NULL;
3181 VERIFY(ifma->ifma_ll->ifma_ifp == ifp);
3182 } else {
3183 ll_firstref = 1;
3184 llifma->ifma_addr = llsa;
3185 llifma->ifma_ifp = ifp;
3186 IFMA_LOCK(llifma);
3187 if_attach_ifma(ifp, llifma, 0);
3188 /* add extra refcnt for ifma */
3189 IFMA_ADDREF_LOCKED(llifma);
3190 IFMA_UNLOCK(llifma);
3191 ifma->ifma_ll = llifma;
3192 }
3193 }
3194
3195 /* "anonymous" request should not result in network address */
3196 VERIFY(!anon || ifma->ifma_ll == NULL);
3197
3198 ifma->ifma_addr = dupsa;
3199 ifma->ifma_ifp = ifp;
3200 IFMA_LOCK(ifma);
3201 if_attach_ifma(ifp, ifma, anon);
3202 IFMA_ADDREF_LOCKED(ifma); /* for this routine */
3203 if (retifma != NULL) {
3204 *retifma = ifma;
3205 IFMA_ADDREF_LOCKED(*retifma); /* for caller */
3206 }
3207 lladdr = (ifma->ifma_addr->sa_family == AF_UNSPEC ||
3208 ifma->ifma_addr->sa_family == AF_LINK);
3209 IFMA_UNLOCK(ifma);
3210 ifnet_lock_done(ifp);
3211
3212 rt_newmaddrmsg(RTM_NEWMADDR, ifma);
3213 IFMA_REMREF(ifma); /* for this routine */
3214
3215 /*
3216 * We are certain we have added something, so call down to the
3217 * interface to let them know about it. Do this only for newly-
3218 * added AF_LINK/AF_UNSPEC address in the if_multiaddrs set.
3219 */
3220 if (lladdr || ll_firstref)
3221 (void) ifnet_ioctl(ifp, 0, SIOCADDMULTI, NULL);
3222
3223 if (ifp->if_updatemcasts > 0)
3224 ifp->if_updatemcasts = 0;
3225
3226 return (0);
3227
3228 cleanup:
3229 if (ifma != NULL)
3230 ifma_free(ifma);
3231 if (dupsa != NULL)
3232 FREE(dupsa, M_IFADDR);
3233 if (llifma != NULL)
3234 ifma_free(llifma);
3235 if (llsa != NULL)
3236 FREE(llsa, M_IFADDR);
3237
3238 return (error);
3239 }
3240
3241 /*
3242 * Delete a multicast group membership by network-layer group address.
3243 * This routine is deprecated.
3244 */
3245 int
3246 if_delmulti(struct ifnet *ifp, const struct sockaddr *sa)
3247 {
3248 return (if_delmulti_common(NULL, ifp, sa, 0));
3249 }
3250
3251 /*
3252 * Delete a multicast group membership by group membership pointer.
3253 * Network-layer protocol domains must use this routine.
3254 */
3255 int
3256 if_delmulti_ifma(struct ifmultiaddr *ifma)
3257 {
3258 return (if_delmulti_common(ifma, NULL, NULL, 0));
3259 }
3260
3261 /*
3262 * Anything other than network-layer protocol domains which hold references
3263 * to the underlying link-layer record must use this routine: SIOCDELMULTI
3264 * ioctl, ifnet_remove_multicast(), if_bond.
3265 */
3266 int
3267 if_delmulti_anon(struct ifnet *ifp, const struct sockaddr *sa)
3268 {
3269 return (if_delmulti_common(NULL, ifp, sa, 1));
3270 }
3271
3272 /*
3273 * Delete a multicast group membership by network-layer group address.
3274 *
3275 * Returns ENOENT if the entry could not be found.
3276 */
3277 static int
3278 if_delmulti_common(struct ifmultiaddr *ifma, struct ifnet *ifp,
3279 const struct sockaddr *sa, int anon)
3280 {
3281 struct sockaddr *dupsa = NULL;
3282 int lastref, ll_lastref = 0, lladdr;
3283 struct ifmultiaddr *ll = NULL;
3284
3285 /* sanity check for callers */
3286 VERIFY(ifma != NULL || (ifp != NULL && sa != NULL));
3287
3288 if (ifma != NULL)
3289 ifp = ifma->ifma_ifp;
3290
3291 if (sa != NULL &&
3292 (sa->sa_family == AF_LINK || sa->sa_family == AF_UNSPEC)) {
3293 dupsa = copy_and_normalize(sa);
3294 if (dupsa == NULL)
3295 return (ENOMEM);
3296 sa = dupsa;
3297 }
3298
3299 ifnet_lock_exclusive(ifp);
3300 if (ifma == NULL) {
3301 for (ifma = LIST_FIRST(&ifp->if_multiaddrs); ifma != NULL;
3302 ifma = LIST_NEXT(ifma, ifma_link)) {
3303 IFMA_LOCK(ifma);
3304 if (!equal(sa, ifma->ifma_addr) ||
3305 (anon && !(ifma->ifma_flags & IFMAF_ANONYMOUS))) {
3306 VERIFY(!(ifma->ifma_flags & IFMAF_ANONYMOUS) ||
3307 ifma->ifma_anoncnt != 0);
3308 IFMA_UNLOCK(ifma);
3309 continue;
3310 }
3311 /* found; keep it locked */
3312 break;
3313 }
3314 if (ifma == NULL) {
3315 if (dupsa != NULL)
3316 FREE(dupsa, M_IFADDR);
3317 ifnet_lock_done(ifp);
3318 return (ENOENT);
3319 }
3320 } else {
3321 IFMA_LOCK(ifma);
3322 }
3323 IFMA_LOCK_ASSERT_HELD(ifma);
3324 IFMA_ADDREF_LOCKED(ifma); /* for this routine */
3325 lastref = if_detach_ifma(ifp, ifma, anon);
3326 VERIFY(!lastref || (!(ifma->ifma_debug & IFD_ATTACHED) &&
3327 ifma->ifma_reqcnt == 0));
3328 VERIFY(!anon || ifma->ifma_ll == NULL);
3329 ll = ifma->ifma_ll;
3330 lladdr = (ifma->ifma_addr->sa_family == AF_UNSPEC ||
3331 ifma->ifma_addr->sa_family == AF_LINK);
3332 IFMA_UNLOCK(ifma);
3333 if (lastref && ll != NULL) {
3334 IFMA_LOCK(ll);
3335 ll_lastref = if_detach_ifma(ifp, ll, 0);
3336 IFMA_UNLOCK(ll);
3337 }
3338 ifnet_lock_done(ifp);
3339
3340 if (lastref)
3341 rt_newmaddrmsg(RTM_DELMADDR, ifma);
3342
3343 if ((ll == NULL && lastref && lladdr) || ll_lastref) {
3344 /*
3345 * Make sure the interface driver is notified in the
3346 * case of a link layer mcast group being left. Do
3347 * this only for a AF_LINK/AF_UNSPEC address that has
3348 * been removed from the if_multiaddrs set.
3349 */
3350 ifnet_ioctl(ifp, 0, SIOCDELMULTI, NULL);
3351 }
3352
3353 if (lastref)
3354 IFMA_REMREF(ifma); /* for if_multiaddrs list */
3355 if (ll_lastref)
3356 IFMA_REMREF(ll); /* for if_multiaddrs list */
3357
3358 IFMA_REMREF(ifma); /* for this routine */
3359 if (dupsa != NULL)
3360 FREE(dupsa, M_IFADDR);
3361
3362 return (0);
3363 }
3364
3365 /*
3366 * Shutdown all network activity. Used boot() when halting
3367 * system.
3368 */
3369 int
3370 if_down_all(void)
3371 {
3372 struct ifnet **ifp;
3373 u_int32_t count;
3374 u_int32_t i;
3375
3376 if (ifnet_list_get_all(IFNET_FAMILY_ANY, &ifp, &count) == 0) {
3377 for (i = 0; i < count; i++) {
3378 if_down(ifp[i]);
3379 dlil_proto_unplumb_all(ifp[i]);
3380 }
3381 ifnet_list_free(ifp);
3382 }
3383
3384 return 0;
3385 }
3386
3387 /*
3388 * Delete Routes for a Network Interface
3389 *
3390 * Called for each routing entry via the rnh->rnh_walktree() call above
3391 * to delete all route entries referencing a detaching network interface.
3392 *
3393 * Arguments:
3394 * rn pointer to node in the routing table
3395 * arg argument passed to rnh->rnh_walktree() - detaching interface
3396 *
3397 * Returns:
3398 * 0 successful
3399 * errno failed - reason indicated
3400 *
3401 */
3402 static int
3403 if_rtdel(struct radix_node *rn, void *arg)
3404 {
3405 struct rtentry *rt = (struct rtentry *)rn;
3406 struct ifnet *ifp = arg;
3407 int err;
3408
3409 if (rt == NULL)
3410 return (0);
3411 /*
3412 * Checking against RTF_UP protects against walktree
3413 * recursion problems with cloned routes.
3414 */
3415 RT_LOCK(rt);
3416 if (rt->rt_ifp == ifp && (rt->rt_flags & RTF_UP)) {
3417 /*
3418 * Safe to drop rt_lock and use rt_key, rt_gateway,
3419 * since holding rnh_lock here prevents another thread
3420 * from calling rt_setgate() on this route.
3421 */
3422 RT_UNLOCK(rt);
3423 err = rtrequest_locked(RTM_DELETE, rt_key(rt), rt->rt_gateway,
3424 rt_mask(rt), rt->rt_flags, NULL);
3425 if (err) {
3426 log(LOG_WARNING, "if_rtdel: error %d\n", err);
3427 }
3428 } else {
3429 RT_UNLOCK(rt);
3430 }
3431 return (0);
3432 }
3433
3434 /*
3435 * Removes routing table reference to a given interface
3436 * for a given protocol family
3437 */
3438 void
3439 if_rtproto_del(struct ifnet *ifp, int protocol)
3440 {
3441 struct radix_node_head *rnh;
3442
3443 if ((protocol <= AF_MAX) && (protocol >= 0) &&
3444 ((rnh = rt_tables[protocol]) != NULL) && (ifp != NULL)) {
3445 lck_mtx_lock(rnh_lock);
3446 (void) rnh->rnh_walktree(rnh, if_rtdel, ifp);
3447 lck_mtx_unlock(rnh_lock);
3448 }
3449 }
3450
3451 static int
3452 if_rtmtu(struct radix_node *rn, void *arg)
3453 {
3454 struct rtentry *rt = (struct rtentry *)rn;
3455 struct ifnet *ifp = arg;
3456
3457 RT_LOCK(rt);
3458 if (rt->rt_ifp == ifp) {
3459 /*
3460 * Update the MTU of this entry only if the MTU
3461 * has not been locked (RTV_MTU is not set) and
3462 * if it was non-zero to begin with.
3463 */
3464 if (!(rt->rt_rmx.rmx_locks & RTV_MTU) && rt->rt_rmx.rmx_mtu)
3465 rt->rt_rmx.rmx_mtu = ifp->if_mtu;
3466 }
3467 RT_UNLOCK(rt);
3468
3469 return (0);
3470 }
3471
3472 /*
3473 * Update the MTU metric of all route entries in all protocol tables
3474 * associated with a particular interface; this is called when the
3475 * MTU of that interface has changed.
3476 */
3477 static
3478 void if_rtmtu_update(struct ifnet *ifp)
3479 {
3480 struct radix_node_head *rnh;
3481 int p;
3482
3483 for (p = 0; p < AF_MAX + 1; p++) {
3484 if ((rnh = rt_tables[p]) == NULL)
3485 continue;
3486
3487 lck_mtx_lock(rnh_lock);
3488 (void) rnh->rnh_walktree(rnh, if_rtmtu, ifp);
3489 lck_mtx_unlock(rnh_lock);
3490 }
3491 routegenid_update();
3492 }
3493
3494 __private_extern__ void
3495 if_data_internal_to_if_data(struct ifnet *ifp,
3496 const struct if_data_internal *if_data_int, struct if_data *if_data)
3497 {
3498 #pragma unused(ifp)
3499 #define COPYFIELD(fld) if_data->fld = if_data_int->fld
3500 #define COPYFIELD32(fld) if_data->fld = (u_int32_t)(if_data_int->fld)
3501 /* compiler will cast down to 32-bit */
3502 #define COPYFIELD32_ATOMIC(fld) do { \
3503 atomic_get_64(if_data->fld, \
3504 (u_int64_t *)(void *)(uintptr_t)&if_data_int->fld); \
3505 } while (0)
3506
3507 COPYFIELD(ifi_type);
3508 COPYFIELD(ifi_typelen);
3509 COPYFIELD(ifi_physical);
3510 COPYFIELD(ifi_addrlen);
3511 COPYFIELD(ifi_hdrlen);
3512 COPYFIELD(ifi_recvquota);
3513 COPYFIELD(ifi_xmitquota);
3514 if_data->ifi_unused1 = 0;
3515 COPYFIELD(ifi_mtu);
3516 COPYFIELD(ifi_metric);
3517 if (if_data_int->ifi_baudrate & 0xFFFFFFFF00000000LL) {
3518 if_data->ifi_baudrate = 0xFFFFFFFF;
3519 } else {
3520 COPYFIELD32(ifi_baudrate);
3521 }
3522
3523 COPYFIELD32_ATOMIC(ifi_ipackets);
3524 COPYFIELD32_ATOMIC(ifi_ierrors);
3525 COPYFIELD32_ATOMIC(ifi_opackets);
3526 COPYFIELD32_ATOMIC(ifi_oerrors);
3527 COPYFIELD32_ATOMIC(ifi_collisions);
3528 COPYFIELD32_ATOMIC(ifi_ibytes);
3529 COPYFIELD32_ATOMIC(ifi_obytes);
3530 COPYFIELD32_ATOMIC(ifi_imcasts);
3531 COPYFIELD32_ATOMIC(ifi_omcasts);
3532 COPYFIELD32_ATOMIC(ifi_iqdrops);
3533 COPYFIELD32_ATOMIC(ifi_noproto);
3534
3535 COPYFIELD(ifi_recvtiming);
3536 COPYFIELD(ifi_xmittiming);
3537
3538 if_data->ifi_lastchange.tv_sec = if_data_int->ifi_lastchange.tv_sec;
3539 if_data->ifi_lastchange.tv_usec = if_data_int->ifi_lastchange.tv_usec;
3540
3541 if_data->ifi_lastchange.tv_sec += boottime_sec();
3542
3543 if_data->ifi_unused2 = 0;
3544 COPYFIELD(ifi_hwassist);
3545 if_data->ifi_reserved1 = 0;
3546 if_data->ifi_reserved2 = 0;
3547 #undef COPYFIELD32_ATOMIC
3548 #undef COPYFIELD32
3549 #undef COPYFIELD
3550 }
3551
3552 __private_extern__ void
3553 if_data_internal_to_if_data64(struct ifnet *ifp,
3554 const struct if_data_internal *if_data_int,
3555 struct if_data64 *if_data64)
3556 {
3557 #pragma unused(ifp)
3558 #define COPYFIELD64(fld) if_data64->fld = if_data_int->fld
3559 #define COPYFIELD64_ATOMIC(fld) do { \
3560 atomic_get_64(if_data64->fld, \
3561 (u_int64_t *)(void *)(uintptr_t)&if_data_int->fld); \
3562 } while (0)
3563
3564 COPYFIELD64(ifi_type);
3565 COPYFIELD64(ifi_typelen);
3566 COPYFIELD64(ifi_physical);
3567 COPYFIELD64(ifi_addrlen);
3568 COPYFIELD64(ifi_hdrlen);
3569 COPYFIELD64(ifi_recvquota);
3570 COPYFIELD64(ifi_xmitquota);
3571 if_data64->ifi_unused1 = 0;
3572 COPYFIELD64(ifi_mtu);
3573 COPYFIELD64(ifi_metric);
3574 COPYFIELD64(ifi_baudrate);
3575
3576 COPYFIELD64_ATOMIC(ifi_ipackets);
3577 COPYFIELD64_ATOMIC(ifi_ierrors);
3578 COPYFIELD64_ATOMIC(ifi_opackets);
3579 COPYFIELD64_ATOMIC(ifi_oerrors);
3580 COPYFIELD64_ATOMIC(ifi_collisions);
3581 COPYFIELD64_ATOMIC(ifi_ibytes);
3582 COPYFIELD64_ATOMIC(ifi_obytes);
3583 COPYFIELD64_ATOMIC(ifi_imcasts);
3584 COPYFIELD64_ATOMIC(ifi_omcasts);
3585 COPYFIELD64_ATOMIC(ifi_iqdrops);
3586 COPYFIELD64_ATOMIC(ifi_noproto);
3587
3588 /* Note these two fields are actually 32 bit, so doing COPYFIELD64_ATOMIC will
3589 * cause them to be misaligned
3590 */
3591 COPYFIELD64(ifi_recvtiming);
3592 COPYFIELD64(ifi_xmittiming);
3593
3594 if_data64->ifi_lastchange.tv_sec = if_data_int->ifi_lastchange.tv_sec;
3595 if_data64->ifi_lastchange.tv_usec = if_data_int->ifi_lastchange.tv_usec;
3596
3597 if_data64->ifi_lastchange.tv_sec += boottime_sec();
3598
3599 #undef COPYFIELD64
3600 }
3601
3602 __private_extern__ void
3603 if_copy_traffic_class(struct ifnet *ifp,
3604 struct if_traffic_class *if_tc)
3605 {
3606 #define COPY_IF_TC_FIELD64_ATOMIC(fld) do { \
3607 atomic_get_64(if_tc->fld, \
3608 (u_int64_t *)(void *)(uintptr_t)&ifp->if_tc.fld); \
3609 } while (0)
3610
3611 bzero(if_tc, sizeof (*if_tc));
3612 COPY_IF_TC_FIELD64_ATOMIC(ifi_ibepackets);
3613 COPY_IF_TC_FIELD64_ATOMIC(ifi_ibebytes);
3614 COPY_IF_TC_FIELD64_ATOMIC(ifi_obepackets);
3615 COPY_IF_TC_FIELD64_ATOMIC(ifi_obebytes);
3616 COPY_IF_TC_FIELD64_ATOMIC(ifi_ibkpackets);
3617 COPY_IF_TC_FIELD64_ATOMIC(ifi_ibkbytes);
3618 COPY_IF_TC_FIELD64_ATOMIC(ifi_obkpackets);
3619 COPY_IF_TC_FIELD64_ATOMIC(ifi_obkbytes);
3620 COPY_IF_TC_FIELD64_ATOMIC(ifi_ivipackets);
3621 COPY_IF_TC_FIELD64_ATOMIC(ifi_ivibytes);
3622 COPY_IF_TC_FIELD64_ATOMIC(ifi_ovipackets);
3623 COPY_IF_TC_FIELD64_ATOMIC(ifi_ovibytes);
3624 COPY_IF_TC_FIELD64_ATOMIC(ifi_ivopackets);
3625 COPY_IF_TC_FIELD64_ATOMIC(ifi_ivobytes);
3626 COPY_IF_TC_FIELD64_ATOMIC(ifi_ovopackets);
3627 COPY_IF_TC_FIELD64_ATOMIC(ifi_ovobytes);
3628 COPY_IF_TC_FIELD64_ATOMIC(ifi_ipvpackets);
3629 COPY_IF_TC_FIELD64_ATOMIC(ifi_ipvbytes);
3630 COPY_IF_TC_FIELD64_ATOMIC(ifi_opvpackets);
3631 COPY_IF_TC_FIELD64_ATOMIC(ifi_opvbytes);
3632
3633 #undef COPY_IF_TC_FIELD64_ATOMIC
3634 }
3635
3636 void
3637 if_copy_data_extended(struct ifnet *ifp, struct if_data_extended *if_de)
3638 {
3639 #define COPY_IF_DE_FIELD64_ATOMIC(fld) do { \
3640 atomic_get_64(if_de->fld, \
3641 (u_int64_t *)(void *)(uintptr_t)&ifp->if_data.fld); \
3642 } while (0)
3643
3644 bzero(if_de, sizeof (*if_de));
3645 COPY_IF_DE_FIELD64_ATOMIC(ifi_alignerrs);
3646 COPY_IF_DE_FIELD64_ATOMIC(ifi_dt_bytes);
3647 COPY_IF_DE_FIELD64_ATOMIC(ifi_fpackets);
3648 COPY_IF_DE_FIELD64_ATOMIC(ifi_fbytes);
3649
3650 #undef COPY_IF_DE_FIELD64_ATOMIC
3651 }
3652
3653 void
3654 if_copy_packet_stats(struct ifnet *ifp, struct if_packet_stats *if_ps)
3655 {
3656 #define COPY_IF_PS_TCP_FIELD64_ATOMIC(fld) do { \
3657 atomic_get_64(if_ps->ifi_tcp_##fld, \
3658 (u_int64_t *)(void *)(uintptr_t)&ifp->if_tcp_stat->fld); \
3659 } while (0)
3660
3661 #define COPY_IF_PS_UDP_FIELD64_ATOMIC(fld) do { \
3662 atomic_get_64(if_ps->ifi_udp_##fld, \
3663 (u_int64_t *)(void *)(uintptr_t)&ifp->if_udp_stat->fld); \
3664 } while (0)
3665
3666 COPY_IF_PS_TCP_FIELD64_ATOMIC(badformat);
3667 COPY_IF_PS_TCP_FIELD64_ATOMIC(unspecv6);
3668 COPY_IF_PS_TCP_FIELD64_ATOMIC(synfin);
3669 COPY_IF_PS_TCP_FIELD64_ATOMIC(badformatipsec);
3670 COPY_IF_PS_TCP_FIELD64_ATOMIC(noconnnolist);
3671 COPY_IF_PS_TCP_FIELD64_ATOMIC(noconnlist);
3672 COPY_IF_PS_TCP_FIELD64_ATOMIC(listbadsyn);
3673 COPY_IF_PS_TCP_FIELD64_ATOMIC(icmp6unreach);
3674 COPY_IF_PS_TCP_FIELD64_ATOMIC(deprecate6);
3675 COPY_IF_PS_TCP_FIELD64_ATOMIC(ooopacket);
3676 COPY_IF_PS_TCP_FIELD64_ATOMIC(rstinsynrcv);
3677 COPY_IF_PS_TCP_FIELD64_ATOMIC(dospacket);
3678 COPY_IF_PS_TCP_FIELD64_ATOMIC(cleanup);
3679 COPY_IF_PS_TCP_FIELD64_ATOMIC(synwindow);
3680
3681 COPY_IF_PS_UDP_FIELD64_ATOMIC(port_unreach);
3682 COPY_IF_PS_UDP_FIELD64_ATOMIC(faithprefix);
3683 COPY_IF_PS_UDP_FIELD64_ATOMIC(port0);
3684 COPY_IF_PS_UDP_FIELD64_ATOMIC(badlength);
3685 COPY_IF_PS_UDP_FIELD64_ATOMIC(badchksum);
3686 COPY_IF_PS_UDP_FIELD64_ATOMIC(badmcast);
3687 COPY_IF_PS_UDP_FIELD64_ATOMIC(cleanup);
3688 COPY_IF_PS_UDP_FIELD64_ATOMIC(badipsec);
3689
3690 #undef COPY_IF_PS_TCP_FIELD64_ATOMIC
3691 #undef COPY_IF_PS_UDP_FIELD64_ATOMIC
3692 }
3693
3694 void
3695 if_copy_rxpoll_stats(struct ifnet *ifp, struct if_rxpoll_stats *if_rs)
3696 {
3697 bzero(if_rs, sizeof (*if_rs));
3698 if (!(ifp->if_eflags & IFEF_RXPOLL) || !ifnet_is_attached(ifp, 1))
3699 return;
3700
3701 /* by now, ifnet will stay attached so if_inp must be valid */
3702 VERIFY(ifp->if_inp != NULL);
3703 bcopy(&ifp->if_inp->pstats, if_rs, sizeof (*if_rs));
3704
3705 /* Release the IO refcnt */
3706 ifnet_decr_iorefcnt(ifp);
3707 }
3708
3709 struct ifaddr *
3710 ifa_remref(struct ifaddr *ifa, int locked)
3711 {
3712 if (!locked)
3713 IFA_LOCK_SPIN(ifa);
3714 else
3715 IFA_LOCK_ASSERT_HELD(ifa);
3716
3717 if (ifa->ifa_refcnt == 0)
3718 panic("%s: ifa %p negative refcnt\n", __func__, ifa);
3719 else if (ifa->ifa_trace != NULL)
3720 (*ifa->ifa_trace)(ifa, FALSE);
3721 if (--ifa->ifa_refcnt == 0) {
3722 if (ifa->ifa_debug & IFD_ATTACHED)
3723 panic("ifa %p attached to ifp is being freed\n", ifa);
3724 /*
3725 * Some interface addresses are allocated either statically
3726 * or carved out of a larger block. Only free it if it was
3727 * allocated via MALLOC or via the corresponding per-address
3728 * family allocator. Otherwise, leave it alone.
3729 */
3730 if (ifa->ifa_debug & IFD_ALLOC) {
3731 if (ifa->ifa_free == NULL) {
3732 IFA_UNLOCK(ifa);
3733 FREE(ifa, M_IFADDR);
3734 } else {
3735 /* Become a regular mutex */
3736 IFA_CONVERT_LOCK(ifa);
3737 /* callee will unlock */
3738 (*ifa->ifa_free)(ifa);
3739 }
3740 } else {
3741 IFA_UNLOCK(ifa);
3742 }
3743 ifa = NULL;
3744 }
3745
3746 if (!locked && ifa != NULL)
3747 IFA_UNLOCK(ifa);
3748
3749 return (ifa);
3750 }
3751
3752 void
3753 ifa_addref(struct ifaddr *ifa, int locked)
3754 {
3755 if (!locked)
3756 IFA_LOCK_SPIN(ifa);
3757 else
3758 IFA_LOCK_ASSERT_HELD(ifa);
3759
3760 if (++ifa->ifa_refcnt == 0) {
3761 panic("%s: ifa %p wraparound refcnt\n", __func__, ifa);
3762 /* NOTREACHED */
3763 } else if (ifa->ifa_trace != NULL) {
3764 (*ifa->ifa_trace)(ifa, TRUE);
3765 }
3766 if (!locked)
3767 IFA_UNLOCK(ifa);
3768 }
3769
3770 void
3771 ifa_lock_init(struct ifaddr *ifa)
3772 {
3773 lck_mtx_init(&ifa->ifa_lock, ifa_mtx_grp, ifa_mtx_attr);
3774 }
3775
3776 void
3777 ifa_lock_destroy(struct ifaddr *ifa)
3778 {
3779 IFA_LOCK_ASSERT_NOTHELD(ifa);
3780 lck_mtx_destroy(&ifa->ifa_lock, ifa_mtx_grp);
3781 }
3782
3783 /*
3784 * 'i' group ioctls.
3785 *
3786 * The switch statement below does nothing at runtime, as it serves as a
3787 * compile time check to ensure that all of the socket 'i' ioctls (those
3788 * in the 'i' group going thru soo_ioctl) that are made available by the
3789 * networking stack is unique. This works as long as this routine gets
3790 * updated each time a new interface ioctl gets added.
3791 *
3792 * Any failures at compile time indicates duplicated ioctl values.
3793 */
3794 static __attribute__((unused)) void
3795 ifioctl_cassert(void)
3796 {
3797 /*
3798 * This is equivalent to _CASSERT() and the compiler wouldn't
3799 * generate any instructions, thus for compile time only.
3800 */
3801 switch ((u_long)0) {
3802 case 0:
3803
3804 /* bsd/net/if_ppp.h */
3805 case SIOCGPPPSTATS:
3806 case SIOCGPPPCSTATS:
3807
3808 #if INET6
3809 /* bsd/netinet6/in6_var.h */
3810 case SIOCSIFADDR_IN6:
3811 case SIOCGIFADDR_IN6:
3812 case SIOCSIFDSTADDR_IN6:
3813 case SIOCSIFNETMASK_IN6:
3814 case SIOCGIFDSTADDR_IN6:
3815 case SIOCGIFNETMASK_IN6:
3816 case SIOCDIFADDR_IN6:
3817 case SIOCAIFADDR_IN6_32:
3818 case SIOCAIFADDR_IN6_64:
3819 case SIOCSIFPHYADDR_IN6_32:
3820 case SIOCSIFPHYADDR_IN6_64:
3821 case SIOCGIFPSRCADDR_IN6:
3822 case SIOCGIFPDSTADDR_IN6:
3823 case SIOCGIFAFLAG_IN6:
3824 case SIOCGDRLST_IN6_32:
3825 case SIOCGDRLST_IN6_64:
3826 case SIOCGPRLST_IN6_32:
3827 case SIOCGPRLST_IN6_64:
3828 case OSIOCGIFINFO_IN6:
3829 case SIOCGIFINFO_IN6:
3830 case SIOCSNDFLUSH_IN6:
3831 case SIOCGNBRINFO_IN6_32:
3832 case SIOCGNBRINFO_IN6_64:
3833 case SIOCSPFXFLUSH_IN6:
3834 case SIOCSRTRFLUSH_IN6:
3835 case SIOCGIFALIFETIME_IN6:
3836 case SIOCSIFALIFETIME_IN6:
3837 case SIOCGIFSTAT_IN6:
3838 case SIOCGIFSTAT_ICMP6:
3839 case SIOCSDEFIFACE_IN6_32:
3840 case SIOCSDEFIFACE_IN6_64:
3841 case SIOCGDEFIFACE_IN6_32:
3842 case SIOCGDEFIFACE_IN6_64:
3843 case SIOCSIFINFO_FLAGS:
3844 case SIOCSSCOPE6:
3845 case SIOCGSCOPE6:
3846 case SIOCGSCOPE6DEF:
3847 case SIOCSIFPREFIX_IN6:
3848 case SIOCGIFPREFIX_IN6:
3849 case SIOCDIFPREFIX_IN6:
3850 case SIOCAIFPREFIX_IN6:
3851 case SIOCCIFPREFIX_IN6:
3852 case SIOCSGIFPREFIX_IN6:
3853 case SIOCPROTOATTACH_IN6_32:
3854 case SIOCPROTOATTACH_IN6_64:
3855 case SIOCPROTODETACH_IN6:
3856 case SIOCLL_START_32:
3857 case SIOCLL_START_64:
3858 case SIOCLL_STOP:
3859 case SIOCAUTOCONF_START:
3860 case SIOCAUTOCONF_STOP:
3861 case SIOCSETROUTERMODE_IN6:
3862 case SIOCLL_CGASTART_32:
3863 case SIOCLL_CGASTART_64:
3864 #endif /* INET6 */
3865
3866 /* bsd/sys/sockio.h */
3867 case SIOCSIFADDR:
3868 case OSIOCGIFADDR:
3869 case SIOCSIFDSTADDR:
3870 case OSIOCGIFDSTADDR:
3871 case SIOCSIFFLAGS:
3872 case SIOCGIFFLAGS:
3873 case OSIOCGIFBRDADDR:
3874 case SIOCSIFBRDADDR:
3875 case OSIOCGIFCONF32:
3876 case OSIOCGIFCONF64:
3877 case OSIOCGIFNETMASK:
3878 case SIOCSIFNETMASK:
3879 case SIOCGIFMETRIC:
3880 case SIOCSIFMETRIC:
3881 case SIOCDIFADDR:
3882 case SIOCAIFADDR:
3883 case SIOCALIFADDR:
3884 case SIOCGLIFADDR:
3885 case SIOCDLIFADDR:
3886 case SIOCGIFADDR:
3887 case SIOCGIFDSTADDR:
3888 case SIOCGIFBRDADDR:
3889 case SIOCGIFCONF32:
3890 case SIOCGIFCONF64:
3891 case SIOCGIFNETMASK:
3892 case SIOCAUTOADDR:
3893 case SIOCAUTONETMASK:
3894 case SIOCARPIPLL:
3895 case SIOCADDMULTI:
3896 case SIOCDELMULTI:
3897 case SIOCGIFMTU:
3898 case SIOCSIFMTU:
3899 case SIOCGIFPHYS:
3900 case SIOCSIFPHYS:
3901 case SIOCSIFMEDIA:
3902 case SIOCGIFMEDIA32:
3903 case SIOCGIFMEDIA64:
3904 case SIOCSIFGENERIC:
3905 case SIOCGIFGENERIC:
3906 case SIOCRSLVMULTI:
3907 case SIOCSIFLLADDR:
3908 case SIOCGIFSTATUS:
3909 case SIOCSIFPHYADDR:
3910 case SIOCGIFPSRCADDR:
3911 case SIOCGIFPDSTADDR:
3912 case SIOCDIFPHYADDR:
3913 case SIOCSLIFPHYADDR:
3914 case SIOCGLIFPHYADDR:
3915 case SIOCGIFDEVMTU:
3916 case SIOCSIFALTMTU:
3917 case SIOCGIFALTMTU:
3918 case SIOCSIFBOND:
3919 case SIOCGIFBOND:
3920 case SIOCPROTOATTACH:
3921 case SIOCPROTODETACH:
3922 case SIOCSIFCAP:
3923 case SIOCGIFCAP:
3924 case SIOCIFCREATE:
3925 case SIOCIFDESTROY:
3926 case SIOCIFCREATE2:
3927 case SIOCSDRVSPEC32:
3928 case SIOCGDRVSPEC32:
3929 case SIOCSDRVSPEC64:
3930 case SIOCGDRVSPEC64:
3931 case SIOCSIFVLAN:
3932 case SIOCGIFVLAN:
3933 case SIOCIFGCLONERS32:
3934 case SIOCIFGCLONERS64:
3935 case SIOCGIFASYNCMAP:
3936 case SIOCSIFASYNCMAP:
3937 #if CONFIG_MACF_NET
3938 case SIOCGIFMAC:
3939 case SIOCSIFMAC:
3940 #endif /* CONFIG_MACF_NET */
3941 case SIOCSIFKPI:
3942 case SIOCGIFKPI:
3943 case SIOCGIFWAKEFLAGS:
3944 case SIOCGIFGETRTREFCNT:
3945 case SIOCGIFLINKQUALITYMETRIC:
3946 case SIOCSIFOPPORTUNISTIC:
3947 case SIOCGIFOPPORTUNISTIC:
3948 case SIOCSETROUTERMODE:
3949 case SIOCGIFEFLAGS:
3950 case SIOCSIFDESC:
3951 case SIOCGIFDESC:
3952 case SIOCSIFLINKPARAMS:
3953 case SIOCGIFLINKPARAMS:
3954 case SIOCGIFQUEUESTATS:
3955 case SIOCSIFTHROTTLE:
3956 case SIOCGIFTHROTTLE:
3957 case SIOCSIFLOG:
3958 case SIOCGIFLOG:
3959 case SIOCGIFDELEGATE:
3960 case SIOCGIFLLADDR:
3961 case SIOCGIFTYPE:
3962 ;
3963 }
3964 }