2 * Copyright (c) 2000-2011 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 * Copyright (c) 1982, 1986, 1991, 1993
30 * The Regents of the University of California. All rights reserved.
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
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.
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
60 * @(#)in.c 8.4 (Berkeley) 1/9/95
61 * $FreeBSD: src/sys/netinet/in.c,v 1.44.2.5 2001/08/13 16:26:17 ume Exp $
64 #include <sys/param.h>
65 #include <sys/systm.h>
66 #include <sys/sockio.h>
67 #include <sys/socketvar.h>
68 #include <sys/malloc.h>
70 #include <sys/socket.h>
71 #include <sys/kernel.h>
72 #include <sys/sysctl.h>
73 #include <sys/kern_event.h>
74 #include <sys/syslog.h>
75 #include <sys/mcache.h>
76 #include <kern/zalloc.h>
78 #include <pexpert/pexpert.h>
81 #include <net/if_types.h>
82 #include <net/route.h>
83 #include <net/kpi_protocol.h>
85 #include <netinet/in.h>
86 #include <netinet/in_var.h>
87 #include <netinet/in_pcb.h>
89 #include <netinet/igmp_var.h>
92 #include <netinet/ip_var.h>
94 #include <netinet/tcp.h>
95 #include <netinet/tcp_timer.h>
96 #include <netinet/tcp_var.h>
101 #include <net/pfvar.h>
104 static int in_mask2len(struct in_addr
*);
105 static void in_len2mask(struct in_addr
*, int);
106 static int in_lifaddr_ioctl(struct socket
*, u_long
, struct if_laddrreq
*,
107 struct ifnet
*, struct proc
*);
108 static int in_setrouter(struct ifnet
*, int);
110 static void in_socktrim(struct sockaddr_in
*);
111 static int in_ifinit(struct ifnet
*,
112 struct in_ifaddr
*, struct sockaddr_in
*, int);
114 #define IA_HASH_INIT(ia) { \
115 (ia)->ia_hash.tqe_next = (void *)(uintptr_t)-1; \
116 (ia)->ia_hash.tqe_prev = (void *)(uintptr_t)-1; \
119 #define IA_IS_HASHED(ia) \
120 (!((ia)->ia_hash.tqe_next == (void *)(uintptr_t)-1 || \
121 (ia)->ia_hash.tqe_prev == (void *)(uintptr_t)-1))
123 static void in_iahash_remove(struct in_ifaddr
*);
124 static void in_iahash_insert(struct in_ifaddr
*);
125 static void in_iahash_insert_ptp(struct in_ifaddr
*);
126 static struct in_ifaddr
*in_ifaddr_alloc(int);
127 static void in_ifaddr_attached(struct ifaddr
*);
128 static void in_ifaddr_detached(struct ifaddr
*);
129 static void in_ifaddr_free(struct ifaddr
*);
130 static void in_ifaddr_trace(struct ifaddr
*, int);
132 static int subnetsarelocal
= 0;
133 SYSCTL_INT(_net_inet_ip
, OID_AUTO
, subnets_are_local
, CTLFLAG_RW
| CTLFLAG_LOCKED
,
134 &subnetsarelocal
, 0, "");
136 /* Track whether or not the SIOCARPIPLL ioctl has been called */
137 __private_extern__ u_int32_t ipv4_ll_arp_aware
= 0;
139 #define INIFA_TRACE_HIST_SIZE 32 /* size of trace history */
142 __private_extern__
unsigned int inifa_trace_hist_size
= INIFA_TRACE_HIST_SIZE
;
144 struct in_ifaddr_dbg
{
145 struct in_ifaddr inifa
; /* in_ifaddr */
146 struct in_ifaddr inifa_old
; /* saved in_ifaddr */
147 u_int16_t inifa_refhold_cnt
; /* # of IFA_ADDREF */
148 u_int16_t inifa_refrele_cnt
; /* # of IFA_REMREF */
150 * Alloc and free callers.
152 ctrace_t inifa_alloc
;
155 * Circular lists of IFA_ADDREF and IFA_REMREF callers.
157 ctrace_t inifa_refhold
[INIFA_TRACE_HIST_SIZE
];
158 ctrace_t inifa_refrele
[INIFA_TRACE_HIST_SIZE
];
162 TAILQ_ENTRY(in_ifaddr_dbg
) inifa_trash_link
;
165 /* List of trash in_ifaddr entries protected by inifa_trash_lock */
166 static TAILQ_HEAD(, in_ifaddr_dbg
) inifa_trash_head
;
167 static decl_lck_mtx_data(, inifa_trash_lock
);
170 static unsigned int inifa_debug
= 1; /* debugging (enabled) */
172 static unsigned int inifa_debug
; /* debugging (disabled) */
174 static unsigned int inifa_size
; /* size of zone element */
175 static struct zone
*inifa_zone
; /* zone for in_ifaddr */
177 #define INIFA_ZONE_MAX 64 /* maximum elements in zone */
178 #define INIFA_ZONE_NAME "in_ifaddr" /* zone name */
181 * Return 1 if the address is
183 * - unicast or multicast link local
184 * - routed via a link level gateway
185 * - belongs to a directly connected (sub)net
188 inaddr_local(struct in_addr in
)
191 struct sockaddr_in sin
;
194 if (ntohl(in
.s_addr
) == INADDR_LOOPBACK
|| IN_LINKLOCAL(ntohl(in
.s_addr
))) {
196 } else if (ntohl(in
.s_addr
) >= INADDR_UNSPEC_GROUP
&&
197 ntohl(in
.s_addr
) <= INADDR_MAX_LOCAL_GROUP
) {
200 sin
.sin_family
= AF_INET
;
201 sin
.sin_len
= sizeof (sin
);
203 rt
= rtalloc1((struct sockaddr
*)&sin
, 0, 0);
207 if (rt
->rt_gateway
->sa_family
== AF_LINK
||
208 (rt
->rt_ifp
->if_flags
& IFF_LOOPBACK
))
213 local
= in_localaddr(in
);
220 * Return 1 if an internet address is for a ``local'' host
221 * (one to which we have a connection). If subnetsarelocal
222 * is true, this includes other subnets of the local net.
223 * Otherwise, it includes only the directly-connected (sub)nets.
226 in_localaddr(struct in_addr in
)
228 u_int32_t i
= ntohl(in
.s_addr
);
229 struct in_ifaddr
*ia
;
231 if (subnetsarelocal
) {
232 lck_rw_lock_shared(in_ifaddr_rwlock
);
233 for (ia
= in_ifaddrhead
.tqh_first
; ia
;
234 ia
= ia
->ia_link
.tqe_next
) {
235 IFA_LOCK(&ia
->ia_ifa
);
236 if ((i
& ia
->ia_netmask
) == ia
->ia_net
) {
237 IFA_UNLOCK(&ia
->ia_ifa
);
238 lck_rw_done(in_ifaddr_rwlock
);
241 IFA_UNLOCK(&ia
->ia_ifa
);
243 lck_rw_done(in_ifaddr_rwlock
);
245 lck_rw_lock_shared(in_ifaddr_rwlock
);
246 for (ia
= in_ifaddrhead
.tqh_first
; ia
;
247 ia
= ia
->ia_link
.tqe_next
) {
248 IFA_LOCK(&ia
->ia_ifa
);
249 if ((i
& ia
->ia_subnetmask
) == ia
->ia_subnet
) {
250 IFA_UNLOCK(&ia
->ia_ifa
);
251 lck_rw_done(in_ifaddr_rwlock
);
254 IFA_UNLOCK(&ia
->ia_ifa
);
256 lck_rw_done(in_ifaddr_rwlock
);
262 * Determine whether an IP address is in a reserved set of addresses
263 * that may not be forwarded, or whether datagrams to that destination
267 in_canforward(struct in_addr in
)
269 u_int32_t i
= ntohl(in
.s_addr
);
272 if (IN_EXPERIMENTAL(i
) || IN_MULTICAST(i
))
275 net
= i
& IN_CLASSA_NET
;
276 if (net
== 0 || net
== (IN_LOOPBACKNET
<< IN_CLASSA_NSHIFT
))
283 * Trim a mask in a sockaddr
286 in_socktrim(struct sockaddr_in
*ap
)
288 char *cplim
= (char *) &ap
->sin_addr
;
289 char *cp
= (char *) (&ap
->sin_addr
+ 1);
292 while (--cp
>= cplim
)
294 (ap
)->sin_len
= cp
- (char *) (ap
) + 1;
300 in_mask2len(struct in_addr
*mask
)
306 for (x
= 0; x
< sizeof(*mask
); x
++) {
311 if (x
< sizeof(*mask
)) {
312 for (y
= 0; y
< 8; y
++) {
313 if ((p
[x
] & (0x80 >> y
)) == 0)
321 in_len2mask(struct in_addr
*mask
, int len
)
327 bzero(mask
, sizeof(*mask
));
328 for (i
= 0; i
< len
/ 8; i
++)
331 p
[i
] = (0xff00 >> (len
% 8)) & 0xff;
334 static int in_interfaces
; /* number of external internet interfaces */
337 in_domifattach(struct ifnet
*ifp
)
341 if ((error
= proto_plumb(PF_INET
, ifp
)) && error
!= EEXIST
)
342 log(LOG_ERR
, "%s: proto_plumb returned %d if=%s%d\n",
343 __func__
, error
, ifp
->if_name
, ifp
->if_unit
);
349 * Generic internet control operations (ioctl's).
350 * Ifp is 0 if not an interface-specific ioctl.
362 * in_lifaddr_ioctl:???
365 * dlil_plumb_protocol:???
366 * dlil_unplumb_protocol:???
370 in_control(struct socket
*so
, u_long cmd
, caddr_t data
, struct ifnet
*ifp
,
373 struct in_ifaddr
*ia
= NULL
;
375 struct sockaddr_in oldaddr
;
377 int hostIsNew
, maskIsNew
;
378 struct kev_msg ev_msg
;
379 struct kev_in_data in_event_data
;
381 bzero(&in_event_data
, sizeof (struct kev_in_data
));
382 bzero(&ev_msg
, sizeof (struct kev_msg
));
385 case SIOCALIFADDR
: /* struct if_laddrreq */
386 case SIOCDLIFADDR
: /* struct if_laddrreq */
387 if ((error
= proc_suser(p
)) != 0)
390 case SIOCGLIFADDR
: { /* struct if_laddrreq */
391 struct if_laddrreq iflr
;
396 bcopy(data
, &iflr
, sizeof (iflr
));
397 error
= in_lifaddr_ioctl(so
, cmd
, &iflr
, ifp
, p
);
398 bcopy(&iflr
, data
, sizeof (iflr
));
404 * Find address for this interface, if it exists.
406 * If an alias address was specified, find that one instead of
407 * the first one on the interface.
410 struct in_ifaddr
*iap
;
411 struct sockaddr_in sin
;
413 bcopy(&((struct ifreq
*)(void *)data
)->ifr_addr
,
416 lck_rw_lock_shared(in_ifaddr_rwlock
);
417 for (iap
= in_ifaddrhead
.tqh_first
; iap
!= NULL
;
418 iap
= iap
->ia_link
.tqe_next
) {
419 if (iap
->ia_ifp
!= ifp
)
422 IFA_LOCK(&iap
->ia_ifa
);
423 if (sin
.sin_addr
.s_addr
==
424 iap
->ia_addr
.sin_addr
.s_addr
) {
426 IFA_UNLOCK(&iap
->ia_ifa
);
428 } else if (ia
== NULL
) {
430 if (sin
.sin_family
!= AF_INET
) {
431 IFA_UNLOCK(&iap
->ia_ifa
);
435 IFA_UNLOCK(&iap
->ia_ifa
);
437 /* take a reference on ia before releasing lock */
439 IFA_ADDREF(&ia
->ia_ifa
);
440 lck_rw_done(in_ifaddr_rwlock
);
444 case SIOCAUTOADDR
: /* struct ifreq */
445 case SIOCARPIPLL
: /* struct ifreq */
446 case SIOCSETROUTERMODE
: /* struct ifreq */
447 if ((error
= proc_suser(p
)) != 0) {
451 error
= EADDRNOTAVAIL
;
456 case SIOCAIFADDR
: /* struct ifaliasreq */
457 case SIOCDIFADDR
: { /* struct ifreq */
458 struct sockaddr_in addr
, dstaddr
;
461 error
= EADDRNOTAVAIL
;
465 if (cmd
== SIOCAIFADDR
) {
466 bcopy(&((struct in_aliasreq
*)(void *)data
)->
467 ifra_addr
, &addr
, sizeof (addr
));
468 bcopy(&((struct in_aliasreq
*)(void *)data
)->
469 ifra_dstaddr
, &dstaddr
, sizeof (dstaddr
));
471 VERIFY(cmd
== SIOCDIFADDR
);
472 bcopy(&((struct ifreq
*)(void *)data
)->ifr_addr
,
473 &addr
, sizeof (addr
));
474 bzero(&dstaddr
, sizeof (dstaddr
));
477 if (addr
.sin_family
== AF_INET
) {
478 struct in_ifaddr
*oia
;
480 lck_rw_lock_shared(in_ifaddr_rwlock
);
481 for (oia
= ia
; ia
; ia
= ia
->ia_link
.tqe_next
) {
482 IFA_LOCK(&ia
->ia_ifa
);
483 if (ia
->ia_ifp
== ifp
&&
484 ia
->ia_addr
.sin_addr
.s_addr
==
485 addr
.sin_addr
.s_addr
) {
486 IFA_ADDREF_LOCKED(&ia
->ia_ifa
);
487 IFA_UNLOCK(&ia
->ia_ifa
);
490 IFA_UNLOCK(&ia
->ia_ifa
);
492 lck_rw_done(in_ifaddr_rwlock
);
494 IFA_REMREF(&oia
->ia_ifa
);
495 if ((ifp
->if_flags
& IFF_POINTOPOINT
) &&
496 (cmd
== SIOCAIFADDR
) &&
497 (dstaddr
.sin_addr
.s_addr
== INADDR_ANY
)) {
498 error
= EDESTADDRREQ
;
501 } else if (cmd
== SIOCAIFADDR
) {
505 if (cmd
== SIOCDIFADDR
&& ia
== NULL
) {
506 error
= EADDRNOTAVAIL
;
511 case SIOCSIFADDR
: /* struct ifreq */
512 case SIOCSIFNETMASK
: /* struct ifreq */
513 case SIOCSIFDSTADDR
: { /* struct ifreq */
514 struct sockaddr_in addr
;
516 if (cmd
== SIOCAIFADDR
) {
517 /* fell thru from above; just repeat it */
518 bcopy(&((struct in_aliasreq
*)(void *)data
)->
519 ifra_addr
, &addr
, sizeof (addr
));
521 VERIFY(cmd
== SIOCDIFADDR
|| cmd
== SIOCSIFADDR
||
522 cmd
== SIOCSIFNETMASK
|| cmd
== SIOCSIFDSTADDR
);
523 bcopy(&((struct ifreq
*)(void *)data
)->ifr_addr
,
524 &addr
, sizeof (addr
));
527 /* socket is NULL if called from in_purgeaddrs() */
528 if (so
!= NULL
&& (so
->so_state
& SS_PRIV
) == 0) {
532 /* in case it's NULL, make sure it came from the kernel */
533 if (so
== NULL
&& p
!= kernproc
) {
538 error
= EADDRNOTAVAIL
;
541 if (addr
.sin_family
!= AF_INET
&& cmd
== SIOCSIFADDR
) {
546 ia
= in_ifaddr_alloc(M_WAITOK
);
551 ifnet_lock_exclusive(ifp
);
554 /* Hold a reference for this routine */
555 IFA_ADDREF_LOCKED(ifa
);
557 ifa
->ifa_addr
= (struct sockaddr
*)&ia
->ia_addr
;
558 ifa
->ifa_dstaddr
= (struct sockaddr
*)&ia
->ia_dstaddr
;
559 ifa
->ifa_netmask
= (struct sockaddr
*)&ia
->ia_sockmask
;
560 ia
->ia_sockmask
.sin_len
= 8;
561 if (ifp
->if_flags
& IFF_BROADCAST
) {
562 ia
->ia_broadaddr
.sin_len
= sizeof (ia
->ia_addr
);
563 ia
->ia_broadaddr
.sin_family
= AF_INET
;
566 if (!(ifp
->if_flags
& IFF_LOOPBACK
))
568 /* if_attach_ifa() holds a reference for ifa_link */
569 if_attach_ifa(ifp
, ifa
);
571 * If we have to go through in_ifinit(), make sure
572 * to avoid installing route(s) based on this address
573 * via PFC_IFUP event, before the link resolver (ARP)
576 if (cmd
== SIOCAIFADDR
|| cmd
== SIOCSIFADDR
)
577 ifa
->ifa_debug
|= IFD_NOTREADY
;
579 ifnet_lock_done(ifp
);
580 lck_rw_lock_exclusive(in_ifaddr_rwlock
);
581 /* Hold a reference for ia_link */
583 TAILQ_INSERT_TAIL(&in_ifaddrhead
, ia
, ia_link
);
584 lck_rw_done(in_ifaddr_rwlock
);
586 (void) in_domifattach(ifp
);
592 case SIOCPROTOATTACH
: /* struct ifreq */
593 case SIOCPROTODETACH
: /* struct ifreq */
594 if ((error
= proc_suser(p
)) != 0) {
598 error
= EADDRNOTAVAIL
;
603 case SIOCSIFBRDADDR
: /* struct ifreq */
604 if ((so
->so_state
& SS_PRIV
) == 0) {
609 case SIOCGIFADDR
: /* struct ifreq */
610 case SIOCGIFNETMASK
: /* struct ifreq */
611 case SIOCGIFDSTADDR
: /* struct ifreq */
612 case SIOCGIFBRDADDR
: /* struct ifreq */
614 error
= EADDRNOTAVAIL
;
621 case SIOCAUTOADDR
: { /* struct ifreq */
625 bcopy(&((struct ifreq
*)(void *)data
)->ifr_intval
,
626 &intval
, sizeof (intval
));
628 ifnet_lock_exclusive(ifp
);
631 * An interface in IPv4 router mode implies that it
632 * is configured with a static IP address and should
633 * not act as a DHCP client; prevent SIOCAUTOADDR from
634 * being set in that mode.
636 if (ifp
->if_eflags
& IFEF_IPV4_ROUTER
) {
637 intval
= 0; /* be safe; clear flag if set */
640 ifp
->if_eflags
|= IFEF_AUTOCONFIGURING
;
644 ifp
->if_eflags
&= ~IFEF_AUTOCONFIGURING
;
645 ifnet_lock_done(ifp
);
649 case SIOCARPIPLL
: { /* struct ifreq */
653 bcopy(&((struct ifreq
*)(void *)data
)->ifr_intval
,
654 &intval
, sizeof (intval
));
655 ipv4_ll_arp_aware
= 1;
657 ifnet_lock_exclusive(ifp
);
660 * An interface in IPv4 router mode implies that it
661 * is configured with a static IP address and should
662 * not have to deal with IPv4 Link-Local Address;
663 * prevent SIOCARPIPLL from being set in that mode.
665 if (ifp
->if_eflags
& IFEF_IPV4_ROUTER
) {
666 intval
= 0; /* be safe; clear flag if set */
669 ifp
->if_eflags
|= IFEF_ARPLL
;
673 ifp
->if_eflags
&= ~IFEF_ARPLL
;
674 ifnet_lock_done(ifp
);
678 case SIOCGIFADDR
: /* struct ifreq */
680 IFA_LOCK(&ia
->ia_ifa
);
681 bcopy(&ia
->ia_addr
, &((struct ifreq
*)(void *)data
)->ifr_addr
,
682 sizeof (struct sockaddr_in
));
683 IFA_UNLOCK(&ia
->ia_ifa
);
686 case SIOCGIFBRDADDR
: /* struct ifreq */
688 if ((ifp
->if_flags
& IFF_BROADCAST
) == 0) {
692 IFA_LOCK(&ia
->ia_ifa
);
693 bcopy(&ia
->ia_broadaddr
,
694 &((struct ifreq
*)(void *)data
)->ifr_broadaddr
,
695 sizeof (struct sockaddr_in
));
696 IFA_UNLOCK(&ia
->ia_ifa
);
699 case SIOCGIFDSTADDR
: /* struct ifreq */
701 if ((ifp
->if_flags
& IFF_POINTOPOINT
) == 0) {
705 IFA_LOCK(&ia
->ia_ifa
);
706 bcopy(&ia
->ia_dstaddr
,
707 &((struct ifreq
*)(void *)data
)->ifr_dstaddr
,
708 sizeof (struct sockaddr_in
));
709 IFA_UNLOCK(&ia
->ia_ifa
);
712 case SIOCGIFNETMASK
: /* struct ifreq */
714 IFA_LOCK(&ia
->ia_ifa
);
715 bcopy(&ia
->ia_sockmask
,
716 &((struct ifreq
*)(void *)data
)->ifr_addr
,
717 sizeof (struct sockaddr_in
));
718 IFA_UNLOCK(&ia
->ia_ifa
);
721 case SIOCSIFDSTADDR
: /* struct ifreq */
722 VERIFY(ifp
!= NULL
&& ia
!= NULL
);
723 if ((ifp
->if_flags
& IFF_POINTOPOINT
) == 0) {
727 IFA_LOCK(&ia
->ia_ifa
);
728 oldaddr
= ia
->ia_dstaddr
;
729 bcopy(&((struct ifreq
*)(void *)data
)->ifr_dstaddr
,
730 &ia
->ia_dstaddr
, sizeof (struct sockaddr_in
));
731 if (ia
->ia_dstaddr
.sin_family
== AF_INET
)
732 ia
->ia_dstaddr
.sin_len
= sizeof (struct sockaddr_in
);
733 IFA_UNLOCK(&ia
->ia_ifa
);
735 * NOTE: SIOCSIFDSTADDR is defined with struct ifreq
736 * as parameter, but here we are sending it down
737 * to the interface with a pointer to struct ifaddr,
738 * for legacy reasons.
740 error
= ifnet_ioctl(ifp
, PF_INET
, SIOCSIFDSTADDR
, ia
);
741 IFA_LOCK(&ia
->ia_ifa
);
742 if (error
== EOPNOTSUPP
) {
746 ia
->ia_dstaddr
= oldaddr
;
747 IFA_UNLOCK(&ia
->ia_ifa
);
750 IFA_LOCK_ASSERT_HELD(&ia
->ia_ifa
);
752 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
753 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
754 ev_msg
.kev_subclass
= KEV_INET_SUBCLASS
;
756 ev_msg
.event_code
= KEV_INET_SIFDSTADDR
;
758 if (ia
->ia_ifa
.ifa_dstaddr
) {
759 in_event_data
.ia_dstaddr
= ((struct sockaddr_in
*)
760 (void *)ia
->ia_ifa
.ifa_dstaddr
)->sin_addr
;
762 in_event_data
.ia_dstaddr
.s_addr
= INADDR_ANY
;
765 in_event_data
.ia_addr
= ia
->ia_addr
.sin_addr
;
766 in_event_data
.ia_net
= ia
->ia_net
;
767 in_event_data
.ia_netmask
= ia
->ia_netmask
;
768 in_event_data
.ia_subnet
= ia
->ia_subnet
;
769 in_event_data
.ia_subnetmask
= ia
->ia_subnetmask
;
770 in_event_data
.ia_netbroadcast
= ia
->ia_netbroadcast
;
771 IFA_UNLOCK(&ia
->ia_ifa
);
772 (void) strncpy(&in_event_data
.link_data
.if_name
[0],
773 ifp
->if_name
, IFNAMSIZ
);
774 in_event_data
.link_data
.if_family
= ifp
->if_family
;
775 in_event_data
.link_data
.if_unit
= (u_int32_t
) ifp
->if_unit
;
777 ev_msg
.dv
[0].data_ptr
= &in_event_data
;
778 ev_msg
.dv
[0].data_length
= sizeof (struct kev_in_data
);
779 ev_msg
.dv
[1].data_length
= 0;
781 kev_post_msg(&ev_msg
);
783 lck_mtx_lock(rnh_lock
);
784 IFA_LOCK(&ia
->ia_ifa
);
785 if (ia
->ia_flags
& IFA_ROUTE
) {
786 ia
->ia_ifa
.ifa_dstaddr
= (struct sockaddr
*)&oldaddr
;
787 IFA_UNLOCK(&ia
->ia_ifa
);
788 rtinit_locked(&(ia
->ia_ifa
), (int)RTM_DELETE
, RTF_HOST
);
789 IFA_LOCK(&ia
->ia_ifa
);
790 ia
->ia_ifa
.ifa_dstaddr
=
791 (struct sockaddr
*)&ia
->ia_dstaddr
;
792 IFA_UNLOCK(&ia
->ia_ifa
);
793 rtinit_locked(&(ia
->ia_ifa
), (int)RTM_ADD
,
796 IFA_UNLOCK(&ia
->ia_ifa
);
798 lck_mtx_unlock(rnh_lock
);
801 case SIOCSIFBRDADDR
: /* struct ifreq */
803 if ((ifp
->if_flags
& IFF_BROADCAST
) == 0) {
807 IFA_LOCK(&ia
->ia_ifa
);
808 bcopy(&((struct ifreq
*)(void *)data
)->ifr_broadaddr
,
809 &ia
->ia_broadaddr
, sizeof (struct sockaddr_in
));
811 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
812 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
813 ev_msg
.kev_subclass
= KEV_INET_SUBCLASS
;
815 ev_msg
.event_code
= KEV_INET_SIFBRDADDR
;
817 if (ia
->ia_ifa
.ifa_dstaddr
) {
818 in_event_data
.ia_dstaddr
= ((struct sockaddr_in
*)
819 (void *)ia
->ia_ifa
.ifa_dstaddr
)->sin_addr
;
821 in_event_data
.ia_dstaddr
.s_addr
= INADDR_ANY
;
823 in_event_data
.ia_addr
= ia
->ia_addr
.sin_addr
;
824 in_event_data
.ia_net
= ia
->ia_net
;
825 in_event_data
.ia_netmask
= ia
->ia_netmask
;
826 in_event_data
.ia_subnet
= ia
->ia_subnet
;
827 in_event_data
.ia_subnetmask
= ia
->ia_subnetmask
;
828 in_event_data
.ia_netbroadcast
= ia
->ia_netbroadcast
;
829 IFA_UNLOCK(&ia
->ia_ifa
);
830 (void) strncpy(&in_event_data
.link_data
.if_name
[0],
831 ifp
->if_name
, IFNAMSIZ
);
832 in_event_data
.link_data
.if_family
= ifp
->if_family
;
833 in_event_data
.link_data
.if_unit
= (u_int32_t
) ifp
->if_unit
;
835 ev_msg
.dv
[0].data_ptr
= &in_event_data
;
836 ev_msg
.dv
[0].data_length
= sizeof (struct kev_in_data
);
837 ev_msg
.dv
[1].data_length
= 0;
839 kev_post_msg(&ev_msg
);
842 case SIOCSIFADDR
: { /* struct ifreq */
843 struct sockaddr_in addr
;
845 VERIFY(ifp
!= NULL
&& ia
!= NULL
);
846 bcopy(&((struct ifreq
*)(void *)data
)->ifr_addr
,
847 &addr
, sizeof (addr
));
849 * If this is a new address, the reference count for the
850 * hash table has been taken at creation time above.
852 error
= in_ifinit(ifp
, ia
, &addr
, 1);
855 (void) pf_ifaddr_hook(ifp
, cmd
);
860 case SIOCPROTOATTACH
: /* struct ifreq */
862 error
= in_domifattach(ifp
);
865 case SIOCPROTODETACH
: /* struct ifreq */
868 * If an IPv4 address is still present, refuse to detach.
870 ifnet_lock_shared(ifp
);
871 TAILQ_FOREACH(ifa
, &ifp
->if_addrhead
, ifa_link
) {
873 if (ifa
->ifa_addr
->sa_family
== AF_INET
) {
879 ifnet_lock_done(ifp
);
885 error
= proto_unplumb(PF_INET
, ifp
);
888 case SIOCSETROUTERMODE
: { /* struct ifreq */
892 bcopy(&((struct ifreq
*)(void *)data
)->ifr_intval
,
893 &intval
, sizeof (intval
));
895 error
= in_setrouter(ifp
, intval
);
899 case SIOCSIFNETMASK
: { /* struct ifreq */
900 struct sockaddr_in addr
;
903 VERIFY(ifp
!= NULL
&& ia
!= NULL
);
904 bcopy(&((struct ifreq
*)(void *)data
)->ifr_addr
,
905 &addr
, sizeof (addr
));
906 i
= addr
.sin_addr
.s_addr
;
908 IFA_LOCK(&ia
->ia_ifa
);
909 ia
->ia_subnetmask
= ntohl(ia
->ia_sockmask
.sin_addr
.s_addr
= i
);
910 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
911 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
912 ev_msg
.kev_subclass
= KEV_INET_SUBCLASS
;
914 ev_msg
.event_code
= KEV_INET_SIFNETMASK
;
916 if (ia
->ia_ifa
.ifa_dstaddr
) {
917 in_event_data
.ia_dstaddr
= ((struct sockaddr_in
*)
918 (void *)ia
->ia_ifa
.ifa_dstaddr
)->sin_addr
;
920 in_event_data
.ia_dstaddr
.s_addr
= INADDR_ANY
;
922 in_event_data
.ia_addr
= ia
->ia_addr
.sin_addr
;
923 in_event_data
.ia_net
= ia
->ia_net
;
924 in_event_data
.ia_netmask
= ia
->ia_netmask
;
925 in_event_data
.ia_subnet
= ia
->ia_subnet
;
926 in_event_data
.ia_subnetmask
= ia
->ia_subnetmask
;
927 in_event_data
.ia_netbroadcast
= ia
->ia_netbroadcast
;
928 IFA_UNLOCK(&ia
->ia_ifa
);
929 (void) strncpy(&in_event_data
.link_data
.if_name
[0],
930 ifp
->if_name
, IFNAMSIZ
);
931 in_event_data
.link_data
.if_family
= ifp
->if_family
;
932 in_event_data
.link_data
.if_unit
= (u_int32_t
) ifp
->if_unit
;
934 ev_msg
.dv
[0].data_ptr
= &in_event_data
;
935 ev_msg
.dv
[0].data_length
= sizeof (struct kev_in_data
);
936 ev_msg
.dv
[1].data_length
= 0;
938 kev_post_msg(&ev_msg
);
942 case SIOCAIFADDR
: { /* struct ifaliasreq */
943 struct sockaddr_in addr
, broadaddr
, mask
;
945 VERIFY(ifp
!= NULL
&& ia
!= NULL
);
946 bcopy(&((struct ifaliasreq
*)(void *)data
)->ifra_addr
,
947 &addr
, sizeof (addr
));
948 bcopy(&((struct ifaliasreq
*)(void *)data
)->ifra_broadaddr
,
949 &broadaddr
, sizeof (broadaddr
));
950 bcopy(&((struct ifaliasreq
*)(void *)data
)->ifra_mask
,
951 &mask
, sizeof (mask
));
957 IFA_LOCK(&ia
->ia_ifa
);
958 if (ia
->ia_addr
.sin_family
== AF_INET
) {
959 if (addr
.sin_len
== 0) {
962 } else if (addr
.sin_addr
.s_addr
==
963 ia
->ia_addr
.sin_addr
.s_addr
) {
968 IFA_UNLOCK(&ia
->ia_ifa
);
969 in_ifscrub(ifp
, ia
, 0);
970 IFA_LOCK(&ia
->ia_ifa
);
971 ia
->ia_sockmask
= mask
;
973 ntohl(ia
->ia_sockmask
.sin_addr
.s_addr
);
976 if ((ifp
->if_flags
& IFF_POINTOPOINT
) &&
977 (broadaddr
.sin_family
== AF_INET
)) {
978 IFA_UNLOCK(&ia
->ia_ifa
);
979 in_ifscrub(ifp
, ia
, 0);
980 IFA_LOCK(&ia
->ia_ifa
);
981 ia
->ia_dstaddr
= broadaddr
;
982 ia
->ia_dstaddr
.sin_len
= sizeof (struct sockaddr_in
);
983 maskIsNew
= 1; /* We lie; but the effect's the same */
985 if (addr
.sin_family
== AF_INET
&& (hostIsNew
|| maskIsNew
)) {
986 IFA_UNLOCK(&ia
->ia_ifa
);
987 error
= in_ifinit(ifp
, ia
, &addr
, 0);
989 IFA_UNLOCK(&ia
->ia_ifa
);
993 (void) pf_ifaddr_hook(ifp
, cmd
);
995 IFA_LOCK(&ia
->ia_ifa
);
996 if ((ifp
->if_flags
& IFF_BROADCAST
) &&
997 (broadaddr
.sin_family
== AF_INET
))
998 ia
->ia_broadaddr
= broadaddr
;
1003 if ((error
== 0) || (error
== EEXIST
)) {
1004 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
1005 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
1006 ev_msg
.kev_subclass
= KEV_INET_SUBCLASS
;
1009 ev_msg
.event_code
= KEV_INET_NEW_ADDR
;
1011 ev_msg
.event_code
= KEV_INET_CHANGED_ADDR
;
1013 if (ia
->ia_ifa
.ifa_dstaddr
) {
1014 in_event_data
.ia_dstaddr
=
1015 ((struct sockaddr_in
*)(void *)ia
->
1016 ia_ifa
.ifa_dstaddr
)->sin_addr
;
1018 in_event_data
.ia_dstaddr
.s_addr
= INADDR_ANY
;
1020 in_event_data
.ia_addr
= ia
->ia_addr
.sin_addr
;
1021 in_event_data
.ia_net
= ia
->ia_net
;
1022 in_event_data
.ia_netmask
= ia
->ia_netmask
;
1023 in_event_data
.ia_subnet
= ia
->ia_subnet
;
1024 in_event_data
.ia_subnetmask
= ia
->ia_subnetmask
;
1025 in_event_data
.ia_netbroadcast
= ia
->ia_netbroadcast
;
1026 IFA_UNLOCK(&ia
->ia_ifa
);
1027 (void) strncpy(&in_event_data
.link_data
.if_name
[0],
1028 ifp
->if_name
, IFNAMSIZ
);
1029 in_event_data
.link_data
.if_family
= ifp
->if_family
;
1030 in_event_data
.link_data
.if_unit
= ifp
->if_unit
;
1032 ev_msg
.dv
[0].data_ptr
= &in_event_data
;
1033 ev_msg
.dv
[0].data_length
= sizeof (struct kev_in_data
);
1034 ev_msg
.dv
[1].data_length
= 0;
1036 kev_post_msg(&ev_msg
);
1038 IFA_UNLOCK(&ia
->ia_ifa
);
1043 case SIOCDIFADDR
: /* struct ifreq */
1044 VERIFY(ifp
!= NULL
&& ia
!= NULL
);
1045 error
= ifnet_ioctl(ifp
, PF_INET
, SIOCDIFADDR
, ia
);
1046 if (error
== EOPNOTSUPP
)
1052 /* Fill out the kernel event information */
1053 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
1054 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
1055 ev_msg
.kev_subclass
= KEV_INET_SUBCLASS
;
1057 ev_msg
.event_code
= KEV_INET_ADDR_DELETED
;
1059 IFA_LOCK(&ia
->ia_ifa
);
1060 if (ia
->ia_ifa
.ifa_dstaddr
) {
1061 in_event_data
.ia_dstaddr
= ((struct sockaddr_in
*)
1062 (void *)ia
->ia_ifa
.ifa_dstaddr
)->sin_addr
;
1064 in_event_data
.ia_dstaddr
.s_addr
= INADDR_ANY
;
1066 in_event_data
.ia_addr
= ia
->ia_addr
.sin_addr
;
1067 in_event_data
.ia_net
= ia
->ia_net
;
1068 in_event_data
.ia_netmask
= ia
->ia_netmask
;
1069 in_event_data
.ia_subnet
= ia
->ia_subnet
;
1070 in_event_data
.ia_subnetmask
= ia
->ia_subnetmask
;
1071 in_event_data
.ia_netbroadcast
= ia
->ia_netbroadcast
;
1072 IFA_UNLOCK(&ia
->ia_ifa
);
1073 (void) strncpy(&in_event_data
.link_data
.if_name
[0],
1074 ifp
->if_name
, IFNAMSIZ
);
1075 in_event_data
.link_data
.if_family
= ifp
->if_family
;
1076 in_event_data
.link_data
.if_unit
= (u_int32_t
) ifp
->if_unit
;
1078 ev_msg
.dv
[0].data_ptr
= &in_event_data
;
1079 ev_msg
.dv
[0].data_length
= sizeof(struct kev_in_data
);
1080 ev_msg
.dv
[1].data_length
= 0;
1083 lck_rw_lock_exclusive(in_ifaddr_rwlock
);
1084 /* Release ia_link reference */
1086 TAILQ_REMOVE(&in_ifaddrhead
, ia
, ia_link
);
1088 if (IA_IS_HASHED(ia
))
1089 in_iahash_remove(ia
);
1091 lck_rw_done(in_ifaddr_rwlock
);
1094 * in_ifscrub kills the interface route.
1096 in_ifscrub(ifp
, ia
, 0);
1097 ifnet_lock_exclusive(ifp
);
1099 /* if_detach_ifa() releases ifa_link reference */
1100 if_detach_ifa(ifp
, ifa
);
1101 /* Our reference to this address is dropped at the bottom */
1105 * If the interface supports multicast, and no address is left,
1106 * remove the "all hosts" multicast group from that interface.
1108 if ((ifp
->if_flags
& IFF_MULTICAST
) != 0 ||
1109 ifp
->if_allhostsinm
!= NULL
) {
1111 TAILQ_FOREACH(ifa
, &ifp
->if_addrhead
, ifa_link
) {
1113 if (ifa
->ifa_addr
->sa_family
== AF_INET
) {
1119 ifnet_lock_done(ifp
);
1121 lck_mtx_lock(&ifp
->if_addrconfig_lock
);
1122 if (ifa
== NULL
&& ifp
->if_allhostsinm
!= NULL
) {
1123 struct in_multi
*inm
= ifp
->if_allhostsinm
;
1124 ifp
->if_allhostsinm
= NULL
;
1127 /* release the reference for allhostsinm */
1130 lck_mtx_unlock(&ifp
->if_addrconfig_lock
);
1132 ifnet_lock_done(ifp
);
1135 /* Post the kernel event */
1136 kev_post_msg(&ev_msg
);
1139 * See if there is any IPV4 address left and if so,
1140 * reconfigure KDP to use current primary address.
1142 ifa
= ifa_ifpgetprimary(ifp
, AF_INET
);
1145 * NOTE: SIOCSIFADDR is defined with struct ifreq
1146 * as parameter, but here we are sending it down
1147 * to the interface with a pointer to struct ifaddr,
1148 * for legacy reasons.
1150 error
= ifnet_ioctl(ifp
, PF_INET
, SIOCSIFADDR
, ifa
);
1151 if (error
== EOPNOTSUPP
)
1154 /* Release reference from ifa_ifpgetprimary() */
1158 (void) pf_ifaddr_hook(ifp
, cmd
);
1163 case SIOCSETOT
: { /* int */
1165 * Inspiration from tcp_ctloutput() and ip_ctloutput()
1166 * Special ioctl for OpenTransport sockets
1168 struct inpcb
*inp
, *cloned_inp
;
1172 bcopy(data
, &cloned_fd
, sizeof (cloned_fd
));
1174 inp
= sotoinpcb(so
);
1179 /* let's make sure it's either -1 or a valid file descriptor */
1180 if (cloned_fd
!= -1) {
1181 struct socket
*cloned_so
;
1182 error2
= file_socket(cloned_fd
, &cloned_so
);
1186 cloned_inp
= sotoinpcb(cloned_so
);
1187 file_drop(cloned_fd
);
1192 if (cloned_inp
== NULL
) {
1193 /* OT always uses IP_PORTRANGE_HIGH */
1194 inp
->inp_flags
&= ~(INP_LOWPORT
);
1195 inp
->inp_flags
|= INP_HIGHPORT
;
1197 * For UDP, OT allows broadcast by default;
1198 * for TCP we want to see MSG_OOB when we
1199 * receive urgent data.
1201 if (so
->so_type
== SOCK_DGRAM
)
1202 so
->so_options
|= SO_BROADCAST
;
1203 else if (so
->so_type
== SOCK_STREAM
)
1204 so
->so_options
|= SO_WANTOOBFLAG
;
1206 inp
->inp_ip_tos
= cloned_inp
->inp_ip_tos
;
1207 inp
->inp_ip_ttl
= cloned_inp
->inp_ip_ttl
;
1208 inp
->inp_flags
= cloned_inp
->inp_flags
;
1210 /* Multicast options */
1211 if (cloned_inp
->inp_moptions
!= NULL
)
1212 error2
= imo_clone(cloned_inp
, inp
);
1216 #endif /* __APPLE__ */
1223 IFA_REMREF(&ia
->ia_ifa
);
1230 * SIOCGLIFADDR: get first address. (?!?)
1231 * SIOCGLIFADDR with IFLR_PREFIX:
1232 * get first address that matches the specified prefix.
1233 * SIOCALIFADDR: add the specified address.
1234 * SIOCALIFADDR with IFLR_PREFIX:
1235 * EINVAL since we can't deduce hostid part of the address.
1236 * SIOCDLIFADDR: delete the specified address.
1237 * SIOCDLIFADDR with IFLR_PREFIX:
1238 * delete the first address that matches the specified prefix.
1240 * EINVAL on invalid parameters
1241 * EADDRNOTAVAIL on prefix match failed/specified address not found
1242 * other values may be returned from in_ioctl()
1245 in_lifaddr_ioctl(struct socket
*so
, u_long cmd
, struct if_laddrreq
*iflr
,
1246 struct ifnet
*ifp
, struct proc
*p
)
1250 VERIFY(ifp
!= NULL
);
1254 /* address must be specified on GET with IFLR_PREFIX */
1255 if ((iflr
->flags
& IFLR_PREFIX
) == 0)
1260 /* address must be specified on ADD and DELETE */
1261 if (iflr
->addr
.ss_family
!= AF_INET
)
1263 if (iflr
->addr
.ss_len
!= sizeof(struct sockaddr_in
))
1265 /* XXX need improvement */
1266 if (iflr
->dstaddr
.ss_family
1267 && iflr
->dstaddr
.ss_family
!= AF_INET
)
1269 if (iflr
->dstaddr
.ss_family
1270 && iflr
->dstaddr
.ss_len
!= sizeof(struct sockaddr_in
))
1273 default: /*shouldn't happen*/
1276 if (sizeof(struct in_addr
) * 8 < iflr
->prefixlen
)
1282 struct in_aliasreq ifra
;
1284 if (iflr
->flags
& IFLR_PREFIX
)
1287 /* copy args to in_aliasreq, perform ioctl(SIOCAIFADDR_IN6). */
1288 bzero(&ifra
, sizeof(ifra
));
1289 bcopy(iflr
->iflr_name
, ifra
.ifra_name
,
1290 sizeof(ifra
.ifra_name
));
1292 bcopy(&iflr
->addr
, &ifra
.ifra_addr
, iflr
->addr
.ss_len
);
1294 if (iflr
->dstaddr
.ss_family
) { /*XXX*/
1295 bcopy(&iflr
->dstaddr
, &ifra
.ifra_dstaddr
,
1296 iflr
->dstaddr
.ss_len
);
1299 ifra
.ifra_mask
.sin_family
= AF_INET
;
1300 ifra
.ifra_mask
.sin_len
= sizeof(struct sockaddr_in
);
1301 in_len2mask(&ifra
.ifra_mask
.sin_addr
, iflr
->prefixlen
);
1303 return in_control(so
, SIOCAIFADDR
, (caddr_t
)&ifra
, ifp
, p
);
1308 struct in_ifaddr
*ia
;
1309 struct in_addr mask
, candidate
;
1310 struct in_addr match
= { 0 };
1311 struct sockaddr_in
*sin
;
1314 bzero(&mask
, sizeof(mask
));
1315 if (iflr
->flags
& IFLR_PREFIX
) {
1316 /* lookup a prefix rather than address. */
1317 in_len2mask(&mask
, iflr
->prefixlen
);
1319 sin
= (struct sockaddr_in
*)&iflr
->addr
;
1320 match
.s_addr
= sin
->sin_addr
.s_addr
;
1321 match
.s_addr
&= mask
.s_addr
;
1323 /* if you set extra bits, that's wrong */
1324 if (match
.s_addr
!= sin
->sin_addr
.s_addr
)
1329 if (cmd
== SIOCGLIFADDR
) {
1330 /* on getting an address, take the 1st match */
1333 /* on deleting an address, do exact match */
1334 in_len2mask(&mask
, 32);
1335 sin
= (struct sockaddr_in
*)&iflr
->addr
;
1336 match
.s_addr
= sin
->sin_addr
.s_addr
;
1342 ifnet_lock_shared(ifp
);
1343 TAILQ_FOREACH(ifa
, &ifp
->if_addrhead
, ifa_link
) {
1345 if (ifa
->ifa_addr
->sa_family
!= AF_INET6
) {
1353 candidate
.s_addr
= ((struct sockaddr_in
*)&ifa
->ifa_addr
)->sin_addr
.s_addr
;
1354 candidate
.s_addr
&= mask
.s_addr
;
1356 if (candidate
.s_addr
== match
.s_addr
)
1361 ifnet_lock_done(ifp
);
1363 return EADDRNOTAVAIL
;
1364 ia
= (struct in_ifaddr
*)ifa
;
1366 if (cmd
== SIOCGLIFADDR
) {
1368 /* fill in the if_laddrreq structure */
1369 bcopy(&ia
->ia_addr
, &iflr
->addr
, ia
->ia_addr
.sin_len
);
1371 if ((ifp
->if_flags
& IFF_POINTOPOINT
) != 0) {
1372 bcopy(&ia
->ia_dstaddr
, &iflr
->dstaddr
,
1373 ia
->ia_dstaddr
.sin_len
);
1375 bzero(&iflr
->dstaddr
, sizeof(iflr
->dstaddr
));
1378 in_mask2len(&ia
->ia_sockmask
.sin_addr
);
1380 iflr
->flags
= 0; /*XXX*/
1386 struct in_aliasreq ifra
;
1388 /* fill in_aliasreq and do ioctl(SIOCDIFADDR_IN6) */
1389 bzero(&ifra
, sizeof(ifra
));
1390 bcopy(iflr
->iflr_name
, ifra
.ifra_name
,
1391 sizeof(ifra
.ifra_name
));
1394 bcopy(&ia
->ia_addr
, &ifra
.ifra_addr
,
1395 ia
->ia_addr
.sin_len
);
1396 if ((ifp
->if_flags
& IFF_POINTOPOINT
) != 0) {
1397 bcopy(&ia
->ia_dstaddr
, &ifra
.ifra_dstaddr
,
1398 ia
->ia_dstaddr
.sin_len
);
1400 bcopy(&ia
->ia_sockmask
, &ifra
.ifra_dstaddr
,
1401 ia
->ia_sockmask
.sin_len
);
1404 return in_control(so
, SIOCDIFADDR
, (caddr_t
)&ifra
,
1410 return EOPNOTSUPP
; /*just for safety*/
1414 * Handle SIOCSETROUTERMODE to set or clear the IPv4 router mode flag on
1415 * the interface. When in this mode, IPv4 Link-Local Address support is
1416 * disabled in ARP, and DHCP client support is disabled in IP input; turning
1417 * any of them on would cause an error to be returned. Entering or exiting
1418 * this mode will result in the removal of IPv4 addresses currently configured
1422 in_setrouter(struct ifnet
*ifp
, int enable
)
1424 if (ifp
->if_flags
& IFF_LOOPBACK
)
1427 ifnet_lock_exclusive(ifp
);
1429 ifp
->if_eflags
|= IFEF_IPV4_ROUTER
;
1430 ifp
->if_eflags
&= ~(IFEF_ARPLL
| IFEF_AUTOCONFIGURING
);
1432 ifp
->if_eflags
&= ~IFEF_IPV4_ROUTER
;
1434 ifnet_lock_done(ifp
);
1436 /* purge all IPv4 addresses configured on this interface */
1443 * Delete any existing route for an interface.
1446 in_ifscrub(struct ifnet
*ifp
, struct in_ifaddr
*ia
, int locked
)
1448 IFA_LOCK(&ia
->ia_ifa
);
1449 if ((ia
->ia_flags
& IFA_ROUTE
) == 0) {
1450 IFA_UNLOCK(&ia
->ia_ifa
);
1453 IFA_UNLOCK(&ia
->ia_ifa
);
1455 lck_mtx_lock(rnh_lock
);
1456 if (ifp
->if_flags
& (IFF_LOOPBACK
|IFF_POINTOPOINT
))
1457 rtinit_locked(&(ia
->ia_ifa
), (int)RTM_DELETE
, RTF_HOST
);
1459 rtinit_locked(&(ia
->ia_ifa
), (int)RTM_DELETE
, 0);
1460 IFA_LOCK(&ia
->ia_ifa
);
1461 ia
->ia_flags
&= ~IFA_ROUTE
;
1462 IFA_UNLOCK(&ia
->ia_ifa
);
1464 lck_mtx_unlock(rnh_lock
);
1468 * Caller must hold in_ifaddr_rwlock as writer.
1471 in_iahash_remove(struct in_ifaddr
*ia
)
1473 lck_rw_assert(in_ifaddr_rwlock
, LCK_RW_ASSERT_EXCLUSIVE
);
1474 IFA_LOCK_ASSERT_HELD(&ia
->ia_ifa
);
1476 if (!IA_IS_HASHED(ia
)) {
1477 panic("attempt to remove wrong ia %p from hash table\n", ia
);
1480 TAILQ_REMOVE(INADDR_HASH(ia
->ia_addr
.sin_addr
.s_addr
), ia
, ia_hash
);
1482 if (IFA_REMREF_LOCKED(&ia
->ia_ifa
) == NULL
) {
1483 panic("%s: unexpected (missing) refcnt ifa=%p", __func__
,
1490 * Caller must hold in_ifaddr_rwlock as writer.
1493 in_iahash_insert(struct in_ifaddr
*ia
)
1495 lck_rw_assert(in_ifaddr_rwlock
, LCK_RW_ASSERT_EXCLUSIVE
);
1496 IFA_LOCK_ASSERT_HELD(&ia
->ia_ifa
);
1498 if (ia
->ia_addr
.sin_family
!= AF_INET
) {
1499 panic("attempt to insert wrong ia %p into hash table\n", ia
);
1501 } else if (IA_IS_HASHED(ia
)) {
1502 panic("attempt to double-insert ia %p into hash table\n", ia
);
1505 TAILQ_INSERT_HEAD(INADDR_HASH(ia
->ia_addr
.sin_addr
.s_addr
), ia
, ia_hash
);
1506 IFA_ADDREF_LOCKED(&ia
->ia_ifa
);
1510 * Some point to point interfaces that are tunnels
1511 * borrow the address from an underlying interface (e.g.
1512 * VPN server). In order for source address selection logic to
1513 * find the underlying interface first, we add the address
1514 * of borrowing point to point interfaces at the end of the list.
1515 * (see rdar://6733789)
1517 * Caller must hold in_ifaddr_rwlock as writer.
1520 in_iahash_insert_ptp(struct in_ifaddr
*ia
)
1522 struct in_ifaddr
*tmp_ifa
;
1523 struct ifnet
*tmp_ifp
;
1525 lck_rw_assert(in_ifaddr_rwlock
, LCK_RW_ASSERT_EXCLUSIVE
);
1526 IFA_LOCK_ASSERT_HELD(&ia
->ia_ifa
);
1528 if (ia
->ia_addr
.sin_family
!= AF_INET
) {
1529 panic("attempt to insert wrong ia %p into hash table\n", ia
);
1531 } else if (IA_IS_HASHED(ia
)) {
1532 panic("attempt to double-insert ia %p into hash table\n", ia
);
1535 IFA_UNLOCK(&ia
->ia_ifa
);
1536 TAILQ_FOREACH(tmp_ifa
, INADDR_HASH(ia
->ia_addr
.sin_addr
.s_addr
),
1538 IFA_LOCK(&tmp_ifa
->ia_ifa
);
1539 /* ia->ia_addr won't change, so check without lock */
1540 if (IA_SIN(tmp_ifa
)->sin_addr
.s_addr
==
1541 ia
->ia_addr
.sin_addr
.s_addr
) {
1542 IFA_UNLOCK(&tmp_ifa
->ia_ifa
);
1545 IFA_UNLOCK(&tmp_ifa
->ia_ifa
);
1547 tmp_ifp
= (tmp_ifa
== NULL
) ? NULL
: tmp_ifa
->ia_ifp
;
1549 IFA_LOCK(&ia
->ia_ifa
);
1550 if (tmp_ifp
== NULL
) {
1551 TAILQ_INSERT_HEAD(INADDR_HASH(ia
->ia_addr
.sin_addr
.s_addr
),
1554 TAILQ_INSERT_TAIL(INADDR_HASH(ia
->ia_addr
.sin_addr
.s_addr
),
1557 IFA_ADDREF_LOCKED(&ia
->ia_ifa
);
1561 * Initialize an interface's internet address
1562 * and routing table entry.
1567 struct in_ifaddr
*ia
,
1568 struct sockaddr_in
*sin
,
1571 u_int32_t i
= ntohl(sin
->sin_addr
.s_addr
);
1572 struct sockaddr_in oldaddr
;
1573 int flags
= RTF_UP
, error
;
1574 struct ifaddr
*ifa0
;
1578 /* Take an extra reference for this routine */
1579 IFA_ADDREF(&ia
->ia_ifa
);
1581 lck_rw_lock_exclusive(in_ifaddr_rwlock
);
1582 IFA_LOCK(&ia
->ia_ifa
);
1583 oldaddr
= ia
->ia_addr
;
1584 if (IA_IS_HASHED(ia
)) {
1586 in_iahash_remove(ia
);
1589 ia
->ia_addr
.sin_len
= sizeof (*sin
);
1590 if ((ifp
->if_flags
& IFF_POINTOPOINT
))
1591 in_iahash_insert_ptp(ia
);
1593 in_iahash_insert(ia
);
1594 IFA_UNLOCK(&ia
->ia_ifa
);
1595 lck_rw_done(in_ifaddr_rwlock
);
1598 * Give the interface a chance to initialize if this is its first
1599 * address, and to validate the address if necessary. Send down
1600 * SIOCSIFADDR for first address, and SIOCAIFADDR for alias(es).
1601 * We find the first IPV4 address assigned to it and check if this
1602 * is the same as the one passed into this routine.
1604 ifa0
= ifa_ifpgetprimary(ifp
, AF_INET
);
1605 cmd
= (&ia
->ia_ifa
== ifa0
) ? SIOCSIFADDR
: SIOCAIFADDR
;
1606 error
= ifnet_ioctl(ifp
, PF_INET
, cmd
, ia
);
1607 if (error
== EOPNOTSUPP
)
1610 * If we've just sent down SIOCAIFADDR, send another ioctl down
1611 * for SIOCSIFADDR for the first IPV4 address of the interface,
1612 * because an address change on one of the addresses will result
1613 * in the removal of the previous first IPV4 address. KDP needs
1614 * be reconfigured with the current primary IPV4 address.
1616 if (error
== 0 && cmd
== SIOCAIFADDR
) {
1618 * NOTE: SIOCSIFADDR is defined with struct ifreq
1619 * as parameter, but here we are sending it down
1620 * to the interface with a pointer to struct ifaddr,
1621 * for legacy reasons.
1623 error
= ifnet_ioctl(ifp
, PF_INET
, SIOCSIFADDR
, ifa0
);
1624 if (error
== EOPNOTSUPP
)
1628 /* Release reference from ifa_ifpgetprimary() */
1632 lck_rw_lock_exclusive(in_ifaddr_rwlock
);
1633 IFA_LOCK(&ia
->ia_ifa
);
1634 if (IA_IS_HASHED(ia
))
1635 in_iahash_remove(ia
);
1636 ia
->ia_addr
= oldaddr
;
1638 if ((ifp
->if_flags
& IFF_POINTOPOINT
))
1639 in_iahash_insert_ptp(ia
);
1641 in_iahash_insert(ia
);
1643 IFA_UNLOCK(&ia
->ia_ifa
);
1644 lck_rw_done(in_ifaddr_rwlock
);
1645 /* Release extra reference taken above */
1646 IFA_REMREF(&ia
->ia_ifa
);
1649 lck_mtx_lock(rnh_lock
);
1650 IFA_LOCK(&ia
->ia_ifa
);
1652 * Address has been initialized by the link resolver (ARP)
1653 * via ifnet_ioctl() above; it may now generate route(s).
1655 ia
->ia_ifa
.ifa_debug
&= ~IFD_NOTREADY
;
1657 ia
->ia_ifa
.ifa_addr
= (struct sockaddr
*)&oldaddr
;
1658 IFA_UNLOCK(&ia
->ia_ifa
);
1659 in_ifscrub(ifp
, ia
, 1);
1660 IFA_LOCK(&ia
->ia_ifa
);
1661 ia
->ia_ifa
.ifa_addr
= (struct sockaddr
*)&ia
->ia_addr
;
1663 IFA_LOCK_ASSERT_HELD(&ia
->ia_ifa
);
1665 ia
->ia_netmask
= IN_CLASSA_NET
;
1666 else if (IN_CLASSB(i
))
1667 ia
->ia_netmask
= IN_CLASSB_NET
;
1669 ia
->ia_netmask
= IN_CLASSC_NET
;
1671 * The subnet mask usually includes at least the standard network part,
1672 * but may may be smaller in the case of supernetting.
1673 * If it is set, we believe it.
1675 if (ia
->ia_subnetmask
== 0) {
1676 ia
->ia_subnetmask
= ia
->ia_netmask
;
1677 ia
->ia_sockmask
.sin_addr
.s_addr
= htonl(ia
->ia_subnetmask
);
1679 ia
->ia_netmask
&= ia
->ia_subnetmask
;
1680 ia
->ia_net
= i
& ia
->ia_netmask
;
1681 ia
->ia_subnet
= i
& ia
->ia_subnetmask
;
1682 in_socktrim(&ia
->ia_sockmask
);
1684 * Add route for the network.
1686 ia
->ia_ifa
.ifa_metric
= ifp
->if_metric
;
1687 if (ifp
->if_flags
& IFF_BROADCAST
) {
1688 ia
->ia_broadaddr
.sin_addr
.s_addr
=
1689 htonl(ia
->ia_subnet
| ~ia
->ia_subnetmask
);
1690 ia
->ia_netbroadcast
.s_addr
=
1691 htonl(ia
->ia_net
| ~ ia
->ia_netmask
);
1692 } else if (ifp
->if_flags
& IFF_LOOPBACK
) {
1693 ia
->ia_ifa
.ifa_dstaddr
= ia
->ia_ifa
.ifa_addr
;
1695 } else if (ifp
->if_flags
& IFF_POINTOPOINT
) {
1696 if (ia
->ia_dstaddr
.sin_family
!= AF_INET
) {
1697 IFA_UNLOCK(&ia
->ia_ifa
);
1698 lck_mtx_unlock(rnh_lock
);
1699 /* Release extra reference taken above */
1700 IFA_REMREF(&ia
->ia_ifa
);
1703 ia
->ia_dstaddr
.sin_len
= sizeof (*sin
);
1706 IFA_UNLOCK(&ia
->ia_ifa
);
1707 if ((error
= rtinit_locked(&(ia
->ia_ifa
), (int)RTM_ADD
, flags
)) == 0) {
1708 IFA_LOCK(&ia
->ia_ifa
);
1709 ia
->ia_flags
|= IFA_ROUTE
;
1710 IFA_UNLOCK(&ia
->ia_ifa
);
1712 lck_mtx_unlock(rnh_lock
);
1714 /* XXX check if the subnet route points to the same interface */
1715 if (error
== EEXIST
)
1719 * If the interface supports multicast, join the "all hosts"
1720 * multicast group on that interface.
1722 if (ifp
->if_flags
& IFF_MULTICAST
) {
1723 struct in_addr addr
;
1725 lck_mtx_lock(&ifp
->if_addrconfig_lock
);
1726 addr
.s_addr
= htonl(INADDR_ALLHOSTS_GROUP
);
1727 if (ifp
->if_allhostsinm
== NULL
) {
1728 struct in_multi
*inm
;
1729 inm
= in_addmulti(&addr
, ifp
);
1732 /* keep the reference on inm added by
1733 * in_addmulti above for storing the
1734 * pointer in allhostsinm
1736 ifp
->if_allhostsinm
= inm
;
1738 printf("Failed to add membership to all-hosts multicast address on interface %s%d\n", ifp
->if_name
, ifp
->if_unit
);
1741 lck_mtx_unlock(&ifp
->if_addrconfig_lock
);
1744 /* Release extra reference taken above */
1745 IFA_REMREF(&ia
->ia_ifa
);
1751 * Return 1 if the address might be a local broadcast address.
1754 in_broadcast(struct in_addr in
, struct ifnet
*ifp
)
1759 if (in
.s_addr
== INADDR_BROADCAST
|| in
.s_addr
== INADDR_ANY
)
1761 if ((ifp
->if_flags
& IFF_BROADCAST
) == 0)
1763 t
= ntohl(in
.s_addr
);
1765 * Look through the list of addresses for a match
1766 * with a broadcast address.
1768 #define ia ((struct in_ifaddr *)ifa)
1769 ifnet_lock_shared(ifp
);
1770 TAILQ_FOREACH(ifa
, &ifp
->if_addrhead
, ifa_link
) {
1772 if (ifa
->ifa_addr
->sa_family
== AF_INET
&&
1773 (in
.s_addr
== ia
->ia_broadaddr
.sin_addr
.s_addr
||
1774 in
.s_addr
== ia
->ia_netbroadcast
.s_addr
||
1776 * Check for old-style (host 0) broadcast.
1778 t
== ia
->ia_subnet
|| t
== ia
->ia_net
) &&
1780 * Check for an all one subnetmask. These
1781 * only exist when an interface gets a secondary
1784 ia
->ia_subnetmask
!= (u_int32_t
)0xffffffff) {
1786 ifnet_lock_done(ifp
);
1791 ifnet_lock_done(ifp
);
1797 in_purgeaddrs(struct ifnet
*ifp
)
1799 struct ifaddr
**ifap
;
1803 * Be nice, and try the civilized way first. If we can't get
1804 * rid of them this way, then do it the rough way. We must
1805 * only get here during detach time, after the ifnet has been
1806 * removed from the global list and arrays.
1808 err
= ifnet_get_address_list_family_internal(ifp
, &ifap
, AF_INET
, 1,
1810 if (err
== 0 && ifap
!= NULL
) {
1811 for (i
= 0; ifap
[i
] != NULL
; i
++) {
1812 struct ifaliasreq ifr
;
1816 bzero(&ifr
, sizeof (ifr
));
1818 ifr
.ifra_addr
= *ifa
->ifa_addr
;
1819 if (ifa
->ifa_dstaddr
!= NULL
)
1820 ifr
.ifra_broadaddr
= *ifa
->ifa_dstaddr
;
1822 err
= in_control(NULL
, SIOCDIFADDR
, (caddr_t
)&ifr
, ifp
,
1824 /* if we lost the race, ignore it */
1825 if (err
== EADDRNOTAVAIL
)
1828 char s_addr
[MAX_IPv4_STR_LEN
];
1829 char s_dstaddr
[MAX_IPv4_STR_LEN
];
1830 struct in_addr
*s
, *d
;
1833 s
= &((struct sockaddr_in
*)
1834 (void *)ifa
->ifa_addr
)->sin_addr
;
1835 d
= &((struct sockaddr_in
*)
1836 (void *)ifa
->ifa_dstaddr
)->sin_addr
;
1837 (void) inet_ntop(AF_INET
, &s
->s_addr
, s_addr
,
1839 (void) inet_ntop(AF_INET
, &d
->s_addr
, s_dstaddr
,
1840 sizeof (s_dstaddr
));
1843 printf("%s: SIOCDIFADDR ifp=%p ifa_addr=%s "
1844 "ifa_dstaddr=%s (err=%d)\n", __func__
, ifp
,
1845 s_addr
, s_dstaddr
, err
);
1848 ifnet_free_address_list(ifap
);
1849 } else if (err
!= 0 && err
!= ENXIO
) {
1850 printf("%s: error retrieving list of AF_INET addresses for "
1851 "ifp=%p (err=%d)\n", __func__
, ifp
, err
);
1855 int inet_aton(char *cp
, struct in_addr
*pin
);
1857 inet_aton(char * cp
, struct in_addr
* pin
)
1859 u_char
* b
= (unsigned char *)pin
;
1863 for (p
= cp
, i
= 0; i
< 4; i
++) {
1864 u_int32_t l
= strtoul(p
, 0, 0);
1869 if (i
< 3 && p
== NULL
)
1876 int inet_ntoa2(struct in_addr
* pin
, char * cp
, const int len
);
1877 int inet_ntoa2(struct in_addr
* pin
, char * cp
, const int len
)
1881 /* address is in network byte order */
1882 ret
= snprintf(cp
, len
, "%u.%u.%u.%u", pin
->s_addr
& 0xFF,
1883 (pin
->s_addr
>> 8) & 0xFF, (pin
->s_addr
>> 16) & 0xFF,
1884 (pin
->s_addr
>> 24) & 0xFF);
1886 return ret
< len
? TRUE
: FALSE
;
1890 * Called as part of ip_init
1893 in_ifaddr_init(void)
1897 PE_parse_boot_argn("ifa_debug", &inifa_debug
, sizeof (inifa_debug
));
1899 inifa_size
= (inifa_debug
== 0) ? sizeof (struct in_ifaddr
) :
1900 sizeof (struct in_ifaddr_dbg
);
1902 inifa_zone
= zinit(inifa_size
, INIFA_ZONE_MAX
* inifa_size
,
1903 0, INIFA_ZONE_NAME
);
1904 if (inifa_zone
== NULL
) {
1905 panic("%s: failed allocating %s", __func__
, INIFA_ZONE_NAME
);
1908 zone_change(inifa_zone
, Z_EXPAND
, TRUE
);
1909 zone_change(inifa_zone
, Z_CALLERACCT
, FALSE
);
1911 lck_mtx_init(&inifa_trash_lock
, ifa_mtx_grp
, ifa_mtx_attr
);
1912 TAILQ_INIT(&inifa_trash_head
);
1915 static struct in_ifaddr
*
1916 in_ifaddr_alloc(int how
)
1918 struct in_ifaddr
*inifa
;
1920 inifa
= (how
== M_WAITOK
) ? zalloc(inifa_zone
) :
1921 zalloc_noblock(inifa_zone
);
1922 if (inifa
!= NULL
) {
1923 bzero(inifa
, inifa_size
);
1924 inifa
->ia_ifa
.ifa_free
= in_ifaddr_free
;
1925 inifa
->ia_ifa
.ifa_debug
|= IFD_ALLOC
;
1926 ifa_lock_init(&inifa
->ia_ifa
);
1927 if (inifa_debug
!= 0) {
1928 struct in_ifaddr_dbg
*inifa_dbg
=
1929 (struct in_ifaddr_dbg
*)inifa
;
1930 inifa
->ia_ifa
.ifa_debug
|= IFD_DEBUG
;
1931 inifa
->ia_ifa
.ifa_trace
= in_ifaddr_trace
;
1932 inifa
->ia_ifa
.ifa_attached
= in_ifaddr_attached
;
1933 inifa
->ia_ifa
.ifa_detached
= in_ifaddr_detached
;
1934 ctrace_record(&inifa_dbg
->inifa_alloc
);
1941 in_ifaddr_free(struct ifaddr
*ifa
)
1943 IFA_LOCK_ASSERT_HELD(ifa
);
1945 if (ifa
->ifa_refcnt
!= 0) {
1946 panic("%s: ifa %p bad ref cnt", __func__
, ifa
);
1948 } if (!(ifa
->ifa_debug
& IFD_ALLOC
)) {
1949 panic("%s: ifa %p cannot be freed", __func__
, ifa
);
1952 if (ifa
->ifa_debug
& IFD_DEBUG
) {
1953 struct in_ifaddr_dbg
*inifa_dbg
= (struct in_ifaddr_dbg
*)ifa
;
1954 ctrace_record(&inifa_dbg
->inifa_free
);
1955 bcopy(&inifa_dbg
->inifa
, &inifa_dbg
->inifa_old
,
1956 sizeof (struct in_ifaddr
));
1957 if (ifa
->ifa_debug
& IFD_TRASHED
) {
1958 /* Become a regular mutex, just in case */
1959 IFA_CONVERT_LOCK(ifa
);
1960 lck_mtx_lock(&inifa_trash_lock
);
1961 TAILQ_REMOVE(&inifa_trash_head
, inifa_dbg
,
1963 lck_mtx_unlock(&inifa_trash_lock
);
1964 ifa
->ifa_debug
&= ~IFD_TRASHED
;
1968 ifa_lock_destroy(ifa
);
1969 bzero(ifa
, sizeof (struct in_ifaddr
));
1970 zfree(inifa_zone
, ifa
);
1974 in_ifaddr_attached(struct ifaddr
*ifa
)
1976 struct in_ifaddr_dbg
*inifa_dbg
= (struct in_ifaddr_dbg
*)ifa
;
1978 IFA_LOCK_ASSERT_HELD(ifa
);
1980 if (!(ifa
->ifa_debug
& IFD_DEBUG
)) {
1981 panic("%s: ifa %p has no debug structure", __func__
, ifa
);
1984 if (ifa
->ifa_debug
& IFD_TRASHED
) {
1985 /* Become a regular mutex, just in case */
1986 IFA_CONVERT_LOCK(ifa
);
1987 lck_mtx_lock(&inifa_trash_lock
);
1988 TAILQ_REMOVE(&inifa_trash_head
, inifa_dbg
, inifa_trash_link
);
1989 lck_mtx_unlock(&inifa_trash_lock
);
1990 ifa
->ifa_debug
&= ~IFD_TRASHED
;
1995 in_ifaddr_detached(struct ifaddr
*ifa
)
1997 struct in_ifaddr_dbg
*inifa_dbg
= (struct in_ifaddr_dbg
*)ifa
;
1999 IFA_LOCK_ASSERT_HELD(ifa
);
2001 if (!(ifa
->ifa_debug
& IFD_DEBUG
)) {
2002 panic("%s: ifa %p has no debug structure", __func__
, ifa
);
2004 } else if (ifa
->ifa_debug
& IFD_TRASHED
) {
2005 panic("%s: ifa %p is already in trash list", __func__
, ifa
);
2008 ifa
->ifa_debug
|= IFD_TRASHED
;
2009 /* Become a regular mutex, just in case */
2010 IFA_CONVERT_LOCK(ifa
);
2011 lck_mtx_lock(&inifa_trash_lock
);
2012 TAILQ_INSERT_TAIL(&inifa_trash_head
, inifa_dbg
, inifa_trash_link
);
2013 lck_mtx_unlock(&inifa_trash_lock
);
2017 in_ifaddr_trace(struct ifaddr
*ifa
, int refhold
)
2019 struct in_ifaddr_dbg
*inifa_dbg
= (struct in_ifaddr_dbg
*)ifa
;
2024 if (!(ifa
->ifa_debug
& IFD_DEBUG
)) {
2025 panic("%s: ifa %p has no debug structure", __func__
, ifa
);
2029 cnt
= &inifa_dbg
->inifa_refhold_cnt
;
2030 tr
= inifa_dbg
->inifa_refhold
;
2032 cnt
= &inifa_dbg
->inifa_refrele_cnt
;
2033 tr
= inifa_dbg
->inifa_refrele
;
2036 idx
= atomic_add_16_ov(cnt
, 1) % INIFA_TRACE_HIST_SIZE
;
2037 ctrace_record(&tr
[idx
]);