123204Smckusick /* 2*25453Ssklower * Copyright (c) 1984, 1985 Regents of the University of California. 323204Smckusick * All rights reserved. The Berkeley software License Agreement 423204Smckusick * specifies the terms and conditions for redistribution. 523204Smckusick * 6*25453Ssklower * @(#)ns.c 6.6 (Berkeley) 11/09/85 723204Smckusick */ 821481Ssklower 921481Ssklower #include "param.h" 1021481Ssklower #include "mbuf.h" 1121481Ssklower #include "ioctl.h" 1221481Ssklower #include "protosw.h" 1321481Ssklower #include "socket.h" 1421481Ssklower #include "socketvar.h" 1521481Ssklower #include "uio.h" 1621481Ssklower #include "dir.h" 1721481Ssklower #include "user.h" 1821481Ssklower 1921481Ssklower 2021481Ssklower #include "../net/if.h" 2121481Ssklower #include "../net/route.h" 2221481Ssklower #include "../net/af.h" 2321481Ssklower 2421481Ssklower #include "ns.h" 2521481Ssklower #include "ns_if.h" 2621481Ssklower 2721481Ssklower #ifdef NS 2821481Ssklower 2921481Ssklower struct ns_ifaddr *ns_ifaddr; 3021481Ssklower 3121481Ssklower ns_hash(sns, hp) 3221481Ssklower register struct sockaddr_ns *sns; 3321481Ssklower struct afhash *hp; 3421481Ssklower { 3521481Ssklower register long hash = 0; 3621481Ssklower register u_short *s = sns->sns_addr.x_host.s_host; 3721481Ssklower 3821481Ssklower hp->afh_nethash = ns_netof(sns->sns_addr); 3921481Ssklower hash = *s++; hash <<= 8; hash += *s++; hash <<= 8; hash += *s; 4021481Ssklower hp->afh_hosthash = hash; 4121481Ssklower } 4221481Ssklower 4321481Ssklower 4421481Ssklower ns_netmatch(sns1, sns2) 4521481Ssklower struct sockaddr_ns *sns1, *sns2; 4621481Ssklower { 4721481Ssklower 4821481Ssklower return (ns_netof(sns1->sns_addr) == ns_netof(sns2->sns_addr)); 4921481Ssklower } 5021481Ssklower 5121481Ssklower /* 5221481Ssklower * Generic internet control operations (ioctl's). 5321481Ssklower */ 5424226Ssklower /* ARGSUSED */ 5521481Ssklower ns_control(so, cmd, data, ifp) 5621481Ssklower struct socket *so; 5721481Ssklower int cmd; 5821481Ssklower caddr_t data; 5921481Ssklower register struct ifnet *ifp; 6021481Ssklower { 6121481Ssklower register struct ifreq *ifr = (struct ifreq *)data; 6221481Ssklower register struct ns_ifaddr *ia; 6321481Ssklower struct ifaddr *ifa; 6421481Ssklower struct mbuf *m; 6521481Ssklower 6621481Ssklower /* 6721481Ssklower * Find address for this interface, if it exists. 6821481Ssklower */ 69*25453Ssklower if (ifp == 0) 7024109Ssklower return (EADDRNOTAVAIL); 7121481Ssklower for (ia = ns_ifaddr; ia; ia = ia->ia_next) 7221481Ssklower if (ia->ia_ifp == ifp) 7321481Ssklower break; 7421481Ssklower 7521481Ssklower switch (cmd) { 7621481Ssklower 7721481Ssklower case SIOCGIFADDR: 7824109Ssklower if (ia == (struct ns_ifaddr *)0) 7924109Ssklower return (EADDRNOTAVAIL); 8024109Ssklower ifr->ifr_addr = ia->ia_addr; 8124109Ssklower return (0); 8224109Ssklower 8324109Ssklower 8421481Ssklower case SIOCGIFBRDADDR: 8524109Ssklower if (ia == (struct ns_ifaddr *)0) 8624109Ssklower return (EADDRNOTAVAIL); 8724109Ssklower if ((ifp->if_flags & IFF_BROADCAST) == 0) 8824109Ssklower return (EINVAL); 8924109Ssklower ifr->ifr_dstaddr = ia->ia_broadaddr; 9024109Ssklower return (0); 9124109Ssklower 9221481Ssklower case SIOCGIFDSTADDR: 9321481Ssklower if (ia == (struct ns_ifaddr *)0) 9421481Ssklower return (EADDRNOTAVAIL); 9524109Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 9624109Ssklower return (EINVAL); 9724109Ssklower ifr->ifr_dstaddr = ia->ia_dstaddr; 9824109Ssklower return (0); 9924109Ssklower } 10021481Ssklower 10124109Ssklower if (!suser()) 10224109Ssklower return (u.u_error); 10324109Ssklower 10424109Ssklower switch (cmd) { 10524109Ssklower 106*25453Ssklower case SIOCSIFADDR: 10721481Ssklower case SIOCSIFDSTADDR: 10821481Ssklower if (ia == (struct ns_ifaddr *)0) { 10921481Ssklower m = m_getclr(M_WAIT, MT_IFADDR); 11021481Ssklower if (m == (struct mbuf *)NULL) 11121481Ssklower return (ENOBUFS); 11221481Ssklower if (ia = ns_ifaddr) { 11321481Ssklower for ( ; ia->ia_next; ia = ia->ia_next) 11421481Ssklower ; 11521481Ssklower ia->ia_next = mtod(m, struct ns_ifaddr *); 11621481Ssklower } else 11721481Ssklower ns_ifaddr = mtod(m, struct ns_ifaddr *); 11821481Ssklower ia = mtod(m, struct ns_ifaddr *); 11921481Ssklower if (ifa = ifp->if_addrlist) { 12021481Ssklower for ( ; ifa->ifa_next; ifa = ifa->ifa_next) 12121481Ssklower ; 12221481Ssklower ifa->ifa_next = (struct ifaddr *) ia; 12321481Ssklower } else 12421481Ssklower ifp->if_addrlist = (struct ifaddr *) ia; 12521481Ssklower ia->ia_ifp = ifp; 12621481Ssklower IA_SNS(ia)->sns_family = AF_NS; 12721481Ssklower } 128*25453Ssklower } 129*25453Ssklower 130*25453Ssklower switch (cmd) { 131*25453Ssklower 132*25453Ssklower case SIOCSIFDSTADDR: 133*25453Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 134*25453Ssklower return (EINVAL); 135*25453Ssklower if (ia->ia_flags & IFA_ROUTE) { 136*25453Ssklower rtinit(&ia->ia_dstaddr, &ia->ia_addr, 137*25453Ssklower (int)SIOCDELRT, RTF_HOST); 138*25453Ssklower ia->ia_flags &= ~IFA_ROUTE; 139*25453Ssklower } 140*25453Ssklower if (ifp->if_ioctl) { 141*25453Ssklower int error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia); 142*25453Ssklower if (error) 143*25453Ssklower return (error); 144*25453Ssklower } 145*25453Ssklower ia->ia_dstaddr = ifr->ifr_dstaddr; 146*25453Ssklower return (0); 147*25453Ssklower 148*25453Ssklower case SIOCSIFADDR: 14921481Ssklower return 15021481Ssklower (ns_ifinit(ifp, ia, (struct sockaddr_ns *)&ifr->ifr_addr)); 15121481Ssklower 15221481Ssklower default: 15321481Ssklower if (ifp->if_ioctl == 0) 15421481Ssklower return (EOPNOTSUPP); 15521481Ssklower return ((*ifp->if_ioctl)(ifp, cmd, data)); 15621481Ssklower } 15721481Ssklower } 15821481Ssklower 15921481Ssklower /* 16021481Ssklower * Initialize an interface's internet address 16121481Ssklower * and routing table entry. 16221481Ssklower */ 16321481Ssklower ns_ifinit(ifp, ia, sns) 16421481Ssklower register struct ifnet *ifp; 16521481Ssklower register struct ns_ifaddr *ia; 16621481Ssklower struct sockaddr_ns *sns; 16721481Ssklower { 16821481Ssklower struct sockaddr_ns netaddr; 16921481Ssklower register union ns_host *h = &(IA_SNS(ia)->sns_addr.x_host); 17021481Ssklower int s = splimp(), error; 17121481Ssklower 17221481Ssklower /* 17321481Ssklower * The convention we shall adopt for naming is that 17421481Ssklower * a supplied address of zero means that "we don't care". 17521481Ssklower * if there is a single interface, use the address of that 17621481Ssklower * interface as our 6 byte host address. 17721481Ssklower * if there are multiple interfaces, use any address already 17821481Ssklower * used. 17921481Ssklower * 18021481Ssklower * If we have gotten into trouble and want to reset back to 18121481Ssklower * virginity, we recognize a request of the broadcast address. 18221481Ssklower */ 18321481Ssklower if (ns_hosteqnh(sns->sns_addr.x_host, ns_broadhost)) { 18421481Ssklower ns_thishost = ns_zerohost; 18521481Ssklower splx(s); 186*25453Ssklower return (0); 18721481Ssklower } 18821481Ssklower 18921481Ssklower /* 19021481Ssklower * Delete any previous route for an old address. 19121481Ssklower */ 19221481Ssklower bzero((caddr_t)&netaddr, sizeof (netaddr)); 19321481Ssklower netaddr.sns_family = AF_NS; 19421481Ssklower netaddr.sns_addr.x_host = ns_broadhost; 19521481Ssklower netaddr.sns_addr.x_net = ia->ia_net; 19621481Ssklower if (ia->ia_flags & IFA_ROUTE) { 19721481Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) == 0) { 198*25453Ssklower rtinit((struct sockaddr *)&netaddr, &ia->ia_addr, 199*25453Ssklower (int)SIOCDELRT, 0); 20021481Ssklower } else 201*25453Ssklower rtinit(&ia->ia_dstaddr, &ia->ia_addr, 202*25453Ssklower (int)SIOCDELRT, RTF_HOST); 20321481Ssklower } 20421481Ssklower 20521481Ssklower /* 20621481Ssklower * Set up new addresses. 20721481Ssklower */ 20821481Ssklower ia->ia_addr = *(struct sockaddr *)sns; 20921481Ssklower ia->ia_net = sns->sns_addr.x_net; 21021481Ssklower netaddr.sns_addr.x_net = ia->ia_net; 21121481Ssklower if (ifp->if_flags & IFF_BROADCAST) { 21221481Ssklower ia->ia_broadaddr = * (struct sockaddr *) &netaddr; 21321481Ssklower } 214*25453Ssklower 21521481Ssklower /* 21621481Ssklower * Give the interface a chance to initialize 21721481Ssklower * if this is its first address, 21821481Ssklower * and to validate the address if necessary. 21921481Ssklower */ 22021481Ssklower if (ns_hosteqnh(ns_thishost, ns_zerohost)) { 22121481Ssklower if (ifp->if_ioctl && 22221481Ssklower (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { 22321481Ssklower splx(s); 22421481Ssklower return (error); 22521481Ssklower } 22621481Ssklower ns_thishost = *h; 22721481Ssklower } else if (ns_hosteqnh(sns->sns_addr.x_host, ns_zerohost) 22821481Ssklower || ns_hosteqnh(sns->sns_addr.x_host, ns_thishost)) { 22921481Ssklower *h = ns_thishost; 23021481Ssklower if (ifp->if_ioctl && 23121481Ssklower (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { 23221481Ssklower splx(s); 23321481Ssklower return (error); 23421481Ssklower } 235*25453Ssklower if (!ns_hosteqnh(ns_thishost,*h)) { 23621481Ssklower splx(s); 23721481Ssklower return (EINVAL); 23821481Ssklower } 23921481Ssklower } else { 24021481Ssklower splx(s); 241*25453Ssklower return (EINVAL); 24221481Ssklower } 243*25453Ssklower 24421481Ssklower /* 24521481Ssklower * Add route for the network. 24621481Ssklower */ 247*25453Ssklower if (ifp->if_flags & IFF_POINTOPOINT) 248*25453Ssklower rtinit(&ia->ia_dstaddr, &ia->ia_addr, (int)SIOCADDRT, 24921481Ssklower RTF_HOST|RTF_UP); 250*25453Ssklower else 251*25453Ssklower rtinit(&ia->ia_broadaddr, &ia->ia_addr, (int)SIOCADDRT, 252*25453Ssklower RTF_UP); 25321481Ssklower ia->ia_flags |= IFA_ROUTE; 254*25453Ssklower return (0); 25521481Ssklower } 25621481Ssklower 25721481Ssklower /* 25821481Ssklower * Return address info for specified internet network. 25921481Ssklower */ 26021481Ssklower struct ns_ifaddr * 26125045Ssklower ns_iaonnetof(dst) 26225045Ssklower register struct ns_addr *dst; 26321481Ssklower { 26421481Ssklower register struct ns_ifaddr *ia; 26525045Ssklower register struct ns_addr *compare; 266*25453Ssklower register struct ifnet *ifp; 267*25453Ssklower struct ns_ifaddr *ia_maybe = 0; 26825045Ssklower long net = ns_netof(*dst); 26925045Ssklower static struct ns_addr laddr; 27021481Ssklower 27125045Ssklower for (ia = ns_ifaddr; ia; ia = ia->ia_next) { 272*25453Ssklower if (ifp = ia->ia_ifp) { 273*25453Ssklower if (ifp->if_flags & IFF_POINTOPOINT) { 274*25453Ssklower compare = &satons_addr(ia->ia_dstaddr); 275*25453Ssklower if (ns_hosteq(*dst, *compare)) 27625045Ssklower return (ia); 277*25453Ssklower laddr.x_net = ia->ia_net; 278*25453Ssklower if (ns_netof(laddr) == net) 279*25453Ssklower ia_maybe = ia; 280*25453Ssklower } else { 281*25453Ssklower laddr.x_net = ia->ia_net; 282*25453Ssklower if (ns_netof(laddr) == net) 283*25453Ssklower return (ia); 28425045Ssklower } 28525045Ssklower } 28625045Ssklower } 28725045Ssklower return (ia_maybe); 28821481Ssklower } 28921481Ssklower #endif 290