* Copyright (c) 1984, 1985, 1986, 1987 Regents of the University of California.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* from: @(#)ns.c 7.8 (Berkeley) 6/27/91
* $Id: ns.c,v 1.4 1993/11/25 01:36:27 wollman Exp $
#include "../net/route.h"
static void ns_ifscrub(struct ifnet
*, struct ns_ifaddr
*);
struct ns_ifaddr
*ns_ifaddr
;
extern struct sockaddr_ns ns_netmask
, ns_hostmask
;
union ns_host ns_thishost
;
union ns_host ns_zerohost
;
union ns_host ns_braodhost
;
union ns_net ns_broadnet
;
* 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) {
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 ns_ifaddr
*);
ns_ifaddr
= mtod(m
, struct ns_ifaddr
*);
ia
= mtod(m
, struct ns_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
*)&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
,
*(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");
(void) m_free(dtom(oia
));
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
,
} 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
,
if (!ns_hosteqnh(ns_thishost
,*h
)) {
* 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_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_net
))
if (ns_neteqnn(net
, ia
->ia_net
))