123204Smckusick /* 233371Ssklower * Copyright (c) 1984, 1985, 1986, 1987 Regents of the University of California. 333371Ssklower * All rights reserved. 423204Smckusick * 533371Ssklower * Redistribution and use in source and binary forms are permitted 634856Sbostic * provided that the above copyright notice and this paragraph are 734856Sbostic * duplicated in all such forms and that any documentation, 834856Sbostic * advertising materials, and other materials related to such 934856Sbostic * distribution and use acknowledge that the software was developed 1034856Sbostic * by the University of California, Berkeley. The name of the 1134856Sbostic * University may not be used to endorse or promote products derived 1234856Sbostic * from this software without specific prior written permission. 1334856Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434856Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1534856Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1633371Ssklower * 17*37473Ssklower * @(#)ns.c 7.4 (Berkeley) 04/22/89 1823204Smckusick */ 1921481Ssklower 2021481Ssklower #include "param.h" 2121481Ssklower #include "mbuf.h" 2221481Ssklower #include "ioctl.h" 2321481Ssklower #include "protosw.h" 2421481Ssklower #include "socket.h" 2521481Ssklower #include "socketvar.h" 2621481Ssklower #include "uio.h" 2721481Ssklower #include "dir.h" 2821481Ssklower #include "user.h" 2921481Ssklower 3021481Ssklower 3121481Ssklower #include "../net/if.h" 3221481Ssklower #include "../net/route.h" 3321481Ssklower #include "../net/af.h" 3421481Ssklower 3521481Ssklower #include "ns.h" 3621481Ssklower #include "ns_if.h" 3721481Ssklower 3821481Ssklower #ifdef NS 3921481Ssklower 4021481Ssklower struct ns_ifaddr *ns_ifaddr; 41*37473Ssklower int ns_interfaces; 42*37473Ssklower extern struct sockaddr_ns ns_netmask, ns_hostmask; 4321481Ssklower 4421481Ssklower /* 4521481Ssklower * Generic internet control operations (ioctl's). 4621481Ssklower */ 4724226Ssklower /* ARGSUSED */ 4821481Ssklower ns_control(so, cmd, data, ifp) 4921481Ssklower struct socket *so; 5021481Ssklower int cmd; 5121481Ssklower caddr_t data; 5221481Ssklower register struct ifnet *ifp; 5321481Ssklower { 5421481Ssklower register struct ifreq *ifr = (struct ifreq *)data; 55*37473Ssklower register struct ns_aliasreq *ifra = (struct ns_aliasreq *)data; 5621481Ssklower register struct ns_ifaddr *ia; 5721481Ssklower struct ifaddr *ifa; 58*37473Ssklower struct ns_ifaddr *oia; 5921481Ssklower struct mbuf *m; 60*37473Ssklower int dstIsNew, hostIsNew; 6121481Ssklower 6221481Ssklower /* 6321481Ssklower * Find address for this interface, if it exists. 6421481Ssklower */ 6525453Ssklower if (ifp == 0) 6624109Ssklower return (EADDRNOTAVAIL); 6721481Ssklower for (ia = ns_ifaddr; ia; ia = ia->ia_next) 6821481Ssklower if (ia->ia_ifp == ifp) 6921481Ssklower break; 7021481Ssklower 7121481Ssklower switch (cmd) { 7221481Ssklower 7321481Ssklower case SIOCGIFADDR: 7424109Ssklower if (ia == (struct ns_ifaddr *)0) 7524109Ssklower return (EADDRNOTAVAIL); 76*37473Ssklower *(struct sockaddr_ns *)&ifr->ifr_addr = ia->ia_addr; 7724109Ssklower return (0); 7824109Ssklower 7924109Ssklower 8021481Ssklower case SIOCGIFBRDADDR: 8124109Ssklower if (ia == (struct ns_ifaddr *)0) 8224109Ssklower return (EADDRNOTAVAIL); 8324109Ssklower if ((ifp->if_flags & IFF_BROADCAST) == 0) 8424109Ssklower return (EINVAL); 85*37473Ssklower *(struct sockaddr_ns *)&ifr->ifr_dstaddr = ia->ia_broadaddr; 8624109Ssklower return (0); 8724109Ssklower 8821481Ssklower case SIOCGIFDSTADDR: 8921481Ssklower if (ia == (struct ns_ifaddr *)0) 9021481Ssklower return (EADDRNOTAVAIL); 9124109Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 9224109Ssklower return (EINVAL); 93*37473Ssklower *(struct sockaddr_ns *)&ifr->ifr_dstaddr = ia->ia_dstaddr; 9424109Ssklower return (0); 9524109Ssklower } 9621481Ssklower 9724109Ssklower if (!suser()) 9824109Ssklower return (u.u_error); 9924109Ssklower 10024109Ssklower switch (cmd) { 101*37473Ssklower case SIOCAIFADDR: 102*37473Ssklower case SIOCDIFADDR: 103*37473Ssklower if (ifra->ifra_addr.sns_family == AF_NS) 104*37473Ssklower for (oia = ia; ia; ia = ia->ia_next) { 105*37473Ssklower if (ia->ia_ifp == ifp && 106*37473Ssklower ns_neteq(ia->ia_addr.sns_addr, 107*37473Ssklower ifra->ifra_addr.sns_addr)) 108*37473Ssklower break; 109*37473Ssklower } 110*37473Ssklower if (cmd == SIOCDIFADDR && ia == 0) 111*37473Ssklower return (EADDRNOTAVAIL); 112*37473Ssklower /* FALLTHROUGH */ 11324109Ssklower 11425453Ssklower case SIOCSIFADDR: 11521481Ssklower case SIOCSIFDSTADDR: 11621481Ssklower if (ia == (struct ns_ifaddr *)0) { 11721481Ssklower m = m_getclr(M_WAIT, MT_IFADDR); 11821481Ssklower if (m == (struct mbuf *)NULL) 11921481Ssklower return (ENOBUFS); 12021481Ssklower if (ia = ns_ifaddr) { 12121481Ssklower for ( ; ia->ia_next; ia = ia->ia_next) 12221481Ssklower ; 12321481Ssklower ia->ia_next = mtod(m, struct ns_ifaddr *); 12421481Ssklower } else 12521481Ssklower ns_ifaddr = mtod(m, struct ns_ifaddr *); 12621481Ssklower ia = mtod(m, struct ns_ifaddr *); 12721481Ssklower if (ifa = ifp->if_addrlist) { 12821481Ssklower for ( ; ifa->ifa_next; ifa = ifa->ifa_next) 12921481Ssklower ; 13021481Ssklower ifa->ifa_next = (struct ifaddr *) ia; 13121481Ssklower } else 13221481Ssklower ifp->if_addrlist = (struct ifaddr *) ia; 13321481Ssklower ia->ia_ifp = ifp; 134*37473Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 135*37473Ssklower 136*37473Ssklower ia->ia_ifa.ifa_netmask = 137*37473Ssklower (struct sockaddr *)&ns_netmask; 138*37473Ssklower 139*37473Ssklower ia->ia_ifa.ifa_dstaddr = 140*37473Ssklower (struct sockaddr *)&ia->ia_dstaddr; 141*37473Ssklower if (ifp->if_flags & IFF_BROADCAST) { 142*37473Ssklower ia->ia_broadaddr.sns_family = AF_NS; 143*37473Ssklower ia->ia_broadaddr.sns_len = sizeof(ia->ia_addr); 144*37473Ssklower ia->ia_broadaddr.sns_addr.x_host = ns_broadhost; 145*37473Ssklower } 146*37473Ssklower ns_interfaces++; 14721481Ssklower } 14825453Ssklower } 14925453Ssklower 15025453Ssklower switch (cmd) { 151*37473Ssklower int error; 15225453Ssklower 15325453Ssklower case SIOCSIFDSTADDR: 15425453Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 15525453Ssklower return (EINVAL); 15625453Ssklower if (ia->ia_flags & IFA_ROUTE) { 157*37473Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 15825453Ssklower ia->ia_flags &= ~IFA_ROUTE; 15925453Ssklower } 16025453Ssklower if (ifp->if_ioctl) { 161*37473Ssklower error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia); 16225453Ssklower if (error) 16325453Ssklower return (error); 16425453Ssklower } 165*37473Ssklower *(struct sockaddr *)&ia->ia_dstaddr = ifr->ifr_dstaddr; 16625453Ssklower return (0); 16725453Ssklower 16825453Ssklower case SIOCSIFADDR: 169*37473Ssklower return (ns_ifinit(ifp, ia, 170*37473Ssklower (struct sockaddr_ns *)&ifr->ifr_addr, 1)); 17121481Ssklower 172*37473Ssklower case SIOCDIFADDR: 173*37473Ssklower ns_ifscrub(ifp, ia); 174*37473Ssklower if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia) 175*37473Ssklower ifp->if_addrlist = ifa->ifa_next; 176*37473Ssklower else { 177*37473Ssklower while (ifa->ifa_next && 178*37473Ssklower (ifa->ifa_next != (struct ifaddr *)ia)) 179*37473Ssklower ifa = ifa->ifa_next; 180*37473Ssklower if (ifa->ifa_next) 181*37473Ssklower ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next; 182*37473Ssklower else 183*37473Ssklower printf("Couldn't unlink nsifaddr from ifp\n"); 184*37473Ssklower } 185*37473Ssklower oia = ia; 186*37473Ssklower if (oia == (ia = ns_ifaddr)) { 187*37473Ssklower ns_ifaddr = ia->ia_next; 188*37473Ssklower } else { 189*37473Ssklower while (ia->ia_next && (ia->ia_next != oia)) { 190*37473Ssklower ia = ia->ia_next; 191*37473Ssklower } 192*37473Ssklower if (ia->ia_next) 193*37473Ssklower ia->ia_next = oia->ia_next; 194*37473Ssklower else 195*37473Ssklower printf("Didn't unlink nsifadr from list\n"); 196*37473Ssklower } 197*37473Ssklower (void) m_free(dtom(oia)); 198*37473Ssklower if (0 == --ns_interfaces) { 199*37473Ssklower /* 200*37473Ssklower * We reset to virginity and start all over again 201*37473Ssklower */ 202*37473Ssklower ns_thishost = ns_zerohost; 203*37473Ssklower } 204*37473Ssklower return (0); 205*37473Ssklower 206*37473Ssklower case SIOCAIFADDR: 207*37473Ssklower dstIsNew = 0; hostIsNew = 1; 208*37473Ssklower if (ia->ia_addr.sns_family == AF_NS) { 209*37473Ssklower if (ifra->ifra_addr.sns_len == 0) { 210*37473Ssklower ifra->ifra_addr = ia->ia_addr; 211*37473Ssklower hostIsNew = 0; 212*37473Ssklower } else if (ns_neteq(ifra->ifra_addr.sns_addr, 213*37473Ssklower ia->ia_addr.sns_addr)) 214*37473Ssklower hostIsNew = 0; 215*37473Ssklower } 216*37473Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) && 217*37473Ssklower (ifra->ifra_dstaddr.sns_family == AF_NS)) { 218*37473Ssklower if (hostIsNew == 0) 219*37473Ssklower ns_ifscrub(ifp, ia); 220*37473Ssklower ia->ia_dstaddr = ifra->ifra_dstaddr; 221*37473Ssklower dstIsNew = 1; 222*37473Ssklower } 223*37473Ssklower if (ifra->ifra_addr.sns_family == AF_NS && 224*37473Ssklower (hostIsNew || dstIsNew)) 225*37473Ssklower error = ns_ifinit(ifp, ia, &ifra->ifra_addr, 0); 226*37473Ssklower return (error); 227*37473Ssklower 22821481Ssklower default: 22921481Ssklower if (ifp->if_ioctl == 0) 23021481Ssklower return (EOPNOTSUPP); 23121481Ssklower return ((*ifp->if_ioctl)(ifp, cmd, data)); 23221481Ssklower } 23321481Ssklower } 23421481Ssklower 23521481Ssklower /* 236*37473Ssklower * Delete any previous route for an old address. 237*37473Ssklower */ 238*37473Ssklower ns_ifscrub(ifp, ia) 239*37473Ssklower register struct ifnet *ifp; 240*37473Ssklower register struct ns_ifaddr *ia; 241*37473Ssklower { 242*37473Ssklower if (ia->ia_flags & IFA_ROUTE) { 243*37473Ssklower if (ifp->if_flags & IFF_POINTOPOINT) { 244*37473Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 245*37473Ssklower } else 246*37473Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0); 247*37473Ssklower ia->ia_flags &= ~IFA_ROUTE; 248*37473Ssklower } 249*37473Ssklower } 250*37473Ssklower /* 25121481Ssklower * Initialize an interface's internet address 25221481Ssklower * and routing table entry. 25321481Ssklower */ 254*37473Ssklower ns_ifinit(ifp, ia, sns, scrub) 25521481Ssklower register struct ifnet *ifp; 25621481Ssklower register struct ns_ifaddr *ia; 257*37473Ssklower register struct sockaddr_ns *sns; 25821481Ssklower { 259*37473Ssklower struct sockaddr_ns oldaddr; 260*37473Ssklower register union ns_host *h = &ia->ia_addr.sns_addr.x_host; 26121481Ssklower int s = splimp(), error; 26221481Ssklower 26321481Ssklower /* 264*37473Ssklower * Set up new addresses. 265*37473Ssklower */ 266*37473Ssklower oldaddr = ia->ia_addr; 267*37473Ssklower ia->ia_addr = *sns; 268*37473Ssklower /* 26921481Ssklower * The convention we shall adopt for naming is that 27021481Ssklower * a supplied address of zero means that "we don't care". 27121481Ssklower * if there is a single interface, use the address of that 27221481Ssklower * interface as our 6 byte host address. 27321481Ssklower * if there are multiple interfaces, use any address already 27421481Ssklower * used. 27521481Ssklower * 27621481Ssklower * Give the interface a chance to initialize 27721481Ssklower * if this is its first address, 27821481Ssklower * and to validate the address if necessary. 27921481Ssklower */ 28021481Ssklower if (ns_hosteqnh(ns_thishost, ns_zerohost)) { 28121481Ssklower if (ifp->if_ioctl && 28221481Ssklower (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { 283*37473Ssklower ia->ia_addr = oldaddr; 28421481Ssklower splx(s); 28521481Ssklower return (error); 28621481Ssklower } 28721481Ssklower ns_thishost = *h; 28821481Ssklower } else if (ns_hosteqnh(sns->sns_addr.x_host, ns_zerohost) 28921481Ssklower || ns_hosteqnh(sns->sns_addr.x_host, ns_thishost)) { 29021481Ssklower *h = ns_thishost; 29121481Ssklower if (ifp->if_ioctl && 29221481Ssklower (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { 293*37473Ssklower ia->ia_addr = oldaddr; 29421481Ssklower splx(s); 29521481Ssklower return (error); 29621481Ssklower } 29725453Ssklower if (!ns_hosteqnh(ns_thishost,*h)) { 298*37473Ssklower ia->ia_addr = oldaddr; 29921481Ssklower splx(s); 30021481Ssklower return (EINVAL); 30121481Ssklower } 30221481Ssklower } else { 303*37473Ssklower ia->ia_addr = oldaddr; 30421481Ssklower splx(s); 30525453Ssklower return (EINVAL); 30621481Ssklower } 30721481Ssklower /* 30821481Ssklower * Add route for the network. 30921481Ssklower */ 310*37473Ssklower if (scrub) { 311*37473Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr; 312*37473Ssklower ns_ifscrub(ifp, ia); 313*37473Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 314*37473Ssklower } 31525453Ssklower if (ifp->if_flags & IFF_POINTOPOINT) 316*37473Ssklower rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 317*37473Ssklower else { 318*37473Ssklower ia->ia_broadaddr.sns_addr.x_net = ia->ia_net; 319*37473Ssklower rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP); 320*37473Ssklower } 32121481Ssklower ia->ia_flags |= IFA_ROUTE; 32225453Ssklower return (0); 32321481Ssklower } 32421481Ssklower 32521481Ssklower /* 32621481Ssklower * Return address info for specified internet network. 32721481Ssklower */ 32821481Ssklower struct ns_ifaddr * 32925045Ssklower ns_iaonnetof(dst) 33025045Ssklower register struct ns_addr *dst; 33121481Ssklower { 33221481Ssklower register struct ns_ifaddr *ia; 33325045Ssklower register struct ns_addr *compare; 33425453Ssklower register struct ifnet *ifp; 33525453Ssklower struct ns_ifaddr *ia_maybe = 0; 33626055Ssklower union ns_net net = dst->x_net; 33721481Ssklower 33825045Ssklower for (ia = ns_ifaddr; ia; ia = ia->ia_next) { 33925453Ssklower if (ifp = ia->ia_ifp) { 34025453Ssklower if (ifp->if_flags & IFF_POINTOPOINT) { 34125453Ssklower compare = &satons_addr(ia->ia_dstaddr); 34225453Ssklower if (ns_hosteq(*dst, *compare)) 34325045Ssklower return (ia); 34426055Ssklower if (ns_neteqnn(net, ia->ia_net)) 34525453Ssklower ia_maybe = ia; 34625453Ssklower } else { 34726055Ssklower if (ns_neteqnn(net, ia->ia_net)) 34825453Ssklower return (ia); 34925045Ssklower } 35025045Ssklower } 35125045Ssklower } 35225045Ssklower return (ia_maybe); 35321481Ssklower } 35421481Ssklower #endif 355