2 * Copyright (c) 2000-2008 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 <kern/zalloc.h>
77 #include <pexpert/pexpert.h>
80 #include <net/if_types.h>
81 #include <net/route.h>
82 #include <net/kpi_protocol.h>
84 #include <netinet/in.h>
85 #include <netinet/in_var.h>
86 #include <netinet/in_pcb.h>
88 #include <netinet/igmp_var.h>
91 #include <netinet/ip_var.h>
93 #include <netinet/tcp.h>
94 #include <netinet/tcp_timer.h>
95 #include <netinet/tcp_var.h>
100 #include <net/pfvar.h>
103 static int in_mask2len(struct in_addr
*);
104 static void in_len2mask(struct in_addr
*, int);
105 static int in_lifaddr_ioctl(struct socket
*, u_long
, caddr_t
,
106 struct ifnet
*, struct proc
*);
108 static void in_socktrim(struct sockaddr_in
*);
109 static int in_ifinit(struct ifnet
*,
110 struct in_ifaddr
*, struct sockaddr_in
*, int);
112 #define IA_HASH_INIT(ia) { \
113 (ia)->ia_hash.tqe_next = (void *)(uintptr_t)-1; \
114 (ia)->ia_hash.tqe_prev = (void *)(uintptr_t)-1; \
117 #define IA_IS_HASHED(ia) \
118 (!((ia)->ia_hash.tqe_next == (void *)(uintptr_t)-1 || \
119 (ia)->ia_hash.tqe_prev == (void *)(uintptr_t)-1))
121 static void in_iahash_remove(struct in_ifaddr
*);
122 static void in_iahash_insert(struct in_ifaddr
*);
123 static void in_iahash_insert_ptp(struct in_ifaddr
*);
124 static struct in_ifaddr
*in_ifaddr_alloc(int);
125 static void in_ifaddr_free(struct ifaddr
*);
126 static void in_ifaddr_trace(struct ifaddr
*, int);
128 static int subnetsarelocal
= 0;
129 SYSCTL_INT(_net_inet_ip
, OID_AUTO
, subnets_are_local
, CTLFLAG_RW
,
130 &subnetsarelocal
, 0, "");
132 struct in_multihead in_multihead
; /* XXX BSS initialization */
134 /* Track whether or not the SIOCARPIPLL ioctl has been called */
135 __private_extern__ u_int32_t ipv4_ll_arp_aware
= 0;
137 struct in_ifaddr_dbg
{
138 struct in_ifaddr inifa
; /* in_ifaddr */
139 struct in_ifaddr inifa_old
; /* saved in_ifaddr */
140 u_int16_t inifa_refhold_cnt
; /* # of ifaref */
141 u_int16_t inifa_refrele_cnt
; /* # of ifafree */
143 * Alloc and free callers.
145 ctrace_t inifa_alloc
;
148 * Circular lists of ifaref and ifafree callers.
150 ctrace_t inifa_refhold
[CTRACE_HIST_SIZE
];
151 ctrace_t inifa_refrele
[CTRACE_HIST_SIZE
];
154 static unsigned int inifa_debug
; /* debug flags */
155 static unsigned int inifa_size
; /* size of zone element */
156 static struct zone
*inifa_zone
; /* zone for in_ifaddr */
158 #define INIFA_ZONE_MAX 64 /* maximum elements in zone */
159 #define INIFA_ZONE_NAME "in_ifaddr" /* zone name */
162 inaddr_local(struct in_addr in
)
165 struct sockaddr_in sin
;
168 sin
.sin_family
= AF_INET
;
169 sin
.sin_len
= sizeof (sin
);
171 rt
= rtalloc1((struct sockaddr
*)&sin
, 0, 0);
175 if (rt
->rt_gateway
->sa_family
== AF_LINK
||
176 (rt
->rt_ifp
->if_flags
& IFF_LOOPBACK
))
181 local
= in_localaddr(in
);
187 * Return 1 if an internet address is for a ``local'' host
188 * (one to which we have a connection). If subnetsarelocal
189 * is true, this includes other subnets of the local net.
190 * Otherwise, it includes only the directly-connected (sub)nets.
193 in_localaddr(struct in_addr in
)
195 u_int32_t i
= ntohl(in
.s_addr
);
196 struct in_ifaddr
*ia
;
198 if (subnetsarelocal
) {
199 lck_rw_lock_shared(in_ifaddr_rwlock
);
200 for (ia
= in_ifaddrhead
.tqh_first
; ia
;
201 ia
= ia
->ia_link
.tqe_next
)
202 if ((i
& ia
->ia_netmask
) == ia
->ia_net
) {
203 lck_rw_done(in_ifaddr_rwlock
);
206 lck_rw_done(in_ifaddr_rwlock
);
208 lck_rw_lock_shared(in_ifaddr_rwlock
);
209 for (ia
= in_ifaddrhead
.tqh_first
; ia
;
210 ia
= ia
->ia_link
.tqe_next
)
211 if ((i
& ia
->ia_subnetmask
) == ia
->ia_subnet
) {
212 lck_rw_done(in_ifaddr_rwlock
);
215 lck_rw_done(in_ifaddr_rwlock
);
221 * Determine whether an IP address is in a reserved set of addresses
222 * that may not be forwarded, or whether datagrams to that destination
226 in_canforward(struct in_addr in
)
228 u_int32_t i
= ntohl(in
.s_addr
);
231 if (IN_EXPERIMENTAL(i
) || IN_MULTICAST(i
))
234 net
= i
& IN_CLASSA_NET
;
235 if (net
== 0 || net
== (IN_LOOPBACKNET
<< IN_CLASSA_NSHIFT
))
242 * Trim a mask in a sockaddr
245 in_socktrim(struct sockaddr_in
*ap
)
247 char *cplim
= (char *) &ap
->sin_addr
;
248 char *cp
= (char *) (&ap
->sin_addr
+ 1);
251 while (--cp
>= cplim
)
253 (ap
)->sin_len
= cp
- (char *) (ap
) + 1;
259 in_mask2len(struct in_addr
*mask
)
265 for (x
= 0; x
< sizeof(*mask
); x
++) {
270 if (x
< sizeof(*mask
)) {
271 for (y
= 0; y
< 8; y
++) {
272 if ((p
[x
] & (0x80 >> y
)) == 0)
280 in_len2mask(struct in_addr
*mask
, int len
)
286 bzero(mask
, sizeof(*mask
));
287 for (i
= 0; i
< len
/ 8; i
++)
290 p
[i
] = (0xff00 >> (len
% 8)) & 0xff;
293 static int in_interfaces
; /* number of external internet interfaces */
296 * Generic internet control operations (ioctl's).
297 * Ifp is 0 if not an interface-specific ioctl.
309 * in_lifaddr_ioctl:???
312 * dlil_plumb_protocol:???
313 * dlil_unplumb_protocol:???
324 struct ifreq
*ifr
= (struct ifreq
*)data
;
325 struct in_ifaddr
*ia
= NULL
, *iap
;
327 struct in_aliasreq
*ifra
= (struct in_aliasreq
*)data
;
328 struct sockaddr_in oldaddr
;
330 int hostIsNew
, maskIsNew
;
331 struct kev_msg ev_msg
;
332 struct kev_in_data in_event_data
;
337 if ((error
= proc_suser(p
)) != 0)
343 return in_lifaddr_ioctl(so
, cmd
, data
, ifp
, p
);
347 * Find address for this interface, if it exists.
349 * If an alias address was specified, find that one instead of
350 * the first one on the interface.
353 lck_rw_lock_shared(in_ifaddr_rwlock
);
354 for (iap
= in_ifaddrhead
.tqh_first
; iap
;
355 iap
= iap
->ia_link
.tqe_next
)
356 if (iap
->ia_ifp
== ifp
) {
357 if (((struct sockaddr_in
*)&ifr
->ifr_addr
)->sin_addr
.s_addr
==
358 iap
->ia_addr
.sin_addr
.s_addr
) {
361 } else if (ia
== NULL
) {
363 if (ifr
->ifr_addr
.sa_family
!= AF_INET
)
367 /* take a reference on ia before releasing lock */
371 lck_rw_done(in_ifaddr_rwlock
);
376 if ((error
= proc_suser(p
)) != 0) {
380 error
= EADDRNOTAVAIL
;
388 error
= EADDRNOTAVAIL
;
391 if (ifra
->ifra_addr
.sin_family
== AF_INET
) {
392 struct in_ifaddr
*oia
;
394 lck_rw_lock_shared(in_ifaddr_rwlock
);
395 for (oia
= ia
; ia
; ia
= ia
->ia_link
.tqe_next
) {
396 if (ia
->ia_ifp
== ifp
&&
397 ia
->ia_addr
.sin_addr
.s_addr
==
398 ifra
->ifra_addr
.sin_addr
.s_addr
)
401 /* take a reference on ia before releasing lock */
402 if (ia
!= NULL
&& ia
!= oia
) {
405 lck_rw_done(in_ifaddr_rwlock
);
406 if (oia
!= NULL
&& oia
!= ia
) {
407 ifafree(&oia
->ia_ifa
);
409 if ((ifp
->if_flags
& IFF_POINTOPOINT
)
410 && (cmd
== SIOCAIFADDR
)
411 && (ifra
->ifra_dstaddr
.sin_addr
.s_addr
413 error
= EDESTADDRREQ
;
417 else if (cmd
== SIOCAIFADDR
) {
421 if (cmd
== SIOCDIFADDR
&& ia
== 0) {
422 error
= EADDRNOTAVAIL
;
429 if ((so
->so_state
& SS_PRIV
) == 0) {
434 error
= EADDRNOTAVAIL
;
437 if (ifra
->ifra_addr
.sin_family
!= AF_INET
438 && cmd
== SIOCSIFADDR
) {
442 if (ia
== (struct in_ifaddr
*)0) {
443 ia
= in_ifaddr_alloc(M_WAITOK
);
444 if (ia
== (struct in_ifaddr
*)NULL
) {
450 /* Hold a reference for this routine */
452 ifa
->ifa_addr
= (struct sockaddr
*)&ia
->ia_addr
;
453 ifa
->ifa_dstaddr
= (struct sockaddr
*)&ia
->ia_dstaddr
;
454 ifa
->ifa_netmask
= (struct sockaddr
*)&ia
->ia_sockmask
;
455 ia
->ia_sockmask
.sin_len
= 8;
456 ifnet_lock_exclusive(ifp
);
457 if (ifp
->if_flags
& IFF_BROADCAST
) {
458 ia
->ia_broadaddr
.sin_len
= sizeof(ia
->ia_addr
);
459 ia
->ia_broadaddr
.sin_family
= AF_INET
;
462 if (!(ifp
->if_flags
& IFF_LOOPBACK
))
464 /* if_attach_ifa() holds a reference for ifa_link */
465 if_attach_ifa(ifp
, ifa
);
466 ifnet_lock_done(ifp
);
467 lck_rw_lock_exclusive(in_ifaddr_rwlock
);
468 /* Hold a reference for ia_link */
470 TAILQ_INSERT_TAIL(&in_ifaddrhead
, ia
, ia_link
);
471 lck_rw_done(in_ifaddr_rwlock
);
473 /* Generic protocol plumbing */
475 if ((error
= proto_plumb(PF_INET
, ifp
))) {
476 if (error
!= EEXIST
) {
477 kprintf("in.c: warning can't plumb proto if=%s%d type %d error=%d\n",
478 ifp
->if_name
, ifp
->if_unit
, ifp
->if_type
, error
);
480 error
= 0; /*discard error, can be cold with unsupported interfaces */
485 case SIOCPROTOATTACH
:
486 case SIOCPROTODETACH
:
487 if ((error
= proc_suser(p
)) != 0) {
491 error
= EADDRNOTAVAIL
;
497 if ((so
->so_state
& SS_PRIV
) == 0) {
507 if (ia
== (struct in_ifaddr
*)0) {
508 error
= EADDRNOTAVAIL
;
515 ifnet_lock_exclusive(ifp
);
517 ifp
->if_eflags
|= IFEF_AUTOCONFIGURING
;
519 ifp
->if_eflags
&= ~IFEF_AUTOCONFIGURING
;
520 ifnet_lock_done(ifp
);
524 ipv4_ll_arp_aware
= 1;
525 ifnet_lock_exclusive(ifp
);
527 ifp
->if_eflags
|= IFEF_ARPLL
;
529 ifp
->if_eflags
&= ~IFEF_ARPLL
;
530 ifnet_lock_done(ifp
);
534 *((struct sockaddr_in
*)&ifr
->ifr_addr
) = ia
->ia_addr
;
538 if ((ifp
->if_flags
& IFF_BROADCAST
) == 0) {
542 *((struct sockaddr_in
*)&ifr
->ifr_dstaddr
) = ia
->ia_broadaddr
;
546 if ((ifp
->if_flags
& IFF_POINTOPOINT
) == 0) {
550 *((struct sockaddr_in
*)&ifr
->ifr_dstaddr
) = ia
->ia_dstaddr
;
554 *((struct sockaddr_in
*)&ifr
->ifr_addr
) = ia
->ia_sockmask
;
558 if ((ifp
->if_flags
& IFF_POINTOPOINT
) == 0) {
562 oldaddr
= ia
->ia_dstaddr
;
563 ia
->ia_dstaddr
= *(struct sockaddr_in
*)&ifr
->ifr_dstaddr
;
564 if (ia
->ia_dstaddr
.sin_family
== AF_INET
)
565 ia
->ia_dstaddr
.sin_len
= sizeof (struct sockaddr_in
);
566 error
= ifnet_ioctl(ifp
, PF_INET
, SIOCSIFDSTADDR
, ia
);
567 if (error
== EOPNOTSUPP
) {
571 ia
->ia_dstaddr
= oldaddr
;
575 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
576 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
577 ev_msg
.kev_subclass
= KEV_INET_SUBCLASS
;
579 ev_msg
.event_code
= KEV_INET_SIFDSTADDR
;
581 if (ia
->ia_ifa
.ifa_dstaddr
)
582 in_event_data
.ia_dstaddr
=
583 ((struct sockaddr_in
*)ia
->ia_ifa
.ifa_dstaddr
)->sin_addr
;
585 in_event_data
.ia_dstaddr
.s_addr
= 0;
587 in_event_data
.ia_addr
= ia
->ia_addr
.sin_addr
;
588 in_event_data
.ia_net
= ia
->ia_net
;
589 in_event_data
.ia_netmask
= ia
->ia_netmask
;
590 in_event_data
.ia_subnet
= ia
->ia_subnet
;
591 in_event_data
.ia_subnetmask
= ia
->ia_subnetmask
;
592 in_event_data
.ia_netbroadcast
= ia
->ia_netbroadcast
;
593 strncpy(&in_event_data
.link_data
.if_name
[0], ifp
->if_name
, IFNAMSIZ
);
594 in_event_data
.link_data
.if_family
= ifp
->if_family
;
595 in_event_data
.link_data
.if_unit
= (u_int32_t
) ifp
->if_unit
;
597 ev_msg
.dv
[0].data_ptr
= &in_event_data
;
598 ev_msg
.dv
[0].data_length
= sizeof(struct kev_in_data
);
599 ev_msg
.dv
[1].data_length
= 0;
601 kev_post_msg(&ev_msg
);
604 if (ia
->ia_flags
& IFA_ROUTE
) {
605 ia
->ia_ifa
.ifa_dstaddr
= (struct sockaddr
*)&oldaddr
;
606 rtinit(&(ia
->ia_ifa
), (int)RTM_DELETE
, RTF_HOST
);
607 ia
->ia_ifa
.ifa_dstaddr
=
608 (struct sockaddr
*)&ia
->ia_dstaddr
;
609 rtinit(&(ia
->ia_ifa
), (int)RTM_ADD
, RTF_HOST
|RTF_UP
);
614 if ((ifp
->if_flags
& IFF_BROADCAST
) == 0) {
618 ia
->ia_broadaddr
= *(struct sockaddr_in
*)&ifr
->ifr_broadaddr
;
620 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
621 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
622 ev_msg
.kev_subclass
= KEV_INET_SUBCLASS
;
624 ev_msg
.event_code
= KEV_INET_SIFBRDADDR
;
626 if (ia
->ia_ifa
.ifa_dstaddr
)
627 in_event_data
.ia_dstaddr
=
628 ((struct sockaddr_in
*)ia
->ia_ifa
.ifa_dstaddr
)->sin_addr
;
630 in_event_data
.ia_dstaddr
.s_addr
= 0;
632 in_event_data
.ia_addr
= ia
->ia_addr
.sin_addr
;
633 in_event_data
.ia_net
= ia
->ia_net
;
634 in_event_data
.ia_netmask
= ia
->ia_netmask
;
635 in_event_data
.ia_subnet
= ia
->ia_subnet
;
636 in_event_data
.ia_subnetmask
= ia
->ia_subnetmask
;
637 in_event_data
.ia_netbroadcast
= ia
->ia_netbroadcast
;
638 strncpy(&in_event_data
.link_data
.if_name
[0], ifp
->if_name
, IFNAMSIZ
);
639 in_event_data
.link_data
.if_family
= ifp
->if_family
;
640 in_event_data
.link_data
.if_unit
= (u_int32_t
) ifp
->if_unit
;
642 ev_msg
.dv
[0].data_ptr
= &in_event_data
;
643 ev_msg
.dv
[0].data_length
= sizeof(struct kev_in_data
);
644 ev_msg
.dv
[1].data_length
= 0;
646 kev_post_msg(&ev_msg
);
652 * If this is a new address, the reference count for the
653 * hash table has been taken at creation time above.
655 error
= in_ifinit(ifp
, ia
,
656 (struct sockaddr_in
*)&ifr
->ifr_addr
, 1);
659 (void) pf_ifaddr_hook(ifp
, cmd
);
663 case SIOCPROTOATTACH
:
664 error
= proto_plumb(PF_INET
, ifp
);
667 case SIOCPROTODETACH
:
668 // if an ip address is still present, refuse to detach
669 ifnet_lock_shared(ifp
);
670 TAILQ_FOREACH(ifa
, &ifp
->if_addrhead
, ifa_link
)
671 if (ifa
->ifa_addr
->sa_family
== AF_INET
)
673 ifnet_lock_done(ifp
);
679 error
= proto_unplumb(PF_INET
, ifp
);
683 case SIOCSIFNETMASK
: {
686 i
= ifra
->ifra_addr
.sin_addr
.s_addr
;
687 ia
->ia_subnetmask
= ntohl(ia
->ia_sockmask
.sin_addr
.s_addr
= i
);
688 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
689 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
690 ev_msg
.kev_subclass
= KEV_INET_SUBCLASS
;
692 ev_msg
.event_code
= KEV_INET_SIFNETMASK
;
694 if (ia
->ia_ifa
.ifa_dstaddr
)
695 in_event_data
.ia_dstaddr
=
696 ((struct sockaddr_in
*)ia
->ia_ifa
.ifa_dstaddr
)->sin_addr
;
698 in_event_data
.ia_dstaddr
.s_addr
= 0;
700 in_event_data
.ia_addr
= ia
->ia_addr
.sin_addr
;
701 in_event_data
.ia_net
= ia
->ia_net
;
702 in_event_data
.ia_netmask
= ia
->ia_netmask
;
703 in_event_data
.ia_subnet
= ia
->ia_subnet
;
704 in_event_data
.ia_subnetmask
= ia
->ia_subnetmask
;
705 in_event_data
.ia_netbroadcast
= ia
->ia_netbroadcast
;
706 strncpy(&in_event_data
.link_data
.if_name
[0], ifp
->if_name
, IFNAMSIZ
);
707 in_event_data
.link_data
.if_family
= ifp
->if_family
;
708 in_event_data
.link_data
.if_unit
= (u_int32_t
) ifp
->if_unit
;
710 ev_msg
.dv
[0].data_ptr
= &in_event_data
;
711 ev_msg
.dv
[0].data_length
= sizeof(struct kev_in_data
);
712 ev_msg
.dv
[1].data_length
= 0;
714 kev_post_msg(&ev_msg
);
723 if (ia
->ia_addr
.sin_family
== AF_INET
) {
724 if (ifra
->ifra_addr
.sin_len
== 0) {
725 ifra
->ifra_addr
= ia
->ia_addr
;
727 } else if (ifra
->ifra_addr
.sin_addr
.s_addr
==
728 ia
->ia_addr
.sin_addr
.s_addr
)
731 if (ifra
->ifra_mask
.sin_len
) {
732 in_ifscrub(ifp
, ia
, 0);
733 ia
->ia_sockmask
= ifra
->ifra_mask
;
735 ntohl(ia
->ia_sockmask
.sin_addr
.s_addr
);
738 if ((ifp
->if_flags
& IFF_POINTOPOINT
) &&
739 (ifra
->ifra_dstaddr
.sin_family
== AF_INET
)) {
740 in_ifscrub(ifp
, ia
, 0);
741 ia
->ia_dstaddr
= ifra
->ifra_dstaddr
;
742 ia
->ia_dstaddr
.sin_len
= sizeof (struct sockaddr_in
);
743 maskIsNew
= 1; /* We lie; but the effect's the same */
745 if (ifra
->ifra_addr
.sin_family
== AF_INET
&&
746 (hostIsNew
|| maskIsNew
)) {
747 error
= in_ifinit(ifp
, ia
, &ifra
->ifra_addr
, 0);
751 (void) pf_ifaddr_hook(ifp
, cmd
);
753 if ((ifp
->if_flags
& IFF_BROADCAST
) &&
754 (ifra
->ifra_broadaddr
.sin_family
== AF_INET
))
755 ia
->ia_broadaddr
= ifra
->ifra_broadaddr
;
761 if ((error
== 0) || (error
== EEXIST
)) {
762 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
763 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
764 ev_msg
.kev_subclass
= KEV_INET_SUBCLASS
;
767 ev_msg
.event_code
= KEV_INET_NEW_ADDR
;
769 ev_msg
.event_code
= KEV_INET_CHANGED_ADDR
;
771 if (ia
->ia_ifa
.ifa_dstaddr
)
772 in_event_data
.ia_dstaddr
=
773 ((struct sockaddr_in
*)ia
->ia_ifa
.ifa_dstaddr
)->sin_addr
;
775 in_event_data
.ia_dstaddr
.s_addr
= 0;
777 in_event_data
.ia_addr
= ia
->ia_addr
.sin_addr
;
778 in_event_data
.ia_net
= ia
->ia_net
;
779 in_event_data
.ia_netmask
= ia
->ia_netmask
;
780 in_event_data
.ia_subnet
= ia
->ia_subnet
;
781 in_event_data
.ia_subnetmask
= ia
->ia_subnetmask
;
782 in_event_data
.ia_netbroadcast
= ia
->ia_netbroadcast
;
783 strncpy(&in_event_data
.link_data
.if_name
[0], ifp
->if_name
, IFNAMSIZ
);
784 in_event_data
.link_data
.if_family
= ifp
->if_family
;
785 in_event_data
.link_data
.if_unit
= (u_int32_t
) ifp
->if_unit
;
787 ev_msg
.dv
[0].data_ptr
= &in_event_data
;
788 ev_msg
.dv
[0].data_length
= sizeof(struct kev_in_data
);
789 ev_msg
.dv
[1].data_length
= 0;
791 kev_post_msg(&ev_msg
);
796 error
= ifnet_ioctl(ifp
, PF_INET
, SIOCDIFADDR
, ia
);
797 if (error
== EOPNOTSUPP
)
803 /* Fill out the kernel event information */
804 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
805 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
806 ev_msg
.kev_subclass
= KEV_INET_SUBCLASS
;
808 ev_msg
.event_code
= KEV_INET_ADDR_DELETED
;
810 if (ia
->ia_ifa
.ifa_dstaddr
)
811 in_event_data
.ia_dstaddr
=
812 ((struct sockaddr_in
*)ia
->ia_ifa
.ifa_dstaddr
)->sin_addr
;
814 in_event_data
.ia_dstaddr
.s_addr
= 0;
816 in_event_data
.ia_addr
= ia
->ia_addr
.sin_addr
;
817 in_event_data
.ia_net
= ia
->ia_net
;
818 in_event_data
.ia_netmask
= ia
->ia_netmask
;
819 in_event_data
.ia_subnet
= ia
->ia_subnet
;
820 in_event_data
.ia_subnetmask
= ia
->ia_subnetmask
;
821 in_event_data
.ia_netbroadcast
= ia
->ia_netbroadcast
;
822 strncpy(&in_event_data
.link_data
.if_name
[0], ifp
->if_name
, IFNAMSIZ
);
823 in_event_data
.link_data
.if_family
= ifp
->if_family
;
824 in_event_data
.link_data
.if_unit
= (u_int32_t
) ifp
->if_unit
;
826 ev_msg
.dv
[0].data_ptr
= &in_event_data
;
827 ev_msg
.dv
[0].data_length
= sizeof(struct kev_in_data
);
828 ev_msg
.dv
[1].data_length
= 0;
831 lck_rw_lock_exclusive(in_ifaddr_rwlock
);
832 /* Release ia_link reference */
834 TAILQ_REMOVE(&in_ifaddrhead
, ia
, ia_link
);
835 if (IA_IS_HASHED(ia
))
836 in_iahash_remove(ia
);
837 lck_rw_done(in_ifaddr_rwlock
);
840 * in_ifscrub kills the interface route.
842 in_ifscrub(ifp
, ia
, 0);
843 ifnet_lock_exclusive(ifp
);
844 /* if_detach_ifa() releases ifa_link reference */
845 if_detach_ifa(ifp
, ifa
);
848 * If the interface supports multicast, and no address is left,
849 * remove the "all hosts" multicast group from that interface.
851 if (ifp
->if_flags
& IFF_MULTICAST
) {
853 struct in_multi
*inm
= NULL
;
855 TAILQ_FOREACH(ifa
, &ifp
->if_addrhead
, ifa_link
)
856 if (ifa
->ifa_addr
->sa_family
== AF_INET
)
860 addr
.s_addr
= htonl(INADDR_ALLHOSTS_GROUP
);
861 IN_LOOKUP_MULTI(addr
, ifp
, inm
);
863 ifnet_lock_done(ifp
);
867 ifnet_lock_done(ifp
);
870 /* Post the kernel event */
871 kev_post_msg(&ev_msg
);
874 * See if there is any IPV4 address left and if so,
875 * reconfigure KDP to use current primary address.
877 ifa
= ifa_ifpgetprimary(ifp
, AF_INET
);
879 error
= ifnet_ioctl(ifp
, PF_INET
, SIOCSIFADDR
, ifa
);
880 if (error
== EOPNOTSUPP
)
883 /* Release reference from ifa_ifpgetprimary() */
887 (void) pf_ifaddr_hook(ifp
, cmd
);
894 * Inspiration from tcp_ctloutput() and ip_ctloutput()
895 * Special ioctl for OpenTransport sockets
897 struct inpcb
*inp
, *cloned_inp
;
899 int cloned_fd
= *(int *)data
;
906 /* let's make sure it's either -1 or a valid file descriptor */
907 if (cloned_fd
!= -1) {
908 struct socket
*cloned_so
;
909 error2
= file_socket(cloned_fd
, &cloned_so
);
913 cloned_inp
= sotoinpcb(cloned_so
);
914 file_drop(cloned_fd
);
919 if (cloned_inp
== NULL
) {
920 /* OT always uses IP_PORTRANGE_HIGH */
921 inp
->inp_flags
&= ~(INP_LOWPORT
);
922 inp
->inp_flags
|= INP_HIGHPORT
;
923 /* For UDP, OT allows broadcast by default */
924 if (so
->so_type
== SOCK_DGRAM
)
925 so
->so_options
|= SO_BROADCAST
;
926 /* For TCP we want to see MSG_OOB when receive urgent data */
927 else if (so
->so_type
== SOCK_STREAM
)
928 so
->so_options
|= SO_WANTOOBFLAG
;
930 inp
->inp_ip_tos
= cloned_inp
->inp_ip_tos
;
931 inp
->inp_ip_ttl
= cloned_inp
->inp_ip_ttl
;
932 inp
->inp_flags
= cloned_inp
->inp_flags
;
934 /* Multicast options */
935 if (cloned_inp
->inp_moptions
!= NULL
) {
937 struct ip_moptions
*cloned_imo
= cloned_inp
->inp_moptions
;
938 struct ip_moptions
*imo
= inp
->inp_moptions
;
942 * No multicast option buffer attached to the pcb;
945 imo
= (struct ip_moptions
*)
946 _MALLOC(sizeof(*imo
), M_IPMOPTS
, M_WAITOK
);
951 inp
->inp_moptions
= imo
;
953 imo
->imo_multicast_ifp
= cloned_imo
->imo_multicast_ifp
;
954 imo
->imo_multicast_vif
= cloned_imo
->imo_multicast_vif
;
955 imo
->imo_multicast_ttl
= cloned_imo
->imo_multicast_ttl
;
956 imo
->imo_multicast_loop
= cloned_imo
->imo_multicast_loop
;
957 imo
->imo_num_memberships
= cloned_imo
->imo_num_memberships
;
958 for (i
= 0; i
< cloned_imo
->imo_num_memberships
; i
++) {
959 imo
->imo_membership
[i
] =
960 in_addmulti(&cloned_imo
->imo_membership
[i
]->inm_addr
,
961 cloned_imo
->imo_membership
[i
]->inm_ifp
);
962 if (imo
->imo_membership
[i
] == NULL
) {
967 if (i
< cloned_imo
->imo_num_memberships
) {
968 /* Failed, perform cleanup */
969 for (i
--; i
>= 0; i
--)
970 in_delmulti(&imo
->imo_membership
[i
]);
971 imo
->imo_num_memberships
= 0;
978 #endif /* __APPLE__ */
985 ifafree(&ia
->ia_ifa
);
992 * SIOCGLIFADDR: get first address. (?!?)
993 * SIOCGLIFADDR with IFLR_PREFIX:
994 * get first address that matches the specified prefix.
995 * SIOCALIFADDR: add the specified address.
996 * SIOCALIFADDR with IFLR_PREFIX:
997 * EINVAL since we can't deduce hostid part of the address.
998 * SIOCDLIFADDR: delete the specified address.
999 * SIOCDLIFADDR with IFLR_PREFIX:
1000 * delete the first address that matches the specified prefix.
1002 * EINVAL on invalid parameters
1003 * EADDRNOTAVAIL on prefix match failed/specified address not found
1004 * other values may be returned from in_ioctl()
1014 struct if_laddrreq
*iflr
= (struct if_laddrreq
*)data
;
1018 if (!data
|| !ifp
) {
1019 panic("invalid argument to in_lifaddr_ioctl");
1025 /* address must be specified on GET with IFLR_PREFIX */
1026 if ((iflr
->flags
& IFLR_PREFIX
) == 0)
1031 /* address must be specified on ADD and DELETE */
1032 if (iflr
->addr
.ss_family
!= AF_INET
)
1034 if (iflr
->addr
.ss_len
!= sizeof(struct sockaddr_in
))
1036 /* XXX need improvement */
1037 if (iflr
->dstaddr
.ss_family
1038 && iflr
->dstaddr
.ss_family
!= AF_INET
)
1040 if (iflr
->dstaddr
.ss_family
1041 && iflr
->dstaddr
.ss_len
!= sizeof(struct sockaddr_in
))
1044 default: /*shouldn't happen*/
1047 if (sizeof(struct in_addr
) * 8 < iflr
->prefixlen
)
1053 struct in_aliasreq ifra
;
1055 if (iflr
->flags
& IFLR_PREFIX
)
1058 /* copy args to in_aliasreq, perform ioctl(SIOCAIFADDR_IN6). */
1059 bzero(&ifra
, sizeof(ifra
));
1060 bcopy(iflr
->iflr_name
, ifra
.ifra_name
,
1061 sizeof(ifra
.ifra_name
));
1063 bcopy(&iflr
->addr
, &ifra
.ifra_addr
, iflr
->addr
.ss_len
);
1065 if (iflr
->dstaddr
.ss_family
) { /*XXX*/
1066 bcopy(&iflr
->dstaddr
, &ifra
.ifra_dstaddr
,
1067 iflr
->dstaddr
.ss_len
);
1070 ifra
.ifra_mask
.sin_family
= AF_INET
;
1071 ifra
.ifra_mask
.sin_len
= sizeof(struct sockaddr_in
);
1072 in_len2mask(&ifra
.ifra_mask
.sin_addr
, iflr
->prefixlen
);
1074 return in_control(so
, SIOCAIFADDR
, (caddr_t
)&ifra
, ifp
, p
);
1079 struct in_ifaddr
*ia
;
1080 struct in_addr mask
, candidate
;
1081 struct in_addr match
= { 0 };
1082 struct sockaddr_in
*sin
;
1085 bzero(&mask
, sizeof(mask
));
1086 if (iflr
->flags
& IFLR_PREFIX
) {
1087 /* lookup a prefix rather than address. */
1088 in_len2mask(&mask
, iflr
->prefixlen
);
1090 sin
= (struct sockaddr_in
*)&iflr
->addr
;
1091 match
.s_addr
= sin
->sin_addr
.s_addr
;
1092 match
.s_addr
&= mask
.s_addr
;
1094 /* if you set extra bits, that's wrong */
1095 if (match
.s_addr
!= sin
->sin_addr
.s_addr
)
1100 if (cmd
== SIOCGLIFADDR
) {
1101 /* on getting an address, take the 1st match */
1104 /* on deleting an address, do exact match */
1105 in_len2mask(&mask
, 32);
1106 sin
= (struct sockaddr_in
*)&iflr
->addr
;
1107 match
.s_addr
= sin
->sin_addr
.s_addr
;
1113 ifnet_lock_shared(ifp
);
1114 TAILQ_FOREACH(ifa
, &ifp
->if_addrhead
, ifa_link
) {
1115 if (ifa
->ifa_addr
->sa_family
!= AF_INET6
)
1119 candidate
.s_addr
= ((struct sockaddr_in
*)&ifa
->ifa_addr
)->sin_addr
.s_addr
;
1120 candidate
.s_addr
&= mask
.s_addr
;
1121 if (candidate
.s_addr
== match
.s_addr
)
1124 ifnet_lock_done(ifp
);
1126 return EADDRNOTAVAIL
;
1127 ia
= (struct in_ifaddr
*)ifa
;
1129 if (cmd
== SIOCGLIFADDR
) {
1130 /* fill in the if_laddrreq structure */
1131 bcopy(&ia
->ia_addr
, &iflr
->addr
, ia
->ia_addr
.sin_len
);
1133 if ((ifp
->if_flags
& IFF_POINTOPOINT
) != 0) {
1134 bcopy(&ia
->ia_dstaddr
, &iflr
->dstaddr
,
1135 ia
->ia_dstaddr
.sin_len
);
1137 bzero(&iflr
->dstaddr
, sizeof(iflr
->dstaddr
));
1140 in_mask2len(&ia
->ia_sockmask
.sin_addr
);
1142 iflr
->flags
= 0; /*XXX*/
1146 struct in_aliasreq ifra
;
1148 /* fill in_aliasreq and do ioctl(SIOCDIFADDR_IN6) */
1149 bzero(&ifra
, sizeof(ifra
));
1150 bcopy(iflr
->iflr_name
, ifra
.ifra_name
,
1151 sizeof(ifra
.ifra_name
));
1153 bcopy(&ia
->ia_addr
, &ifra
.ifra_addr
,
1154 ia
->ia_addr
.sin_len
);
1155 if ((ifp
->if_flags
& IFF_POINTOPOINT
) != 0) {
1156 bcopy(&ia
->ia_dstaddr
, &ifra
.ifra_dstaddr
,
1157 ia
->ia_dstaddr
.sin_len
);
1159 bcopy(&ia
->ia_sockmask
, &ifra
.ifra_dstaddr
,
1160 ia
->ia_sockmask
.sin_len
);
1162 return in_control(so
, SIOCDIFADDR
, (caddr_t
)&ifra
,
1168 return EOPNOTSUPP
; /*just for safety*/
1172 * Delete any existing route for an interface.
1177 struct in_ifaddr
*ia
,
1181 if ((ia
->ia_flags
& IFA_ROUTE
) == 0)
1184 lck_mtx_lock(rnh_lock
);
1185 if (ifp
->if_flags
& (IFF_LOOPBACK
|IFF_POINTOPOINT
))
1186 rtinit_locked(&(ia
->ia_ifa
), (int)RTM_DELETE
, RTF_HOST
);
1188 rtinit_locked(&(ia
->ia_ifa
), (int)RTM_DELETE
, 0);
1189 ia
->ia_flags
&= ~IFA_ROUTE
;
1191 lck_mtx_unlock(rnh_lock
);
1195 * Caller must hold in_ifaddr_rwlock as writer.
1198 in_iahash_remove(struct in_ifaddr
*ia
)
1200 if (!IA_IS_HASHED(ia
))
1201 panic("attempt to remove wrong ia %p from hash table\n", ia
);
1203 TAILQ_REMOVE(INADDR_HASH(ia
->ia_addr
.sin_addr
.s_addr
), ia
, ia_hash
);
1205 ifafree(&ia
->ia_ifa
);
1209 * Caller must hold in_ifaddr_rwlock as writer.
1212 in_iahash_insert(struct in_ifaddr
*ia
)
1214 if (ia
->ia_addr
.sin_family
!= AF_INET
)
1215 panic("attempt to insert wrong ia %p into hash table\n", ia
);
1216 else if (IA_IS_HASHED(ia
))
1217 panic("attempt to double-insert ia %p into hash table\n", ia
);
1219 TAILQ_INSERT_HEAD(INADDR_HASH(ia
->ia_addr
.sin_addr
.s_addr
), ia
, ia_hash
);
1220 ifaref(&ia
->ia_ifa
);
1224 * Some point to point interfaces that are tunnels
1225 * borrow the address from an underlying interface (e.g.
1226 * VPN server). In order for source address selection logic to
1227 * find the underlying interface first, we add the address
1228 * of borrowing point to point interfaces at the end of the list.
1229 * (see rdar://6733789)
1231 * Caller must hold in_ifaddr_rwlock as writer.
1234 in_iahash_insert_ptp(struct in_ifaddr
*ia
)
1236 struct in_ifaddr
*tmp_ifa
;
1237 struct ifnet
*tmp_ifp
;
1239 if (ia
->ia_addr
.sin_family
!= AF_INET
)
1240 panic("attempt to insert wrong ia %p into hash table\n", ia
);
1241 else if (IA_IS_HASHED(ia
))
1242 panic("attempt to double-insert ia %p into hash table\n", ia
);
1244 TAILQ_FOREACH(tmp_ifa
, INADDR_HASH(ia
->ia_addr
.sin_addr
.s_addr
), ia_hash
)
1245 if (IA_SIN(tmp_ifa
)->sin_addr
.s_addr
== ia
->ia_addr
.sin_addr
.s_addr
)
1247 tmp_ifp
= (tmp_ifa
== NULL
) ? NULL
: tmp_ifa
->ia_ifp
;
1249 if (tmp_ifp
== NULL
)
1250 TAILQ_INSERT_HEAD(INADDR_HASH(ia
->ia_addr
.sin_addr
.s_addr
), ia
, ia_hash
);
1252 TAILQ_INSERT_TAIL(INADDR_HASH(ia
->ia_addr
.sin_addr
.s_addr
), ia
, ia_hash
);
1254 ifaref(&ia
->ia_ifa
);
1258 * Initialize an interface's internet address
1259 * and routing table entry.
1264 struct in_ifaddr
*ia
,
1265 struct sockaddr_in
*sin
,
1268 u_int32_t i
= ntohl(sin
->sin_addr
.s_addr
);
1269 struct sockaddr_in oldaddr
;
1270 int flags
= RTF_UP
, error
;
1271 struct ifaddr
*ifa0
;
1275 /* Take an extra reference for this routine */
1276 ifaref(&ia
->ia_ifa
);
1278 lck_rw_lock_exclusive(in_ifaddr_rwlock
);
1279 oldaddr
= ia
->ia_addr
;
1280 if (IA_IS_HASHED(ia
)) {
1282 in_iahash_remove(ia
);
1285 ia
->ia_addr
.sin_len
= sizeof (*sin
);
1286 if ((ifp
->if_flags
& IFF_POINTOPOINT
))
1287 in_iahash_insert_ptp(ia
);
1289 in_iahash_insert(ia
);
1290 lck_rw_done(in_ifaddr_rwlock
);
1293 * Give the interface a chance to initialize if this is its first
1294 * address, and to validate the address if necessary. Send down
1295 * SIOCSIFADDR for first address, and SIOCAIFADDR for alias(es).
1296 * We find the first IPV4 address assigned to it and check if this
1297 * is the same as the one passed into this routine.
1299 ifa0
= ifa_ifpgetprimary(ifp
, AF_INET
);
1300 cmd
= (&ia
->ia_ifa
== ifa0
) ? SIOCSIFADDR
: SIOCAIFADDR
;
1301 error
= ifnet_ioctl(ifp
, PF_INET
, cmd
, ia
);
1302 if (error
== EOPNOTSUPP
)
1305 * If we've just sent down SIOCAIFADDR, send another ioctl down
1306 * for SIOCSIFADDR for the first IPV4 address of the interface,
1307 * because an address change on one of the addresses will result
1308 * in the removal of the previous first IPV4 address. KDP needs
1309 * be reconfigured with the current primary IPV4 address.
1311 if (error
== 0 && cmd
== SIOCAIFADDR
) {
1312 error
= ifnet_ioctl(ifp
, PF_INET
, SIOCSIFADDR
, ifa0
);
1313 if (error
== EOPNOTSUPP
)
1317 /* Release reference from ifa_ifpgetprimary() */
1321 lck_rw_lock_exclusive(in_ifaddr_rwlock
);
1322 if (IA_IS_HASHED(ia
))
1323 in_iahash_remove(ia
);
1324 ia
->ia_addr
= oldaddr
;
1326 if ((ifp
->if_flags
& IFF_POINTOPOINT
))
1327 in_iahash_insert_ptp(ia
);
1329 in_iahash_insert(ia
);
1331 lck_rw_done(in_ifaddr_rwlock
);
1332 /* Release extra reference taken above */
1333 ifafree(&ia
->ia_ifa
);
1336 lck_mtx_lock(rnh_lock
);
1338 ia
->ia_ifa
.ifa_addr
= (struct sockaddr
*)&oldaddr
;
1339 in_ifscrub(ifp
, ia
, 1);
1340 ia
->ia_ifa
.ifa_addr
= (struct sockaddr
*)&ia
->ia_addr
;
1343 ia
->ia_netmask
= IN_CLASSA_NET
;
1344 else if (IN_CLASSB(i
))
1345 ia
->ia_netmask
= IN_CLASSB_NET
;
1347 ia
->ia_netmask
= IN_CLASSC_NET
;
1349 * The subnet mask usually includes at least the standard network part,
1350 * but may may be smaller in the case of supernetting.
1351 * If it is set, we believe it.
1353 if (ia
->ia_subnetmask
== 0) {
1354 ia
->ia_subnetmask
= ia
->ia_netmask
;
1355 ia
->ia_sockmask
.sin_addr
.s_addr
= htonl(ia
->ia_subnetmask
);
1357 ia
->ia_netmask
&= ia
->ia_subnetmask
;
1358 ia
->ia_net
= i
& ia
->ia_netmask
;
1359 ia
->ia_subnet
= i
& ia
->ia_subnetmask
;
1360 in_socktrim(&ia
->ia_sockmask
);
1362 * Add route for the network.
1364 ia
->ia_ifa
.ifa_metric
= ifp
->if_metric
;
1365 if (ifp
->if_flags
& IFF_BROADCAST
) {
1366 ia
->ia_broadaddr
.sin_addr
.s_addr
=
1367 htonl(ia
->ia_subnet
| ~ia
->ia_subnetmask
);
1368 ia
->ia_netbroadcast
.s_addr
=
1369 htonl(ia
->ia_net
| ~ ia
->ia_netmask
);
1370 } else if (ifp
->if_flags
& IFF_LOOPBACK
) {
1371 ia
->ia_ifa
.ifa_dstaddr
= ia
->ia_ifa
.ifa_addr
;
1373 } else if (ifp
->if_flags
& IFF_POINTOPOINT
) {
1374 if (ia
->ia_dstaddr
.sin_family
!= AF_INET
) {
1375 lck_mtx_unlock(rnh_lock
);
1376 /* Release extra reference taken above */
1377 ifafree(&ia
->ia_ifa
);
1380 ia
->ia_dstaddr
.sin_len
= sizeof (*sin
);
1383 if ((error
= rtinit_locked(&(ia
->ia_ifa
), (int)RTM_ADD
, flags
)) == 0)
1384 ia
->ia_flags
|= IFA_ROUTE
;
1385 lck_mtx_unlock(rnh_lock
);
1387 /* XXX check if the subnet route points to the same interface */
1388 if (error
== EEXIST
)
1392 * If the interface supports multicast, join the "all hosts"
1393 * multicast group on that interface.
1395 if (ifp
->if_flags
& IFF_MULTICAST
) {
1396 struct in_multi
*inm
;
1397 struct in_addr addr
;
1399 addr
.s_addr
= htonl(INADDR_ALLHOSTS_GROUP
);
1400 ifnet_lock_shared(ifp
);
1401 IN_LOOKUP_MULTI(addr
, ifp
, inm
);
1402 ifnet_lock_done(ifp
);
1404 in_addmulti(&addr
, ifp
);
1407 /* Release extra reference taken above */
1408 ifafree(&ia
->ia_ifa
);
1414 * Return 1 if the address might be a local broadcast address.
1424 if (in
.s_addr
== INADDR_BROADCAST
||
1425 in
.s_addr
== INADDR_ANY
)
1427 if ((ifp
->if_flags
& IFF_BROADCAST
) == 0)
1429 t
= ntohl(in
.s_addr
);
1431 * Look through the list of addresses for a match
1432 * with a broadcast address.
1434 #define ia ((struct in_ifaddr *)ifa)
1435 ifnet_lock_shared(ifp
);
1436 TAILQ_FOREACH(ifa
, &ifp
->if_addrhead
, ifa_link
) {
1437 if (ifa
->ifa_addr
== NULL
) {
1438 ifnet_lock_done(ifp
);
1441 if (ifa
->ifa_addr
->sa_family
== AF_INET
&&
1442 (in
.s_addr
== ia
->ia_broadaddr
.sin_addr
.s_addr
||
1443 in
.s_addr
== ia
->ia_netbroadcast
.s_addr
||
1445 * Check for old-style (host 0) broadcast.
1447 t
== ia
->ia_subnet
|| t
== ia
->ia_net
) &&
1449 * Check for an all one subnetmask. These
1450 * only exist when an interface gets a secondary
1453 ia
->ia_subnetmask
!= (u_int32_t
)0xffffffff) {
1454 ifnet_lock_done(ifp
);
1458 ifnet_lock_done(ifp
);
1465 void* ifma_protospec
)
1467 struct in_multi
*inm
= ifma_protospec
;
1470 * No remaining claims to this record; let IGMP know that
1471 * we are leaving the multicast group.
1473 igmp_leavegroup(inm
);
1474 lck_mtx_lock(rnh_lock
);
1475 LIST_REMOVE(inm
, inm_link
);
1476 lck_mtx_unlock(rnh_lock
);
1477 FREE(inm
, M_IPMADDR
);
1481 * Add an address to the list of IP multicast addresses for a given interface.
1488 struct in_multi
*inm
;
1490 struct sockaddr_in sin
;
1491 struct ifmultiaddr
*ifma
;
1494 * Call generic routine to add membership or increment
1495 * refcount. It wants addresses in the form of a sockaddr,
1496 * so we build one here (being careful to zero the unused bytes).
1498 bzero(&sin
, sizeof sin
);
1499 sin
.sin_family
= AF_INET
;
1500 sin
.sin_len
= sizeof sin
;
1502 error
= if_addmulti(ifp
, (struct sockaddr
*)&sin
, &ifma
);
1508 * If ifma->ifma_protospec is null, then if_addmulti() created
1509 * a new record. Otherwise, we are done.
1511 if (ifma
->ifma_protospec
!= 0) {
1512 return ifma
->ifma_protospec
;
1515 inm
= (struct in_multi
*) _MALLOC(sizeof(*inm
), M_IPMADDR
, M_WAITOK
);
1520 bzero(inm
, sizeof *inm
);
1521 inm
->inm_addr
= *ap
;
1523 inm
->inm_ifma
= ifma
;
1524 lck_mtx_lock(rnh_lock
);
1525 if (ifma
->ifma_protospec
== NULL
) {
1526 ifma
->ifma_protospec
= inm
;
1527 ifma
->ifma_free
= in_free_inm
;
1528 LIST_INSERT_HEAD(&in_multihead
, inm
, inm_link
);
1530 lck_mtx_unlock(rnh_lock
);
1532 if (ifma
->ifma_protospec
!= inm
) {
1533 _FREE(inm
, M_IPMADDR
);
1534 return ifma
->ifma_protospec
;
1538 * Let IGMP know that we have joined a new IP multicast group.
1540 error
= igmp_joingroup(inm
);
1545 * We can't free the inm because someone else may already be
1546 * using it. Once we put it in to ifma->ifma_protospec, it
1547 * must exist as long as the ifma does. Might be nice to flag
1548 * the error so we can try igmp_joingroup the next time through.
1550 log(LOG_ERR
, "igmp_joingroup error %d joining multicast %s on %s%d\n",
1551 error
, inet_ntop(AF_INET
, &sin
.sin_addr
, addrbuf
, sizeof(addrbuf
)),
1552 ifp
->if_name
, ifp
->if_unit
);
1559 * Delete a multicast address record.
1563 struct in_multi
**inm
)
1565 struct in_multi
*inm2
;
1567 lck_mtx_lock(rnh_lock
);
1568 LIST_FOREACH(inm2
, &in_multihead
, inm_link
) {
1573 lck_mtx_unlock(rnh_lock
);
1574 printf("in_delmulti - ignoring invalid inm (%p)\n", *inm
);
1577 lck_mtx_unlock(rnh_lock
);
1579 /* We intentionally do this a bit differently than BSD */
1580 if ((*inm
)->inm_ifma
) {
1581 if_delmultiaddr((*inm
)->inm_ifma
, 0);
1582 ifma_release((*inm
)->inm_ifma
);
1588 int inet_aton(char *cp
, struct in_addr
*pin
);
1590 inet_aton(char * cp
, struct in_addr
* pin
)
1592 u_char
* b
= (unsigned char *)pin
;
1596 for (p
= cp
, i
= 0; i
< 4; i
++) {
1597 u_int32_t l
= strtoul(p
, 0, 0);
1602 if (i
< 3 && p
== NULL
)
1611 * Called as part of ip_init
1614 in_ifaddr_init(void)
1616 PE_parse_boot_argn("ifa_debug", &inifa_debug
, sizeof (inifa_debug
));
1618 inifa_size
= (inifa_debug
== 0) ? sizeof (struct in_ifaddr
) :
1619 sizeof (struct in_ifaddr_dbg
);
1621 inifa_zone
= zinit(inifa_size
, INIFA_ZONE_MAX
* inifa_size
,
1622 0, INIFA_ZONE_NAME
);
1623 if (inifa_zone
== NULL
)
1624 panic("%s: failed allocating %s", __func__
, INIFA_ZONE_NAME
);
1626 zone_change(inifa_zone
, Z_EXPAND
, TRUE
);
1629 static struct in_ifaddr
*
1630 in_ifaddr_alloc(int how
)
1632 struct in_ifaddr
*inifa
;
1634 inifa
= (how
== M_WAITOK
) ? zalloc(inifa_zone
) :
1635 zalloc_noblock(inifa_zone
);
1636 if (inifa
!= NULL
) {
1637 bzero(inifa
, inifa_size
);
1638 inifa
->ia_ifa
.ifa_free
= in_ifaddr_free
;
1639 inifa
->ia_ifa
.ifa_debug
|= IFD_ALLOC
;
1640 if (inifa_debug
!= 0) {
1641 struct in_ifaddr_dbg
*inifa_dbg
=
1642 (struct in_ifaddr_dbg
*)inifa
;
1643 inifa
->ia_ifa
.ifa_debug
|= IFD_DEBUG
;
1644 inifa
->ia_ifa
.ifa_trace
= in_ifaddr_trace
;
1645 ctrace_record(&inifa_dbg
->inifa_alloc
);
1652 in_ifaddr_free(struct ifaddr
*ifa
)
1654 if (ifa
->ifa_refcnt
!= 0)
1655 panic("%s: ifa %p bad ref cnt", __func__
, ifa
);
1656 if (!(ifa
->ifa_debug
& IFD_ALLOC
))
1657 panic("%s: ifa %p cannot be freed", __func__
, ifa
);
1659 if (ifa
->ifa_debug
& IFD_DEBUG
) {
1660 struct in_ifaddr_dbg
*inifa_dbg
= (struct in_ifaddr_dbg
*)ifa
;
1661 ctrace_record(&inifa_dbg
->inifa_free
);
1662 bcopy(&inifa_dbg
->inifa
, &inifa_dbg
->inifa_old
,
1663 sizeof (struct in_ifaddr
));
1665 bzero(ifa
, sizeof (struct in_ifaddr
));
1666 zfree(inifa_zone
, ifa
);
1670 in_ifaddr_trace(struct ifaddr
*ifa
, int refhold
)
1672 struct in_ifaddr_dbg
*inifa_dbg
= (struct in_ifaddr_dbg
*)ifa
;
1677 if (!(ifa
->ifa_debug
& IFD_DEBUG
))
1678 panic("%s: ifa %p has no debug structure", __func__
, ifa
);
1681 cnt
= &inifa_dbg
->inifa_refhold_cnt
;
1682 tr
= inifa_dbg
->inifa_refhold
;
1684 cnt
= &inifa_dbg
->inifa_refrele_cnt
;
1685 tr
= inifa_dbg
->inifa_refrele
;
1688 idx
= OSAddAtomic16(1, (volatile SInt16
*)cnt
) % CTRACE_HIST_SIZE
;
1689 ctrace_record(&tr
[idx
]);