2 * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved.
4 * @APPLE_LICENSE_OSREFERENCE_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
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
31 * Copyright (c) 1982, 1986, 1991, 1993
32 * The Regents of the University of California. All rights reserved.
34 * Redistribution and use in source and binary forms, with or without
35 * modification, are permitted provided that the following conditions
37 * 1. Redistributions of source code must retain the above copyright
38 * notice, this list of conditions and the following disclaimer.
39 * 2. Redistributions in binary form must reproduce the above copyright
40 * notice, this list of conditions and the following disclaimer in the
41 * documentation and/or other materials provided with the distribution.
42 * 3. All advertising materials mentioning features or use of this software
43 * must display the following acknowledgement:
44 * This product includes software developed by the University of
45 * California, Berkeley and its contributors.
46 * 4. Neither the name of the University nor the names of its contributors
47 * may be used to endorse or promote products derived from this software
48 * without specific prior written permission.
50 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
51 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
54 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
58 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
59 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 * @(#)in.c 8.4 (Berkeley) 1/9/95
63 * $FreeBSD: src/sys/netinet/in.c,v 1.44.2.5 2001/08/13 16:26:17 ume Exp $
66 #include <sys/param.h>
67 #include <sys/systm.h>
68 #include <sys/sockio.h>
69 #include <sys/socketvar.h>
70 #include <sys/malloc.h>
72 #include <sys/socket.h>
73 #include <sys/kernel.h>
74 #include <sys/sysctl.h>
75 #include <sys/kern_event.h>
76 #include <sys/syslog.h>
79 #include <net/if_types.h>
80 #include <net/route.h>
82 #include <netinet/in.h>
83 #include <netinet/in_var.h>
84 #include <netinet/in_pcb.h>
86 #include <netinet/igmp_var.h>
89 #include <netinet/ip_var.h>
91 #include <netinet/tcp.h>
92 #include <netinet/tcp_timer.h>
93 #include <netinet/tcp_var.h>
98 static int in_mask2len(struct in_addr
*);
99 static void in_len2mask(struct in_addr
*, int);
100 static int in_lifaddr_ioctl(struct socket
*, u_long
, caddr_t
,
101 struct ifnet
*, struct proc
*);
103 static void in_socktrim(struct sockaddr_in
*);
104 static int in_ifinit(struct ifnet
*,
105 struct in_ifaddr
*, struct sockaddr_in
*, int);
107 static int subnetsarelocal
= 0;
108 SYSCTL_INT(_net_inet_ip
, OID_AUTO
, subnets_are_local
, CTLFLAG_RW
,
109 &subnetsarelocal
, 0, "");
111 struct in_multihead in_multihead
; /* XXX BSS initialization */
113 extern lck_mtx_t
*rt_mtx
;
115 /* Track whether or not the SIOCARPIPLL ioctl has been called */
116 __private_extern__ u_int32_t ipv4_ll_arp_aware
= 0;
119 * Return 1 if an internet address is for a ``local'' host
120 * (one to which we have a connection). If subnetsarelocal
121 * is true, this includes other subnets of the local net.
122 * Otherwise, it includes only the directly-connected (sub)nets.
128 u_long i
= ntohl(in
.s_addr
);
129 struct in_ifaddr
*ia
;
131 if (subnetsarelocal
) {
132 lck_mtx_lock(rt_mtx
);
133 for (ia
= in_ifaddrhead
.tqh_first
; ia
;
134 ia
= ia
->ia_link
.tqe_next
)
135 if ((i
& ia
->ia_netmask
) == ia
->ia_net
) {
136 lck_mtx_unlock(rt_mtx
);
139 lck_mtx_unlock(rt_mtx
);
141 lck_mtx_lock(rt_mtx
);
142 for (ia
= in_ifaddrhead
.tqh_first
; ia
;
143 ia
= ia
->ia_link
.tqe_next
)
144 if ((i
& ia
->ia_subnetmask
) == ia
->ia_subnet
) {
145 lck_mtx_unlock(rt_mtx
);
148 lck_mtx_unlock(rt_mtx
);
154 * Determine whether an IP address is in a reserved set of addresses
155 * that may not be forwarded, or whether datagrams to that destination
162 u_long i
= ntohl(in
.s_addr
);
165 if (IN_EXPERIMENTAL(i
) || IN_MULTICAST(i
))
168 net
= i
& IN_CLASSA_NET
;
169 if (net
== 0 || net
== (IN_LOOPBACKNET
<< IN_CLASSA_NSHIFT
))
176 * Trim a mask in a sockaddr
180 struct sockaddr_in
*ap
;
182 char *cplim
= (char *) &ap
->sin_addr
;
183 char *cp
= (char *) (&ap
->sin_addr
+ 1);
186 while (--cp
>= cplim
)
188 (ap
)->sin_len
= cp
- (char *) (ap
) + 1;
195 struct in_addr
*mask
;
201 for (x
= 0; x
< sizeof(*mask
); x
++) {
206 if (x
< sizeof(*mask
)) {
207 for (y
= 0; y
< 8; y
++) {
208 if ((p
[x
] & (0x80 >> y
)) == 0)
216 in_len2mask(mask
, len
)
217 struct in_addr
*mask
;
224 bzero(mask
, sizeof(*mask
));
225 for (i
= 0; i
< len
/ 8; i
++)
228 p
[i
] = (0xff00 >> (len
% 8)) & 0xff;
231 static int in_interfaces
; /* number of external internet interfaces */
234 * Generic internet control operations (ioctl's).
235 * Ifp is 0 if not an interface-specific ioctl.
246 struct ifreq
*ifr
= (struct ifreq
*)data
;
247 struct in_ifaddr
*ia
= 0, *iap
;
249 struct in_ifaddr
*oia
;
250 struct in_aliasreq
*ifra
= (struct in_aliasreq
*)data
;
251 struct sockaddr_in oldaddr
;
252 int error
, hostIsNew
, maskIsNew
;
254 struct kev_msg ev_msg
;
255 struct kev_in_data in_event_data
;
261 if (p
&& (error
= proc_suser(p
)) != 0)
267 return in_lifaddr_ioctl(so
, cmd
, data
, ifp
, p
);
271 * Find address for this interface, if it exists.
273 * If an alias address was specified, find that one instead of
274 * the first one on the interface.
277 lck_mtx_lock(rt_mtx
);
278 for (iap
= in_ifaddrhead
.tqh_first
; iap
;
279 iap
= iap
->ia_link
.tqe_next
)
280 if (iap
->ia_ifp
== ifp
) {
281 if (((struct sockaddr_in
*)&ifr
->ifr_addr
)->sin_addr
.s_addr
==
282 iap
->ia_addr
.sin_addr
.s_addr
) {
285 } else if (ia
== NULL
) {
287 if (ifr
->ifr_addr
.sa_family
!= AF_INET
)
291 lck_mtx_unlock(rt_mtx
);
296 if (p
&& (error
= proc_suser(p
)) != 0)
303 return (EADDRNOTAVAIL
);
304 if (ifra
->ifra_addr
.sin_family
== AF_INET
) {
305 lck_mtx_lock(rt_mtx
);
306 for (oia
= ia
; ia
; ia
= ia
->ia_link
.tqe_next
) {
307 if (ia
->ia_ifp
== ifp
&&
308 ia
->ia_addr
.sin_addr
.s_addr
==
309 ifra
->ifra_addr
.sin_addr
.s_addr
)
312 lck_mtx_unlock(rt_mtx
);
313 if ((ifp
->if_flags
& IFF_POINTOPOINT
)
314 && (cmd
== SIOCAIFADDR
)
315 && (ifra
->ifra_dstaddr
.sin_addr
.s_addr
320 else if (cmd
== SIOCAIFADDR
)
322 if (cmd
== SIOCDIFADDR
&& ia
== 0)
323 return (EADDRNOTAVAIL
);
328 if ((so
->so_state
& SS_PRIV
) == 0)
332 return (EADDRNOTAVAIL
);
333 if (ifra
->ifra_addr
.sin_family
!= AF_INET
&& cmd
== SIOCSIFADDR
)
335 if (ia
== (struct in_ifaddr
*)0) {
336 ia
= (struct in_ifaddr
*)
337 _MALLOC(sizeof *ia
, M_IFADDR
, M_WAITOK
);
338 if (ia
== (struct in_ifaddr
*)NULL
)
340 bzero((caddr_t
)ia
, sizeof *ia
);
342 * Protect from ipintr() traversing address list
343 * while we're modifying it.
348 ifa
->ifa_addr
= (struct sockaddr
*)&ia
->ia_addr
;
349 ifa
->ifa_dstaddr
= (struct sockaddr
*)&ia
->ia_dstaddr
;
350 ifa
->ifa_netmask
= (struct sockaddr
*)&ia
->ia_sockmask
;
351 ia
->ia_sockmask
.sin_len
= 8;
352 ifnet_lock_exclusive(ifp
);
353 if (ifp
->if_flags
& IFF_BROADCAST
) {
354 ia
->ia_broadaddr
.sin_len
= sizeof(ia
->ia_addr
);
355 ia
->ia_broadaddr
.sin_family
= AF_INET
;
358 if (!(ifp
->if_flags
& IFF_LOOPBACK
))
360 if_attach_ifa(ifp
, ifa
);
361 ifnet_lock_done(ifp
);
363 lck_mtx_lock(rt_mtx
);
364 TAILQ_INSERT_TAIL(&in_ifaddrhead
, ia
, ia_link
);
365 lck_mtx_unlock(rt_mtx
);
367 /* Generic protocol plumbing */
369 if (error
= dlil_plumb_protocol(PF_INET
, ifp
)) {
370 kprintf("in.c: warning can't plumb proto if=%s%n type %d error=%d\n",
371 ifp
->if_name
, ifp
->if_unit
, ifp
->if_type
, error
);
372 error
= 0; /*discard error, can be cold with unsupported interfaces */
378 case SIOCPROTOATTACH
:
379 case SIOCPROTODETACH
:
380 if (p
&& (error
= proc_suser(p
)) != 0)
383 return (EADDRNOTAVAIL
);
388 if ((so
->so_state
& SS_PRIV
) == 0)
391 if (p
&& (error
= suser(p
)) != 0)
400 if (ia
== (struct in_ifaddr
*)0)
401 return (EADDRNOTAVAIL
);
407 return (EADDRNOTAVAIL
);
408 ifnet_lock_exclusive(ifp
);
410 ifp
->if_eflags
|= IFEF_AUTOCONFIGURING
;
412 ifp
->if_eflags
&= ~IFEF_AUTOCONFIGURING
;
413 ifnet_lock_done(ifp
);
418 return (EADDRNOTAVAIL
);
419 ipv4_ll_arp_aware
= 1;
420 ifnet_lock_exclusive(ifp
);
422 ifp
->if_eflags
|= IFEF_ARPLL
;
424 ifp
->if_eflags
&= ~IFEF_ARPLL
;
425 ifnet_lock_done(ifp
);
429 *((struct sockaddr_in
*)&ifr
->ifr_addr
) = ia
->ia_addr
;
433 if ((ifp
->if_flags
& IFF_BROADCAST
) == 0)
435 *((struct sockaddr_in
*)&ifr
->ifr_dstaddr
) = ia
->ia_broadaddr
;
439 if ((ifp
->if_flags
& IFF_POINTOPOINT
) == 0)
441 *((struct sockaddr_in
*)&ifr
->ifr_dstaddr
) = ia
->ia_dstaddr
;
445 *((struct sockaddr_in
*)&ifr
->ifr_addr
) = ia
->ia_sockmask
;
449 if ((ifp
->if_flags
& IFF_POINTOPOINT
) == 0)
451 oldaddr
= ia
->ia_dstaddr
;
452 ia
->ia_dstaddr
= *(struct sockaddr_in
*)&ifr
->ifr_dstaddr
;
453 error
= dlil_ioctl(PF_INET
, ifp
, SIOCSIFDSTADDR
, (caddr_t
)ia
);
454 if (error
== EOPNOTSUPP
)
458 ia
->ia_dstaddr
= oldaddr
;
462 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
463 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
464 ev_msg
.kev_subclass
= KEV_INET_SUBCLASS
;
466 ev_msg
.event_code
= KEV_INET_SIFDSTADDR
;
468 if (ia
->ia_ifa
.ifa_dstaddr
)
469 in_event_data
.ia_dstaddr
=
470 ((struct sockaddr_in
*)ia
->ia_ifa
.ifa_dstaddr
)->sin_addr
;
472 in_event_data
.ia_dstaddr
.s_addr
= 0;
474 in_event_data
.ia_addr
= ia
->ia_addr
.sin_addr
;
475 in_event_data
.ia_net
= ia
->ia_net
;
476 in_event_data
.ia_netmask
= ia
->ia_netmask
;
477 in_event_data
.ia_subnet
= ia
->ia_subnet
;
478 in_event_data
.ia_subnetmask
= ia
->ia_subnetmask
;
479 in_event_data
.ia_netbroadcast
= ia
->ia_netbroadcast
;
480 strncpy(&in_event_data
.link_data
.if_name
[0], ifp
->if_name
, IFNAMSIZ
);
481 in_event_data
.link_data
.if_family
= ifp
->if_family
;
482 in_event_data
.link_data
.if_unit
= (unsigned long) ifp
->if_unit
;
484 ev_msg
.dv
[0].data_ptr
= &in_event_data
;
485 ev_msg
.dv
[0].data_length
= sizeof(struct kev_in_data
);
486 ev_msg
.dv
[1].data_length
= 0;
488 kev_post_msg(&ev_msg
);
491 if (ia
->ia_flags
& IFA_ROUTE
) {
492 ia
->ia_ifa
.ifa_dstaddr
= (struct sockaddr
*)&oldaddr
;
493 rtinit(&(ia
->ia_ifa
), (int)RTM_DELETE
, RTF_HOST
);
494 ia
->ia_ifa
.ifa_dstaddr
=
495 (struct sockaddr
*)&ia
->ia_dstaddr
;
496 rtinit(&(ia
->ia_ifa
), (int)RTM_ADD
, RTF_HOST
|RTF_UP
);
501 if ((ifp
->if_flags
& IFF_BROADCAST
) == 0)
503 ia
->ia_broadaddr
= *(struct sockaddr_in
*)&ifr
->ifr_broadaddr
;
505 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
506 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
507 ev_msg
.kev_subclass
= KEV_INET_SUBCLASS
;
509 ev_msg
.event_code
= KEV_INET_SIFBRDADDR
;
511 if (ia
->ia_ifa
.ifa_dstaddr
)
512 in_event_data
.ia_dstaddr
=
513 ((struct sockaddr_in
*)ia
->ia_ifa
.ifa_dstaddr
)->sin_addr
;
515 in_event_data
.ia_dstaddr
.s_addr
= 0;
517 in_event_data
.ia_addr
= ia
->ia_addr
.sin_addr
;
518 in_event_data
.ia_net
= ia
->ia_net
;
519 in_event_data
.ia_netmask
= ia
->ia_netmask
;
520 in_event_data
.ia_subnet
= ia
->ia_subnet
;
521 in_event_data
.ia_subnetmask
= ia
->ia_subnetmask
;
522 in_event_data
.ia_netbroadcast
= ia
->ia_netbroadcast
;
523 strncpy(&in_event_data
.link_data
.if_name
[0], ifp
->if_name
, IFNAMSIZ
);
524 in_event_data
.link_data
.if_family
= ifp
->if_family
;
525 in_event_data
.link_data
.if_unit
= (unsigned long) ifp
->if_unit
;
527 ev_msg
.dv
[0].data_ptr
= &in_event_data
;
528 ev_msg
.dv
[0].data_length
= sizeof(struct kev_in_data
);
529 ev_msg
.dv
[1].data_length
= 0;
531 kev_post_msg(&ev_msg
);
536 return (in_ifinit(ifp
, ia
,
537 (struct sockaddr_in
*) &ifr
->ifr_addr
, 1));
539 case SIOCPROTOATTACH
:
540 error
= dlil_plumb_protocol(PF_INET
, ifp
);
545 case SIOCPROTODETACH
:
546 // if an ip address is still present, refuse to detach
547 ifnet_lock_shared(ifp
);
548 TAILQ_FOREACH(ifa
, &ifp
->if_addrhead
, ifa_link
)
549 if (ifa
->ifa_addr
->sa_family
== AF_INET
)
551 ifnet_lock_done(ifp
);
555 error
= dlil_unplumb_protocol(PF_INET
, ifp
);
562 i
= ifra
->ifra_addr
.sin_addr
.s_addr
;
563 ia
->ia_subnetmask
= ntohl(ia
->ia_sockmask
.sin_addr
.s_addr
= i
);
564 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
565 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
566 ev_msg
.kev_subclass
= KEV_INET_SUBCLASS
;
568 ev_msg
.event_code
= KEV_INET_SIFNETMASK
;
570 if (ia
->ia_ifa
.ifa_dstaddr
)
571 in_event_data
.ia_dstaddr
=
572 ((struct sockaddr_in
*)ia
->ia_ifa
.ifa_dstaddr
)->sin_addr
;
574 in_event_data
.ia_dstaddr
.s_addr
= 0;
576 in_event_data
.ia_addr
= ia
->ia_addr
.sin_addr
;
577 in_event_data
.ia_net
= ia
->ia_net
;
578 in_event_data
.ia_netmask
= ia
->ia_netmask
;
579 in_event_data
.ia_subnet
= ia
->ia_subnet
;
580 in_event_data
.ia_subnetmask
= ia
->ia_subnetmask
;
581 in_event_data
.ia_netbroadcast
= ia
->ia_netbroadcast
;
582 strncpy(&in_event_data
.link_data
.if_name
[0], ifp
->if_name
, IFNAMSIZ
);
583 in_event_data
.link_data
.if_family
= ifp
->if_family
;
584 in_event_data
.link_data
.if_unit
= (unsigned long) ifp
->if_unit
;
586 ev_msg
.dv
[0].data_ptr
= &in_event_data
;
587 ev_msg
.dv
[0].data_length
= sizeof(struct kev_in_data
);
588 ev_msg
.dv
[1].data_length
= 0;
590 kev_post_msg(&ev_msg
);
598 if (ia
->ia_addr
.sin_family
== AF_INET
) {
599 if (ifra
->ifra_addr
.sin_len
== 0) {
600 ifra
->ifra_addr
= ia
->ia_addr
;
602 } else if (ifra
->ifra_addr
.sin_addr
.s_addr
==
603 ia
->ia_addr
.sin_addr
.s_addr
)
606 if (ifra
->ifra_mask
.sin_len
) {
607 in_ifscrub(ifp
, ia
, 0);
608 ia
->ia_sockmask
= ifra
->ifra_mask
;
610 ntohl(ia
->ia_sockmask
.sin_addr
.s_addr
);
613 if ((ifp
->if_flags
& IFF_POINTOPOINT
) &&
614 (ifra
->ifra_dstaddr
.sin_family
== AF_INET
)) {
615 in_ifscrub(ifp
, ia
, 0);
616 ia
->ia_dstaddr
= ifra
->ifra_dstaddr
;
617 maskIsNew
= 1; /* We lie; but the effect's the same */
619 if (ifra
->ifra_addr
.sin_family
== AF_INET
&&
620 (hostIsNew
|| maskIsNew
)) {
621 error
= in_ifinit(ifp
, ia
, &ifra
->ifra_addr
, 0);
623 if ((ifp
->if_flags
& IFF_BROADCAST
) &&
624 (ifra
->ifra_broadaddr
.sin_family
== AF_INET
))
625 ia
->ia_broadaddr
= ifra
->ifra_broadaddr
;
631 if ((error
== 0) || (error
== EEXIST
)) {
632 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
633 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
634 ev_msg
.kev_subclass
= KEV_INET_SUBCLASS
;
637 ev_msg
.event_code
= KEV_INET_NEW_ADDR
;
639 ev_msg
.event_code
= KEV_INET_CHANGED_ADDR
;
641 if (ia
->ia_ifa
.ifa_dstaddr
)
642 in_event_data
.ia_dstaddr
=
643 ((struct sockaddr_in
*)ia
->ia_ifa
.ifa_dstaddr
)->sin_addr
;
645 in_event_data
.ia_dstaddr
.s_addr
= 0;
647 in_event_data
.ia_addr
= ia
->ia_addr
.sin_addr
;
648 in_event_data
.ia_net
= ia
->ia_net
;
649 in_event_data
.ia_netmask
= ia
->ia_netmask
;
650 in_event_data
.ia_subnet
= ia
->ia_subnet
;
651 in_event_data
.ia_subnetmask
= ia
->ia_subnetmask
;
652 in_event_data
.ia_netbroadcast
= ia
->ia_netbroadcast
;
653 strncpy(&in_event_data
.link_data
.if_name
[0], ifp
->if_name
, IFNAMSIZ
);
654 in_event_data
.link_data
.if_family
= ifp
->if_family
;
655 in_event_data
.link_data
.if_unit
= (unsigned long) ifp
->if_unit
;
657 ev_msg
.dv
[0].data_ptr
= &in_event_data
;
658 ev_msg
.dv
[0].data_length
= sizeof(struct kev_in_data
);
659 ev_msg
.dv
[1].data_length
= 0;
661 kev_post_msg(&ev_msg
);
667 error
= dlil_ioctl(PF_INET
, ifp
, SIOCDIFADDR
, (caddr_t
)ia
);
668 if (error
== EOPNOTSUPP
)
673 /* Fill out the kernel event information */
674 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
675 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
676 ev_msg
.kev_subclass
= KEV_INET_SUBCLASS
;
678 ev_msg
.event_code
= KEV_INET_ADDR_DELETED
;
680 if (ia
->ia_ifa
.ifa_dstaddr
)
681 in_event_data
.ia_dstaddr
=
682 ((struct sockaddr_in
*)ia
->ia_ifa
.ifa_dstaddr
)->sin_addr
;
684 in_event_data
.ia_dstaddr
.s_addr
= 0;
686 in_event_data
.ia_addr
= ia
->ia_addr
.sin_addr
;
687 in_event_data
.ia_net
= ia
->ia_net
;
688 in_event_data
.ia_netmask
= ia
->ia_netmask
;
689 in_event_data
.ia_subnet
= ia
->ia_subnet
;
690 in_event_data
.ia_subnetmask
= ia
->ia_subnetmask
;
691 in_event_data
.ia_netbroadcast
= ia
->ia_netbroadcast
;
692 strncpy(&in_event_data
.link_data
.if_name
[0], ifp
->if_name
, IFNAMSIZ
);
693 in_event_data
.link_data
.if_family
= ifp
->if_family
;
694 in_event_data
.link_data
.if_unit
= (unsigned long) ifp
->if_unit
;
696 ev_msg
.dv
[0].data_ptr
= &in_event_data
;
697 ev_msg
.dv
[0].data_length
= sizeof(struct kev_in_data
);
698 ev_msg
.dv
[1].data_length
= 0;
700 lck_mtx_lock(rt_mtx
);
701 TAILQ_REMOVE(&in_ifaddrhead
, ia
, ia_link
);
703 * in_ifscrub kills the interface route.
705 in_ifscrub(ifp
, ia
, 1);
707 lck_mtx_unlock(rt_mtx
);
708 ifnet_lock_exclusive(ifp
);
709 if_detach_ifa(ifp
, ifa
);
710 ifafree(&ia
->ia_ifa
);
714 * If the interface supports multicast, and no address is left,
715 * remove the "all hosts" multicast group from that interface.
717 if (ifp
->if_flags
& IFF_MULTICAST
) {
719 struct in_multi
*inm
;
721 TAILQ_FOREACH(ifa
, &ifp
->if_addrhead
, ifa_link
)
722 if (ifa
->ifa_addr
->sa_family
== AF_INET
)
726 addr
.s_addr
= htonl(INADDR_ALLHOSTS_GROUP
);
727 IN_LOOKUP_MULTI(addr
, ifp
, inm
);
729 ifnet_lock_done(ifp
);
733 ifnet_lock_done(ifp
);
736 /* Post the kernel event */
737 kev_post_msg(&ev_msg
);
743 * Inspiration from tcp_ctloutput() and ip_ctloutput()
744 * Special ioctl for OpenTransport sockets
746 struct inpcb
*inp
, *cloned_inp
;
748 int cloned_fd
= *(int *)data
;
755 /* let's make sure it's either -1 or a valid file descriptor */
756 if (cloned_fd
!= -1) {
757 struct socket
*cloned_so
;
758 error2
= file_socket(cloned_fd
, &cloned_so
);
762 cloned_inp
= sotoinpcb(cloned_so
);
763 file_drop(cloned_fd
);
768 if (cloned_inp
== NULL
) {
769 /* OT always uses IP_PORTRANGE_HIGH */
770 inp
->inp_flags
&= ~(INP_LOWPORT
);
771 inp
->inp_flags
|= INP_HIGHPORT
;
772 /* For UDP, OT allows broadcast by default */
773 if (so
->so_type
== SOCK_DGRAM
)
774 so
->so_options
|= SO_BROADCAST
;
775 /* For TCP we want to see MSG_OOB when receive urgent data */
776 else if (so
->so_type
== SOCK_STREAM
)
777 so
->so_options
|= SO_WANTOOBFLAG
;
779 inp
->inp_ip_tos
= cloned_inp
->inp_ip_tos
;
780 inp
->inp_ip_ttl
= cloned_inp
->inp_ip_ttl
;
781 inp
->inp_flags
= cloned_inp
->inp_flags
;
783 /* Multicast options */
784 if (cloned_inp
->inp_moptions
!= NULL
) {
786 struct ip_moptions
*cloned_imo
= cloned_inp
->inp_moptions
;
787 struct ip_moptions
*imo
= inp
->inp_moptions
;
791 * No multicast option buffer attached to the pcb;
794 imo
= (struct ip_moptions
*)
795 _MALLOC(sizeof(*imo
), M_IPMOPTS
, M_WAITOK
);
800 inp
->inp_moptions
= imo
;
802 imo
->imo_multicast_ifp
= cloned_imo
->imo_multicast_ifp
;
803 imo
->imo_multicast_vif
= cloned_imo
->imo_multicast_vif
;
804 imo
->imo_multicast_ttl
= cloned_imo
->imo_multicast_ttl
;
805 imo
->imo_multicast_loop
= cloned_imo
->imo_multicast_loop
;
806 imo
->imo_num_memberships
= cloned_imo
->imo_num_memberships
;
807 for (i
= 0; i
< cloned_imo
->imo_num_memberships
; i
++) {
808 imo
->imo_membership
[i
] =
809 in_addmulti(&cloned_imo
->imo_membership
[i
]->inm_addr
,
810 cloned_imo
->imo_membership
[i
]->inm_ifp
);
811 if (imo
->imo_membership
[i
] == NULL
) {
816 if (i
< cloned_imo
->imo_num_memberships
) {
817 /* Failed, perform cleanup */
818 for (i
--; i
>= 0; i
--)
819 in_delmulti(&imo
->imo_membership
[i
]);
820 imo
->imo_num_memberships
= 0;
827 #endif /* __APPLE__ */
837 * SIOCGLIFADDR: get first address. (?!?)
838 * SIOCGLIFADDR with IFLR_PREFIX:
839 * get first address that matches the specified prefix.
840 * SIOCALIFADDR: add the specified address.
841 * SIOCALIFADDR with IFLR_PREFIX:
842 * EINVAL since we can't deduce hostid part of the address.
843 * SIOCDLIFADDR: delete the specified address.
844 * SIOCDLIFADDR with IFLR_PREFIX:
845 * delete the first address that matches the specified prefix.
847 * EINVAL on invalid parameters
848 * EADDRNOTAVAIL on prefix match failed/specified address not found
849 * other values may be returned from in_ioctl()
859 struct if_laddrreq
*iflr
= (struct if_laddrreq
*)data
;
864 panic("invalid argument to in_lifaddr_ioctl");
870 /* address must be specified on GET with IFLR_PREFIX */
871 if ((iflr
->flags
& IFLR_PREFIX
) == 0)
876 /* address must be specified on ADD and DELETE */
877 if (iflr
->addr
.ss_family
!= AF_INET
)
879 if (iflr
->addr
.ss_len
!= sizeof(struct sockaddr_in
))
881 /* XXX need improvement */
882 if (iflr
->dstaddr
.ss_family
883 && iflr
->dstaddr
.ss_family
!= AF_INET
)
885 if (iflr
->dstaddr
.ss_family
886 && iflr
->dstaddr
.ss_len
!= sizeof(struct sockaddr_in
))
889 default: /*shouldn't happen*/
892 if (sizeof(struct in_addr
) * 8 < iflr
->prefixlen
)
898 struct in_aliasreq ifra
;
900 if (iflr
->flags
& IFLR_PREFIX
)
903 /* copy args to in_aliasreq, perform ioctl(SIOCAIFADDR_IN6). */
904 bzero(&ifra
, sizeof(ifra
));
905 bcopy(iflr
->iflr_name
, ifra
.ifra_name
,
906 sizeof(ifra
.ifra_name
));
908 bcopy(&iflr
->addr
, &ifra
.ifra_addr
, iflr
->addr
.ss_len
);
910 if (iflr
->dstaddr
.ss_family
) { /*XXX*/
911 bcopy(&iflr
->dstaddr
, &ifra
.ifra_dstaddr
,
912 iflr
->dstaddr
.ss_len
);
915 ifra
.ifra_mask
.sin_family
= AF_INET
;
916 ifra
.ifra_mask
.sin_len
= sizeof(struct sockaddr_in
);
917 in_len2mask(&ifra
.ifra_mask
.sin_addr
, iflr
->prefixlen
);
919 return in_control(so
, SIOCAIFADDR
, (caddr_t
)&ifra
, ifp
, p
);
924 struct in_ifaddr
*ia
;
925 struct in_addr mask
, candidate
, match
;
926 struct sockaddr_in
*sin
;
929 bzero(&mask
, sizeof(mask
));
930 if (iflr
->flags
& IFLR_PREFIX
) {
931 /* lookup a prefix rather than address. */
932 in_len2mask(&mask
, iflr
->prefixlen
);
934 sin
= (struct sockaddr_in
*)&iflr
->addr
;
935 match
.s_addr
= sin
->sin_addr
.s_addr
;
936 match
.s_addr
&= mask
.s_addr
;
938 /* if you set extra bits, that's wrong */
939 if (match
.s_addr
!= sin
->sin_addr
.s_addr
)
944 if (cmd
== SIOCGLIFADDR
) {
945 /* on getting an address, take the 1st match */
948 /* on deleting an address, do exact match */
949 in_len2mask(&mask
, 32);
950 sin
= (struct sockaddr_in
*)&iflr
->addr
;
951 match
.s_addr
= sin
->sin_addr
.s_addr
;
957 ifnet_lock_shared(ifp
);
958 TAILQ_FOREACH(ifa
, &ifp
->if_addrhead
, ifa_link
) {
959 if (ifa
->ifa_addr
->sa_family
!= AF_INET6
)
963 candidate
.s_addr
= ((struct sockaddr_in
*)&ifa
->ifa_addr
)->sin_addr
.s_addr
;
964 candidate
.s_addr
&= mask
.s_addr
;
965 if (candidate
.s_addr
== match
.s_addr
)
968 ifnet_lock_done(ifp
);
970 return EADDRNOTAVAIL
;
971 ia
= (struct in_ifaddr
*)ifa
;
973 if (cmd
== SIOCGLIFADDR
) {
974 /* fill in the if_laddrreq structure */
975 bcopy(&ia
->ia_addr
, &iflr
->addr
, ia
->ia_addr
.sin_len
);
977 if ((ifp
->if_flags
& IFF_POINTOPOINT
) != 0) {
978 bcopy(&ia
->ia_dstaddr
, &iflr
->dstaddr
,
979 ia
->ia_dstaddr
.sin_len
);
981 bzero(&iflr
->dstaddr
, sizeof(iflr
->dstaddr
));
984 in_mask2len(&ia
->ia_sockmask
.sin_addr
);
986 iflr
->flags
= 0; /*XXX*/
990 struct in_aliasreq ifra
;
992 /* fill in_aliasreq and do ioctl(SIOCDIFADDR_IN6) */
993 bzero(&ifra
, sizeof(ifra
));
994 bcopy(iflr
->iflr_name
, ifra
.ifra_name
,
995 sizeof(ifra
.ifra_name
));
997 bcopy(&ia
->ia_addr
, &ifra
.ifra_addr
,
998 ia
->ia_addr
.sin_len
);
999 if ((ifp
->if_flags
& IFF_POINTOPOINT
) != 0) {
1000 bcopy(&ia
->ia_dstaddr
, &ifra
.ifra_dstaddr
,
1001 ia
->ia_dstaddr
.sin_len
);
1003 bcopy(&ia
->ia_sockmask
, &ifra
.ifra_dstaddr
,
1004 ia
->ia_sockmask
.sin_len
);
1006 return in_control(so
, SIOCDIFADDR
, (caddr_t
)&ifra
,
1012 return EOPNOTSUPP
; /*just for safety*/
1016 * Delete any existing route for an interface.
1021 struct in_ifaddr
*ia
,
1025 if ((ia
->ia_flags
& IFA_ROUTE
) == 0)
1028 lck_mtx_lock(rt_mtx
);
1029 if (ifp
->if_flags
& (IFF_LOOPBACK
|IFF_POINTOPOINT
))
1030 rtinit_locked(&(ia
->ia_ifa
), (int)RTM_DELETE
, RTF_HOST
);
1032 rtinit_locked(&(ia
->ia_ifa
), (int)RTM_DELETE
, 0);
1033 ia
->ia_flags
&= ~IFA_ROUTE
;
1035 lck_mtx_unlock(rt_mtx
);
1039 * Initialize an interface's internet address
1040 * and routing table entry.
1045 struct in_ifaddr
*ia
,
1046 struct sockaddr_in
*sin
,
1049 u_long i
= ntohl(sin
->sin_addr
.s_addr
);
1050 struct sockaddr_in oldaddr
;
1051 int flags
= RTF_UP
, error
;
1053 oldaddr
= ia
->ia_addr
;
1057 * Give the interface a chance to initialize
1058 * if this is its first address,
1059 * and to validate the address if necessary.
1061 error
= dlil_ioctl(PF_INET
, ifp
, SIOCSIFADDR
, (caddr_t
)ia
);
1062 if (error
== EOPNOTSUPP
)
1065 ia
->ia_addr
= oldaddr
;
1069 ia
->ia_ifa
.ifa_addr
= (struct sockaddr
*)&oldaddr
;
1070 in_ifscrub(ifp
, ia
, 0);
1071 ia
->ia_ifa
.ifa_addr
= (struct sockaddr
*)&ia
->ia_addr
;
1074 ia
->ia_netmask
= IN_CLASSA_NET
;
1075 else if (IN_CLASSB(i
))
1076 ia
->ia_netmask
= IN_CLASSB_NET
;
1078 ia
->ia_netmask
= IN_CLASSC_NET
;
1080 * The subnet mask usually includes at least the standard network part,
1081 * but may may be smaller in the case of supernetting.
1082 * If it is set, we believe it.
1084 if (ia
->ia_subnetmask
== 0) {
1085 ia
->ia_subnetmask
= ia
->ia_netmask
;
1086 ia
->ia_sockmask
.sin_addr
.s_addr
= htonl(ia
->ia_subnetmask
);
1088 ia
->ia_netmask
&= ia
->ia_subnetmask
;
1089 ia
->ia_net
= i
& ia
->ia_netmask
;
1090 ia
->ia_subnet
= i
& ia
->ia_subnetmask
;
1091 in_socktrim(&ia
->ia_sockmask
);
1093 * Add route for the network.
1095 ia
->ia_ifa
.ifa_metric
= ifp
->if_metric
;
1096 if (ifp
->if_flags
& IFF_BROADCAST
) {
1097 ia
->ia_broadaddr
.sin_addr
.s_addr
=
1098 htonl(ia
->ia_subnet
| ~ia
->ia_subnetmask
);
1099 ia
->ia_netbroadcast
.s_addr
=
1100 htonl(ia
->ia_net
| ~ ia
->ia_netmask
);
1101 } else if (ifp
->if_flags
& IFF_LOOPBACK
) {
1102 ia
->ia_ifa
.ifa_dstaddr
= ia
->ia_ifa
.ifa_addr
;
1104 } else if (ifp
->if_flags
& IFF_POINTOPOINT
) {
1105 if (ia
->ia_dstaddr
.sin_family
!= AF_INET
)
1109 if ((error
= rtinit(&(ia
->ia_ifa
), (int)RTM_ADD
, flags
)) == 0)
1110 ia
->ia_flags
|= IFA_ROUTE
;
1111 /* XXX check if the subnet route points to the same interface */
1112 if (error
== EEXIST
)
1116 * If the interface supports multicast, join the "all hosts"
1117 * multicast group on that interface.
1119 if (ifp
->if_flags
& IFF_MULTICAST
) {
1120 struct in_multi
*inm
;
1121 struct in_addr addr
;
1123 addr
.s_addr
= htonl(INADDR_ALLHOSTS_GROUP
);
1124 ifnet_lock_shared(ifp
);
1125 IN_LOOKUP_MULTI(addr
, ifp
, inm
);
1126 ifnet_lock_done(ifp
);
1128 in_addmulti(&addr
, ifp
);
1135 * Return 1 if the address might be a local broadcast address.
1145 if (in
.s_addr
== INADDR_BROADCAST
||
1146 in
.s_addr
== INADDR_ANY
)
1148 if ((ifp
->if_flags
& IFF_BROADCAST
) == 0)
1150 t
= ntohl(in
.s_addr
);
1152 * Look through the list of addresses for a match
1153 * with a broadcast address.
1155 #define ia ((struct in_ifaddr *)ifa)
1156 ifnet_lock_shared(ifp
);
1157 TAILQ_FOREACH(ifa
, &ifp
->if_addrhead
, ifa_link
) {
1158 if (ifa
->ifa_addr
== NULL
) {
1159 ifnet_lock_done(ifp
);
1162 if (ifa
->ifa_addr
->sa_family
== AF_INET
&&
1163 (in
.s_addr
== ia
->ia_broadaddr
.sin_addr
.s_addr
||
1164 in
.s_addr
== ia
->ia_netbroadcast
.s_addr
||
1166 * Check for old-style (host 0) broadcast.
1168 t
== ia
->ia_subnet
|| t
== ia
->ia_net
) &&
1170 * Check for an all one subnetmask. These
1171 * only exist when an interface gets a secondary
1174 ia
->ia_subnetmask
!= (u_long
)0xffffffff) {
1175 ifnet_lock_done(ifp
);
1179 ifnet_lock_done(ifp
);
1186 void* ifma_protospec
)
1188 struct in_multi
*inm
= ifma_protospec
;
1191 * No remaining claims to this record; let IGMP know that
1192 * we are leaving the multicast group.
1194 igmp_leavegroup(inm
);
1195 lck_mtx_lock(rt_mtx
);
1196 LIST_REMOVE(inm
, inm_link
);
1197 lck_mtx_unlock(rt_mtx
);
1198 FREE(inm
, M_IPMADDR
);
1202 * Add an address to the list of IP multicast addresses for a given interface.
1209 struct in_multi
*inm
;
1211 struct sockaddr_in sin
;
1212 struct ifmultiaddr
*ifma
;
1215 * Call generic routine to add membership or increment
1216 * refcount. It wants addresses in the form of a sockaddr,
1217 * so we build one here (being careful to zero the unused bytes).
1219 bzero(&sin
, sizeof sin
);
1220 sin
.sin_family
= AF_INET
;
1221 sin
.sin_len
= sizeof sin
;
1223 error
= if_addmulti(ifp
, (struct sockaddr
*)&sin
, &ifma
);
1229 * If ifma->ifma_protospec is null, then if_addmulti() created
1230 * a new record. Otherwise, we are done.
1232 if (ifma
->ifma_protospec
!= 0) {
1233 return ifma
->ifma_protospec
;
1236 inm
= (struct in_multi
*) _MALLOC(sizeof(*inm
), M_IPMADDR
, M_WAITOK
);
1241 bzero(inm
, sizeof *inm
);
1242 inm
->inm_addr
= *ap
;
1244 inm
->inm_ifma
= ifma
;
1245 lck_mtx_lock(rt_mtx
);
1246 if (ifma
->ifma_protospec
== NULL
) {
1247 ifma
->ifma_protospec
= inm
;
1248 ifma
->ifma_free
= in_free_inm
;
1249 LIST_INSERT_HEAD(&in_multihead
, inm
, inm_link
);
1251 lck_mtx_unlock(rt_mtx
);
1253 if (ifma
->ifma_protospec
!= inm
) {
1254 _FREE(inm
, M_IPMADDR
);
1255 return ifma
->ifma_protospec
;
1259 * Let IGMP know that we have joined a new IP multicast group.
1261 error
= igmp_joingroup(inm
);
1266 * We can't free the inm because someone else may already be
1267 * using it. Once we put it in to ifma->ifma_protospec, it
1268 * must exist as long as the ifma does. Might be nice to flag
1269 * the error so we can try igmp_joingroup the next time through.
1271 log(LOG_ERR
, "igmp_joingroup error %d joining multicast %s on %s%d\n",
1272 error
, inet_ntop(AF_INET
, &sin
.sin_addr
, addrbuf
, sizeof(addrbuf
)),
1273 ifp
->if_name
, ifp
->if_unit
);
1280 * Delete a multicast address record.
1284 struct in_multi
**inm
)
1286 struct in_multi
*inm2
;
1288 lck_mtx_lock(rt_mtx
);
1289 LIST_FOREACH(inm2
, &in_multihead
, inm_link
) {
1294 lck_mtx_unlock(rt_mtx
);
1295 printf("in_delmulti - ignorning invalid inm (0x%x)\n", *inm
);
1298 lck_mtx_unlock(rt_mtx
);
1300 /* We intentionally do this a bit differently than BSD */
1301 if ((*inm
)->inm_ifma
) {
1302 if_delmultiaddr((*inm
)->inm_ifma
, 0);
1303 ifma_release((*inm
)->inm_ifma
);
1310 inet_aton(char * cp
, struct in_addr
* pin
)
1312 u_char
* b
= (char *)pin
;
1316 for (p
= cp
, i
= 0; i
< 4; i
++) {
1317 u_long l
= strtoul(p
, 0, 0);
1322 if (i
< 3 && p
== NULL
)