2 * Copyright (c) 2000 Apple Computer, 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>
77 #include <net/if_types.h>
78 #include <net/route.h>
80 #include <netinet/in.h>
81 #include <netinet/in_var.h>
82 #include <netinet/in_pcb.h>
84 #include <netinet/igmp_var.h>
87 #include <netinet/ip_var.h>
89 #include <netinet/tcp.h>
90 #include <netinet/tcp_timer.h>
91 #include <netinet/tcp_var.h>
96 static int in_mask2len(struct in_addr
*);
97 static void in_len2mask(struct in_addr
*, int);
98 static int in_lifaddr_ioctl(struct socket
*, u_long
, caddr_t
,
99 struct ifnet
*, struct proc
*);
101 static void in_socktrim(struct sockaddr_in
*);
102 static int in_ifinit(struct ifnet
*,
103 struct in_ifaddr
*, struct sockaddr_in
*, int);
105 static int subnetsarelocal
= 0;
106 SYSCTL_INT(_net_inet_ip
, OID_AUTO
, subnets_are_local
, CTLFLAG_RW
,
107 &subnetsarelocal
, 0, "");
109 struct in_multihead in_multihead
; /* XXX BSS initialization */
111 extern lck_mtx_t
*rt_mtx
;
113 /* Track whether or not the SIOCARPIPLL ioctl has been called */
114 __private_extern__ u_int32_t ipv4_ll_arp_aware
= 0;
117 * Return 1 if an internet address is for a ``local'' host
118 * (one to which we have a connection). If subnetsarelocal
119 * is true, this includes other subnets of the local net.
120 * Otherwise, it includes only the directly-connected (sub)nets.
126 u_long i
= ntohl(in
.s_addr
);
127 struct in_ifaddr
*ia
;
129 if (subnetsarelocal
) {
130 lck_mtx_lock(rt_mtx
);
131 for (ia
= in_ifaddrhead
.tqh_first
; ia
;
132 ia
= ia
->ia_link
.tqe_next
)
133 if ((i
& ia
->ia_netmask
) == ia
->ia_net
) {
134 lck_mtx_unlock(rt_mtx
);
137 lck_mtx_unlock(rt_mtx
);
139 lck_mtx_lock(rt_mtx
);
140 for (ia
= in_ifaddrhead
.tqh_first
; ia
;
141 ia
= ia
->ia_link
.tqe_next
)
142 if ((i
& ia
->ia_subnetmask
) == ia
->ia_subnet
) {
143 lck_mtx_unlock(rt_mtx
);
146 lck_mtx_unlock(rt_mtx
);
152 * Determine whether an IP address is in a reserved set of addresses
153 * that may not be forwarded, or whether datagrams to that destination
160 u_long i
= ntohl(in
.s_addr
);
163 if (IN_EXPERIMENTAL(i
) || IN_MULTICAST(i
))
166 net
= i
& IN_CLASSA_NET
;
167 if (net
== 0 || net
== (IN_LOOPBACKNET
<< IN_CLASSA_NSHIFT
))
174 * Trim a mask in a sockaddr
178 struct sockaddr_in
*ap
;
180 char *cplim
= (char *) &ap
->sin_addr
;
181 char *cp
= (char *) (&ap
->sin_addr
+ 1);
184 while (--cp
>= cplim
)
186 (ap
)->sin_len
= cp
- (char *) (ap
) + 1;
193 struct in_addr
*mask
;
199 for (x
= 0; x
< sizeof(*mask
); x
++) {
204 if (x
< sizeof(*mask
)) {
205 for (y
= 0; y
< 8; y
++) {
206 if ((p
[x
] & (0x80 >> y
)) == 0)
214 in_len2mask(mask
, len
)
215 struct in_addr
*mask
;
222 bzero(mask
, sizeof(*mask
));
223 for (i
= 0; i
< len
/ 8; i
++)
226 p
[i
] = (0xff00 >> (len
% 8)) & 0xff;
229 static int in_interfaces
; /* number of external internet interfaces */
232 * Generic internet control operations (ioctl's).
233 * Ifp is 0 if not an interface-specific ioctl.
244 struct ifreq
*ifr
= (struct ifreq
*)data
;
245 struct in_ifaddr
*ia
= 0, *iap
;
247 struct in_ifaddr
*oia
;
248 struct in_aliasreq
*ifra
= (struct in_aliasreq
*)data
;
249 struct sockaddr_in oldaddr
;
250 int error
, hostIsNew
, maskIsNew
;
252 struct kev_msg ev_msg
;
253 struct kev_in_data in_event_data
;
259 if (p
&& (error
= proc_suser(p
)) != 0)
265 return in_lifaddr_ioctl(so
, cmd
, data
, ifp
, p
);
269 * Find address for this interface, if it exists.
271 * If an alias address was specified, find that one instead of
272 * the first one on the interface.
275 lck_mtx_lock(rt_mtx
);
276 for (iap
= in_ifaddrhead
.tqh_first
; iap
;
277 iap
= iap
->ia_link
.tqe_next
)
278 if (iap
->ia_ifp
== ifp
) {
279 if (((struct sockaddr_in
*)&ifr
->ifr_addr
)->sin_addr
.s_addr
==
280 iap
->ia_addr
.sin_addr
.s_addr
) {
283 } else if (ia
== NULL
) {
285 if (ifr
->ifr_addr
.sa_family
!= AF_INET
)
289 lck_mtx_unlock(rt_mtx
);
294 if (p
&& (error
= proc_suser(p
)) != 0)
301 return (EADDRNOTAVAIL
);
302 if (ifra
->ifra_addr
.sin_family
== AF_INET
) {
303 lck_mtx_lock(rt_mtx
);
304 for (oia
= ia
; ia
; ia
= ia
->ia_link
.tqe_next
) {
305 if (ia
->ia_ifp
== ifp
&&
306 ia
->ia_addr
.sin_addr
.s_addr
==
307 ifra
->ifra_addr
.sin_addr
.s_addr
)
310 lck_mtx_unlock(rt_mtx
);
311 if ((ifp
->if_flags
& IFF_POINTOPOINT
)
312 && (cmd
== SIOCAIFADDR
)
313 && (ifra
->ifra_dstaddr
.sin_addr
.s_addr
318 else if (cmd
== SIOCAIFADDR
)
320 if (cmd
== SIOCDIFADDR
&& ia
== 0)
321 return (EADDRNOTAVAIL
);
326 if ((so
->so_state
& SS_PRIV
) == 0)
330 return (EADDRNOTAVAIL
);
331 if (ifra
->ifra_addr
.sin_family
!= AF_INET
&& cmd
== SIOCSIFADDR
)
333 if (ia
== (struct in_ifaddr
*)0) {
334 ia
= (struct in_ifaddr
*)
335 _MALLOC(sizeof *ia
, M_IFADDR
, M_WAITOK
);
336 if (ia
== (struct in_ifaddr
*)NULL
)
338 bzero((caddr_t
)ia
, sizeof *ia
);
340 * Protect from ipintr() traversing address list
341 * while we're modifying it.
346 ifa
->ifa_addr
= (struct sockaddr
*)&ia
->ia_addr
;
347 ifa
->ifa_dstaddr
= (struct sockaddr
*)&ia
->ia_dstaddr
;
348 ifa
->ifa_netmask
= (struct sockaddr
*)&ia
->ia_sockmask
;
349 ia
->ia_sockmask
.sin_len
= 8;
350 ifnet_lock_exclusive(ifp
);
351 if (ifp
->if_flags
& IFF_BROADCAST
) {
352 ia
->ia_broadaddr
.sin_len
= sizeof(ia
->ia_addr
);
353 ia
->ia_broadaddr
.sin_family
= AF_INET
;
356 if (!(ifp
->if_flags
& IFF_LOOPBACK
))
358 if_attach_ifa(ifp
, ifa
);
359 ifnet_lock_done(ifp
);
361 lck_mtx_lock(rt_mtx
);
362 TAILQ_INSERT_TAIL(&in_ifaddrhead
, ia
, ia_link
);
363 lck_mtx_unlock(rt_mtx
);
365 /* Generic protocol plumbing */
367 if (error
= dlil_plumb_protocol(PF_INET
, ifp
)) {
368 kprintf("in.c: warning can't plumb proto if=%s%n type %d error=%d\n",
369 ifp
->if_name
, ifp
->if_unit
, ifp
->if_type
, error
);
370 error
= 0; /*discard error, can be cold with unsupported interfaces */
376 case SIOCPROTOATTACH
:
377 case SIOCPROTODETACH
:
378 if (p
&& (error
= proc_suser(p
)) != 0)
381 return (EADDRNOTAVAIL
);
386 if ((so
->so_state
& SS_PRIV
) == 0)
389 if (p
&& (error
= suser(p
)) != 0)
398 if (ia
== (struct in_ifaddr
*)0)
399 return (EADDRNOTAVAIL
);
405 return (EADDRNOTAVAIL
);
406 ifnet_lock_exclusive(ifp
);
408 ifp
->if_eflags
|= IFEF_AUTOCONFIGURING
;
410 ifp
->if_eflags
&= ~IFEF_AUTOCONFIGURING
;
411 ifnet_lock_done(ifp
);
416 return (EADDRNOTAVAIL
);
417 ipv4_ll_arp_aware
= 1;
418 ifnet_lock_exclusive(ifp
);
420 ifp
->if_eflags
|= IFEF_ARPLL
;
422 ifp
->if_eflags
&= ~IFEF_ARPLL
;
423 ifnet_lock_done(ifp
);
427 *((struct sockaddr_in
*)&ifr
->ifr_addr
) = ia
->ia_addr
;
431 if ((ifp
->if_flags
& IFF_BROADCAST
) == 0)
433 *((struct sockaddr_in
*)&ifr
->ifr_dstaddr
) = ia
->ia_broadaddr
;
437 if ((ifp
->if_flags
& IFF_POINTOPOINT
) == 0)
439 *((struct sockaddr_in
*)&ifr
->ifr_dstaddr
) = ia
->ia_dstaddr
;
443 *((struct sockaddr_in
*)&ifr
->ifr_addr
) = ia
->ia_sockmask
;
447 if ((ifp
->if_flags
& IFF_POINTOPOINT
) == 0)
449 oldaddr
= ia
->ia_dstaddr
;
450 ia
->ia_dstaddr
= *(struct sockaddr_in
*)&ifr
->ifr_dstaddr
;
451 error
= dlil_ioctl(PF_INET
, ifp
, SIOCSIFDSTADDR
, (caddr_t
)ia
);
452 if (error
== EOPNOTSUPP
)
456 ia
->ia_dstaddr
= oldaddr
;
460 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
461 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
462 ev_msg
.kev_subclass
= KEV_INET_SUBCLASS
;
464 ev_msg
.event_code
= KEV_INET_SIFDSTADDR
;
466 if (ia
->ia_ifa
.ifa_dstaddr
)
467 in_event_data
.ia_dstaddr
=
468 ((struct sockaddr_in
*)ia
->ia_ifa
.ifa_dstaddr
)->sin_addr
;
470 in_event_data
.ia_dstaddr
.s_addr
= 0;
472 in_event_data
.ia_addr
= ia
->ia_addr
.sin_addr
;
473 in_event_data
.ia_net
= ia
->ia_net
;
474 in_event_data
.ia_netmask
= ia
->ia_netmask
;
475 in_event_data
.ia_subnet
= ia
->ia_subnet
;
476 in_event_data
.ia_subnetmask
= ia
->ia_subnetmask
;
477 in_event_data
.ia_netbroadcast
= ia
->ia_netbroadcast
;
478 strncpy(&in_event_data
.link_data
.if_name
[0], ifp
->if_name
, IFNAMSIZ
);
479 in_event_data
.link_data
.if_family
= ifp
->if_family
;
480 in_event_data
.link_data
.if_unit
= (unsigned long) ifp
->if_unit
;
482 ev_msg
.dv
[0].data_ptr
= &in_event_data
;
483 ev_msg
.dv
[0].data_length
= sizeof(struct kev_in_data
);
484 ev_msg
.dv
[1].data_length
= 0;
486 kev_post_msg(&ev_msg
);
489 if (ia
->ia_flags
& IFA_ROUTE
) {
490 ia
->ia_ifa
.ifa_dstaddr
= (struct sockaddr
*)&oldaddr
;
491 rtinit(&(ia
->ia_ifa
), (int)RTM_DELETE
, RTF_HOST
);
492 ia
->ia_ifa
.ifa_dstaddr
=
493 (struct sockaddr
*)&ia
->ia_dstaddr
;
494 rtinit(&(ia
->ia_ifa
), (int)RTM_ADD
, RTF_HOST
|RTF_UP
);
499 if ((ifp
->if_flags
& IFF_BROADCAST
) == 0)
501 ia
->ia_broadaddr
= *(struct sockaddr_in
*)&ifr
->ifr_broadaddr
;
503 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
504 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
505 ev_msg
.kev_subclass
= KEV_INET_SUBCLASS
;
507 ev_msg
.event_code
= KEV_INET_SIFBRDADDR
;
509 if (ia
->ia_ifa
.ifa_dstaddr
)
510 in_event_data
.ia_dstaddr
=
511 ((struct sockaddr_in
*)ia
->ia_ifa
.ifa_dstaddr
)->sin_addr
;
513 in_event_data
.ia_dstaddr
.s_addr
= 0;
515 in_event_data
.ia_addr
= ia
->ia_addr
.sin_addr
;
516 in_event_data
.ia_net
= ia
->ia_net
;
517 in_event_data
.ia_netmask
= ia
->ia_netmask
;
518 in_event_data
.ia_subnet
= ia
->ia_subnet
;
519 in_event_data
.ia_subnetmask
= ia
->ia_subnetmask
;
520 in_event_data
.ia_netbroadcast
= ia
->ia_netbroadcast
;
521 strncpy(&in_event_data
.link_data
.if_name
[0], ifp
->if_name
, IFNAMSIZ
);
522 in_event_data
.link_data
.if_family
= ifp
->if_family
;
523 in_event_data
.link_data
.if_unit
= (unsigned long) ifp
->if_unit
;
525 ev_msg
.dv
[0].data_ptr
= &in_event_data
;
526 ev_msg
.dv
[0].data_length
= sizeof(struct kev_in_data
);
527 ev_msg
.dv
[1].data_length
= 0;
529 kev_post_msg(&ev_msg
);
534 return (in_ifinit(ifp
, ia
,
535 (struct sockaddr_in
*) &ifr
->ifr_addr
, 1));
537 case SIOCPROTOATTACH
:
538 error
= dlil_plumb_protocol(PF_INET
, ifp
);
543 case SIOCPROTODETACH
:
544 // if an ip address is still present, refuse to detach
545 ifnet_lock_shared(ifp
);
546 TAILQ_FOREACH(ifa
, &ifp
->if_addrhead
, ifa_link
)
547 if (ifa
->ifa_addr
->sa_family
== AF_INET
)
549 ifnet_lock_done(ifp
);
553 error
= dlil_unplumb_protocol(PF_INET
, ifp
);
560 i
= ifra
->ifra_addr
.sin_addr
.s_addr
;
561 ia
->ia_subnetmask
= ntohl(ia
->ia_sockmask
.sin_addr
.s_addr
= i
);
562 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
563 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
564 ev_msg
.kev_subclass
= KEV_INET_SUBCLASS
;
566 ev_msg
.event_code
= KEV_INET_SIFNETMASK
;
568 if (ia
->ia_ifa
.ifa_dstaddr
)
569 in_event_data
.ia_dstaddr
=
570 ((struct sockaddr_in
*)ia
->ia_ifa
.ifa_dstaddr
)->sin_addr
;
572 in_event_data
.ia_dstaddr
.s_addr
= 0;
574 in_event_data
.ia_addr
= ia
->ia_addr
.sin_addr
;
575 in_event_data
.ia_net
= ia
->ia_net
;
576 in_event_data
.ia_netmask
= ia
->ia_netmask
;
577 in_event_data
.ia_subnet
= ia
->ia_subnet
;
578 in_event_data
.ia_subnetmask
= ia
->ia_subnetmask
;
579 in_event_data
.ia_netbroadcast
= ia
->ia_netbroadcast
;
580 strncpy(&in_event_data
.link_data
.if_name
[0], ifp
->if_name
, IFNAMSIZ
);
581 in_event_data
.link_data
.if_family
= ifp
->if_family
;
582 in_event_data
.link_data
.if_unit
= (unsigned long) ifp
->if_unit
;
584 ev_msg
.dv
[0].data_ptr
= &in_event_data
;
585 ev_msg
.dv
[0].data_length
= sizeof(struct kev_in_data
);
586 ev_msg
.dv
[1].data_length
= 0;
588 kev_post_msg(&ev_msg
);
596 if (ia
->ia_addr
.sin_family
== AF_INET
) {
597 if (ifra
->ifra_addr
.sin_len
== 0) {
598 ifra
->ifra_addr
= ia
->ia_addr
;
600 } else if (ifra
->ifra_addr
.sin_addr
.s_addr
==
601 ia
->ia_addr
.sin_addr
.s_addr
)
604 if (ifra
->ifra_mask
.sin_len
) {
605 in_ifscrub(ifp
, ia
, 0);
606 ia
->ia_sockmask
= ifra
->ifra_mask
;
608 ntohl(ia
->ia_sockmask
.sin_addr
.s_addr
);
611 if ((ifp
->if_flags
& IFF_POINTOPOINT
) &&
612 (ifra
->ifra_dstaddr
.sin_family
== AF_INET
)) {
613 in_ifscrub(ifp
, ia
, 0);
614 ia
->ia_dstaddr
= ifra
->ifra_dstaddr
;
615 maskIsNew
= 1; /* We lie; but the effect's the same */
617 if (ifra
->ifra_addr
.sin_family
== AF_INET
&&
618 (hostIsNew
|| maskIsNew
)) {
619 error
= in_ifinit(ifp
, ia
, &ifra
->ifra_addr
, 0);
621 if ((ifp
->if_flags
& IFF_BROADCAST
) &&
622 (ifra
->ifra_broadaddr
.sin_family
== AF_INET
))
623 ia
->ia_broadaddr
= ifra
->ifra_broadaddr
;
629 if ((error
== 0) || (error
== EEXIST
)) {
630 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
631 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
632 ev_msg
.kev_subclass
= KEV_INET_SUBCLASS
;
635 ev_msg
.event_code
= KEV_INET_NEW_ADDR
;
637 ev_msg
.event_code
= KEV_INET_CHANGED_ADDR
;
639 if (ia
->ia_ifa
.ifa_dstaddr
)
640 in_event_data
.ia_dstaddr
=
641 ((struct sockaddr_in
*)ia
->ia_ifa
.ifa_dstaddr
)->sin_addr
;
643 in_event_data
.ia_dstaddr
.s_addr
= 0;
645 in_event_data
.ia_addr
= ia
->ia_addr
.sin_addr
;
646 in_event_data
.ia_net
= ia
->ia_net
;
647 in_event_data
.ia_netmask
= ia
->ia_netmask
;
648 in_event_data
.ia_subnet
= ia
->ia_subnet
;
649 in_event_data
.ia_subnetmask
= ia
->ia_subnetmask
;
650 in_event_data
.ia_netbroadcast
= ia
->ia_netbroadcast
;
651 strncpy(&in_event_data
.link_data
.if_name
[0], ifp
->if_name
, IFNAMSIZ
);
652 in_event_data
.link_data
.if_family
= ifp
->if_family
;
653 in_event_data
.link_data
.if_unit
= (unsigned long) ifp
->if_unit
;
655 ev_msg
.dv
[0].data_ptr
= &in_event_data
;
656 ev_msg
.dv
[0].data_length
= sizeof(struct kev_in_data
);
657 ev_msg
.dv
[1].data_length
= 0;
659 kev_post_msg(&ev_msg
);
665 error
= dlil_ioctl(PF_INET
, ifp
, SIOCDIFADDR
, (caddr_t
)ia
);
666 if (error
== EOPNOTSUPP
)
671 /* Fill out the kernel event information */
672 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
673 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
674 ev_msg
.kev_subclass
= KEV_INET_SUBCLASS
;
676 ev_msg
.event_code
= KEV_INET_ADDR_DELETED
;
678 if (ia
->ia_ifa
.ifa_dstaddr
)
679 in_event_data
.ia_dstaddr
=
680 ((struct sockaddr_in
*)ia
->ia_ifa
.ifa_dstaddr
)->sin_addr
;
682 in_event_data
.ia_dstaddr
.s_addr
= 0;
684 in_event_data
.ia_addr
= ia
->ia_addr
.sin_addr
;
685 in_event_data
.ia_net
= ia
->ia_net
;
686 in_event_data
.ia_netmask
= ia
->ia_netmask
;
687 in_event_data
.ia_subnet
= ia
->ia_subnet
;
688 in_event_data
.ia_subnetmask
= ia
->ia_subnetmask
;
689 in_event_data
.ia_netbroadcast
= ia
->ia_netbroadcast
;
690 strncpy(&in_event_data
.link_data
.if_name
[0], ifp
->if_name
, IFNAMSIZ
);
691 in_event_data
.link_data
.if_family
= ifp
->if_family
;
692 in_event_data
.link_data
.if_unit
= (unsigned long) ifp
->if_unit
;
694 ev_msg
.dv
[0].data_ptr
= &in_event_data
;
695 ev_msg
.dv
[0].data_length
= sizeof(struct kev_in_data
);
696 ev_msg
.dv
[1].data_length
= 0;
698 lck_mtx_lock(rt_mtx
);
699 TAILQ_REMOVE(&in_ifaddrhead
, ia
, ia_link
);
701 * in_ifscrub kills the interface route.
703 in_ifscrub(ifp
, ia
, 1);
705 lck_mtx_unlock(rt_mtx
);
706 ifnet_lock_exclusive(ifp
);
707 if_detach_ifa(ifp
, ifa
);
708 ifafree(&ia
->ia_ifa
);
712 * If the interface supports multicast, and no address is left,
713 * remove the "all hosts" multicast group from that interface.
715 if (ifp
->if_flags
& IFF_MULTICAST
) {
717 struct in_multi
*inm
= NULL
;
719 TAILQ_FOREACH(ifa
, &ifp
->if_addrhead
, ifa_link
)
720 if (ifa
->ifa_addr
->sa_family
== AF_INET
)
724 addr
.s_addr
= htonl(INADDR_ALLHOSTS_GROUP
);
725 IN_LOOKUP_MULTI(addr
, ifp
, inm
);
727 ifnet_lock_done(ifp
);
731 ifnet_lock_done(ifp
);
734 /* Post the kernel event */
735 kev_post_msg(&ev_msg
);
741 * Inspiration from tcp_ctloutput() and ip_ctloutput()
742 * Special ioctl for OpenTransport sockets
744 struct inpcb
*inp
, *cloned_inp
;
746 int cloned_fd
= *(int *)data
;
753 /* let's make sure it's either -1 or a valid file descriptor */
754 if (cloned_fd
!= -1) {
755 struct socket
*cloned_so
;
756 error2
= file_socket(cloned_fd
, &cloned_so
);
760 cloned_inp
= sotoinpcb(cloned_so
);
761 file_drop(cloned_fd
);
766 if (cloned_inp
== NULL
) {
767 /* OT always uses IP_PORTRANGE_HIGH */
768 inp
->inp_flags
&= ~(INP_LOWPORT
);
769 inp
->inp_flags
|= INP_HIGHPORT
;
770 /* For UDP, OT allows broadcast by default */
771 if (so
->so_type
== SOCK_DGRAM
)
772 so
->so_options
|= SO_BROADCAST
;
773 /* For TCP we want to see MSG_OOB when receive urgent data */
774 else if (so
->so_type
== SOCK_STREAM
)
775 so
->so_options
|= SO_WANTOOBFLAG
;
777 inp
->inp_ip_tos
= cloned_inp
->inp_ip_tos
;
778 inp
->inp_ip_ttl
= cloned_inp
->inp_ip_ttl
;
779 inp
->inp_flags
= cloned_inp
->inp_flags
;
781 /* Multicast options */
782 if (cloned_inp
->inp_moptions
!= NULL
) {
784 struct ip_moptions
*cloned_imo
= cloned_inp
->inp_moptions
;
785 struct ip_moptions
*imo
= inp
->inp_moptions
;
789 * No multicast option buffer attached to the pcb;
792 imo
= (struct ip_moptions
*)
793 _MALLOC(sizeof(*imo
), M_IPMOPTS
, M_WAITOK
);
798 inp
->inp_moptions
= imo
;
800 imo
->imo_multicast_ifp
= cloned_imo
->imo_multicast_ifp
;
801 imo
->imo_multicast_vif
= cloned_imo
->imo_multicast_vif
;
802 imo
->imo_multicast_ttl
= cloned_imo
->imo_multicast_ttl
;
803 imo
->imo_multicast_loop
= cloned_imo
->imo_multicast_loop
;
804 imo
->imo_num_memberships
= cloned_imo
->imo_num_memberships
;
805 for (i
= 0; i
< cloned_imo
->imo_num_memberships
; i
++) {
806 imo
->imo_membership
[i
] =
807 in_addmulti(&cloned_imo
->imo_membership
[i
]->inm_addr
,
808 cloned_imo
->imo_membership
[i
]->inm_ifp
);
809 if (imo
->imo_membership
[i
] == NULL
) {
814 if (i
< cloned_imo
->imo_num_memberships
) {
815 /* Failed, perform cleanup */
816 for (i
--; i
>= 0; i
--)
817 in_delmulti(&imo
->imo_membership
[i
]);
818 imo
->imo_num_memberships
= 0;
825 #endif /* __APPLE__ */
835 * SIOCGLIFADDR: get first address. (?!?)
836 * SIOCGLIFADDR with IFLR_PREFIX:
837 * get first address that matches the specified prefix.
838 * SIOCALIFADDR: add the specified address.
839 * SIOCALIFADDR with IFLR_PREFIX:
840 * EINVAL since we can't deduce hostid part of the address.
841 * SIOCDLIFADDR: delete the specified address.
842 * SIOCDLIFADDR with IFLR_PREFIX:
843 * delete the first address that matches the specified prefix.
845 * EINVAL on invalid parameters
846 * EADDRNOTAVAIL on prefix match failed/specified address not found
847 * other values may be returned from in_ioctl()
857 struct if_laddrreq
*iflr
= (struct if_laddrreq
*)data
;
862 panic("invalid argument to in_lifaddr_ioctl");
868 /* address must be specified on GET with IFLR_PREFIX */
869 if ((iflr
->flags
& IFLR_PREFIX
) == 0)
874 /* address must be specified on ADD and DELETE */
875 if (iflr
->addr
.ss_family
!= AF_INET
)
877 if (iflr
->addr
.ss_len
!= sizeof(struct sockaddr_in
))
879 /* XXX need improvement */
880 if (iflr
->dstaddr
.ss_family
881 && iflr
->dstaddr
.ss_family
!= AF_INET
)
883 if (iflr
->dstaddr
.ss_family
884 && iflr
->dstaddr
.ss_len
!= sizeof(struct sockaddr_in
))
887 default: /*shouldn't happen*/
890 if (sizeof(struct in_addr
) * 8 < iflr
->prefixlen
)
896 struct in_aliasreq ifra
;
898 if (iflr
->flags
& IFLR_PREFIX
)
901 /* copy args to in_aliasreq, perform ioctl(SIOCAIFADDR_IN6). */
902 bzero(&ifra
, sizeof(ifra
));
903 bcopy(iflr
->iflr_name
, ifra
.ifra_name
,
904 sizeof(ifra
.ifra_name
));
906 bcopy(&iflr
->addr
, &ifra
.ifra_addr
, iflr
->addr
.ss_len
);
908 if (iflr
->dstaddr
.ss_family
) { /*XXX*/
909 bcopy(&iflr
->dstaddr
, &ifra
.ifra_dstaddr
,
910 iflr
->dstaddr
.ss_len
);
913 ifra
.ifra_mask
.sin_family
= AF_INET
;
914 ifra
.ifra_mask
.sin_len
= sizeof(struct sockaddr_in
);
915 in_len2mask(&ifra
.ifra_mask
.sin_addr
, iflr
->prefixlen
);
917 return in_control(so
, SIOCAIFADDR
, (caddr_t
)&ifra
, ifp
, p
);
922 struct in_ifaddr
*ia
;
923 struct in_addr mask
, candidate
, match
;
924 struct sockaddr_in
*sin
;
927 bzero(&mask
, sizeof(mask
));
928 if (iflr
->flags
& IFLR_PREFIX
) {
929 /* lookup a prefix rather than address. */
930 in_len2mask(&mask
, iflr
->prefixlen
);
932 sin
= (struct sockaddr_in
*)&iflr
->addr
;
933 match
.s_addr
= sin
->sin_addr
.s_addr
;
934 match
.s_addr
&= mask
.s_addr
;
936 /* if you set extra bits, that's wrong */
937 if (match
.s_addr
!= sin
->sin_addr
.s_addr
)
942 if (cmd
== SIOCGLIFADDR
) {
943 /* on getting an address, take the 1st match */
946 /* on deleting an address, do exact match */
947 in_len2mask(&mask
, 32);
948 sin
= (struct sockaddr_in
*)&iflr
->addr
;
949 match
.s_addr
= sin
->sin_addr
.s_addr
;
955 ifnet_lock_shared(ifp
);
956 TAILQ_FOREACH(ifa
, &ifp
->if_addrhead
, ifa_link
) {
957 if (ifa
->ifa_addr
->sa_family
!= AF_INET6
)
961 candidate
.s_addr
= ((struct sockaddr_in
*)&ifa
->ifa_addr
)->sin_addr
.s_addr
;
962 candidate
.s_addr
&= mask
.s_addr
;
963 if (candidate
.s_addr
== match
.s_addr
)
966 ifnet_lock_done(ifp
);
968 return EADDRNOTAVAIL
;
969 ia
= (struct in_ifaddr
*)ifa
;
971 if (cmd
== SIOCGLIFADDR
) {
972 /* fill in the if_laddrreq structure */
973 bcopy(&ia
->ia_addr
, &iflr
->addr
, ia
->ia_addr
.sin_len
);
975 if ((ifp
->if_flags
& IFF_POINTOPOINT
) != 0) {
976 bcopy(&ia
->ia_dstaddr
, &iflr
->dstaddr
,
977 ia
->ia_dstaddr
.sin_len
);
979 bzero(&iflr
->dstaddr
, sizeof(iflr
->dstaddr
));
982 in_mask2len(&ia
->ia_sockmask
.sin_addr
);
984 iflr
->flags
= 0; /*XXX*/
988 struct in_aliasreq ifra
;
990 /* fill in_aliasreq and do ioctl(SIOCDIFADDR_IN6) */
991 bzero(&ifra
, sizeof(ifra
));
992 bcopy(iflr
->iflr_name
, ifra
.ifra_name
,
993 sizeof(ifra
.ifra_name
));
995 bcopy(&ia
->ia_addr
, &ifra
.ifra_addr
,
996 ia
->ia_addr
.sin_len
);
997 if ((ifp
->if_flags
& IFF_POINTOPOINT
) != 0) {
998 bcopy(&ia
->ia_dstaddr
, &ifra
.ifra_dstaddr
,
999 ia
->ia_dstaddr
.sin_len
);
1001 bcopy(&ia
->ia_sockmask
, &ifra
.ifra_dstaddr
,
1002 ia
->ia_sockmask
.sin_len
);
1004 return in_control(so
, SIOCDIFADDR
, (caddr_t
)&ifra
,
1010 return EOPNOTSUPP
; /*just for safety*/
1014 * Delete any existing route for an interface.
1019 struct in_ifaddr
*ia
,
1023 if ((ia
->ia_flags
& IFA_ROUTE
) == 0)
1026 lck_mtx_lock(rt_mtx
);
1027 if (ifp
->if_flags
& (IFF_LOOPBACK
|IFF_POINTOPOINT
))
1028 rtinit_locked(&(ia
->ia_ifa
), (int)RTM_DELETE
, RTF_HOST
);
1030 rtinit_locked(&(ia
->ia_ifa
), (int)RTM_DELETE
, 0);
1031 ia
->ia_flags
&= ~IFA_ROUTE
;
1033 lck_mtx_unlock(rt_mtx
);
1037 * Initialize an interface's internet address
1038 * and routing table entry.
1043 struct in_ifaddr
*ia
,
1044 struct sockaddr_in
*sin
,
1047 u_long i
= ntohl(sin
->sin_addr
.s_addr
);
1048 struct sockaddr_in oldaddr
;
1049 int flags
= RTF_UP
, error
;
1051 oldaddr
= ia
->ia_addr
;
1055 * Give the interface a chance to initialize
1056 * if this is its first address,
1057 * and to validate the address if necessary.
1059 error
= dlil_ioctl(PF_INET
, ifp
, SIOCSIFADDR
, (caddr_t
)ia
);
1060 if (error
== EOPNOTSUPP
)
1063 ia
->ia_addr
= oldaddr
;
1067 ia
->ia_ifa
.ifa_addr
= (struct sockaddr
*)&oldaddr
;
1068 in_ifscrub(ifp
, ia
, 0);
1069 ia
->ia_ifa
.ifa_addr
= (struct sockaddr
*)&ia
->ia_addr
;
1072 ia
->ia_netmask
= IN_CLASSA_NET
;
1073 else if (IN_CLASSB(i
))
1074 ia
->ia_netmask
= IN_CLASSB_NET
;
1076 ia
->ia_netmask
= IN_CLASSC_NET
;
1078 * The subnet mask usually includes at least the standard network part,
1079 * but may may be smaller in the case of supernetting.
1080 * If it is set, we believe it.
1082 if (ia
->ia_subnetmask
== 0) {
1083 ia
->ia_subnetmask
= ia
->ia_netmask
;
1084 ia
->ia_sockmask
.sin_addr
.s_addr
= htonl(ia
->ia_subnetmask
);
1086 ia
->ia_netmask
&= ia
->ia_subnetmask
;
1087 ia
->ia_net
= i
& ia
->ia_netmask
;
1088 ia
->ia_subnet
= i
& ia
->ia_subnetmask
;
1089 in_socktrim(&ia
->ia_sockmask
);
1091 * Add route for the network.
1093 ia
->ia_ifa
.ifa_metric
= ifp
->if_metric
;
1094 if (ifp
->if_flags
& IFF_BROADCAST
) {
1095 ia
->ia_broadaddr
.sin_addr
.s_addr
=
1096 htonl(ia
->ia_subnet
| ~ia
->ia_subnetmask
);
1097 ia
->ia_netbroadcast
.s_addr
=
1098 htonl(ia
->ia_net
| ~ ia
->ia_netmask
);
1099 } else if (ifp
->if_flags
& IFF_LOOPBACK
) {
1100 ia
->ia_ifa
.ifa_dstaddr
= ia
->ia_ifa
.ifa_addr
;
1102 } else if (ifp
->if_flags
& IFF_POINTOPOINT
) {
1103 if (ia
->ia_dstaddr
.sin_family
!= AF_INET
)
1107 if ((error
= rtinit(&(ia
->ia_ifa
), (int)RTM_ADD
, flags
)) == 0)
1108 ia
->ia_flags
|= IFA_ROUTE
;
1109 /* XXX check if the subnet route points to the same interface */
1110 if (error
== EEXIST
)
1114 * If the interface supports multicast, join the "all hosts"
1115 * multicast group on that interface.
1117 if (ifp
->if_flags
& IFF_MULTICAST
) {
1118 struct in_multi
*inm
;
1119 struct in_addr addr
;
1121 addr
.s_addr
= htonl(INADDR_ALLHOSTS_GROUP
);
1122 ifnet_lock_shared(ifp
);
1123 IN_LOOKUP_MULTI(addr
, ifp
, inm
);
1124 ifnet_lock_done(ifp
);
1126 in_addmulti(&addr
, ifp
);
1133 * Return 1 if the address might be a local broadcast address.
1143 if (in
.s_addr
== INADDR_BROADCAST
||
1144 in
.s_addr
== INADDR_ANY
)
1146 if ((ifp
->if_flags
& IFF_BROADCAST
) == 0)
1148 t
= ntohl(in
.s_addr
);
1150 * Look through the list of addresses for a match
1151 * with a broadcast address.
1153 #define ia ((struct in_ifaddr *)ifa)
1154 ifnet_lock_shared(ifp
);
1155 TAILQ_FOREACH(ifa
, &ifp
->if_addrhead
, ifa_link
) {
1156 if (ifa
->ifa_addr
== NULL
) {
1157 ifnet_lock_done(ifp
);
1160 if (ifa
->ifa_addr
->sa_family
== AF_INET
&&
1161 (in
.s_addr
== ia
->ia_broadaddr
.sin_addr
.s_addr
||
1162 in
.s_addr
== ia
->ia_netbroadcast
.s_addr
||
1164 * Check for old-style (host 0) broadcast.
1166 t
== ia
->ia_subnet
|| t
== ia
->ia_net
) &&
1168 * Check for an all one subnetmask. These
1169 * only exist when an interface gets a secondary
1172 ia
->ia_subnetmask
!= (u_long
)0xffffffff) {
1173 ifnet_lock_done(ifp
);
1177 ifnet_lock_done(ifp
);
1184 void* ifma_protospec
)
1186 struct in_multi
*inm
= ifma_protospec
;
1189 * No remaining claims to this record; let IGMP know that
1190 * we are leaving the multicast group.
1192 igmp_leavegroup(inm
);
1193 lck_mtx_lock(rt_mtx
);
1194 LIST_REMOVE(inm
, inm_link
);
1195 lck_mtx_unlock(rt_mtx
);
1196 FREE(inm
, M_IPMADDR
);
1200 * Add an address to the list of IP multicast addresses for a given interface.
1207 struct in_multi
*inm
;
1209 struct sockaddr_in sin
;
1210 struct ifmultiaddr
*ifma
;
1213 * Call generic routine to add membership or increment
1214 * refcount. It wants addresses in the form of a sockaddr,
1215 * so we build one here (being careful to zero the unused bytes).
1217 bzero(&sin
, sizeof sin
);
1218 sin
.sin_family
= AF_INET
;
1219 sin
.sin_len
= sizeof sin
;
1221 error
= if_addmulti(ifp
, (struct sockaddr
*)&sin
, &ifma
);
1227 * If ifma->ifma_protospec is null, then if_addmulti() created
1228 * a new record. Otherwise, we are done.
1230 if (ifma
->ifma_protospec
!= 0) {
1231 return ifma
->ifma_protospec
;
1234 inm
= (struct in_multi
*) _MALLOC(sizeof(*inm
), M_IPMADDR
, M_WAITOK
);
1239 bzero(inm
, sizeof *inm
);
1240 inm
->inm_addr
= *ap
;
1242 inm
->inm_ifma
= ifma
;
1243 lck_mtx_lock(rt_mtx
);
1244 if (ifma
->ifma_protospec
== NULL
) {
1245 ifma
->ifma_protospec
= inm
;
1246 ifma
->ifma_free
= in_free_inm
;
1247 LIST_INSERT_HEAD(&in_multihead
, inm
, inm_link
);
1249 lck_mtx_unlock(rt_mtx
);
1251 if (ifma
->ifma_protospec
!= inm
) {
1252 _FREE(inm
, M_IPMADDR
);
1253 return ifma
->ifma_protospec
;
1257 * Let IGMP know that we have joined a new IP multicast group.
1259 error
= igmp_joingroup(inm
);
1264 * We can't free the inm because someone else may already be
1265 * using it. Once we put it in to ifma->ifma_protospec, it
1266 * must exist as long as the ifma does. Might be nice to flag
1267 * the error so we can try igmp_joingroup the next time through.
1269 log(LOG_ERR
, "igmp_joingroup error %d joining multicast %s on %s%d\n",
1270 error
, inet_ntop(AF_INET
, &sin
.sin_addr
, addrbuf
, sizeof(addrbuf
)),
1271 ifp
->if_name
, ifp
->if_unit
);
1278 * Delete a multicast address record.
1282 struct in_multi
**inm
)
1284 struct in_multi
*inm2
;
1286 lck_mtx_lock(rt_mtx
);
1287 LIST_FOREACH(inm2
, &in_multihead
, inm_link
) {
1292 lck_mtx_unlock(rt_mtx
);
1293 printf("in_delmulti - ignorning invalid inm (0x%x)\n", *inm
);
1296 lck_mtx_unlock(rt_mtx
);
1298 /* We intentionally do this a bit differently than BSD */
1299 if ((*inm
)->inm_ifma
) {
1300 if_delmultiaddr((*inm
)->inm_ifma
, 0);
1301 ifma_release((*inm
)->inm_ifma
);
1308 inet_aton(char * cp
, struct in_addr
* pin
)
1310 u_char
* b
= (char *)pin
;
1314 for (p
= cp
, i
= 0; i
< 4; i
++) {
1315 u_long l
= strtoul(p
, 0, 0);
1320 if (i
< 3 && p
== NULL
)