123204Smckusick /* 2*63231Sbostic * Copyright (c) 1984, 1985, 1986, 1987, 1993 3*63231Sbostic * The Regents of the University of California. All rights reserved. 423204Smckusick * 544500Sbostic * %sccs.include.redist.c% 633371Ssklower * 7*63231Sbostic * @(#)ns.c 8.1 (Berkeley) 06/10/93 823204Smckusick */ 921481Ssklower 1056534Sbostic #include <sys/param.h> 1156534Sbostic #include <sys/mbuf.h> 1256534Sbostic #include <sys/ioctl.h> 1356534Sbostic #include <sys/protosw.h> 1456534Sbostic #include <sys/errno.h> 1556534Sbostic #include <sys/socket.h> 1656534Sbostic #include <sys/socketvar.h> 1721481Ssklower 1856534Sbostic #include <net/if.h> 1956534Sbostic #include <net/route.h> 2056534Sbostic #include <net/af.h> 2121481Ssklower 2256534Sbostic #include <netns/ns.h> 2356534Sbostic #include <netns/ns_if.h> 2421481Ssklower 2521481Ssklower #ifdef NS 2621481Ssklower 2721481Ssklower struct ns_ifaddr *ns_ifaddr; 2837473Ssklower int ns_interfaces; 2937473Ssklower extern struct sockaddr_ns ns_netmask, ns_hostmask; 3021481Ssklower 3121481Ssklower /* 3221481Ssklower * Generic internet control operations (ioctl's). 3321481Ssklower */ 3424226Ssklower /* ARGSUSED */ 3521481Ssklower ns_control(so, cmd, data, ifp) 3621481Ssklower struct socket *so; 3721481Ssklower int cmd; 3821481Ssklower caddr_t data; 3921481Ssklower register struct ifnet *ifp; 4021481Ssklower { 4121481Ssklower register struct ifreq *ifr = (struct ifreq *)data; 4237473Ssklower register struct ns_aliasreq *ifra = (struct ns_aliasreq *)data; 4321481Ssklower register struct ns_ifaddr *ia; 4421481Ssklower struct ifaddr *ifa; 4537473Ssklower struct ns_ifaddr *oia; 4637546Smckusick int error, dstIsNew, hostIsNew; 4721481Ssklower 4821481Ssklower /* 4921481Ssklower * Find address for this interface, if it exists. 5021481Ssklower */ 5125453Ssklower if (ifp == 0) 5224109Ssklower return (EADDRNOTAVAIL); 5321481Ssklower for (ia = ns_ifaddr; ia; ia = ia->ia_next) 5421481Ssklower if (ia->ia_ifp == ifp) 5521481Ssklower break; 5621481Ssklower 5721481Ssklower switch (cmd) { 5821481Ssklower 5921481Ssklower case SIOCGIFADDR: 6024109Ssklower if (ia == (struct ns_ifaddr *)0) 6124109Ssklower return (EADDRNOTAVAIL); 6237473Ssklower *(struct sockaddr_ns *)&ifr->ifr_addr = ia->ia_addr; 6324109Ssklower return (0); 6424109Ssklower 6524109Ssklower 6621481Ssklower case SIOCGIFBRDADDR: 6724109Ssklower if (ia == (struct ns_ifaddr *)0) 6824109Ssklower return (EADDRNOTAVAIL); 6924109Ssklower if ((ifp->if_flags & IFF_BROADCAST) == 0) 7024109Ssklower return (EINVAL); 7137473Ssklower *(struct sockaddr_ns *)&ifr->ifr_dstaddr = ia->ia_broadaddr; 7224109Ssklower return (0); 7324109Ssklower 7421481Ssklower case SIOCGIFDSTADDR: 7521481Ssklower if (ia == (struct ns_ifaddr *)0) 7621481Ssklower return (EADDRNOTAVAIL); 7724109Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 7824109Ssklower return (EINVAL); 7937473Ssklower *(struct sockaddr_ns *)&ifr->ifr_dstaddr = ia->ia_dstaddr; 8024109Ssklower return (0); 8124109Ssklower } 8221481Ssklower 8350240Ssklower if ((so->so_state & SS_PRIV) == 0) 8450240Ssklower return (EPERM); 8524109Ssklower 8624109Ssklower switch (cmd) { 8737473Ssklower case SIOCAIFADDR: 8837473Ssklower case SIOCDIFADDR: 8937473Ssklower if (ifra->ifra_addr.sns_family == AF_NS) 9037473Ssklower for (oia = ia; ia; ia = ia->ia_next) { 9137473Ssklower if (ia->ia_ifp == ifp && 9237473Ssklower ns_neteq(ia->ia_addr.sns_addr, 9337473Ssklower ifra->ifra_addr.sns_addr)) 9437473Ssklower break; 9537473Ssklower } 9637473Ssklower if (cmd == SIOCDIFADDR && ia == 0) 9737473Ssklower return (EADDRNOTAVAIL); 9837473Ssklower /* FALLTHROUGH */ 9924109Ssklower 10025453Ssklower case SIOCSIFADDR: 10121481Ssklower case SIOCSIFDSTADDR: 10221481Ssklower if (ia == (struct ns_ifaddr *)0) { 10352029Ssklower oia = (struct ns_ifaddr *) 10452029Ssklower malloc(sizeof *ia, M_IFADDR, M_WAITOK); 10552029Ssklower if (oia == (struct ns_ifaddr *)NULL) 10621481Ssklower return (ENOBUFS); 10752630Ssklower bzero((caddr_t)oia, sizeof(*oia)); 10821481Ssklower if (ia = ns_ifaddr) { 10921481Ssklower for ( ; ia->ia_next; ia = ia->ia_next) 11021481Ssklower ; 11152029Ssklower ia->ia_next = oia; 11221481Ssklower } else 11352029Ssklower ns_ifaddr = oia; 11452029Ssklower ia = oia; 11521481Ssklower if (ifa = ifp->if_addrlist) { 11621481Ssklower for ( ; ifa->ifa_next; ifa = ifa->ifa_next) 11721481Ssklower ; 11821481Ssklower ifa->ifa_next = (struct ifaddr *) ia; 11921481Ssklower } else 12021481Ssklower ifp->if_addrlist = (struct ifaddr *) ia; 12121481Ssklower ia->ia_ifp = ifp; 12237473Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 12337473Ssklower 12437473Ssklower ia->ia_ifa.ifa_netmask = 12537473Ssklower (struct sockaddr *)&ns_netmask; 12637473Ssklower 12737473Ssklower ia->ia_ifa.ifa_dstaddr = 12837473Ssklower (struct sockaddr *)&ia->ia_dstaddr; 12937473Ssklower if (ifp->if_flags & IFF_BROADCAST) { 13037473Ssklower ia->ia_broadaddr.sns_family = AF_NS; 13137473Ssklower ia->ia_broadaddr.sns_len = sizeof(ia->ia_addr); 13237473Ssklower ia->ia_broadaddr.sns_addr.x_host = ns_broadhost; 13337473Ssklower } 13437473Ssklower ns_interfaces++; 13521481Ssklower } 13625453Ssklower } 13725453Ssklower 13825453Ssklower switch (cmd) { 13937473Ssklower int error; 14025453Ssklower 14125453Ssklower case SIOCSIFDSTADDR: 14225453Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 14325453Ssklower return (EINVAL); 14425453Ssklower if (ia->ia_flags & IFA_ROUTE) { 14537473Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 14625453Ssklower ia->ia_flags &= ~IFA_ROUTE; 14725453Ssklower } 14825453Ssklower if (ifp->if_ioctl) { 14937473Ssklower error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia); 15025453Ssklower if (error) 15125453Ssklower return (error); 15225453Ssklower } 15337473Ssklower *(struct sockaddr *)&ia->ia_dstaddr = ifr->ifr_dstaddr; 15425453Ssklower return (0); 15525453Ssklower 15625453Ssklower case SIOCSIFADDR: 15737473Ssklower return (ns_ifinit(ifp, ia, 15837473Ssklower (struct sockaddr_ns *)&ifr->ifr_addr, 1)); 15921481Ssklower 16037473Ssklower case SIOCDIFADDR: 16137473Ssklower ns_ifscrub(ifp, ia); 16237473Ssklower if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia) 16337473Ssklower ifp->if_addrlist = ifa->ifa_next; 16437473Ssklower else { 16537473Ssklower while (ifa->ifa_next && 16637473Ssklower (ifa->ifa_next != (struct ifaddr *)ia)) 16737473Ssklower ifa = ifa->ifa_next; 16837473Ssklower if (ifa->ifa_next) 16937473Ssklower ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next; 17037473Ssklower else 17137473Ssklower printf("Couldn't unlink nsifaddr from ifp\n"); 17237473Ssklower } 17337473Ssklower oia = ia; 17437473Ssklower if (oia == (ia = ns_ifaddr)) { 17537473Ssklower ns_ifaddr = ia->ia_next; 17637473Ssklower } else { 17737473Ssklower while (ia->ia_next && (ia->ia_next != oia)) { 17837473Ssklower ia = ia->ia_next; 17937473Ssklower } 18037473Ssklower if (ia->ia_next) 18137473Ssklower ia->ia_next = oia->ia_next; 18237473Ssklower else 18337473Ssklower printf("Didn't unlink nsifadr from list\n"); 18437473Ssklower } 18552029Ssklower IFAFREE((&oia->ia_ifa)); 18637473Ssklower if (0 == --ns_interfaces) { 18737473Ssklower /* 18837473Ssklower * We reset to virginity and start all over again 18937473Ssklower */ 19037473Ssklower ns_thishost = ns_zerohost; 19137473Ssklower } 19237473Ssklower return (0); 19337473Ssklower 19437473Ssklower case SIOCAIFADDR: 19537473Ssklower dstIsNew = 0; hostIsNew = 1; 19637473Ssklower if (ia->ia_addr.sns_family == AF_NS) { 19737473Ssklower if (ifra->ifra_addr.sns_len == 0) { 19837473Ssklower ifra->ifra_addr = ia->ia_addr; 19937473Ssklower hostIsNew = 0; 20037473Ssklower } else if (ns_neteq(ifra->ifra_addr.sns_addr, 20137473Ssklower ia->ia_addr.sns_addr)) 20237473Ssklower hostIsNew = 0; 20337473Ssklower } 20437473Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) && 20537473Ssklower (ifra->ifra_dstaddr.sns_family == AF_NS)) { 20637473Ssklower if (hostIsNew == 0) 20737473Ssklower ns_ifscrub(ifp, ia); 20837473Ssklower ia->ia_dstaddr = ifra->ifra_dstaddr; 20937473Ssklower dstIsNew = 1; 21037473Ssklower } 21137473Ssklower if (ifra->ifra_addr.sns_family == AF_NS && 21237473Ssklower (hostIsNew || dstIsNew)) 21337473Ssklower error = ns_ifinit(ifp, ia, &ifra->ifra_addr, 0); 21437473Ssklower return (error); 21537473Ssklower 21621481Ssklower default: 21721481Ssklower if (ifp->if_ioctl == 0) 21821481Ssklower return (EOPNOTSUPP); 21921481Ssklower return ((*ifp->if_ioctl)(ifp, cmd, data)); 22021481Ssklower } 22121481Ssklower } 22221481Ssklower 22321481Ssklower /* 22437473Ssklower * Delete any previous route for an old address. 22537473Ssklower */ 22637473Ssklower ns_ifscrub(ifp, ia) 22737473Ssklower register struct ifnet *ifp; 22837473Ssklower register struct ns_ifaddr *ia; 22937473Ssklower { 23037473Ssklower if (ia->ia_flags & IFA_ROUTE) { 23137473Ssklower if (ifp->if_flags & IFF_POINTOPOINT) { 23237473Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 23337473Ssklower } else 23437473Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0); 23537473Ssklower ia->ia_flags &= ~IFA_ROUTE; 23637473Ssklower } 23737473Ssklower } 23837473Ssklower /* 23921481Ssklower * Initialize an interface's internet address 24021481Ssklower * and routing table entry. 24121481Ssklower */ 24237473Ssklower ns_ifinit(ifp, ia, sns, scrub) 24321481Ssklower register struct ifnet *ifp; 24421481Ssklower register struct ns_ifaddr *ia; 24537473Ssklower register struct sockaddr_ns *sns; 24621481Ssklower { 24737473Ssklower struct sockaddr_ns oldaddr; 24837473Ssklower register union ns_host *h = &ia->ia_addr.sns_addr.x_host; 24921481Ssklower int s = splimp(), error; 25021481Ssklower 25121481Ssklower /* 25237473Ssklower * Set up new addresses. 25337473Ssklower */ 25437473Ssklower oldaddr = ia->ia_addr; 25537473Ssklower ia->ia_addr = *sns; 25637473Ssklower /* 25721481Ssklower * The convention we shall adopt for naming is that 25821481Ssklower * a supplied address of zero means that "we don't care". 25921481Ssklower * if there is a single interface, use the address of that 26021481Ssklower * interface as our 6 byte host address. 26121481Ssklower * if there are multiple interfaces, use any address already 26221481Ssklower * used. 26321481Ssklower * 26421481Ssklower * Give the interface a chance to initialize 26521481Ssklower * if this is its first address, 26621481Ssklower * and to validate the address if necessary. 26721481Ssklower */ 26821481Ssklower if (ns_hosteqnh(ns_thishost, ns_zerohost)) { 26921481Ssklower if (ifp->if_ioctl && 27021481Ssklower (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { 27137473Ssklower ia->ia_addr = oldaddr; 27221481Ssklower splx(s); 27321481Ssklower return (error); 27421481Ssklower } 27521481Ssklower ns_thishost = *h; 27621481Ssklower } else if (ns_hosteqnh(sns->sns_addr.x_host, ns_zerohost) 27721481Ssklower || ns_hosteqnh(sns->sns_addr.x_host, ns_thishost)) { 27821481Ssklower *h = ns_thishost; 27921481Ssklower if (ifp->if_ioctl && 28021481Ssklower (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { 28137473Ssklower ia->ia_addr = oldaddr; 28221481Ssklower splx(s); 28321481Ssklower return (error); 28421481Ssklower } 28525453Ssklower if (!ns_hosteqnh(ns_thishost,*h)) { 28637473Ssklower ia->ia_addr = oldaddr; 28721481Ssklower splx(s); 28821481Ssklower return (EINVAL); 28921481Ssklower } 29021481Ssklower } else { 29137473Ssklower ia->ia_addr = oldaddr; 29221481Ssklower splx(s); 29325453Ssklower return (EINVAL); 29421481Ssklower } 29552618Ssklower ia->ia_ifa.ifa_metric = ifp->if_metric; 29621481Ssklower /* 29721481Ssklower * Add route for the network. 29821481Ssklower */ 29937473Ssklower if (scrub) { 30037473Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr; 30137473Ssklower ns_ifscrub(ifp, ia); 30237473Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 30337473Ssklower } 30425453Ssklower if (ifp->if_flags & IFF_POINTOPOINT) 30537473Ssklower rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 30637473Ssklower else { 30753397Ssklower ia->ia_broadaddr.sns_addr.x_net = ia->ia_addr.sns_addr.x_net; 30837473Ssklower rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP); 30937473Ssklower } 31021481Ssklower ia->ia_flags |= IFA_ROUTE; 31125453Ssklower return (0); 31221481Ssklower } 31321481Ssklower 31421481Ssklower /* 31521481Ssklower * Return address info for specified internet network. 31621481Ssklower */ 31721481Ssklower struct ns_ifaddr * 31825045Ssklower ns_iaonnetof(dst) 31925045Ssklower register struct ns_addr *dst; 32021481Ssklower { 32121481Ssklower register struct ns_ifaddr *ia; 32225045Ssklower register struct ns_addr *compare; 32325453Ssklower register struct ifnet *ifp; 32425453Ssklower struct ns_ifaddr *ia_maybe = 0; 32526055Ssklower union ns_net net = dst->x_net; 32621481Ssklower 32725045Ssklower for (ia = ns_ifaddr; ia; ia = ia->ia_next) { 32825453Ssklower if (ifp = ia->ia_ifp) { 32925453Ssklower if (ifp->if_flags & IFF_POINTOPOINT) { 33025453Ssklower compare = &satons_addr(ia->ia_dstaddr); 33125453Ssklower if (ns_hosteq(*dst, *compare)) 33225045Ssklower return (ia); 33353397Ssklower if (ns_neteqnn(net, ia->ia_addr.sns_addr.x_net)) 33425453Ssklower ia_maybe = ia; 33525453Ssklower } else { 33653397Ssklower if (ns_neteqnn(net, ia->ia_addr.sns_addr.x_net)) 33725453Ssklower return (ia); 33825045Ssklower } 33925045Ssklower } 34025045Ssklower } 34125045Ssklower return (ia_maybe); 34221481Ssklower } 34321481Ssklower #endif 344