1*21481Ssklower /* ns.c 6.1 85/05/30 */ 2*21481Ssklower 3*21481Ssklower #include "param.h" 4*21481Ssklower #include "mbuf.h" 5*21481Ssklower #include "ioctl.h" 6*21481Ssklower #include "protosw.h" 7*21481Ssklower #include "socket.h" 8*21481Ssklower #include "socketvar.h" 9*21481Ssklower #include "uio.h" 10*21481Ssklower #include "dir.h" 11*21481Ssklower #include "user.h" 12*21481Ssklower 13*21481Ssklower 14*21481Ssklower #include "../net/if.h" 15*21481Ssklower #include "../net/route.h" 16*21481Ssklower #include "../net/af.h" 17*21481Ssklower 18*21481Ssklower #include "ns.h" 19*21481Ssklower #include "ns_if.h" 20*21481Ssklower 21*21481Ssklower #ifdef NS 22*21481Ssklower 23*21481Ssklower struct ns_ifaddr *ns_ifaddr; 24*21481Ssklower 25*21481Ssklower ns_hash(sns, hp) 26*21481Ssklower register struct sockaddr_ns *sns; 27*21481Ssklower struct afhash *hp; 28*21481Ssklower { 29*21481Ssklower register long hash = 0; 30*21481Ssklower register u_short *s = sns->sns_addr.x_host.s_host; 31*21481Ssklower 32*21481Ssklower hp->afh_nethash = ns_netof(sns->sns_addr); 33*21481Ssklower hash = *s++; hash <<= 8; hash += *s++; hash <<= 8; hash += *s; 34*21481Ssklower hp->afh_hosthash = hash; 35*21481Ssklower } 36*21481Ssklower 37*21481Ssklower 38*21481Ssklower ns_netmatch(sns1, sns2) 39*21481Ssklower struct sockaddr_ns *sns1, *sns2; 40*21481Ssklower { 41*21481Ssklower 42*21481Ssklower return (ns_netof(sns1->sns_addr) == ns_netof(sns2->sns_addr)); 43*21481Ssklower } 44*21481Ssklower 45*21481Ssklower /* 46*21481Ssklower * Generic internet control operations (ioctl's). 47*21481Ssklower */ 48*21481Ssklower ns_control(so, cmd, data, ifp) 49*21481Ssklower struct socket *so; 50*21481Ssklower int cmd; 51*21481Ssklower caddr_t data; 52*21481Ssklower register struct ifnet *ifp; 53*21481Ssklower { 54*21481Ssklower register struct ifreq *ifr = (struct ifreq *)data; 55*21481Ssklower register struct ns_ifaddr *ia; 56*21481Ssklower struct ifaddr *ifa; 57*21481Ssklower struct mbuf *m; 58*21481Ssklower int error; 59*21481Ssklower 60*21481Ssklower if (!suser()) 61*21481Ssklower return (u.u_error); 62*21481Ssklower 63*21481Ssklower /* 64*21481Ssklower * Find address for this interface, if it exists. 65*21481Ssklower */ 66*21481Ssklower for (ia = ns_ifaddr; ia; ia = ia->ia_next) 67*21481Ssklower if (ia->ia_ifp == ifp) 68*21481Ssklower break; 69*21481Ssklower 70*21481Ssklower switch (cmd) { 71*21481Ssklower 72*21481Ssklower case SIOCGIFADDR: 73*21481Ssklower case SIOCGIFBRDADDR: 74*21481Ssklower case SIOCGIFDSTADDR: 75*21481Ssklower if (ia == (struct ns_ifaddr *)0) 76*21481Ssklower return (EADDRNOTAVAIL); 77*21481Ssklower break; 78*21481Ssklower 79*21481Ssklower case SIOCSIFDSTADDR: 80*21481Ssklower return (EOPNOTSUPP); 81*21481Ssklower 82*21481Ssklower case SIOCSIFADDR: 83*21481Ssklower if (ia == (struct ns_ifaddr *)0) { 84*21481Ssklower m = m_getclr(M_WAIT, MT_IFADDR); 85*21481Ssklower if (m == (struct mbuf *)NULL) 86*21481Ssklower return (ENOBUFS); 87*21481Ssklower if (ia = ns_ifaddr) { 88*21481Ssklower for ( ; ia->ia_next; ia = ia->ia_next) 89*21481Ssklower ; 90*21481Ssklower ia->ia_next = mtod(m, struct ns_ifaddr *); 91*21481Ssklower } else 92*21481Ssklower ns_ifaddr = mtod(m, struct ns_ifaddr *); 93*21481Ssklower ia = mtod(m, struct ns_ifaddr *); 94*21481Ssklower if (ifa = ifp->if_addrlist) { 95*21481Ssklower for ( ; ifa->ifa_next; ifa = ifa->ifa_next) 96*21481Ssklower ; 97*21481Ssklower ifa->ifa_next = (struct ifaddr *) ia; 98*21481Ssklower } else 99*21481Ssklower ifp->if_addrlist = (struct ifaddr *) ia; 100*21481Ssklower ia->ia_ifp = ifp; 101*21481Ssklower IA_SNS(ia)->sns_family = AF_NS; 102*21481Ssklower } 103*21481Ssklower break; 104*21481Ssklower } 105*21481Ssklower 106*21481Ssklower switch (cmd) { 107*21481Ssklower 108*21481Ssklower case SIOCGIFADDR: 109*21481Ssklower ifr->ifr_addr = ia->ia_addr; 110*21481Ssklower break; 111*21481Ssklower 112*21481Ssklower case SIOCGIFBRDADDR: 113*21481Ssklower if (ia == (struct ns_ifaddr *)0) 114*21481Ssklower return (EADDRNOTAVAIL); 115*21481Ssklower if ((ifp->if_flags & IFF_BROADCAST) == 0) 116*21481Ssklower return (EINVAL); 117*21481Ssklower ifr->ifr_dstaddr = ia->ia_broadaddr; 118*21481Ssklower break; 119*21481Ssklower 120*21481Ssklower case SIOCGIFDSTADDR: 121*21481Ssklower if (ia == (struct ns_ifaddr *)0) 122*21481Ssklower return (EADDRNOTAVAIL); 123*21481Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 124*21481Ssklower return (EINVAL); 125*21481Ssklower ifr->ifr_dstaddr = ia->ia_dstaddr; 126*21481Ssklower break; 127*21481Ssklower 128*21481Ssklower case SIOCSIFADDR: 129*21481Ssklower return 130*21481Ssklower (ns_ifinit(ifp, ia, (struct sockaddr_ns *)&ifr->ifr_addr)); 131*21481Ssklower 132*21481Ssklower default: 133*21481Ssklower if (ifp->if_ioctl == 0) 134*21481Ssklower return (EOPNOTSUPP); 135*21481Ssklower return ((*ifp->if_ioctl)(ifp, cmd, data)); 136*21481Ssklower } 137*21481Ssklower return (0); 138*21481Ssklower } 139*21481Ssklower 140*21481Ssklower /* 141*21481Ssklower * Initialize an interface's internet address 142*21481Ssklower * and routing table entry. 143*21481Ssklower */ 144*21481Ssklower ns_ifinit(ifp, ia, sns) 145*21481Ssklower register struct ifnet *ifp; 146*21481Ssklower register struct ns_ifaddr *ia; 147*21481Ssklower struct sockaddr_ns *sns; 148*21481Ssklower { 149*21481Ssklower struct sockaddr_ns netaddr; 150*21481Ssklower register union ns_host *h = &(IA_SNS(ia)->sns_addr.x_host); 151*21481Ssklower int s = splimp(), error; 152*21481Ssklower 153*21481Ssklower /* 154*21481Ssklower * The convention we shall adopt for naming is that 155*21481Ssklower * a supplied address of zero means that "we don't care". 156*21481Ssklower * if there is a single interface, use the address of that 157*21481Ssklower * interface as our 6 byte host address. 158*21481Ssklower * if there are multiple interfaces, use any address already 159*21481Ssklower * used. 160*21481Ssklower * 161*21481Ssklower * If we have gotten into trouble and want to reset back to 162*21481Ssklower * virginity, we recognize a request of the broadcast address. 163*21481Ssklower */ 164*21481Ssklower if (ns_hosteqnh(sns->sns_addr.x_host, ns_broadhost)) { 165*21481Ssklower ns_thishost = ns_zerohost; 166*21481Ssklower splx(s); 167*21481Ssklower return(EINVAL); 168*21481Ssklower } 169*21481Ssklower 170*21481Ssklower /* 171*21481Ssklower * Delete any previous route for an old address. 172*21481Ssklower */ 173*21481Ssklower 174*21481Ssklower bzero((caddr_t)&netaddr, sizeof (netaddr)); 175*21481Ssklower netaddr.sns_family = AF_NS; 176*21481Ssklower netaddr.sns_addr.x_host = ns_broadhost; 177*21481Ssklower netaddr.sns_addr.x_net = ia->ia_net; 178*21481Ssklower if (ia->ia_flags & IFA_ROUTE) { 179*21481Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) == 0) { 180*21481Ssklower rtinit((struct sockaddr *)&netaddr, &ia->ia_addr, -1); 181*21481Ssklower } else 182*21481Ssklower rtinit((struct sockaddr *)&ia->ia_dstaddr, &ia->ia_addr, -1); 183*21481Ssklower } 184*21481Ssklower 185*21481Ssklower /* 186*21481Ssklower * Set up new addresses. 187*21481Ssklower */ 188*21481Ssklower ia->ia_addr = *(struct sockaddr *)sns; 189*21481Ssklower ia->ia_net = sns->sns_addr.x_net; 190*21481Ssklower netaddr.sns_addr.x_net = ia->ia_net; 191*21481Ssklower if (ifp->if_flags & IFF_BROADCAST) { 192*21481Ssklower ia->ia_broadaddr = * (struct sockaddr *) &netaddr; 193*21481Ssklower } 194*21481Ssklower /* 195*21481Ssklower * Point to point links are a little touchier -- 196*21481Ssklower * We have to have an address of our own first, 197*21481Ssklower * and will use the supplied address as that of the other end. 198*21481Ssklower */ 199*21481Ssklower if (ifp->if_flags & IFF_POINTOPOINT) { 200*21481Ssklower struct sockaddr_ns *sns2 = IA_SNS(ia); 201*21481Ssklower if (ns_hosteqnh(ns_zerohost,ns_thishost)) 202*21481Ssklower return(EINVAL); 203*21481Ssklower ia->ia_dstaddr = ia->ia_addr; 204*21481Ssklower sns2->sns_addr.x_host = ns_thishost; 205*21481Ssklower sns->sns_addr.x_host = ns_thishost; 206*21481Ssklower } 207*21481Ssklower /* 208*21481Ssklower * Give the interface a chance to initialize 209*21481Ssklower * if this is its first address, 210*21481Ssklower * and to validate the address if necessary. 211*21481Ssklower */ 212*21481Ssklower 213*21481Ssklower if (ns_hosteqnh(ns_thishost, ns_zerohost)) { 214*21481Ssklower if (ifp->if_ioctl && 215*21481Ssklower (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { 216*21481Ssklower splx(s); 217*21481Ssklower return (error); 218*21481Ssklower } 219*21481Ssklower ns_thishost = *h; 220*21481Ssklower } else if (ns_hosteqnh(sns->sns_addr.x_host, ns_zerohost) 221*21481Ssklower || ns_hosteqnh(sns->sns_addr.x_host, ns_thishost)) { 222*21481Ssklower *h = ns_thishost; 223*21481Ssklower if (ifp->if_ioctl && 224*21481Ssklower (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { 225*21481Ssklower splx(s); 226*21481Ssklower return (error); 227*21481Ssklower } 228*21481Ssklower if(!ns_hosteqnh(ns_thishost,*h)) { 229*21481Ssklower splx(s); 230*21481Ssklower return (EINVAL); 231*21481Ssklower } 232*21481Ssklower } else { 233*21481Ssklower splx(s); 234*21481Ssklower return(EINVAL); 235*21481Ssklower } 236*21481Ssklower /* 237*21481Ssklower * Add route for the network. 238*21481Ssklower */ 239*21481Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) == 0) { 240*21481Ssklower rtinit((struct sockaddr *)&netaddr, &ia->ia_addr, RTF_UP); 241*21481Ssklower } else 242*21481Ssklower rtinit((struct sockaddr *)&ia->ia_dstaddr, &ia->ia_addr, 243*21481Ssklower RTF_HOST|RTF_UP); 244*21481Ssklower ia->ia_flags |= IFA_ROUTE; 245*21481Ssklower return(0); 246*21481Ssklower } 247*21481Ssklower 248*21481Ssklower /* 249*21481Ssklower * Return address info for specified internet network. 250*21481Ssklower */ 251*21481Ssklower struct ns_ifaddr * 252*21481Ssklower ns_iaonnetof(net) 253*21481Ssklower union ns_net net; 254*21481Ssklower { 255*21481Ssklower register struct ns_ifaddr *ia; 256*21481Ssklower 257*21481Ssklower #define NtoL(x) (*(long *)(&(x))) 258*21481Ssklower for (ia = ns_ifaddr; ia; ia = ia->ia_next) 259*21481Ssklower if (NtoL(ia->ia_net) == NtoL(net)) 260*21481Ssklower return (ia); 261*21481Ssklower return ((struct ns_ifaddr *)0); 262*21481Ssklower } 263*21481Ssklower #endif 264