1 /* $NetBSD: in.c,v 1.135 2009/09/11 22:06:29 dyoung Exp $ */
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * Copyright (c) 1998 The NetBSD Foundation, Inc.
34 * All rights reserved.
36 * This code is derived from software contributed to The NetBSD Foundation
37 * by Public Access Networks Corporation ("Panix"). It was developed under
38 * contract to Panix by Eric Haszlakiewicz and Thor Lancelot Simon.
40 * Redistribution and use in source and binary forms, with or without
41 * modification, are permitted provided that the following conditions
43 * 1. Redistributions of source code must retain the above copyright
44 * notice, this list of conditions and the following disclaimer.
45 * 2. Redistributions in binary form must reproduce the above copyright
46 * notice, this list of conditions and the following disclaimer in the
47 * documentation and/or other materials provided with the distribution.
49 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
50 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
51 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
52 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
53 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
54 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
55 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
56 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
57 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
58 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
59 * POSSIBILITY OF SUCH DAMAGE.
63 * Copyright (c) 1982, 1986, 1991, 1993
64 * The Regents of the University of California. All rights reserved.
66 * Redistribution and use in source and binary forms, with or without
67 * modification, are permitted provided that the following conditions
69 * 1. Redistributions of source code must retain the above copyright
70 * notice, this list of conditions and the following disclaimer.
71 * 2. Redistributions in binary form must reproduce the above copyright
72 * notice, this list of conditions and the following disclaimer in the
73 * documentation and/or other materials provided with the distribution.
74 * 3. Neither the name of the University nor the names of its contributors
75 * may be used to endorse or promote products derived from this software
76 * without specific prior written permission.
78 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
79 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
80 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
81 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
82 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
83 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
84 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
85 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
86 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
87 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
90 * @(#)in.c 8.4 (Berkeley) 1/9/95
93 #include <sys/cdefs.h>
94 __KERNEL_RCSID(0, "$NetBSD: in.c,v 1.135 2009/09/11 22:06:29 dyoung Exp $");
97 #include "opt_inet_conf.h"
98 #include "opt_mrouting.h"
99 #include "opt_pfil_hooks.h"
101 #include <sys/param.h>
102 #include <sys/ioctl.h>
103 #include <sys/errno.h>
104 #include <sys/malloc.h>
105 #include <sys/socket.h>
106 #include <sys/socketvar.h>
107 #include <sys/sysctl.h>
108 #include <sys/systm.h>
109 #include <sys/proc.h>
110 #include <sys/syslog.h>
111 #include <sys/kauth.h>
114 #include <net/route.h>
116 #include <net/if_ether.h>
118 #include <netinet/in_systm.h>
119 #include <netinet/in.h>
120 #include <netinet/in_var.h>
121 #include <netinet/ip.h>
122 #include <netinet/ip_var.h>
123 #include <netinet/in_ifattach.h>
124 #include <netinet/in_pcb.h>
125 #include <netinet/if_inarp.h>
126 #include <netinet/ip_mroute.h>
127 #include <netinet/igmp_var.h>
130 #include <netinet/in_selsrc.h>
134 #include <net/pfil.h>
137 static u_int
in_mask2len(struct in_addr
*);
138 static void in_len2mask(struct in_addr
*, u_int
);
139 static int in_lifaddr_ioctl(struct socket
*, u_long
, void *,
140 struct ifnet
*, struct lwp
*);
142 static int in_addprefix(struct in_ifaddr
*, int);
143 static int in_scrubprefix(struct in_ifaddr
*);
145 #ifndef SUBNETSARELOCAL
146 #define SUBNETSARELOCAL 1
149 #ifndef HOSTZEROBROADCAST
150 #define HOSTZEROBROADCAST 1
153 int subnetsarelocal
= SUBNETSARELOCAL
;
154 int hostzeroisbroadcast
= HOSTZEROBROADCAST
;
157 * This list is used to keep track of in_multi chains which belong to
158 * deleted interface addresses. We use in_ifaddr so that a chain head
159 * won't be deallocated until all multicast address record are deleted.
161 static TAILQ_HEAD(, in_ifaddr
) in_mk
= TAILQ_HEAD_INITIALIZER(in_mk
);
164 * Return 1 if an internet address is for a ``local'' host
165 * (one to which we have a connection). If subnetsarelocal
166 * is true, this includes other subnets of the local net.
167 * Otherwise, it includes only the directly-connected (sub)nets.
170 in_localaddr(struct in_addr in
)
172 struct in_ifaddr
*ia
;
174 if (subnetsarelocal
) {
175 TAILQ_FOREACH(ia
, &in_ifaddrhead
, ia_list
)
176 if ((in
.s_addr
& ia
->ia_netmask
) == ia
->ia_net
)
179 TAILQ_FOREACH(ia
, &in_ifaddrhead
, ia_list
)
180 if ((in
.s_addr
& ia
->ia_subnetmask
) == ia
->ia_subnet
)
187 * Determine whether an IP address is in a reserved set of addresses
188 * that may not be forwarded, or whether datagrams to that destination
192 in_canforward(struct in_addr in
)
196 if (IN_EXPERIMENTAL(in
.s_addr
) || IN_MULTICAST(in
.s_addr
))
198 if (IN_CLASSA(in
.s_addr
)) {
199 net
= in
.s_addr
& IN_CLASSA_NET
;
200 if (net
== 0 || net
== htonl(IN_LOOPBACKNET
<< IN_CLASSA_NSHIFT
))
207 * Trim a mask in a sockaddr
210 in_socktrim(struct sockaddr_in
*ap
)
212 char *cplim
= (char *) &ap
->sin_addr
;
213 char *cp
= (char *) (&ap
->sin_addr
+ 1);
216 while (--cp
>= cplim
)
218 (ap
)->sin_len
= cp
- (char *) (ap
) + 1;
224 * Routine to take an Internet address and convert into a
225 * "dotted quad" representation for printing.
228 in_fmtaddr(struct in_addr addr
)
230 static char buf
[sizeof("123.456.789.123")];
232 addr
.s_addr
= ntohl(addr
.s_addr
);
234 snprintf(buf
, sizeof(buf
), "%d.%d.%d.%d",
235 (addr
.s_addr
>> 24) & 0xFF,
236 (addr
.s_addr
>> 16) & 0xFF,
237 (addr
.s_addr
>> 8) & 0xFF,
238 (addr
.s_addr
>> 0) & 0xFF);
243 * Maintain the "in_maxmtu" variable, which is the largest
244 * mtu for non-local interfaces with AF_INET addresses assigned
245 * to them that are up.
247 unsigned long in_maxmtu
;
252 struct in_ifaddr
*ia
;
254 unsigned long maxmtu
= 0;
256 TAILQ_FOREACH(ia
, &in_ifaddrhead
, ia_list
) {
257 if ((ifp
= ia
->ia_ifp
) == 0)
259 if ((ifp
->if_flags
& (IFF_UP
|IFF_LOOPBACK
)) != IFF_UP
)
261 if (ifp
->if_mtu
> maxmtu
)
262 maxmtu
= ifp
->if_mtu
;
269 in_mask2len(struct in_addr
*mask
)
275 for (x
= 0; x
< sizeof(*mask
); x
++) {
280 if (x
< sizeof(*mask
)) {
281 for (y
= 0; y
< NBBY
; y
++) {
282 if ((p
[x
] & (0x80 >> y
)) == 0)
290 in_len2mask(struct in_addr
*mask
, u_int len
)
296 memset(mask
, 0, sizeof(*mask
));
297 for (i
= 0; i
< len
/ NBBY
; i
++)
300 p
[i
] = (0xff00 >> (len
% NBBY
)) & 0xff;
304 * Generic internet control operations (ioctl's).
305 * Ifp is 0 if not an interface-specific ioctl.
309 in_control(struct socket
*so
, u_long cmd
, void *data
, struct ifnet
*ifp
,
312 struct ifreq
*ifr
= (struct ifreq
*)data
;
313 struct in_ifaddr
*ia
= NULL
;
314 struct in_aliasreq
*ifra
= (struct in_aliasreq
*)data
;
315 struct sockaddr_in oldaddr
;
316 int error
, hostIsNew
, maskIsNew
;
325 return in_lifaddr_ioctl(so
, cmd
, data
, ifp
, l
);
326 case SIOCGIFADDRPREF
:
327 case SIOCSIFADDRPREF
:
330 return ifaddrpref_ioctl(so
, cmd
, data
, ifp
, l
);
334 * Find address for this interface, if it exists.
343 if (ifra
->ifra_addr
.sin_family
== AF_INET
)
345 &IN_IFADDR_HASH(ifra
->ifra_addr
.sin_addr
.s_addr
),
347 if (ia
->ia_ifp
== ifp
&&
348 in_hosteq(ia
->ia_addr
.sin_addr
,
349 ifra
->ifra_addr
.sin_addr
))
352 if ((cmd
== SIOCDIFADDR
|| cmd
== SIOCGIFALIAS
) && ia
== NULL
)
353 return (EADDRNOTAVAIL
);
355 #if 1 /*def COMPAT_43*/
356 if (cmd
== SIOCDIFADDR
&&
357 ifra
->ifra_addr
.sin_family
== AF_UNSPEC
) {
358 ifra
->ifra_addr
.sin_family
= AF_INET
;
364 if (ifra
->ifra_addr
.sin_family
!= AF_INET
)
365 return (EAFNOSUPPORT
);
371 if (cmd
== SIOCGIFALIAS
)
375 (cmd
== SIOCSIFNETMASK
|| cmd
== SIOCSIFDSTADDR
))
376 return (EADDRNOTAVAIL
);
380 if (kauth_authorize_network(l
->l_cred
, KAUTH_NETWORK_INTERFACE
,
381 KAUTH_REQ_NETWORK_INTERFACE_SETPRIV
, ifp
, (void *)cmd
,
386 ia
= malloc(sizeof(*ia
), M_IFADDR
, M_WAITOK
|M_ZERO
);
389 TAILQ_INSERT_TAIL(&in_ifaddrhead
, ia
, ia_list
);
391 ifa_insert(ifp
, &ia
->ia_ifa
);
392 ia
->ia_ifa
.ifa_addr
= sintosa(&ia
->ia_addr
);
393 ia
->ia_ifa
.ifa_dstaddr
= sintosa(&ia
->ia_dstaddr
);
394 ia
->ia_ifa
.ifa_netmask
= sintosa(&ia
->ia_sockmask
);
396 ia
->ia_ifa
.ifa_getifa
= in_getifa
;
398 ia
->ia_ifa
.ifa_getifa
= NULL
;
399 #endif /* IPSELSRC */
400 ia
->ia_sockmask
.sin_len
= 8;
401 if (ifp
->if_flags
& IFF_BROADCAST
) {
402 ia
->ia_broadaddr
.sin_len
= sizeof(ia
->ia_addr
);
403 ia
->ia_broadaddr
.sin_family
= AF_INET
;
406 ia
->ia_idsalt
= arc4random() % 65535;
407 LIST_INIT(&ia
->ia_multiaddrs
);
415 if (kauth_authorize_network(l
->l_cred
, KAUTH_NETWORK_INTERFACE
,
416 KAUTH_REQ_NETWORK_INTERFACE_SETPRIV
, ifp
, (void *)cmd
,
426 return (EADDRNOTAVAIL
);
433 ifreq_setaddr(cmd
, ifr
, sintocsa(&ia
->ia_addr
));
437 if ((ifp
->if_flags
& IFF_BROADCAST
) == 0)
439 ifreq_setdstaddr(cmd
, ifr
, sintocsa(&ia
->ia_broadaddr
));
443 if ((ifp
->if_flags
& IFF_POINTOPOINT
) == 0)
445 ifreq_setdstaddr(cmd
, ifr
, sintocsa(&ia
->ia_dstaddr
));
449 ifreq_setaddr(cmd
, ifr
, sintocsa(&ia
->ia_sockmask
));
453 if ((ifp
->if_flags
& IFF_POINTOPOINT
) == 0)
455 oldaddr
= ia
->ia_dstaddr
;
456 ia
->ia_dstaddr
= *satocsin(ifreq_getdstaddr(cmd
, ifr
));
457 if ((error
= (*ifp
->if_ioctl
)(ifp
, SIOCSIFDSTADDR
, ia
)) != 0) {
458 ia
->ia_dstaddr
= oldaddr
;
461 if (ia
->ia_flags
& IFA_ROUTE
) {
462 ia
->ia_ifa
.ifa_dstaddr
= sintosa(&oldaddr
);
463 rtinit(&ia
->ia_ifa
, RTM_DELETE
, RTF_HOST
);
464 ia
->ia_ifa
.ifa_dstaddr
= sintosa(&ia
->ia_dstaddr
);
465 rtinit(&ia
->ia_ifa
, RTM_ADD
, RTF_HOST
|RTF_UP
);
470 if ((ifp
->if_flags
& IFF_BROADCAST
) == 0)
472 ia
->ia_broadaddr
= *satocsin(ifreq_getbroadaddr(cmd
, ifr
));
476 error
= in_ifinit(ifp
, ia
, satocsin(ifreq_getaddr(cmd
, ifr
)),
480 (void)pfil_run_hooks(&if_pfil
,
481 (struct mbuf
**)SIOCSIFADDR
, ifp
, PFIL_IFADDR
);
487 ia
->ia_sockmask
= *satocsin(ifreq_getaddr(cmd
, ifr
));
488 ia
->ia_subnetmask
= ia
->ia_sockmask
.sin_addr
.s_addr
;
489 error
= in_ifinit(ifp
, ia
, NULL
, 0);
495 if (ia
->ia_addr
.sin_family
!= AF_INET
)
497 else if (ifra
->ifra_addr
.sin_len
== 0) {
498 ifra
->ifra_addr
= ia
->ia_addr
;
500 } else if (in_hosteq(ia
->ia_addr
.sin_addr
,
501 ifra
->ifra_addr
.sin_addr
))
503 if (ifra
->ifra_mask
.sin_len
) {
505 ia
->ia_sockmask
= ifra
->ifra_mask
;
506 ia
->ia_subnetmask
= ia
->ia_sockmask
.sin_addr
.s_addr
;
509 if ((ifp
->if_flags
& IFF_POINTOPOINT
) &&
510 (ifra
->ifra_dstaddr
.sin_family
== AF_INET
)) {
512 ia
->ia_dstaddr
= ifra
->ifra_dstaddr
;
513 maskIsNew
= 1; /* We lie; but the effect's the same */
515 if (ifra
->ifra_addr
.sin_family
== AF_INET
&&
516 (hostIsNew
|| maskIsNew
)) {
517 error
= in_ifinit(ifp
, ia
, &ifra
->ifra_addr
, 0);
519 if ((ifp
->if_flags
& IFF_BROADCAST
) &&
520 (ifra
->ifra_broadaddr
.sin_family
== AF_INET
))
521 ia
->ia_broadaddr
= ifra
->ifra_broadaddr
;
524 (void)pfil_run_hooks(&if_pfil
,
525 (struct mbuf
**)SIOCAIFADDR
, ifp
, PFIL_IFADDR
);
530 ifra
->ifra_mask
= ia
->ia_sockmask
;
531 if ((ifp
->if_flags
& IFF_POINTOPOINT
) &&
532 (ia
->ia_dstaddr
.sin_family
== AF_INET
))
533 ifra
->ifra_dstaddr
= ia
->ia_dstaddr
;
534 else if ((ifp
->if_flags
& IFF_BROADCAST
) &&
535 (ia
->ia_broadaddr
.sin_family
== AF_INET
))
536 ifra
->ifra_broadaddr
= ia
->ia_broadaddr
;
538 memset(&ifra
->ifra_broadaddr
, 0,
539 sizeof(ifra
->ifra_broadaddr
));
543 in_purgeaddr(&ia
->ia_ifa
);
545 (void)pfil_run_hooks(&if_pfil
, (struct mbuf
**)SIOCDIFADDR
,
553 error
= mrt_ioctl(so
, cmd
, data
);
555 #endif /* MROUTING */
561 if (error
!= 0 && newifaddr
) {
563 in_purgeaddr(&ia
->ia_ifa
);
570 in_purgeaddr(struct ifaddr
*ifa
)
572 struct ifnet
*ifp
= ifa
->ifa_ifp
;
573 struct in_ifaddr
*ia
= (void *) ifa
;
576 LIST_REMOVE(ia
, ia_hash
);
577 ifa_remove(ifp
, &ia
->ia_ifa
);
578 TAILQ_REMOVE(&in_ifaddrhead
, ia
, ia_list
);
579 if (ia
->ia_allhosts
!= NULL
)
580 in_delmulti(ia
->ia_allhosts
);
581 IFAFREE(&ia
->ia_ifa
);
586 in_purgeif(struct ifnet
*ifp
) /* MUST be called at splsoftnet() */
588 if_purgeaddrs(ifp
, AF_INET
, in_purgeaddr
);
589 igmp_purgeif(ifp
); /* manipulates pools */
591 ip_mrouter_detach(ifp
);
597 * SIOCGLIFADDR: get first address. (???)
598 * SIOCGLIFADDR with IFLR_PREFIX:
599 * get first address that matches the specified prefix.
600 * SIOCALIFADDR: add the specified address.
601 * SIOCALIFADDR with IFLR_PREFIX:
602 * EINVAL since we can't deduce hostid part of the address.
603 * SIOCDLIFADDR: delete the specified address.
604 * SIOCDLIFADDR with IFLR_PREFIX:
605 * delete the first address that matches the specified prefix.
607 * EINVAL on invalid parameters
608 * EADDRNOTAVAIL on prefix match failed/specified address not found
609 * other values may be returned from in_ioctl()
612 in_lifaddr_ioctl(struct socket
*so
, u_long cmd
, void *data
,
613 struct ifnet
*ifp
, struct lwp
*l
)
615 struct if_laddrreq
*iflr
= (struct if_laddrreq
*)data
;
620 if (data
== NULL
|| ifp
== NULL
) {
621 panic("invalid argument to in_lifaddr_ioctl");
627 /* address must be specified on GET with IFLR_PREFIX */
628 if ((iflr
->flags
& IFLR_PREFIX
) == 0)
633 /* address must be specified on ADD and DELETE */
634 sa
= (struct sockaddr
*)&iflr
->addr
;
635 if (sa
->sa_family
!= AF_INET
)
637 if (sa
->sa_len
!= sizeof(struct sockaddr_in
))
639 /* XXX need improvement */
640 sa
= (struct sockaddr
*)&iflr
->dstaddr
;
641 if (sa
->sa_family
!= AF_UNSPEC
&& sa
->sa_family
!= AF_INET
)
643 if (sa
->sa_len
!= 0 && sa
->sa_len
!= sizeof(struct sockaddr_in
))
646 default: /*shouldn't happen*/
648 panic("invalid cmd to in_lifaddr_ioctl");
654 if (sizeof(struct in_addr
) * NBBY
< iflr
->prefixlen
)
660 struct in_aliasreq ifra
;
662 if (iflr
->flags
& IFLR_PREFIX
)
665 /* copy args to in_aliasreq, perform ioctl(SIOCAIFADDR). */
666 memset(&ifra
, 0, sizeof(ifra
));
667 memcpy(ifra
.ifra_name
, iflr
->iflr_name
,
668 sizeof(ifra
.ifra_name
));
670 memcpy(&ifra
.ifra_addr
, &iflr
->addr
,
671 ((struct sockaddr
*)&iflr
->addr
)->sa_len
);
673 if (((struct sockaddr
*)&iflr
->dstaddr
)->sa_family
) { /*XXX*/
674 memcpy(&ifra
.ifra_dstaddr
, &iflr
->dstaddr
,
675 ((struct sockaddr
*)&iflr
->dstaddr
)->sa_len
);
678 ifra
.ifra_mask
.sin_family
= AF_INET
;
679 ifra
.ifra_mask
.sin_len
= sizeof(struct sockaddr_in
);
680 in_len2mask(&ifra
.ifra_mask
.sin_addr
, iflr
->prefixlen
);
682 return in_control(so
, SIOCAIFADDR
, (void *)&ifra
, ifp
, l
);
687 struct in_ifaddr
*ia
;
688 struct in_addr mask
, candidate
, match
;
689 struct sockaddr_in
*sin
;
692 memset(&mask
, 0, sizeof(mask
));
693 memset(&match
, 0, sizeof(match
)); /* XXX gcc */
694 if (iflr
->flags
& IFLR_PREFIX
) {
695 /* lookup a prefix rather than address. */
696 in_len2mask(&mask
, iflr
->prefixlen
);
698 sin
= (struct sockaddr_in
*)&iflr
->addr
;
699 match
.s_addr
= sin
->sin_addr
.s_addr
;
700 match
.s_addr
&= mask
.s_addr
;
702 /* if you set extra bits, that's wrong */
703 if (match
.s_addr
!= sin
->sin_addr
.s_addr
)
708 if (cmd
== SIOCGLIFADDR
) {
709 /* on getting an address, take the 1st match */
712 /* on deleting an address, do exact match */
713 in_len2mask(&mask
, 32);
714 sin
= (struct sockaddr_in
*)&iflr
->addr
;
715 match
.s_addr
= sin
->sin_addr
.s_addr
;
721 IFADDR_FOREACH(ifa
, ifp
) {
722 if (ifa
->ifa_addr
->sa_family
!= AF_INET
)
726 candidate
.s_addr
= ((struct sockaddr_in
*)&ifa
->ifa_addr
)->sin_addr
.s_addr
;
727 candidate
.s_addr
&= mask
.s_addr
;
728 if (candidate
.s_addr
== match
.s_addr
)
732 return EADDRNOTAVAIL
;
733 ia
= (struct in_ifaddr
*)ifa
;
735 if (cmd
== SIOCGLIFADDR
) {
736 /* fill in the if_laddrreq structure */
737 memcpy(&iflr
->addr
, &ia
->ia_addr
, ia
->ia_addr
.sin_len
);
739 if ((ifp
->if_flags
& IFF_POINTOPOINT
) != 0) {
740 memcpy(&iflr
->dstaddr
, &ia
->ia_dstaddr
,
741 ia
->ia_dstaddr
.sin_len
);
743 memset(&iflr
->dstaddr
, 0, sizeof(iflr
->dstaddr
));
746 in_mask2len(&ia
->ia_sockmask
.sin_addr
);
748 iflr
->flags
= 0; /*XXX*/
752 struct in_aliasreq ifra
;
754 /* fill in_aliasreq and do ioctl(SIOCDIFADDR) */
755 memset(&ifra
, 0, sizeof(ifra
));
756 memcpy(ifra
.ifra_name
, iflr
->iflr_name
,
757 sizeof(ifra
.ifra_name
));
759 memcpy(&ifra
.ifra_addr
, &ia
->ia_addr
,
760 ia
->ia_addr
.sin_len
);
761 if ((ifp
->if_flags
& IFF_POINTOPOINT
) != 0) {
762 memcpy(&ifra
.ifra_dstaddr
, &ia
->ia_dstaddr
,
763 ia
->ia_dstaddr
.sin_len
);
765 memcpy(&ifra
.ifra_dstaddr
, &ia
->ia_sockmask
,
766 ia
->ia_sockmask
.sin_len
);
768 return in_control(so
, SIOCDIFADDR
, (void *)&ifra
,
774 return EOPNOTSUPP
; /*just for safety*/
778 * Delete any existing route for an interface.
781 in_ifscrub(struct ifnet
*ifp
, struct in_ifaddr
*ia
)
788 * Initialize an interface's internet address
789 * and routing table entry.
792 in_ifinit(struct ifnet
*ifp
, struct in_ifaddr
*ia
,
793 const struct sockaddr_in
*sin
, int scrub
)
796 struct sockaddr_in oldaddr
;
797 int s
= splnet(), flags
= RTF_UP
, error
;
803 * Set up new addresses.
805 oldaddr
= ia
->ia_addr
;
806 if (ia
->ia_addr
.sin_family
== AF_INET
)
807 LIST_REMOVE(ia
, ia_hash
);
809 LIST_INSERT_HEAD(&IN_IFADDR_HASH(ia
->ia_addr
.sin_addr
.s_addr
), ia
, ia_hash
);
812 * Give the interface a chance to initialize
813 * if this is its first address,
814 * and to validate the address if necessary.
816 if ((error
= (*ifp
->if_ioctl
)(ifp
, SIOCINITIFADDR
, ia
)) != 0)
820 ia
->ia_ifa
.ifa_addr
= sintosa(&oldaddr
);
822 ia
->ia_ifa
.ifa_addr
= sintosa(&ia
->ia_addr
);
825 i
= ia
->ia_addr
.sin_addr
.s_addr
;
827 ia
->ia_netmask
= IN_CLASSA_NET
;
828 else if (IN_CLASSB(i
))
829 ia
->ia_netmask
= IN_CLASSB_NET
;
831 ia
->ia_netmask
= IN_CLASSC_NET
;
833 * The subnet mask usually includes at least the standard network part,
834 * but may may be smaller in the case of supernetting.
835 * If it is set, we believe it.
837 if (ia
->ia_subnetmask
== 0) {
838 ia
->ia_subnetmask
= ia
->ia_netmask
;
839 ia
->ia_sockmask
.sin_addr
.s_addr
= ia
->ia_subnetmask
;
841 ia
->ia_netmask
&= ia
->ia_subnetmask
;
843 ia
->ia_net
= i
& ia
->ia_netmask
;
844 ia
->ia_subnet
= i
& ia
->ia_subnetmask
;
845 in_socktrim(&ia
->ia_sockmask
);
846 /* re-calculate the "in_maxmtu" value */
849 * Add route for the network.
851 ia
->ia_ifa
.ifa_metric
= ifp
->if_metric
;
852 if (ifp
->if_flags
& IFF_BROADCAST
) {
853 ia
->ia_broadaddr
.sin_addr
.s_addr
=
854 ia
->ia_subnet
| ~ia
->ia_subnetmask
;
855 ia
->ia_netbroadcast
.s_addr
=
856 ia
->ia_net
| ~ia
->ia_netmask
;
857 } else if (ifp
->if_flags
& IFF_LOOPBACK
) {
858 ia
->ia_dstaddr
= ia
->ia_addr
;
860 } else if (ifp
->if_flags
& IFF_POINTOPOINT
) {
861 if (ia
->ia_dstaddr
.sin_family
!= AF_INET
)
865 error
= in_addprefix(ia
, flags
);
867 * If the interface supports multicast, join the "all hosts"
868 * multicast group on that interface.
870 if ((ifp
->if_flags
& IFF_MULTICAST
) != 0 && ia
->ia_allhosts
== NULL
) {
873 addr
.s_addr
= INADDR_ALLHOSTS_GROUP
;
874 ia
->ia_allhosts
= in_addmulti(&addr
, ifp
);
879 LIST_REMOVE(ia
, ia_hash
);
880 ia
->ia_addr
= oldaddr
;
881 if (ia
->ia_addr
.sin_family
== AF_INET
)
882 LIST_INSERT_HEAD(&IN_IFADDR_HASH(ia
->ia_addr
.sin_addr
.s_addr
),
887 #define rtinitflags(x) \
888 ((((x)->ia_ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) != 0) \
892 * add a route to prefix ("connected route" in cisco terminology).
893 * does nothing if there's some interface address with the same prefix already.
896 in_addprefix(struct in_ifaddr
*target
, int flags
)
898 struct in_ifaddr
*ia
;
899 struct in_addr prefix
, mask
, p
;
902 if ((flags
& RTF_HOST
) != 0)
903 prefix
= target
->ia_dstaddr
.sin_addr
;
905 prefix
= target
->ia_addr
.sin_addr
;
906 mask
= target
->ia_sockmask
.sin_addr
;
907 prefix
.s_addr
&= mask
.s_addr
;
910 TAILQ_FOREACH(ia
, &in_ifaddrhead
, ia_list
) {
912 p
= ia
->ia_dstaddr
.sin_addr
;
914 p
= ia
->ia_addr
.sin_addr
;
915 p
.s_addr
&= ia
->ia_sockmask
.sin_addr
.s_addr
;
918 if (prefix
.s_addr
!= p
.s_addr
)
922 * if we got a matching prefix route inserted by other
923 * interface address, we don't need to bother
925 * XXX RADIX_MPATH implications here? -dyoung
927 if (ia
->ia_flags
& IFA_ROUTE
)
932 * noone seem to have prefix route. insert it.
934 error
= rtinit(&target
->ia_ifa
, RTM_ADD
, flags
);
936 target
->ia_flags
|= IFA_ROUTE
;
937 else if (error
== EEXIST
) {
939 * the fact the route already exists is not an error.
947 * remove a route to prefix ("connected route" in cisco terminology).
948 * re-installs the route by using another interface address, if there's one
949 * with the same prefix (otherwise we lose the route mistakenly).
952 in_scrubprefix(struct in_ifaddr
*target
)
954 struct in_ifaddr
*ia
;
955 struct in_addr prefix
, mask
, p
;
958 if ((target
->ia_flags
& IFA_ROUTE
) == 0)
961 if (rtinitflags(target
))
962 prefix
= target
->ia_dstaddr
.sin_addr
;
964 prefix
= target
->ia_addr
.sin_addr
;
965 mask
= target
->ia_sockmask
.sin_addr
;
966 prefix
.s_addr
&= mask
.s_addr
;
969 TAILQ_FOREACH(ia
, &in_ifaddrhead
, ia_list
) {
971 p
= ia
->ia_dstaddr
.sin_addr
;
973 p
= ia
->ia_addr
.sin_addr
;
974 p
.s_addr
&= ia
->ia_sockmask
.sin_addr
.s_addr
;
977 if (prefix
.s_addr
!= p
.s_addr
)
981 * if we got a matching prefix route, move IFA_ROUTE to him
983 if ((ia
->ia_flags
& IFA_ROUTE
) == 0) {
984 rtinit(&target
->ia_ifa
, RTM_DELETE
,
985 rtinitflags(target
));
986 target
->ia_flags
&= ~IFA_ROUTE
;
988 error
= rtinit(&ia
->ia_ifa
, RTM_ADD
,
989 rtinitflags(ia
) | RTF_UP
);
991 ia
->ia_flags
|= IFA_ROUTE
;
997 * noone seem to have prefix route. remove it.
999 rtinit(&target
->ia_ifa
, RTM_DELETE
, rtinitflags(target
));
1000 target
->ia_flags
&= ~IFA_ROUTE
;
1007 * Return 1 if the address might be a local broadcast address.
1010 in_broadcast(struct in_addr in
, struct ifnet
*ifp
)
1014 if (in
.s_addr
== INADDR_BROADCAST
||
1017 if ((ifp
->if_flags
& IFF_BROADCAST
) == 0)
1020 * Look through the list of addresses for a match
1021 * with a broadcast address.
1023 #define ia (ifatoia(ifa))
1024 IFADDR_FOREACH(ifa
, ifp
)
1025 if (ifa
->ifa_addr
->sa_family
== AF_INET
&&
1026 !in_hosteq(in
, ia
->ia_addr
.sin_addr
) &&
1027 (in_hosteq(in
, ia
->ia_broadaddr
.sin_addr
) ||
1028 in_hosteq(in
, ia
->ia_netbroadcast
) ||
1029 (hostzeroisbroadcast
&&
1031 * Check for old-style (host 0) broadcast.
1033 (in
.s_addr
== ia
->ia_subnet
||
1034 in
.s_addr
== ia
->ia_net
))))
1041 * Add an address to the list of IP multicast addresses for a given interface.
1044 in_addmulti(struct in_addr
*ap
, struct ifnet
*ifp
)
1046 struct sockaddr_in sin
;
1047 struct in_multi
*inm
;
1049 int s
= splsoftnet();
1052 * See if address already in list.
1054 IN_LOOKUP_MULTI(*ap
, ifp
, inm
);
1057 * Found it; just increment the reference count.
1059 ++inm
->inm_refcount
;
1062 * New address; allocate a new multicast record
1063 * and link it into the interface's multicast list.
1065 inm
= pool_get(&inmulti_pool
, PR_NOWAIT
);
1070 inm
->inm_addr
= *ap
;
1072 inm
->inm_refcount
= 1;
1074 &IN_MULTI_HASH(inm
->inm_addr
.s_addr
, ifp
),
1077 * Ask the network driver to update its multicast reception
1078 * filter appropriately for the new address.
1080 sockaddr_in_init(&sin
, ap
, 0);
1081 ifreq_setaddr(SIOCADDMULTI
, &ifr
, sintosa(&sin
));
1082 if ((*ifp
->if_ioctl
)(ifp
, SIOCADDMULTI
, &ifr
) != 0) {
1083 LIST_REMOVE(inm
, inm_list
);
1084 pool_put(&inmulti_pool
, inm
);
1089 * Let IGMP know that we have joined a new IP multicast group.
1091 if (igmp_joingroup(inm
) != 0) {
1092 LIST_REMOVE(inm
, inm_list
);
1093 pool_put(&inmulti_pool
, inm
);
1104 * Delete a multicast address record.
1107 in_delmulti(struct in_multi
*inm
)
1109 struct sockaddr_in sin
;
1111 int s
= splsoftnet();
1113 if (--inm
->inm_refcount
== 0) {
1115 * No remaining claims to this record; let IGMP know that
1116 * we are leaving the multicast group.
1118 igmp_leavegroup(inm
);
1122 LIST_REMOVE(inm
, inm_list
);
1125 * Notify the network driver to update its multicast reception
1128 sockaddr_in_init(&sin
, &inm
->inm_addr
, 0);
1129 ifreq_setaddr(SIOCDELMULTI
, &ifr
, sintosa(&sin
));
1130 (*inm
->inm_ifp
->if_ioctl
)(inm
->inm_ifp
, SIOCDELMULTI
, &ifr
);
1131 pool_put(&inmulti_pool
, inm
);