* Copyright (c) 1984, 1985, 1986, 1987 Regents of the University of California.
* %sccs.include.redist.c%
* @(#)ns.c 7.12 (Berkeley) %G%
#include "../net/route.h"
struct ns_ifaddr
*ns_ifaddr
;
extern struct sockaddr_ns ns_netmask
, ns_hostmask
;
* Generic internet control operations (ioctl's).
ns_control(so
, cmd
, data
, ifp
)
register struct ifnet
*ifp
;
register struct ifreq
*ifr
= (struct ifreq
*)data
;
register struct ns_aliasreq
*ifra
= (struct ns_aliasreq
*)data
;
register struct ns_ifaddr
*ia
;
int error
, dstIsNew
, hostIsNew
;
* Find address for this interface, if it exists.
for (ia
= ns_ifaddr
; ia
; ia
= ia
->ia_next
)
if (ia
== (struct ns_ifaddr
*)0)
*(struct sockaddr_ns
*)&ifr
->ifr_addr
= ia
->ia_addr
;
if (ia
== (struct ns_ifaddr
*)0)
if ((ifp
->if_flags
& IFF_BROADCAST
) == 0)
*(struct sockaddr_ns
*)&ifr
->ifr_dstaddr
= ia
->ia_broadaddr
;
if (ia
== (struct ns_ifaddr
*)0)
if ((ifp
->if_flags
& IFF_POINTOPOINT
) == 0)
*(struct sockaddr_ns
*)&ifr
->ifr_dstaddr
= ia
->ia_dstaddr
;
if ((so
->so_state
& SS_PRIV
) == 0)
if (ifra
->ifra_addr
.sns_family
== AF_NS
)
for (oia
= ia
; ia
; ia
= ia
->ia_next
) {
ns_neteq(ia
->ia_addr
.sns_addr
,
ifra
->ifra_addr
.sns_addr
))
if (cmd
== SIOCDIFADDR
&& ia
== 0)
if (ia
== (struct ns_ifaddr
*)0) {
oia
= (struct ns_ifaddr
*)
malloc(sizeof *ia
, M_IFADDR
, M_WAITOK
);
if (oia
== (struct ns_ifaddr
*)NULL
)
bzero((caddr_t
)oia
, sizeof(*oia
));
for ( ; ia
->ia_next
; ia
= ia
->ia_next
)
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
*)&ns_netmask
;
(struct sockaddr
*)&ia
->ia_dstaddr
;
if (ifp
->if_flags
& IFF_BROADCAST
) {
ia
->ia_broadaddr
.sns_family
= AF_NS
;
ia
->ia_broadaddr
.sns_len
= sizeof(ia
->ia_addr
);
ia
->ia_broadaddr
.sns_addr
.x_host
= ns_broadhost
;
if ((ifp
->if_flags
& IFF_POINTOPOINT
) == 0)
if (ia
->ia_flags
& IFA_ROUTE
) {
rtinit(&(ia
->ia_ifa
), (int)RTM_DELETE
, RTF_HOST
);
ia
->ia_flags
&= ~IFA_ROUTE
;
error
= (*ifp
->if_ioctl
)(ifp
, SIOCSIFDSTADDR
, ia
);
*(struct sockaddr
*)&ia
->ia_dstaddr
= ifr
->ifr_dstaddr
;
return (ns_ifinit(ifp
, ia
,
(struct sockaddr_ns
*)&ifr
->ifr_addr
, 1));
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 nsifaddr from ifp\n");
if (oia
== (ia
= ns_ifaddr
)) {
while (ia
->ia_next
&& (ia
->ia_next
!= oia
)) {
ia
->ia_next
= oia
->ia_next
;
printf("Didn't unlink nsifadr from list\n");
if (0 == --ns_interfaces
) {
* We reset to virginity and start all over again
ns_thishost
= ns_zerohost
;
dstIsNew
= 0; hostIsNew
= 1;
if (ia
->ia_addr
.sns_family
== AF_NS
) {
if (ifra
->ifra_addr
.sns_len
== 0) {
ifra
->ifra_addr
= ia
->ia_addr
;
} else if (ns_neteq(ifra
->ifra_addr
.sns_addr
,
if ((ifp
->if_flags
& IFF_POINTOPOINT
) &&
(ifra
->ifra_dstaddr
.sns_family
== AF_NS
)) {
ia
->ia_dstaddr
= ifra
->ifra_dstaddr
;
if (ifra
->ifra_addr
.sns_family
== AF_NS
&&
error
= ns_ifinit(ifp
, ia
, &ifra
->ifra_addr
, 0);
return ((*ifp
->if_ioctl
)(ifp
, cmd
, data
));
* Delete any previous route for an old address.
register struct ifnet
*ifp
;
register struct ns_ifaddr
*ia
;
if (ia
->ia_flags
& IFA_ROUTE
) {
if (ifp
->if_flags
& 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.
ns_ifinit(ifp
, ia
, sns
, scrub
)
register struct ifnet
*ifp
;
register struct ns_ifaddr
*ia
;
register struct sockaddr_ns
*sns
;
struct sockaddr_ns oldaddr
;
register union ns_host
*h
= &ia
->ia_addr
.sns_addr
.x_host
;
* The convention we shall adopt for naming is that
* a supplied address of zero means that "we don't care".
* if there is a single interface, use the address of that
* interface as our 6 byte host address.
* if there are multiple interfaces, use any address already
* Give the interface a chance to initialize
* if this is its first address,
* and to validate the address if necessary.
if (ns_hosteqnh(ns_thishost
, ns_zerohost
)) {
(error
= (*ifp
->if_ioctl
)(ifp
, SIOCSIFADDR
, ia
))) {
} else if (ns_hosteqnh(sns
->sns_addr
.x_host
, ns_zerohost
)
|| ns_hosteqnh(sns
->sns_addr
.x_host
, ns_thishost
)) {
(error
= (*ifp
->if_ioctl
)(ifp
, SIOCSIFADDR
, ia
))) {
if (!ns_hosteqnh(ns_thishost
,*h
)) {
ia
->ia_ifa
.ifa_metric
= ifp
->if_metric
;
* Add route for the network.
ia
->ia_ifa
.ifa_addr
= (struct sockaddr
*)&oldaddr
;
ia
->ia_ifa
.ifa_addr
= (struct sockaddr
*)&ia
->ia_addr
;
if (ifp
->if_flags
& IFF_POINTOPOINT
)
rtinit(&(ia
->ia_ifa
), (int)RTM_ADD
, RTF_HOST
|RTF_UP
);
ia
->ia_broadaddr
.sns_addr
.x_net
= ia
->ia_addr
.sns_addr
.x_net
;
rtinit(&(ia
->ia_ifa
), (int)RTM_ADD
, RTF_UP
);
ia
->ia_flags
|= IFA_ROUTE
;
* Return address info for specified internet network.
register struct ns_addr
*dst
;
register struct ns_ifaddr
*ia
;
register struct ns_addr
*compare
;
register struct ifnet
*ifp
;
struct ns_ifaddr
*ia_maybe
= 0;
union ns_net net
= dst
->x_net
;
for (ia
= ns_ifaddr
; ia
; ia
= ia
->ia_next
) {
if (ifp
->if_flags
& IFF_POINTOPOINT
) {
compare
= &satons_addr(ia
->ia_dstaddr
);
if (ns_hosteq(*dst
, *compare
))
if (ns_neteqnn(net
, ia
->ia_addr
.sns_addr
.x_net
))
if (ns_neteqnn(net
, ia
->ia_addr
.sns_addr
.x_net
))