2 * Copyright (C) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>
3 * Helsinki University of Technology, Finland.
5 * Copyright (C) 2005 Neil Cafferkey
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
24 * Copyright (c) 1982, 1986, 1991 Regents of the University of California.
25 * All rights reserved.
27 * Redistribution and use in source and binary forms, with or without
28 * modification, are permitted provided that the following conditions
30 * 1. Redistributions of source code must retain the above copyright
31 * notice, this list of conditions and the following disclaimer.
32 * 2. Redistributions in binary form must reproduce the above copyright
33 * notice, this list of conditions and the following disclaimer in the
34 * documentation and/or other materials provided with the distribution.
35 * 3. All advertising materials mentioning features or use of this software
36 * must display the following acknowledgement:
37 * This product includes software developed by the University of
38 * California, Berkeley and its contributors.
39 * 4. Neither the name of the University nor the names of its contributors
40 * may be used to endorse or promote products derived from this software
41 * without specific prior written permission.
43 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
44 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
47 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55 * @(#)in.c 7.17 (Berkeley) 4/20/91
60 #include <sys/param.h>
61 #include <sys/systm.h>
62 #include <sys/ioctl.h>
63 #include <sys/malloc.h>
65 #include <sys/socket.h>
66 #include <sys/socketvar.h>
67 #include <sys/synch.h>
69 #include <netinet/in_systm.h>
71 #include <net/route.h>
72 #include <netinet/in.h>
73 #include <netinet/in_var.h>
75 #include <netinet/in_protos.h>
79 * Formulate an Internet address from network + host.
82 in_makeaddr(net
, host
)
85 register struct in_ifaddr
*ia
;
89 struct in_addr in_addr
;
93 mask
= IN_CLASSA_HOST
;
94 else if (IN_CLASSB(net
))
95 mask
= IN_CLASSB_HOST
;
97 mask
= IN_CLASSC_HOST
;
98 for (ia
= in_ifaddr
; ia
; ia
= ia
->ia_next
)
99 if ((ia
->ia_netmask
& net
) == ia
->ia_net
) {
100 mask
= ~ia
->ia_subnetmask
;
103 __tmp
.addr
= htonl(net
| (host
& mask
));
104 return __tmp
.in_addr
;
108 * Return the network number from an internet address.
114 register u_long i
= ntohl(in
.s_addr
);
116 register struct in_ifaddr
*ia
;
119 net
= i
& IN_CLASSA_NET
;
120 else if (IN_CLASSB(i
))
121 net
= i
& IN_CLASSB_NET
;
122 else if (IN_CLASSC(i
))
123 net
= i
& IN_CLASSC_NET
;
128 * Check whether network is a subnet;
129 * if so, return subnet number.
131 for (ia
= in_ifaddr
; ia
; ia
= ia
->ia_next
)
132 if (net
== ia
->ia_net
)
133 return (i
& ia
->ia_subnetmask
);
138 * Compute and save network mask as sockaddr from an internet address.
141 in_sockmaskof(in
, sockmask
)
143 register struct sockaddr_in
*sockmask
;
146 register u_long mask
;
148 register u_long i
= ntohl(in
.s_addr
);
152 else if (IN_CLASSA(i
))
153 net
= i
& IN_CLASSA_NET
, mask
= IN_CLASSA_NET
;
154 else if (IN_CLASSB(i
))
155 net
= i
& IN_CLASSB_NET
, mask
= IN_CLASSB_NET
;
156 else if (IN_CLASSC(i
))
157 net
= i
& IN_CLASSC_NET
, mask
= IN_CLASSC_NET
;
162 register struct in_ifaddr
*ia
;
164 * Check whether network is a subnet;
165 * if so, return subnet number.
167 for (ia
= in_ifaddr
; ia
; ia
= ia
->ia_next
)
168 if (net
== ia
->ia_net
)
169 mask
= ia
->ia_subnetmask
;
172 register char *cpbase
= (char *)&(sockmask
->sin_addr
);
173 register char *cp
= (char *)(1 + &(sockmask
->sin_addr
));
175 sockmask
->sin_addr
.s_addr
= htonl(mask
);
176 sockmask
->sin_len
= 0;
177 while (--cp
>= cpbase
)
179 sockmask
->sin_len
= 1 + cp
- (caddr_t
)sockmask
;
186 * Return the host portion of an internet address.
192 register u_long i
= ntohl(in
.s_addr
);
193 register u_long net
, host
;
194 register struct in_ifaddr
*ia
;
197 net
= i
& IN_CLASSA_NET
;
198 host
= i
& IN_CLASSA_HOST
;
199 } else if (IN_CLASSB(i
)) {
200 net
= i
& IN_CLASSB_NET
;
201 host
= i
& IN_CLASSB_HOST
;
202 } else if (IN_CLASSC(i
)) {
203 net
= i
& IN_CLASSC_NET
;
204 host
= i
& IN_CLASSC_HOST
;
209 * Check whether network is a subnet;
210 * if so, use the modified interpretation of `host'.
212 for (ia
= in_ifaddr
; ia
; ia
= ia
->ia_next
)
213 if (net
== ia
->ia_net
)
214 return (host
&~ ia
->ia_subnetmask
);
218 #ifndef SUBNETSARELOCAL
219 #define SUBNETSARELOCAL 1
221 int subnetsarelocal
= SUBNETSARELOCAL
;
223 * Return 1 if an internet address is for a ``local'' host
224 * (one to which we have a connection). If subnetsarelocal
225 * is true, this includes other subnets of the local net.
226 * Otherwise, it includes only the directly-connected (sub)nets.
232 register u_long i
= ntohl(in
.s_addr
);
233 register struct in_ifaddr
*ia
;
235 if (subnetsarelocal
) {
236 for (ia
= in_ifaddr
; ia
; ia
= ia
->ia_next
)
237 if ((i
& ia
->ia_netmask
) == ia
->ia_net
)
240 for (ia
= in_ifaddr
; ia
; ia
= ia
->ia_next
)
241 if ((i
& ia
->ia_subnetmask
) == ia
->ia_subnet
)
248 * Determine whether an IP address is in a reserved set of addresses
249 * that may not be forwarded, or whether datagrams to that destination
256 register u_long i
= ntohl(in
.s_addr
);
259 if (IN_EXPERIMENTAL(i
))
262 net
= i
& IN_CLASSA_NET
;
263 if (net
== 0 || net
== IN_LOOPBACKNET
)
269 int in_interfaces
; /* number of external internet interfaces */
270 extern struct ifnet loif
;
273 * Generic internet control operations (ioctl's).
274 * Ifp is 0 if not an interface-specific ioctl.
277 in_control(so
, cmd
, data
, ifp
)
281 register struct ifnet
*ifp
;
283 register struct ifreq
*ifr
= (struct ifreq
*)data
;
284 register struct in_ifaddr
*ia
= 0;
285 register struct ifaddr
*ifa
;
286 struct in_ifaddr
*oia
;
287 struct in_aliasreq
*ifra
= (struct in_aliasreq
*)data
;
289 struct sockaddr_in oldaddr
;
290 int error
, hostIsNew
, maskIsNew
;
294 * Find address for this interface, if it exists.
297 for (ia
= in_ifaddr
; ia
; ia
= ia
->ia_next
)
298 if (ia
->ia_ifp
== ifp
)
305 if (ifra
->ifra_addr
.sin_family
== AF_INET
)
306 for (oia
= ia
; ia
; ia
= ia
->ia_next
) {
307 if (ia
->ia_ifp
== ifp
&&
308 ia
->ia_addr
.sin_addr
.s_addr
==
309 ifra
->ifra_addr
.sin_addr
.s_addr
)
312 if (cmd
== SIOCDIFADDR
&& ia
== 0)
313 return (EADDRNOTAVAIL
);
318 /* if ((so->so_state & SS_PRIV) == 0)
323 if (ia
== (struct in_ifaddr
*)0) {
324 m
= m_getclr(M_WAIT
, MT_IFADDR
);
325 if (m
== (struct mbuf
*)NULL
)
327 if (ia
= in_ifaddr
) {
328 for ( ; ia
->ia_next
; ia
= ia
->ia_next
)
330 ia
->ia_next
= mtod(m
, struct in_ifaddr
*);
332 in_ifaddr
= mtod(m
, struct in_ifaddr
*);
333 ia
= mtod(m
, struct in_ifaddr
*);
334 if (ifa
= ifp
->if_addrlist
) {
335 for ( ; ifa
->ifa_next
; ifa
= ifa
->ifa_next
)
337 ifa
->ifa_next
= (struct ifaddr
*) ia
;
339 ifp
->if_addrlist
= (struct ifaddr
*) ia
;
340 ia
->ia_ifa
.ifa_addr
= (struct sockaddr
*)&ia
->ia_addr
;
341 ia
->ia_ifa
.ifa_dstaddr
342 = (struct sockaddr
*)&ia
->ia_dstaddr
;
343 ia
->ia_ifa
.ifa_netmask
344 = (struct sockaddr
*)&ia
->ia_sockmask
;
345 ia
->ia_sockmask
.sin_len
= 8;
346 if (ifp
->if_flags
& IFF_BROADCAST
) {
347 ia
->ia_broadaddr
.sin_len
= sizeof(ia
->ia_addr
);
348 ia
->ia_broadaddr
.sin_family
= AF_INET
;
357 /* if ((so->so_state & SS_PRIV) == 0)
365 if (ia
== (struct in_ifaddr
*)0)
366 return (EADDRNOTAVAIL
);
377 struct sockaddr_in
*ifr_saddr
= (struct sockaddr_in
*)&ifr
->ifr_addr
;
378 *ifr_saddr
= ia
->ia_addr
;
384 struct sockaddr_in
*ifrdst_saddr
= (struct sockaddr_in
*)&ifr
->ifr_dstaddr
;
385 if ((ifp
->if_flags
& IFF_BROADCAST
) == 0)
387 *ifrdst_saddr
= ia
->ia_broadaddr
;
393 struct sockaddr_in
*ifrdst_saddr
= (struct sockaddr_in
*)&ifr
->ifr_dstaddr
;
394 if ((ifp
->if_flags
& IFF_POINTOPOINT
) == 0)
396 *ifrdst_saddr
= ia
->ia_dstaddr
;
402 struct sockaddr_in
*ifr_saddr
= (struct sockaddr_in
*)&ifr
->ifr_addr
;
403 *ifr_saddr
= ia
->ia_sockmask
;
409 struct sockaddr_in
*ifrdst_saddr
= (struct sockaddr_in
*)&ifr
->ifr_dstaddr
;
410 if ((ifp
->if_flags
& IFF_POINTOPOINT
) == 0)
412 oldaddr
= ia
->ia_dstaddr
;
413 ia
->ia_dstaddr
= *ifrdst_saddr
;
415 (error
= (*ifp
->if_ioctl
)(ifp
, SIOCSIFDSTADDR
, (caddr_t
)ia
))) {
416 ia
->ia_dstaddr
= oldaddr
;
419 if (ia
->ia_flags
& IFA_ROUTE
) {
420 ia
->ia_ifa
.ifa_dstaddr
= (struct sockaddr
*)&oldaddr
;
421 rtinit(&(ia
->ia_ifa
), (int)RTM_DELETE
, RTF_HOST
);
422 ia
->ia_ifa
.ifa_dstaddr
=
423 (struct sockaddr
*)&ia
->ia_dstaddr
;
424 rtinit(&(ia
->ia_ifa
), (int)RTM_ADD
, RTF_HOST
|RTF_UP
);
431 struct sockaddr_in
*ifrbrd_saddr
= (struct sockaddr_in
*)&ifr
->ifr_broadaddr
;
432 if ((ifp
->if_flags
& IFF_BROADCAST
) == 0)
434 ia
->ia_broadaddr
= *ifrbrd_saddr
;
439 return (in_ifinit(ifp
, ia
,
440 (struct sockaddr_in
*) &ifr
->ifr_addr
, 1));
443 i
= ifra
->ifra_addr
.sin_addr
.s_addr
;
444 ia
->ia_subnetmask
= ntohl(ia
->ia_sockmask
.sin_addr
.s_addr
= i
);
451 if (ia
->ia_addr
.sin_family
== AF_INET
) {
452 if (ifra
->ifra_addr
.sin_len
== 0) {
453 ifra
->ifra_addr
= ia
->ia_addr
;
455 } else if (ifra
->ifra_addr
.sin_addr
.s_addr
==
456 ia
->ia_addr
.sin_addr
.s_addr
)
459 if (ifra
->ifra_mask
.sin_len
) {
461 ia
->ia_sockmask
= ifra
->ifra_mask
;
463 ntohl(ia
->ia_sockmask
.sin_addr
.s_addr
);
466 if ((ifp
->if_flags
& IFF_POINTOPOINT
) &&
467 (ifra
->ifra_dstaddr
.sin_family
== AF_INET
)) {
469 ia
->ia_dstaddr
= ifra
->ifra_dstaddr
;
470 maskIsNew
= 1; /* We lie; but the effect's the same */
472 if (ifra
->ifra_addr
.sin_family
== AF_INET
&&
473 (hostIsNew
|| maskIsNew
))
474 error
= in_ifinit(ifp
, ia
, &ifra
->ifra_addr
, 0);
475 if ((ifp
->if_flags
& IFF_BROADCAST
) &&
476 (ifra
->ifra_broadaddr
.sin_family
== AF_INET
))
477 ia
->ia_broadaddr
= ifra
->ifra_broadaddr
;
482 if ((ifa
= ifp
->if_addrlist
) == (struct ifaddr
*)ia
)
483 ifp
->if_addrlist
= ifa
->ifa_next
;
485 while (ifa
->ifa_next
&&
486 (ifa
->ifa_next
!= (struct ifaddr
*)ia
))
489 ifa
->ifa_next
= ((struct ifaddr
*)ia
)->ifa_next
;
491 printf("Couldn't unlink inifaddr from ifp\n");
494 if (oia
== (ia
= in_ifaddr
))
495 in_ifaddr
= ia
->ia_next
;
497 while (ia
->ia_next
&& (ia
->ia_next
!= oia
))
500 ia
->ia_next
= oia
->ia_next
;
502 printf("Didn't unlink inifadr from list\n");
504 (void) m_free(dtom(oia
));
508 if (ifp
== 0 || ifp
->if_ioctl
== 0)
510 return ((*ifp
->if_ioctl
)(ifp
, cmd
, data
));
516 * Delete any existing route for an interface.
520 register struct ifnet
*ifp
;
521 register struct in_ifaddr
*ia
;
524 if ((ia
->ia_flags
& IFA_ROUTE
) == 0)
526 if (ifp
->if_flags
& (IFF_LOOPBACK
|IFF_POINTOPOINT
))
527 rtinit(&(ia
->ia_ifa
), (int)RTM_DELETE
, RTF_HOST
);
529 rtinit(&(ia
->ia_ifa
), (int)RTM_DELETE
, 0);
530 ia
->ia_flags
&= ~IFA_ROUTE
;
534 * Initialize an interface's internet address
535 * and routing table entry.
538 in_ifinit(ifp
, ia
, sin
, scrub
)
539 register struct ifnet
*ifp
;
540 register struct in_ifaddr
*ia
;
541 struct sockaddr_in
*sin
;
544 register u_long i
= ntohl(sin
->sin_addr
.s_addr
);
545 struct sockaddr_in oldaddr
;
546 int error
, flags
= RTF_UP
;
549 oldaddr
= ia
->ia_addr
;
552 * Give the interface a chance to initialize
553 * if this is its first address,
554 * and to validate the address if necessary.
557 && (error
= (*ifp
->if_ioctl
)(ifp
, SIOCSIFADDR
, (caddr_t
)ia
))) {
559 ia
->ia_addr
= oldaddr
;
564 ia
->ia_ifa
.ifa_addr
= (struct sockaddr
*)&oldaddr
;
566 ia
->ia_ifa
.ifa_addr
= (struct sockaddr
*)&ia
->ia_addr
;
569 ia
->ia_netmask
= IN_CLASSA_NET
;
570 else if (IN_CLASSB(i
))
571 ia
->ia_netmask
= IN_CLASSB_NET
;
573 ia
->ia_netmask
= IN_CLASSC_NET
;
575 * The subnet mask usually includes at least the standard network part,
576 * but may may be smaller in the case of supernetting.
577 * If it is set, we believe it.
579 if (ia
->ia_subnetmask
== 0) {
580 ia
->ia_subnetmask
= ia
->ia_netmask
;
581 ia
->ia_sockmask
.sin_addr
.s_addr
= htonl(ia
->ia_subnetmask
);
583 ia
->ia_netmask
&= ia
->ia_subnetmask
;
584 ia
->ia_net
= i
& ia
->ia_netmask
;
585 ia
->ia_subnet
= i
& ia
->ia_subnetmask
;
587 register char *cp
= (char *) (1 + &(ia
->ia_sockmask
.sin_addr
));
588 register char *cpbase
= (char *) &(ia
->ia_sockmask
.sin_addr
);
589 while (--cp
>= cpbase
)
591 ia
->ia_sockmask
.sin_len
=
592 1 + cp
- (char *) &(ia
->ia_sockmask
);
597 * Add route for the network.
599 if (ifp
->if_flags
& IFF_BROADCAST
) {
600 ia
->ia_broadaddr
.sin_addr
=
601 in_makeaddr(ia
->ia_subnet
, INADDR_BROADCAST
);
602 ia
->ia_netbroadcast
.s_addr
=
603 htonl(ia
->ia_net
| (INADDR_BROADCAST
&~ ia
->ia_netmask
));
604 } else if (ifp
->if_flags
& IFF_LOOPBACK
) {
605 ia
->ia_ifa
.ifa_dstaddr
= ia
->ia_ifa
.ifa_addr
;
607 } else if (ifp
->if_flags
& IFF_POINTOPOINT
) {
608 if (ia
->ia_dstaddr
.sin_family
!= AF_INET
)
612 if ((error
= rtinit(&(ia
->ia_ifa
), (int)RTM_ADD
, flags
)) == 0)
613 ia
->ia_flags
|= IFA_ROUTE
;
618 * Return address info for specified internet network.
624 register struct in_ifaddr
*ia
;
626 for (ia
= in_ifaddr
; ia
; ia
= ia
->ia_next
)
627 if (ia
->ia_subnet
== net
)
629 return ((struct in_ifaddr
*)0);
633 * Return 1 if the address might be a local broadcast address.
639 register struct in_ifaddr
*ia
;
643 * Look through the list of addresses for a match
644 * with a broadcast address.
646 for (ia
= in_ifaddr
; ia
; ia
= ia
->ia_next
)
647 if (ia
->ia_ifp
->if_flags
& IFF_BROADCAST
) {
648 if (ia
->ia_broadaddr
.sin_addr
.s_addr
== in
.s_addr
)
651 * Check for old-style (host 0) broadcast.
653 if ((t
= ntohl(in
.s_addr
)) == ia
->ia_subnet
|| t
== ia
->ia_net
)
656 if (in
.s_addr
== INADDR_BROADCAST
|| in
.s_addr
== INADDR_ANY
)