2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) 1982, 1986, 1991, 1993
24 * The Regents of the University of California. All rights reserved.
26 * Redistribution and use in source and binary forms, with or without
27 * modification, are permitted provided that the following conditions
29 * 1. Redistributions of source code must retain the above copyright
30 * notice, this list of conditions and the following disclaimer.
31 * 2. Redistributions in binary form must reproduce the above copyright
32 * notice, this list of conditions and the following disclaimer in the
33 * documentation and/or other materials provided with the distribution.
34 * 3. All advertising materials mentioning features or use of this software
35 * must display the following acknowledgement:
36 * This product includes software developed by the University of
37 * California, Berkeley and its contributors.
38 * 4. Neither the name of the University nor the names of its contributors
39 * may be used to endorse or promote products derived from this software
40 * without specific prior written permission.
42 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
43 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
46 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
48 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
50 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
51 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
54 * @(#)in.c 8.4 (Berkeley) 1/9/95
57 #include <sys/param.h>
58 #include <sys/systm.h>
59 #include <sys/sockio.h>
60 #include <sys/socketvar.h>
61 #include <sys/malloc.h>
63 #include <sys/socket.h>
64 #include <sys/kernel.h>
65 #include <sys/sysctl.h>
66 #include <sys/kern_event.h>
69 #include <net/route.h>
72 #include <net/if_types.h>
73 #include <net/if_gif.h>
76 #include <netinet/in.h>
77 #include <netinet/in_var.h>
78 #include <netinet/in_pcb.h>
80 #include <netinet/igmp_var.h>
83 #include <netinet/ip_var.h>
85 #include <netinet/tcp.h>
86 #include <netinet/tcp_timer.h>
87 #include <netinet/tcp_var.h>
92 static int in_mask2len
__P((struct in_addr
*));
93 static void in_len2mask
__P((struct in_addr
*, int));
94 static int in_lifaddr_ioctl
__P((struct socket
*, u_long
, caddr_t
,
95 struct ifnet
*, struct proc
*));
97 static void in_socktrim
__P((struct sockaddr_in
*));
98 static int in_ifinit
__P((struct ifnet
*,
99 struct in_ifaddr
*, struct sockaddr_in
*, int));
101 static int subnetsarelocal
= 0;
102 SYSCTL_INT(_net_inet_ip
, OID_AUTO
, subnets_are_local
, CTLFLAG_RW
,
103 &subnetsarelocal
, 0, "");
105 struct in_multihead in_multihead
; /* XXX BSS initialization */
107 extern void arp_rtrequest();
108 extern int ether_detach_inet(struct ifnet
*ifp
);
112 * Return 1 if an internet address is for a ``local'' host
113 * (one to which we have a connection). If subnetsarelocal
114 * is true, this includes other subnets of the local net.
115 * Otherwise, it includes only the directly-connected (sub)nets.
121 register u_long i
= ntohl(in
.s_addr
);
122 register struct in_ifaddr
*ia
;
124 if (subnetsarelocal
) {
125 for (ia
= in_ifaddrhead
.tqh_first
; ia
;
126 ia
= ia
->ia_link
.tqe_next
)
127 if ((i
& ia
->ia_netmask
) == ia
->ia_net
)
130 for (ia
= in_ifaddrhead
.tqh_first
; ia
;
131 ia
= ia
->ia_link
.tqe_next
)
132 if ((i
& ia
->ia_subnetmask
) == ia
->ia_subnet
)
139 * Determine whether an IP address is in a reserved set of addresses
140 * that may not be forwarded, or whether datagrams to that destination
147 register u_long i
= ntohl(in
.s_addr
);
150 if (IN_EXPERIMENTAL(i
) || IN_MULTICAST(i
))
153 net
= i
& IN_CLASSA_NET
;
154 if (net
== 0 || net
== (IN_LOOPBACKNET
<< IN_CLASSA_NSHIFT
))
161 * Trim a mask in a sockaddr
165 struct sockaddr_in
*ap
;
167 register char *cplim
= (char *) &ap
->sin_addr
;
168 register char *cp
= (char *) (&ap
->sin_addr
+ 1);
171 while (--cp
>= cplim
)
173 (ap
)->sin_len
= cp
- (char *) (ap
) + 1;
180 struct in_addr
*mask
;
186 for (x
= 0; x
< sizeof(*mask
); x
++) {
191 if (x
< sizeof(*mask
)) {
192 for (y
= 0; y
< 8; y
++) {
193 if ((p
[x
] & (0x80 >> y
)) == 0)
201 in_len2mask(mask
, len
)
202 struct in_addr
*mask
;
209 bzero(mask
, sizeof(*mask
));
210 for (i
= 0; i
< len
/ 8; i
++)
213 p
[i
] = (0xff00 >> (len
% 8)) & 0xff;
216 static int in_interfaces
; /* number of external internet interfaces */
219 * Generic internet control operations (ioctl's).
220 * Ifp is 0 if not an interface-specific ioctl.
224 in_control(so
, cmd
, data
, ifp
, p
)
228 register struct ifnet
*ifp
;
231 register struct ifreq
*ifr
= (struct ifreq
*)data
;
232 register struct in_ifaddr
*ia
= 0, *iap
;
233 register struct ifaddr
*ifa
;
234 struct in_ifaddr
*oia
;
235 struct in_aliasreq
*ifra
= (struct in_aliasreq
*)data
;
236 struct sockaddr_in oldaddr
;
237 int error
, hostIsNew
, maskIsNew
, s
;
239 struct kev_msg ev_msg
;
240 struct kev_in_data in_event_data
;
243 if (ifp
&& ifp
->if_type
== IFT_GIF
) {
248 (error
= suser(p
->p_ucred
, &p
->p_acflag
)) != 0)
251 if ((so
->so_state
& SS_PRIV
) == 0)
254 case SIOCGIFPSRCADDR
:
255 case SIOCGIFPDSTADDR
:
257 if (strcmp(ifp
->if_name
, "gif") == 0)
258 dl_tag
= gif_attach_inet(ifp
);
259 return gif_ioctl(ifp
, cmd
, data
);
265 if (ifp
&& ifp
->if_type
== IFT_FAITH
)
266 dl_tag
= faith_attach_inet(ifp
);
273 if (p
&& (error
= suser(p
->p_ucred
, &p
->p_acflag
)) != 0)
276 if ((so
->so_state
& SS_PRIV
) == 0)
283 return in_lifaddr_ioctl(so
, cmd
, data
, ifp
, p
);
287 * Find address for this interface, if it exists.
289 * If an alias address was specified, find that one instead of
290 * the first one on the interface.
293 for (iap
= in_ifaddrhead
.tqh_first
; iap
;
294 iap
= iap
->ia_link
.tqe_next
)
295 if (iap
->ia_ifp
== ifp
) {
296 if (((struct sockaddr_in
*)&ifr
->ifr_addr
)->sin_addr
.s_addr
==
297 iap
->ia_addr
.sin_addr
.s_addr
) {
300 } else if (ia
== NULL
) {
302 if (ifr
->ifr_addr
.sa_family
!= AF_INET
)
310 if (p
&& (error
= suser(p
->p_ucred
, &p
->p_acflag
)) != 0)
313 if ((so
->so_state
& SS_PRIV
) == 0)
321 return (EADDRNOTAVAIL
);
322 if (ifra
->ifra_addr
.sin_family
== AF_INET
) {
323 for (oia
= ia
; ia
; ia
= ia
->ia_link
.tqe_next
) {
324 if (ia
->ia_ifp
== ifp
&&
325 ia
->ia_addr
.sin_addr
.s_addr
==
326 ifra
->ifra_addr
.sin_addr
.s_addr
)
329 if ((ifp
->if_flags
& IFF_POINTOPOINT
)
330 && (cmd
== SIOCAIFADDR
)
331 && (ifra
->ifra_dstaddr
.sin_addr
.s_addr
336 else if (cmd
== SIOCAIFADDR
)
338 if (cmd
== SIOCDIFADDR
&& ia
== 0)
339 return (EADDRNOTAVAIL
);
346 if (p
&& (error
= suser(p
->p_ucred
, &p
->p_acflag
)) != 0)
349 if ((so
->so_state
& SS_PRIV
) == 0)
354 return (EADDRNOTAVAIL
);
355 if (ifra
->ifra_addr
.sin_family
!= AF_INET
&& cmd
== SIOCSIFADDR
)
357 if (ia
== (struct in_ifaddr
*)0) {
358 ia
= (struct in_ifaddr
*)
359 _MALLOC(sizeof *ia
, M_IFADDR
, M_WAITOK
);
360 if (ia
== (struct in_ifaddr
*)NULL
)
362 bzero((caddr_t
)ia
, sizeof *ia
);
364 * Protect from ipintr() traversing address list
365 * while we're modifying it.
369 TAILQ_INSERT_TAIL(&in_ifaddrhead
, ia
, ia_link
);
371 TAILQ_INSERT_TAIL(&ifp
->if_addrhead
, ifa
, ifa_link
);
374 * Temorary code for protocol attachment XXX
377 if (strcmp(ifp
->if_name
, "en") == 0)
378 dl_tag
= ether_attach_inet(ifp
);
380 if (strcmp(ifp
->if_name
, "lo") == 0)
381 dl_tag
= lo_attach_inet(ifp
);
382 /* End of temp code */
384 ifa
->ifa_dlt
= dl_tag
;
385 ifa
->ifa_addr
= (struct sockaddr
*)&ia
->ia_addr
;
386 ifa
->ifa_dstaddr
= (struct sockaddr
*)&ia
->ia_dstaddr
;
387 ifa
->ifa_netmask
= (struct sockaddr
*)&ia
->ia_sockmask
;
388 ia
->ia_sockmask
.sin_len
= 8;
389 if (ifp
->if_flags
& IFF_BROADCAST
) {
390 ia
->ia_broadaddr
.sin_len
= sizeof(ia
->ia_addr
);
391 ia
->ia_broadaddr
.sin_family
= AF_INET
;
394 if (!(ifp
->if_flags
& IFF_LOOPBACK
))
400 case SIOCPROTOATTACH
:
401 case SIOCPROTODETACH
:
402 if (p
&& (error
= suser(p
->p_ucred
, &p
->p_acflag
)) != 0)
405 return (EADDRNOTAVAIL
);
406 if (strcmp(ifp
->if_name
, "en"))
412 if (p
&& (error
= suser(p
->p_ucred
, &p
->p_acflag
)) != 0)
415 if ((so
->so_state
& SS_PRIV
) == 0)
424 if (ia
== (struct in_ifaddr
*)0)
425 return (EADDRNOTAVAIL
);
431 return (EADDRNOTAVAIL
);
433 ifp
->if_eflags
|= IFEF_AUTOCONFIGURING
;
435 ifp
->if_eflags
&= ~IFEF_AUTOCONFIGURING
;
439 *((struct sockaddr_in
*)&ifr
->ifr_addr
) = ia
->ia_addr
;
443 if ((ifp
->if_flags
& IFF_BROADCAST
) == 0)
445 *((struct sockaddr_in
*)&ifr
->ifr_dstaddr
) = ia
->ia_broadaddr
;
449 if ((ifp
->if_flags
& IFF_POINTOPOINT
) == 0)
451 *((struct sockaddr_in
*)&ifr
->ifr_dstaddr
) = ia
->ia_dstaddr
;
455 *((struct sockaddr_in
*)&ifr
->ifr_addr
) = ia
->ia_sockmask
;
459 if ((ifp
->if_flags
& IFF_POINTOPOINT
) == 0)
461 oldaddr
= ia
->ia_dstaddr
;
462 ia
->ia_dstaddr
= *(struct sockaddr_in
*)&ifr
->ifr_dstaddr
;
463 error
= dlil_ioctl(PF_INET
, ifp
, SIOCSIFDSTADDR
, (caddr_t
)ia
);
464 if (error
== EOPNOTSUPP
)
468 ia
->ia_dstaddr
= oldaddr
;
472 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
473 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
474 ev_msg
.kev_subclass
= KEV_INET_SUBCLASS
;
476 ev_msg
.event_code
= KEV_INET_SIFDSTADDR
;
478 if (ia
->ia_ifa
.ifa_dstaddr
)
479 in_event_data
.ia_dstaddr
=
480 ((struct sockaddr_in
*)ia
->ia_ifa
.ifa_dstaddr
)->sin_addr
;
482 in_event_data
.ia_dstaddr
.s_addr
= 0;
484 in_event_data
.ia_addr
= ia
->ia_addr
.sin_addr
;
485 in_event_data
.ia_net
= ia
->ia_net
;
486 in_event_data
.ia_netmask
= ia
->ia_netmask
;
487 in_event_data
.ia_subnet
= ia
->ia_subnet
;
488 in_event_data
.ia_subnetmask
= ia
->ia_subnetmask
;
489 in_event_data
.ia_netbroadcast
= ia
->ia_netbroadcast
;
490 strncpy(&in_event_data
.link_data
.if_name
[0], ifp
->if_name
, IFNAMSIZ
);
491 in_event_data
.link_data
.if_family
= ifp
->if_family
;
492 in_event_data
.link_data
.if_unit
= (unsigned long) ifp
->if_unit
;
494 ev_msg
.dv
[0].data_ptr
= &in_event_data
;
495 ev_msg
.dv
[0].data_length
= sizeof(struct kev_in_data
);
496 ev_msg
.dv
[1].data_length
= 0;
498 kev_post_msg(&ev_msg
);
501 if (ia
->ia_flags
& IFA_ROUTE
) {
502 ia
->ia_ifa
.ifa_dstaddr
= (struct sockaddr
*)&oldaddr
;
503 rtinit(&(ia
->ia_ifa
), (int)RTM_DELETE
, RTF_HOST
);
504 ia
->ia_ifa
.ifa_dstaddr
=
505 (struct sockaddr
*)&ia
->ia_dstaddr
;
506 rtinit(&(ia
->ia_ifa
), (int)RTM_ADD
, RTF_HOST
|RTF_UP
);
511 if ((ifp
->if_flags
& IFF_BROADCAST
) == 0)
513 ia
->ia_broadaddr
= *(struct sockaddr_in
*)&ifr
->ifr_broadaddr
;
515 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
516 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
517 ev_msg
.kev_subclass
= KEV_INET_SUBCLASS
;
519 ev_msg
.event_code
= KEV_INET_SIFBRDADDR
;
521 if (ia
->ia_ifa
.ifa_dstaddr
)
522 in_event_data
.ia_dstaddr
=
523 ((struct sockaddr_in
*)ia
->ia_ifa
.ifa_dstaddr
)->sin_addr
;
525 in_event_data
.ia_dstaddr
.s_addr
= 0;
527 in_event_data
.ia_addr
= ia
->ia_addr
.sin_addr
;
528 in_event_data
.ia_net
= ia
->ia_net
;
529 in_event_data
.ia_netmask
= ia
->ia_netmask
;
530 in_event_data
.ia_subnet
= ia
->ia_subnet
;
531 in_event_data
.ia_subnetmask
= ia
->ia_subnetmask
;
532 in_event_data
.ia_netbroadcast
= ia
->ia_netbroadcast
;
533 strncpy(&in_event_data
.link_data
.if_name
[0], ifp
->if_name
, IFNAMSIZ
);
534 in_event_data
.link_data
.if_family
= ifp
->if_family
;
535 in_event_data
.link_data
.if_unit
= (unsigned long) ifp
->if_unit
;
537 ev_msg
.dv
[0].data_ptr
= &in_event_data
;
538 ev_msg
.dv
[0].data_length
= sizeof(struct kev_in_data
);
539 ev_msg
.dv
[1].data_length
= 0;
541 kev_post_msg(&ev_msg
);
546 return (in_ifinit(ifp
, ia
,
547 (struct sockaddr_in
*) &ifr
->ifr_addr
, 1));
549 case SIOCPROTOATTACH
:
550 ether_attach_inet(ifp
);
553 case SIOCPROTODETACH
:
554 // if an ip address is still present, refuse to detach
555 TAILQ_FOREACH(ifa
, &ifp
->if_addrhead
, ifa_link
)
556 if (ifa
->ifa_addr
->sa_family
== AF_INET
)
558 return ether_detach_inet(ifp
);
561 i
= ifra
->ifra_addr
.sin_addr
.s_addr
;
562 ia
->ia_subnetmask
= ntohl(ia
->ia_sockmask
.sin_addr
.s_addr
= i
);
563 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
564 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
565 ev_msg
.kev_subclass
= KEV_INET_SUBCLASS
;
567 ev_msg
.event_code
= KEV_INET_SIFNETMASK
;
569 if (ia
->ia_ifa
.ifa_dstaddr
)
570 in_event_data
.ia_dstaddr
=
571 ((struct sockaddr_in
*)ia
->ia_ifa
.ifa_dstaddr
)->sin_addr
;
573 in_event_data
.ia_dstaddr
.s_addr
= 0;
575 in_event_data
.ia_addr
= ia
->ia_addr
.sin_addr
;
576 in_event_data
.ia_net
= ia
->ia_net
;
577 in_event_data
.ia_netmask
= ia
->ia_netmask
;
578 in_event_data
.ia_subnet
= ia
->ia_subnet
;
579 in_event_data
.ia_subnetmask
= ia
->ia_subnetmask
;
580 in_event_data
.ia_netbroadcast
= ia
->ia_netbroadcast
;
581 strncpy(&in_event_data
.link_data
.if_name
[0], ifp
->if_name
, IFNAMSIZ
);
582 in_event_data
.link_data
.if_family
= ifp
->if_family
;
583 in_event_data
.link_data
.if_unit
= (unsigned long) ifp
->if_unit
;
585 ev_msg
.dv
[0].data_ptr
= &in_event_data
;
586 ev_msg
.dv
[0].data_length
= sizeof(struct kev_in_data
);
587 ev_msg
.dv
[1].data_length
= 0;
589 kev_post_msg(&ev_msg
);
597 if (ia
->ia_addr
.sin_family
== AF_INET
) {
598 if (ifra
->ifra_addr
.sin_len
== 0) {
599 ifra
->ifra_addr
= ia
->ia_addr
;
601 } else if (ifra
->ifra_addr
.sin_addr
.s_addr
==
602 ia
->ia_addr
.sin_addr
.s_addr
)
605 if (ifra
->ifra_mask
.sin_len
) {
607 ia
->ia_sockmask
= ifra
->ifra_mask
;
609 ntohl(ia
->ia_sockmask
.sin_addr
.s_addr
);
612 if ((ifp
->if_flags
& IFF_POINTOPOINT
) &&
613 (ifra
->ifra_dstaddr
.sin_family
== AF_INET
)) {
615 ia
->ia_dstaddr
= ifra
->ifra_dstaddr
;
616 maskIsNew
= 1; /* We lie; but the effect's the same */
618 if (ifra
->ifra_addr
.sin_family
== AF_INET
&&
619 (hostIsNew
|| maskIsNew
)) {
620 error
= in_ifinit(ifp
, ia
, &ifra
->ifra_addr
, 0);
622 if ((ifp
->if_flags
& IFF_BROADCAST
) &&
623 (ifra
->ifra_broadaddr
.sin_family
== AF_INET
))
624 ia
->ia_broadaddr
= ifra
->ifra_broadaddr
;
631 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
632 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
633 ev_msg
.kev_subclass
= KEV_INET_SUBCLASS
;
636 ev_msg
.event_code
= KEV_INET_NEW_ADDR
;
638 ev_msg
.event_code
= KEV_INET_CHANGED_ADDR
;
640 if (ia
->ia_ifa
.ifa_dstaddr
)
641 in_event_data
.ia_dstaddr
=
642 ((struct sockaddr_in
*)ia
->ia_ifa
.ifa_dstaddr
)->sin_addr
;
644 in_event_data
.ia_dstaddr
.s_addr
= 0;
646 in_event_data
.ia_addr
= ia
->ia_addr
.sin_addr
;
647 in_event_data
.ia_net
= ia
->ia_net
;
648 in_event_data
.ia_netmask
= ia
->ia_netmask
;
649 in_event_data
.ia_subnet
= ia
->ia_subnet
;
650 in_event_data
.ia_subnetmask
= ia
->ia_subnetmask
;
651 in_event_data
.ia_netbroadcast
= ia
->ia_netbroadcast
;
652 strncpy(&in_event_data
.link_data
.if_name
[0], ifp
->if_name
, IFNAMSIZ
);
653 in_event_data
.link_data
.if_family
= ifp
->if_family
;
654 in_event_data
.link_data
.if_unit
= (unsigned long) ifp
->if_unit
;
656 ev_msg
.dv
[0].data_ptr
= &in_event_data
;
657 ev_msg
.dv
[0].data_length
= sizeof(struct kev_in_data
);
658 ev_msg
.dv
[1].data_length
= 0;
660 kev_post_msg(&ev_msg
);
666 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
667 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
668 ev_msg
.kev_subclass
= KEV_INET_SUBCLASS
;
670 ev_msg
.event_code
= KEV_INET_ADDR_DELETED
;
672 if (ia
->ia_ifa
.ifa_dstaddr
)
673 in_event_data
.ia_dstaddr
=
674 ((struct sockaddr_in
*)ia
->ia_ifa
.ifa_dstaddr
)->sin_addr
;
676 in_event_data
.ia_dstaddr
.s_addr
= 0;
678 in_event_data
.ia_addr
= ia
->ia_addr
.sin_addr
;
679 in_event_data
.ia_net
= ia
->ia_net
;
680 in_event_data
.ia_netmask
= ia
->ia_netmask
;
681 in_event_data
.ia_subnet
= ia
->ia_subnet
;
682 in_event_data
.ia_subnetmask
= ia
->ia_subnetmask
;
683 in_event_data
.ia_netbroadcast
= ia
->ia_netbroadcast
;
684 strncpy(&in_event_data
.link_data
.if_name
[0], ifp
->if_name
, IFNAMSIZ
);
685 in_event_data
.link_data
.if_family
= ifp
->if_family
;
686 in_event_data
.link_data
.if_unit
= (unsigned long) ifp
->if_unit
;
688 ev_msg
.dv
[0].data_ptr
= &in_event_data
;
689 ev_msg
.dv
[0].data_length
= sizeof(struct kev_in_data
);
690 ev_msg
.dv
[1].data_length
= 0;
692 kev_post_msg(&ev_msg
);
696 * Protect from ipintr() traversing address list
697 * while we're modifying it.
702 TAILQ_REMOVE(&ifp
->if_addrhead
, ifa
, ifa_link
);
704 TAILQ_REMOVE(&in_ifaddrhead
, oia
, ia_link
);
705 IFAFREE(&oia
->ia_ifa
);
708 * If the interface supports multicast, and no address is left,
709 * remove the "all hosts" multicast group from that interface.
711 if (ifp
->if_flags
& IFF_MULTICAST
) {
713 struct in_multi
*inm
;
715 TAILQ_FOREACH(ifa
, &ifp
->if_addrhead
, ifa_link
)
716 if (ifa
->ifa_addr
->sa_family
== AF_INET
)
720 addr
.s_addr
= htonl(INADDR_ALLHOSTS_GROUP
);
721 IN_LOOKUP_MULTI(addr
, ifp
, inm
);
731 * Inspiration from tcp_ctloutput() and ip_ctloutput()
733 struct inpcb
*inp
, *cloned_inp
;
735 int cloned_fd
= *(int *)data
;
737 s
= splnet(); /* XXX */
744 /* let's make sure it's either -1 or a valid file descriptor */
745 if (cloned_fd
!= -1) {
746 struct socket
*cloned_so
;
747 struct file
*cloned_fp
;
748 error
= getsock(p
->p_fd
, cloned_fd
, &cloned_fp
);
753 cloned_so
= (struct socket
*)cloned_fp
->f_data
;
754 cloned_inp
= sotoinpcb(cloned_so
);
759 if (cloned_inp
== NULL
) {
760 /* OT always uses IP_PORTRANGE_HIGH */
761 inp
->inp_flags
&= ~(INP_LOWPORT
);
762 inp
->inp_flags
|= INP_HIGHPORT
;
763 /* For UDP, OT allows broadcast by default */
764 if (so
->so_type
== SOCK_DGRAM
)
765 so
->so_options
|= SO_BROADCAST
;
766 /* For TCP we want to see MSG_OOB when receive urgent data */
767 else if (so
->so_type
== SOCK_STREAM
)
768 so
->so_options
|= SO_WANTOOBFLAG
;
770 inp
->inp_ip_tos
= cloned_inp
->inp_ip_tos
;
771 inp
->inp_ip_ttl
= cloned_inp
->inp_ip_ttl
;
772 inp
->inp_flags
= cloned_inp
->inp_flags
;
774 /* Multicast options */
775 if (cloned_inp
->inp_moptions
!= NULL
) {
777 struct ip_moptions
*cloned_imo
= cloned_inp
->inp_moptions
;
778 struct ip_moptions
*imo
= inp
->inp_moptions
;
782 * No multicast option buffer attached to the pcb;
786 imo
= (struct ip_moptions
*)
787 _MALLOC(sizeof(*imo
), M_IPMOPTS
, M_WAITOK
);
792 s
= splnet(); /* XXX */
793 inp
->inp_moptions
= imo
;
795 imo
->imo_multicast_ifp
= cloned_imo
->imo_multicast_ifp
;
796 imo
->imo_multicast_vif
= cloned_imo
->imo_multicast_vif
;
797 imo
->imo_multicast_ttl
= cloned_imo
->imo_multicast_ttl
;
798 imo
->imo_multicast_loop
= cloned_imo
->imo_multicast_loop
;
799 imo
->imo_num_memberships
= cloned_imo
->imo_num_memberships
;
800 for (i
= 0; i
< cloned_imo
->imo_num_memberships
; i
++) {
801 imo
->imo_membership
[i
] =
802 in_addmulti(&cloned_imo
->imo_membership
[i
]->inm_addr
,
803 cloned_imo
->imo_membership
[i
]->inm_ifp
);
820 * SIOCGLIFADDR: get first address. (???)
821 * SIOCGLIFADDR with IFLR_PREFIX:
822 * get first address that matches the specified prefix.
823 * SIOCALIFADDR: add the specified address.
824 * SIOCALIFADDR with IFLR_PREFIX:
825 * EINVAL since we can't deduce hostid part of the address.
826 * SIOCDLIFADDR: delete the specified address.
827 * SIOCDLIFADDR with IFLR_PREFIX:
828 * delete the first address that matches the specified prefix.
830 * EINVAL on invalid parameters
831 * EADDRNOTAVAIL on prefix match failed/specified address not found
832 * other values may be returned from in_ioctl()
835 in_lifaddr_ioctl(so
, cmd
, data
, ifp
, p
)
842 struct if_laddrreq
*iflr
= (struct if_laddrreq
*)data
;
847 panic("invalid argument to in_lifaddr_ioctl");
853 /* address must be specified on GET with IFLR_PREFIX */
854 if ((iflr
->flags
& IFLR_PREFIX
) == 0)
859 /* address must be specified on ADD and DELETE */
860 if (iflr
->addr
.ss_family
!= AF_INET
)
862 if (iflr
->addr
.ss_len
!= sizeof(struct sockaddr_in
))
864 /* XXX need improvement */
865 if (iflr
->dstaddr
.ss_family
866 && iflr
->dstaddr
.ss_family
!= AF_INET
)
868 if (iflr
->dstaddr
.ss_family
869 && iflr
->dstaddr
.ss_len
!= sizeof(struct sockaddr_in
))
872 default: /*shouldn't happen*/
874 panic("invalid cmd to in_lifaddr_ioctl");
880 if (sizeof(struct in_addr
) * 8 < iflr
->prefixlen
)
886 struct in_aliasreq ifra
;
888 if (iflr
->flags
& IFLR_PREFIX
)
891 /* copy args to in_aliasreq, perform ioctl(SIOCAIFADDR_IN6). */
892 bzero(&ifra
, sizeof(ifra
));
893 bcopy(iflr
->iflr_name
, ifra
.ifra_name
,
894 sizeof(ifra
.ifra_name
));
896 bcopy(&iflr
->addr
, &ifra
.ifra_addr
, iflr
->addr
.ss_len
);
898 if (iflr
->dstaddr
.ss_family
) { /*XXX*/
899 bcopy(&iflr
->dstaddr
, &ifra
.ifra_dstaddr
,
900 iflr
->dstaddr
.ss_len
);
903 ifra
.ifra_mask
.sin_family
= AF_INET
;
904 ifra
.ifra_mask
.sin_len
= sizeof(struct sockaddr_in
);
905 in_len2mask(&ifra
.ifra_mask
.sin_addr
, iflr
->prefixlen
);
907 return in_control(so
, SIOCAIFADDR
, (caddr_t
)&ifra
, ifp
, p
);
912 struct in_ifaddr
*ia
;
913 struct in_addr mask
, candidate
, match
;
914 struct sockaddr_in
*sin
;
917 bzero(&mask
, sizeof(mask
));
918 if (iflr
->flags
& IFLR_PREFIX
) {
919 /* lookup a prefix rather than address. */
920 in_len2mask(&mask
, iflr
->prefixlen
);
922 sin
= (struct sockaddr_in
*)&iflr
->addr
;
923 match
.s_addr
= sin
->sin_addr
.s_addr
;
924 match
.s_addr
&= mask
.s_addr
;
926 /* if you set extra bits, that's wrong */
927 if (match
.s_addr
!= sin
->sin_addr
.s_addr
)
932 if (cmd
== SIOCGLIFADDR
) {
933 /* on getting an address, take the 1st match */
936 /* on deleting an address, do exact match */
937 in_len2mask(&mask
, 32);
938 sin
= (struct sockaddr_in
*)&iflr
->addr
;
939 match
.s_addr
= sin
->sin_addr
.s_addr
;
945 TAILQ_FOREACH(ifa
, &ifp
->if_addrhead
, ifa_link
) {
946 if (ifa
->ifa_addr
->sa_family
!= AF_INET6
)
950 candidate
.s_addr
= ((struct sockaddr_in
*)&ifa
->ifa_addr
)->sin_addr
.s_addr
;
951 candidate
.s_addr
&= mask
.s_addr
;
952 if (candidate
.s_addr
== match
.s_addr
)
956 return EADDRNOTAVAIL
;
957 ia
= (struct in_ifaddr
*)ifa
;
959 if (cmd
== SIOCGLIFADDR
) {
960 /* fill in the if_laddrreq structure */
961 bcopy(&ia
->ia_addr
, &iflr
->addr
, ia
->ia_addr
.sin_len
);
963 if ((ifp
->if_flags
& IFF_POINTOPOINT
) != 0) {
964 bcopy(&ia
->ia_dstaddr
, &iflr
->dstaddr
,
965 ia
->ia_dstaddr
.sin_len
);
967 bzero(&iflr
->dstaddr
, sizeof(iflr
->dstaddr
));
970 in_mask2len(&ia
->ia_sockmask
.sin_addr
);
972 iflr
->flags
= 0; /*XXX*/
976 struct in_aliasreq ifra
;
978 /* fill in_aliasreq and do ioctl(SIOCDIFADDR_IN6) */
979 bzero(&ifra
, sizeof(ifra
));
980 bcopy(iflr
->iflr_name
, ifra
.ifra_name
,
981 sizeof(ifra
.ifra_name
));
983 bcopy(&ia
->ia_addr
, &ifra
.ifra_addr
,
984 ia
->ia_addr
.sin_len
);
985 if ((ifp
->if_flags
& IFF_POINTOPOINT
) != 0) {
986 bcopy(&ia
->ia_dstaddr
, &ifra
.ifra_dstaddr
,
987 ia
->ia_dstaddr
.sin_len
);
989 bcopy(&ia
->ia_sockmask
, &ifra
.ifra_dstaddr
,
990 ia
->ia_sockmask
.sin_len
);
992 return in_control(so
, SIOCDIFADDR
, (caddr_t
)&ifra
,
998 return EOPNOTSUPP
; /*just for safety*/
1002 * Delete any existing route for an interface.
1006 register struct ifnet
*ifp
;
1007 register struct in_ifaddr
*ia
;
1010 if ((ia
->ia_flags
& IFA_ROUTE
) == 0)
1012 if (ifp
->if_flags
& (IFF_LOOPBACK
|IFF_POINTOPOINT
))
1013 rtinit(&(ia
->ia_ifa
), (int)RTM_DELETE
, RTF_HOST
);
1015 rtinit(&(ia
->ia_ifa
), (int)RTM_DELETE
, 0);
1016 ia
->ia_flags
&= ~IFA_ROUTE
;
1020 * Initialize an interface's internet address
1021 * and routing table entry.
1024 in_ifinit(ifp
, ia
, sin
, scrub
)
1025 register struct ifnet
*ifp
;
1026 register struct in_ifaddr
*ia
;
1027 struct sockaddr_in
*sin
;
1030 register u_long i
= ntohl(sin
->sin_addr
.s_addr
);
1031 struct sockaddr_in oldaddr
;
1032 int s
= splimp(), flags
= RTF_UP
, error
;
1037 oldaddr
= ia
->ia_addr
;
1041 error
= dlil_ioctl(PF_INET
, ifp
, SIOCSIFADDR
, (caddr_t
)ia
);
1042 if (error
== EOPNOTSUPP
)
1047 ia
->ia_addr
= oldaddr
;
1053 ia
->ia_ifa
.ifa_addr
= (struct sockaddr
*)&oldaddr
;
1054 in_ifscrub(ifp
, ia
);
1055 ia
->ia_ifa
.ifa_addr
= (struct sockaddr
*)&ia
->ia_addr
;
1058 ia
->ia_netmask
= IN_CLASSA_NET
;
1059 else if (IN_CLASSB(i
))
1060 ia
->ia_netmask
= IN_CLASSB_NET
;
1062 ia
->ia_netmask
= IN_CLASSC_NET
;
1064 * The subnet mask usually includes at least the standard network part,
1065 * but may may be smaller in the case of supernetting.
1066 * If it is set, we believe it.
1068 if (ia
->ia_subnetmask
== 0) {
1069 ia
->ia_subnetmask
= ia
->ia_netmask
;
1070 ia
->ia_sockmask
.sin_addr
.s_addr
= htonl(ia
->ia_subnetmask
);
1072 ia
->ia_netmask
&= ia
->ia_subnetmask
;
1073 ia
->ia_net
= i
& ia
->ia_netmask
;
1074 ia
->ia_subnet
= i
& ia
->ia_subnetmask
;
1075 in_socktrim(&ia
->ia_sockmask
);
1077 * Add route for the network.
1079 ia
->ia_ifa
.ifa_metric
= ifp
->if_metric
;
1080 if (ifp
->if_flags
& IFF_BROADCAST
) {
1081 ia
->ia_broadaddr
.sin_addr
.s_addr
=
1082 htonl(ia
->ia_subnet
| ~ia
->ia_subnetmask
);
1083 ia
->ia_netbroadcast
.s_addr
=
1084 htonl(ia
->ia_net
| ~ ia
->ia_netmask
);
1085 } else if (ifp
->if_flags
& IFF_LOOPBACK
) {
1086 ia
->ia_ifa
.ifa_dstaddr
= ia
->ia_ifa
.ifa_addr
;
1088 } else if (ifp
->if_flags
& IFF_POINTOPOINT
) {
1089 if (ia
->ia_dstaddr
.sin_family
!= AF_INET
)
1093 if ((error
= rtinit(&(ia
->ia_ifa
), (int)RTM_ADD
, flags
)) == 0)
1094 ia
->ia_flags
|= IFA_ROUTE
;
1097 * If the interface supports multicast, join the "all hosts"
1098 * multicast group on that interface.
1100 if (ifp
->if_flags
& IFF_MULTICAST
) {
1101 struct in_multi
*inm
;
1102 struct in_addr addr
;
1104 addr
.s_addr
= htonl(INADDR_ALLHOSTS_GROUP
);
1105 IN_LOOKUP_MULTI(addr
, ifp
, inm
);
1107 in_addmulti(&addr
, ifp
);
1114 * Return 1 if the address might be a local broadcast address.
1117 in_broadcast(in
, ifp
)
1121 register struct ifaddr
*ifa
;
1124 if (in
.s_addr
== INADDR_BROADCAST
||
1125 in
.s_addr
== INADDR_ANY
)
1127 if ((ifp
->if_flags
& IFF_BROADCAST
) == 0)
1129 t
= ntohl(in
.s_addr
);
1131 * Look through the list of addresses for a match
1132 * with a broadcast address.
1134 #define ia ((struct in_ifaddr *)ifa)
1135 for (ifa
= ifp
->if_addrhead
.tqh_first
; ifa
;
1136 ifa
= ifa
->ifa_link
.tqe_next
) {
1137 if (ifa
->ifa_addr
== NULL
)
1139 if (ifa
->ifa_addr
->sa_family
== AF_INET
&&
1140 (in
.s_addr
== ia
->ia_broadaddr
.sin_addr
.s_addr
||
1141 in
.s_addr
== ia
->ia_netbroadcast
.s_addr
||
1143 * Check for old-style (host 0) broadcast.
1145 t
== ia
->ia_subnet
|| t
== ia
->ia_net
) &&
1147 * Check for an all one subnetmask. These
1148 * only exist when an interface gets a secondary
1151 ia
->ia_subnetmask
!= (u_long
)0xffffffff)
1158 * Add an address to the list of IP multicast addresses for a given interface.
1161 in_addmulti(ap
, ifp
)
1162 register struct in_addr
*ap
;
1163 register struct ifnet
*ifp
;
1165 register struct in_multi
*inm
;
1167 struct sockaddr_in sin
;
1168 struct ifmultiaddr
*ifma
;
1172 * Call generic routine to add membership or increment
1173 * refcount. It wants addresses in the form of a sockaddr,
1174 * so we build one here (being careful to zero the unused bytes).
1176 bzero(&sin
, sizeof sin
);
1177 sin
.sin_family
= AF_INET
;
1178 sin
.sin_len
= sizeof sin
;
1180 error
= if_addmulti(ifp
, (struct sockaddr
*)&sin
, &ifma
);
1187 * If ifma->ifma_protospec is null, then if_addmulti() created
1188 * a new record. Otherwise, we are done.
1190 if (ifma
->ifma_protospec
!= 0)
1191 return ifma
->ifma_protospec
;
1193 inm
= (struct in_multi
*) _MALLOC(sizeof(*inm
), M_IPMADDR
, M_WAITOK
);
1199 bzero(inm
, sizeof *inm
);
1200 inm
->inm_addr
= *ap
;
1202 inm
->inm_ifma
= ifma
;
1203 ifma
->ifma_protospec
= inm
;
1204 LIST_INSERT_HEAD(&in_multihead
, inm
, inm_link
);
1207 * Let IGMP know that we have joined a new IP multicast group.
1209 igmp_joingroup(inm
);
1215 * Delete a multicast address record.
1219 register struct in_multi
*inm
;
1221 struct ifmultiaddr
*ifma
= inm
->inm_ifma
;
1224 if (ifma
->ifma_refcount
== 1) {
1226 * No remaining claims to this record; let IGMP know that
1227 * we are leaving the multicast group.
1229 igmp_leavegroup(inm
);
1230 ifma
->ifma_protospec
= 0;
1231 LIST_REMOVE(inm
, inm_link
);
1232 FREE(inm
, M_IPMADDR
);
1234 /* XXX - should be separate API for when we have an ifma? */
1235 if_delmulti(ifma
->ifma_ifp
, ifma
->ifma_addr
);