* Copyright (c) 1982 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
* @(#)in.c 6.15 (Berkeley) %G%
#include "../net/route.h"
register struct sockaddr_in
*sin
;
n
= in_netof(sin
->sin_addr
);
hp
->afh_hosthash
= ntohl(sin
->sin_addr
.s_addr
);
inet_netmatch(sin1
, sin2
)
struct sockaddr_in
*sin1
, *sin2
;
return (in_netof(sin1
->sin_addr
) == in_netof(sin2
->sin_addr
));
* Formulate an Internet address from network + host.
register struct in_ifaddr
*ia
;
for (ia
= in_ifaddr
; ia
; ia
= ia
->ia_next
)
if ((ia
->ia_netmask
& net
) == ia
->ia_net
) {
mask
= ~ia
->ia_subnetmask
;
addr
= htonl(net
| (host
& mask
));
return (*(struct in_addr
*)&addr
);
* Return the network number from an internet address.
register u_long i
= ntohl(in
.s_addr
);
register struct in_ifaddr
*ia
;
* Check whether network is a subnet;
* if so, return subnet number.
for (ia
= in_ifaddr
; ia
; ia
= ia
->ia_next
)
return (i
& ia
->ia_subnetmask
);
* Return the host portion of an internet address.
register u_long i
= ntohl(in
.s_addr
);
register u_long net
, host
;
register struct in_ifaddr
*ia
;
host
= i
& IN_CLASSA_HOST
;
} else if (IN_CLASSB(i
)) {
host
= i
& IN_CLASSB_HOST
;
host
= i
& IN_CLASSC_HOST
;
* Check whether network is a subnet;
* if so, use the modified interpretation of `host'.
for (ia
= in_ifaddr
; ia
; ia
= ia
->ia_next
)
return (host
&~ ia
->ia_subnetmask
);
#define SUBNETSARELOCAL 1
int subnetsarelocal
= SUBNETSARELOCAL
;
* Return 1 if an internet address is for a ``local'' host
* (one to which we have a connection). If subnetsarelocal
* is true, this includes other subnets of the local net.
* Otherwise, it includes only the directly-connected (sub)nets.
register u_long i
= ntohl(in
.s_addr
);
register struct in_ifaddr
*ia
;
for (ia
= in_ifaddr
; ia
; ia
= ia
->ia_next
)
if (net
== subnetsarelocal
? ia
->ia_net
: ia
->ia_subnet
)
int in_interfaces
; /* number of external internet interfaces */
extern struct ifnet loif
;
* Generic internet control operations (ioctl's).
* Ifp is 0 if not an interface-specific ioctl.
in_control(so
, cmd
, data
, ifp
)
register struct ifnet
*ifp
;
register struct ifreq
*ifr
= (struct ifreq
*)data
;
register struct in_ifaddr
*ia
= 0;
* Find address for this interface, if it exists.
for (ia
= in_ifaddr
; ia
; ia
= ia
->ia_next
)
if (ia
== (struct in_ifaddr
*)0) {
m
= m_getclr(M_WAIT
, MT_IFADDR
);
if (m
== (struct mbuf
*)NULL
)
for ( ; ia
->ia_next
; ia
= ia
->ia_next
)
ia
->ia_next
= mtod(m
, struct in_ifaddr
*);
in_ifaddr
= mtod(m
, struct in_ifaddr
*);
ia
= mtod(m
, struct in_ifaddr
*);
if (ifa
= ifp
->if_addrlist
) {
for ( ; ifa
->ifa_next
; ifa
= ifa
->ifa_next
)
ifa
->ifa_next
= (struct ifaddr
*) ia
;
ifp
->if_addrlist
= (struct ifaddr
*) ia
;
IA_SIN(ia
)->sin_family
= AF_INET
;
if (ia
== (struct in_ifaddr
*)0)
ifr
->ifr_addr
= ia
->ia_addr
;
if ((ifp
->if_flags
& IFF_BROADCAST
) == 0)
ifr
->ifr_dstaddr
= ia
->ia_broadaddr
;
if ((ifp
->if_flags
& IFF_POINTOPOINT
) == 0)
ifr
->ifr_dstaddr
= ia
->ia_dstaddr
;
#define satosin(sa) ((struct sockaddr_in *)(sa))
satosin(&ifr
->ifr_addr
)->sin_family
= AF_INET
;
satosin(&ifr
->ifr_addr
)->sin_addr
.s_addr
= htonl(ia
->ia_subnetmask
);
if ((ifp
->if_flags
& IFF_POINTOPOINT
) == 0)
oldaddr
= ia
->ia_dstaddr
;
ia
->ia_dstaddr
= ifr
->ifr_dstaddr
;
(error
= (*ifp
->if_ioctl
)(ifp
, SIOCSIFDSTADDR
, ia
))) {
ia
->ia_dstaddr
= oldaddr
;
if (ia
->ia_flags
& IFA_ROUTE
) {
rtinit(&oldaddr
, &ia
->ia_addr
, (int)SIOCDELRT
,
rtinit(&ia
->ia_dstaddr
, &ia
->ia_addr
, (int)SIOCADDRT
,
if ((ifp
->if_flags
& IFF_BROADCAST
) == 0)
ia
->ia_broadaddr
= ifr
->ifr_broadaddr
;
tmp
= ntohl(satosin(&ia
->ia_broadaddr
)->sin_addr
.s_addr
);
if ((tmp
&~ ia
->ia_subnetmask
) == ~ia
->ia_subnetmask
)
else if ((tmp
&~ ia
->ia_subnetmask
) == 0)
ia
->ia_netbroadcast
.s_addr
= htonl(tmp
);
return (in_ifinit(ifp
, ia
, &ifr
->ifr_addr
));
ia
->ia_subnetmask
= ntohl(satosin(&ifr
->ifr_addr
)->sin_addr
.s_addr
);
if (ifp
== 0 || ifp
->if_ioctl
== 0)
return ((*ifp
->if_ioctl
)(ifp
, cmd
, data
));
* Initialize an interface's internet address
* and routing table entry.
register struct ifnet
*ifp
;
register struct in_ifaddr
*ia
;
register u_long i
= ntohl(sin
->sin_addr
.s_addr
);
struct sockaddr_in netaddr
;
ia
->ia_addr
= *(struct sockaddr
*)sin
;
* Give the interface a chance to initialize
* if this is its first address,
* and to validate the address if necessary.
if (ifp
->if_ioctl
&& (error
= (*ifp
->if_ioctl
)(ifp
, SIOCSIFADDR
, ia
))) {
* Delete any previous route for an old address.
bzero((caddr_t
)&netaddr
, sizeof (netaddr
));
netaddr
.sin_family
= AF_INET
;
if (ia
->ia_flags
& IFA_ROUTE
) {
if (ifp
->if_flags
& IFF_LOOPBACK
)
rtinit(&oldaddr
, &oldaddr
, (int)SIOCDELRT
, RTF_HOST
);
else if (ifp
->if_flags
& IFF_POINTOPOINT
)
rtinit(&ia
->ia_dstaddr
, &oldaddr
, (int)SIOCDELRT
,
netaddr
.sin_addr
= in_makeaddr(ia
->ia_subnet
,
rtinit((struct sockaddr
*)&netaddr
, &oldaddr
,
ia
->ia_flags
&= ~IFA_ROUTE
;
ia
->ia_netmask
= IN_CLASSA_NET
;
ia
->ia_netmask
= IN_CLASSB_NET
;
ia
->ia_netmask
= IN_CLASSC_NET
;
ia
->ia_net
= i
& ia
->ia_netmask
;
* The subnet mask includes at least the standard network part,
* but may already have been set to a larger value.
ia
->ia_subnetmask
|= ia
->ia_netmask
;
ia
->ia_subnet
= i
& ia
->ia_subnetmask
;
if (ifp
->if_flags
& IFF_BROADCAST
) {
ia
->ia_broadaddr
.sa_family
= AF_INET
;
((struct sockaddr_in
*)(&ia
->ia_broadaddr
))->sin_addr
=
in_makeaddr(ia
->ia_subnet
, INADDR_BROADCAST
);
ia
->ia_netbroadcast
.s_addr
=
htonl(ia
->ia_net
| (INADDR_BROADCAST
&~ ia
->ia_netmask
));
* Add route for the network.
if (ifp
->if_flags
& IFF_LOOPBACK
)
rtinit(&ia
->ia_addr
, &ia
->ia_addr
, (int)SIOCADDRT
,
else if (ifp
->if_flags
& IFF_POINTOPOINT
)
rtinit(&ia
->ia_dstaddr
, &ia
->ia_addr
, (int)SIOCADDRT
,
netaddr
.sin_addr
= in_makeaddr(ia
->ia_subnet
, INADDR_ANY
);
rtinit((struct sockaddr
*)&netaddr
, &ia
->ia_addr
,
ia
->ia_flags
|= IFA_ROUTE
;
* Return address info for specified internet network.
register struct in_ifaddr
*ia
;
for (ia
= in_ifaddr
; ia
; ia
= ia
->ia_next
)
if (ia
->ia_subnet
== net
)
return ((struct in_ifaddr
*)0);
* Return 1 if the address is a local broadcast address.
register struct in_ifaddr
*ia
;
* Look through the list of addresses for a match
* with a broadcast address.
for (ia
= in_ifaddr
; ia
; ia
= ia
->ia_next
)
if (((struct sockaddr_in
*)&ia
->ia_broadaddr
)->sin_addr
.s_addr
==
in
.s_addr
&& (ia
->ia_ifp
->if_flags
& IFF_BROADCAST
))