* Copyright (c) 1982, 1986, 1991 Regents of the University of California.
* %sccs.include.redist.c%
* @(#)in.c 7.18 (Berkeley) %G%
* 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
);
* Compute and save network mask as sockaddr from an internet address.
in_sockmaskof(in
, sockmask
)
register struct sockaddr_in
*sockmask
;
register u_long i
= ntohl(in
.s_addr
);
net
= i
& IN_CLASSA_NET
, mask
= IN_CLASSA_NET
;
net
= i
& IN_CLASSB_NET
, mask
= IN_CLASSB_NET
;
net
= i
& IN_CLASSC_NET
, mask
= IN_CLASSC_NET
;
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
)
mask
= ia
->ia_subnetmask
;
register char *cpbase
= (char *)&(sockmask
->sin_addr
);
register char *cp
= (char *)(1 + &(sockmask
->sin_addr
));
sockmask
->sin_addr
.s_addr
= htonl(mask
);
sockmask
->sin_len
= 1 + cp
- (caddr_t
)sockmask
;
* 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
;
} else if (IN_CLASSC(i
)) {
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 ((i
& ia
->ia_netmask
) == ia
->ia_net
)
for (ia
= in_ifaddr
; ia
; ia
= ia
->ia_next
)
if ((i
& ia
->ia_subnetmask
) == ia
->ia_subnet
)
* Determine whether an IP address is in a reserved set of addresses
* that may not be forwarded, or whether datagrams to that destination
register u_long i
= ntohl(in
.s_addr
);
if (net
== 0 || net
== IN_LOOPBACKNET
)
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;
register struct ifaddr
*ifa
;
struct in_aliasreq
*ifra
= (struct in_aliasreq
*)data
;
struct sockaddr_in oldaddr
;
int error
, hostIsNew
, maskIsNew
;
* Find address for this interface, if it exists.
for (ia
= in_ifaddr
; ia
; ia
= ia
->ia_next
)
if (ifra
->ifra_addr
.sin_family
== AF_INET
)
for (oia
= ia
; ia
; ia
= ia
->ia_next
) {
ia
->ia_addr
.sin_addr
.s_addr
==
ifra
->ifra_addr
.sin_addr
.s_addr
)
if (cmd
== SIOCDIFADDR
&& ia
== 0)
if ((so
->so_state
& SS_PRIV
) == 0)
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
->ia_ifa
.ifa_addr
= (struct sockaddr
*)&ia
->ia_addr
;
= (struct sockaddr
*)&ia
->ia_dstaddr
;
= (struct sockaddr
*)&ia
->ia_sockmask
;
ia
->ia_sockmask
.sin_len
= 8;
if (ifp
->if_flags
& IFF_BROADCAST
) {
ia
->ia_broadaddr
.sin_len
= sizeof(ia
->ia_addr
);
ia
->ia_broadaddr
.sin_family
= AF_INET
;
if ((so
->so_state
& SS_PRIV
) == 0)
if (ia
== (struct in_ifaddr
*)0)
*((struct sockaddr_in
*)&ifr
->ifr_addr
) = ia
->ia_addr
;
if ((ifp
->if_flags
& IFF_BROADCAST
) == 0)
*((struct sockaddr_in
*)&ifr
->ifr_dstaddr
) = ia
->ia_broadaddr
;
if ((ifp
->if_flags
& IFF_POINTOPOINT
) == 0)
*((struct sockaddr_in
*)&ifr
->ifr_dstaddr
) = ia
->ia_dstaddr
;
*((struct sockaddr_in
*)&ifr
->ifr_addr
) = ia
->ia_sockmask
;
if ((ifp
->if_flags
& IFF_POINTOPOINT
) == 0)
oldaddr
= ia
->ia_dstaddr
;
ia
->ia_dstaddr
= *(struct sockaddr_in
*)&ifr
->ifr_dstaddr
;
(error
= (*ifp
->if_ioctl
)(ifp
, SIOCSIFDSTADDR
, ia
))) {
ia
->ia_dstaddr
= oldaddr
;
if (ia
->ia_flags
& IFA_ROUTE
) {
ia
->ia_ifa
.ifa_dstaddr
= (struct sockaddr
*)&oldaddr
;
rtinit(&(ia
->ia_ifa
), (int)RTM_DELETE
, RTF_HOST
);
(struct sockaddr
*)&ia
->ia_dstaddr
;
rtinit(&(ia
->ia_ifa
), (int)RTM_ADD
, RTF_HOST
|RTF_UP
);
if ((ifp
->if_flags
& IFF_BROADCAST
) == 0)
ia
->ia_broadaddr
= *(struct sockaddr_in
*)&ifr
->ifr_broadaddr
;
return (in_ifinit(ifp
, ia
,
(struct sockaddr_in
*) &ifr
->ifr_addr
, 1));
i
= ifra
->ifra_addr
.sin_addr
.s_addr
;
ia
->ia_subnetmask
= ntohl(ia
->ia_sockmask
.sin_addr
.s_addr
= i
);
if (ia
->ia_addr
.sin_family
== AF_INET
) {
if (ifra
->ifra_addr
.sin_len
== 0) {
ifra
->ifra_addr
= ia
->ia_addr
;
} else if (ifra
->ifra_addr
.sin_addr
.s_addr
==
ia
->ia_addr
.sin_addr
.s_addr
)
if (ifra
->ifra_mask
.sin_len
) {
ia
->ia_sockmask
= ifra
->ifra_mask
;
ntohl(ia
->ia_sockmask
.sin_addr
.s_addr
);
if ((ifp
->if_flags
& IFF_POINTOPOINT
) &&
(ifra
->ifra_dstaddr
.sin_family
== AF_INET
)) {
ia
->ia_dstaddr
= ifra
->ifra_dstaddr
;
maskIsNew
= 1; /* We lie; but the effect's the same */
if (ifra
->ifra_addr
.sin_family
== AF_INET
&&
(hostIsNew
|| maskIsNew
))
error
= in_ifinit(ifp
, ia
, &ifra
->ifra_addr
, 0);
if ((ifp
->if_flags
& IFF_BROADCAST
) &&
(ifra
->ifra_broadaddr
.sin_family
== AF_INET
))
ia
->ia_broadaddr
= ifra
->ifra_broadaddr
;
if ((ifa
= ifp
->if_addrlist
) == (struct ifaddr
*)ia
)
ifp
->if_addrlist
= ifa
->ifa_next
;
(ifa
->ifa_next
!= (struct ifaddr
*)ia
))
ifa
->ifa_next
= ((struct ifaddr
*)ia
)->ifa_next
;
printf("Couldn't unlink inifaddr from ifp\n");
if (oia
== (ia
= in_ifaddr
))
while (ia
->ia_next
&& (ia
->ia_next
!= oia
))
ia
->ia_next
= oia
->ia_next
;
printf("Didn't unlink inifadr from list\n");
(void) m_free(dtom(oia
));
if (ifp
== 0 || ifp
->if_ioctl
== 0)
return ((*ifp
->if_ioctl
)(ifp
, cmd
, data
));
* Delete any existing route for an interface.
register struct ifnet
*ifp
;
register struct in_ifaddr
*ia
;
if ((ia
->ia_flags
& IFA_ROUTE
) == 0)
if (ifp
->if_flags
& (IFF_LOOPBACK
|IFF_POINTOPOINT
))
rtinit(&(ia
->ia_ifa
), (int)RTM_DELETE
, RTF_HOST
);
rtinit(&(ia
->ia_ifa
), (int)RTM_DELETE
, 0);
ia
->ia_flags
&= ~IFA_ROUTE
;
* Initialize an interface's internet address
* and routing table entry.
in_ifinit(ifp
, ia
, sin
, scrub
)
register struct ifnet
*ifp
;
register struct in_ifaddr
*ia
;
register u_long i
= ntohl(sin
->sin_addr
.s_addr
);
struct sockaddr_in oldaddr
;
int s
= splimp(), error
, flags
= RTF_UP
;
int ether_output(), arp_rtrequest();
* 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
))) {
if (ifp
->if_output
== ether_output
) { /* XXX: Another Kludge */
ia
->ia_ifa
.ifa_rtrequest
= arp_rtrequest
;
ia
->ia_ifa
.ifa_flags
|= RTF_CLONING
;
ia
->ia_ifa
.ifa_addr
= (struct sockaddr
*)&oldaddr
;
ia
->ia_ifa
.ifa_addr
= (struct sockaddr
*)&ia
->ia_addr
;
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
;
ia
->ia_sockmask
.sin_addr
.s_addr
= htonl(ia
->ia_subnetmask
);
register char *cp
= (char *) (1 + &(ia
->ia_sockmask
.sin_addr
));
register char *cpbase
= (char *) &(ia
->ia_sockmask
.sin_addr
);
ia
->ia_sockmask
.sin_len
=
1 + cp
- (char *) &(ia
->ia_sockmask
);
* Add route for the network.
if (ifp
->if_flags
& IFF_BROADCAST
) {
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
));
} else if (ifp
->if_flags
& IFF_LOOPBACK
) {
ia
->ia_ifa
.ifa_dstaddr
= ia
->ia_ifa
.ifa_addr
;
} else if (ifp
->if_flags
& IFF_POINTOPOINT
) {
if (ia
->ia_dstaddr
.sin_family
!= AF_INET
)
if ((error
= rtinit(&(ia
->ia_ifa
), (int)RTM_ADD
, flags
)) == 0)
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 might be 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 (ia
->ia_ifp
->if_flags
& IFF_BROADCAST
) {
if (ia
->ia_broadaddr
.sin_addr
.s_addr
== in
.s_addr
)
* Check for old-style (host 0) broadcast.
if ((t
= ntohl(in
.s_addr
)) == ia
->ia_subnet
|| t
== ia
->ia_net
)
if (in
.s_addr
== INADDR_BROADCAST
|| in
.s_addr
== INADDR_ANY
)