123204Smckusick /* 233371Ssklower * Copyright (c) 1984, 1985, 1986, 1987 Regents of the University of California. 333371Ssklower * All rights reserved. 423204Smckusick * 544500Sbostic * %sccs.include.redist.c% 633371Ssklower * 7*53397Ssklower * @(#)ns.c 7.12 (Berkeley) 05/08/92 823204Smckusick */ 921481Ssklower 1021481Ssklower #include "param.h" 1121481Ssklower #include "mbuf.h" 1221481Ssklower #include "ioctl.h" 1321481Ssklower #include "protosw.h" 1450240Ssklower #include "errno.h" 1521481Ssklower #include "socket.h" 1621481Ssklower #include "socketvar.h" 1721481Ssklower 1821481Ssklower 1921481Ssklower #include "../net/if.h" 2021481Ssklower #include "../net/route.h" 2121481Ssklower #include "../net/af.h" 2221481Ssklower 2321481Ssklower #include "ns.h" 2421481Ssklower #include "ns_if.h" 2521481Ssklower 2621481Ssklower #ifdef NS 2721481Ssklower 2821481Ssklower struct ns_ifaddr *ns_ifaddr; 2937473Ssklower int ns_interfaces; 3037473Ssklower extern struct sockaddr_ns ns_netmask, ns_hostmask; 3121481Ssklower 3221481Ssklower /* 3321481Ssklower * Generic internet control operations (ioctl's). 3421481Ssklower */ 3524226Ssklower /* ARGSUSED */ 3621481Ssklower ns_control(so, cmd, data, ifp) 3721481Ssklower struct socket *so; 3821481Ssklower int cmd; 3921481Ssklower caddr_t data; 4021481Ssklower register struct ifnet *ifp; 4121481Ssklower { 4221481Ssklower register struct ifreq *ifr = (struct ifreq *)data; 4337473Ssklower register struct ns_aliasreq *ifra = (struct ns_aliasreq *)data; 4421481Ssklower register struct ns_ifaddr *ia; 4521481Ssklower struct ifaddr *ifa; 4637473Ssklower struct ns_ifaddr *oia; 4737546Smckusick int error, dstIsNew, hostIsNew; 4821481Ssklower 4921481Ssklower /* 5021481Ssklower * Find address for this interface, if it exists. 5121481Ssklower */ 5225453Ssklower if (ifp == 0) 5324109Ssklower return (EADDRNOTAVAIL); 5421481Ssklower for (ia = ns_ifaddr; ia; ia = ia->ia_next) 5521481Ssklower if (ia->ia_ifp == ifp) 5621481Ssklower break; 5721481Ssklower 5821481Ssklower switch (cmd) { 5921481Ssklower 6021481Ssklower case SIOCGIFADDR: 6124109Ssklower if (ia == (struct ns_ifaddr *)0) 6224109Ssklower return (EADDRNOTAVAIL); 6337473Ssklower *(struct sockaddr_ns *)&ifr->ifr_addr = ia->ia_addr; 6424109Ssklower return (0); 6524109Ssklower 6624109Ssklower 6721481Ssklower case SIOCGIFBRDADDR: 6824109Ssklower if (ia == (struct ns_ifaddr *)0) 6924109Ssklower return (EADDRNOTAVAIL); 7024109Ssklower if ((ifp->if_flags & IFF_BROADCAST) == 0) 7124109Ssklower return (EINVAL); 7237473Ssklower *(struct sockaddr_ns *)&ifr->ifr_dstaddr = ia->ia_broadaddr; 7324109Ssklower return (0); 7424109Ssklower 7521481Ssklower case SIOCGIFDSTADDR: 7621481Ssklower if (ia == (struct ns_ifaddr *)0) 7721481Ssklower return (EADDRNOTAVAIL); 7824109Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 7924109Ssklower return (EINVAL); 8037473Ssklower *(struct sockaddr_ns *)&ifr->ifr_dstaddr = ia->ia_dstaddr; 8124109Ssklower return (0); 8224109Ssklower } 8321481Ssklower 8450240Ssklower if ((so->so_state & SS_PRIV) == 0) 8550240Ssklower return (EPERM); 8624109Ssklower 8724109Ssklower switch (cmd) { 8837473Ssklower case SIOCAIFADDR: 8937473Ssklower case SIOCDIFADDR: 9037473Ssklower if (ifra->ifra_addr.sns_family == AF_NS) 9137473Ssklower for (oia = ia; ia; ia = ia->ia_next) { 9237473Ssklower if (ia->ia_ifp == ifp && 9337473Ssklower ns_neteq(ia->ia_addr.sns_addr, 9437473Ssklower ifra->ifra_addr.sns_addr)) 9537473Ssklower break; 9637473Ssklower } 9737473Ssklower if (cmd == SIOCDIFADDR && ia == 0) 9837473Ssklower return (EADDRNOTAVAIL); 9937473Ssklower /* FALLTHROUGH */ 10024109Ssklower 10125453Ssklower case SIOCSIFADDR: 10221481Ssklower case SIOCSIFDSTADDR: 10321481Ssklower if (ia == (struct ns_ifaddr *)0) { 10452029Ssklower oia = (struct ns_ifaddr *) 10552029Ssklower malloc(sizeof *ia, M_IFADDR, M_WAITOK); 10652029Ssklower if (oia == (struct ns_ifaddr *)NULL) 10721481Ssklower return (ENOBUFS); 10852630Ssklower bzero((caddr_t)oia, sizeof(*oia)); 10921481Ssklower if (ia = ns_ifaddr) { 11021481Ssklower for ( ; ia->ia_next; ia = ia->ia_next) 11121481Ssklower ; 11252029Ssklower ia->ia_next = oia; 11321481Ssklower } else 11452029Ssklower ns_ifaddr = oia; 11552029Ssklower ia = oia; 11621481Ssklower if (ifa = ifp->if_addrlist) { 11721481Ssklower for ( ; ifa->ifa_next; ifa = ifa->ifa_next) 11821481Ssklower ; 11921481Ssklower ifa->ifa_next = (struct ifaddr *) ia; 12021481Ssklower } else 12121481Ssklower ifp->if_addrlist = (struct ifaddr *) ia; 12221481Ssklower ia->ia_ifp = ifp; 12337473Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 12437473Ssklower 12537473Ssklower ia->ia_ifa.ifa_netmask = 12637473Ssklower (struct sockaddr *)&ns_netmask; 12737473Ssklower 12837473Ssklower ia->ia_ifa.ifa_dstaddr = 12937473Ssklower (struct sockaddr *)&ia->ia_dstaddr; 13037473Ssklower if (ifp->if_flags & IFF_BROADCAST) { 13137473Ssklower ia->ia_broadaddr.sns_family = AF_NS; 13237473Ssklower ia->ia_broadaddr.sns_len = sizeof(ia->ia_addr); 13337473Ssklower ia->ia_broadaddr.sns_addr.x_host = ns_broadhost; 13437473Ssklower } 13537473Ssklower ns_interfaces++; 13621481Ssklower } 13725453Ssklower } 13825453Ssklower 13925453Ssklower switch (cmd) { 14037473Ssklower int error; 14125453Ssklower 14225453Ssklower case SIOCSIFDSTADDR: 14325453Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 14425453Ssklower return (EINVAL); 14525453Ssklower if (ia->ia_flags & IFA_ROUTE) { 14637473Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 14725453Ssklower ia->ia_flags &= ~IFA_ROUTE; 14825453Ssklower } 14925453Ssklower if (ifp->if_ioctl) { 15037473Ssklower error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia); 15125453Ssklower if (error) 15225453Ssklower return (error); 15325453Ssklower } 15437473Ssklower *(struct sockaddr *)&ia->ia_dstaddr = ifr->ifr_dstaddr; 15525453Ssklower return (0); 15625453Ssklower 15725453Ssklower case SIOCSIFADDR: 15837473Ssklower return (ns_ifinit(ifp, ia, 15937473Ssklower (struct sockaddr_ns *)&ifr->ifr_addr, 1)); 16021481Ssklower 16137473Ssklower case SIOCDIFADDR: 16237473Ssklower ns_ifscrub(ifp, ia); 16337473Ssklower if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia) 16437473Ssklower ifp->if_addrlist = ifa->ifa_next; 16537473Ssklower else { 16637473Ssklower while (ifa->ifa_next && 16737473Ssklower (ifa->ifa_next != (struct ifaddr *)ia)) 16837473Ssklower ifa = ifa->ifa_next; 16937473Ssklower if (ifa->ifa_next) 17037473Ssklower ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next; 17137473Ssklower else 17237473Ssklower printf("Couldn't unlink nsifaddr from ifp\n"); 17337473Ssklower } 17437473Ssklower oia = ia; 17537473Ssklower if (oia == (ia = ns_ifaddr)) { 17637473Ssklower ns_ifaddr = ia->ia_next; 17737473Ssklower } else { 17837473Ssklower while (ia->ia_next && (ia->ia_next != oia)) { 17937473Ssklower ia = ia->ia_next; 18037473Ssklower } 18137473Ssklower if (ia->ia_next) 18237473Ssklower ia->ia_next = oia->ia_next; 18337473Ssklower else 18437473Ssklower printf("Didn't unlink nsifadr from list\n"); 18537473Ssklower } 18652029Ssklower IFAFREE((&oia->ia_ifa)); 18737473Ssklower if (0 == --ns_interfaces) { 18837473Ssklower /* 18937473Ssklower * We reset to virginity and start all over again 19037473Ssklower */ 19137473Ssklower ns_thishost = ns_zerohost; 19237473Ssklower } 19337473Ssklower return (0); 19437473Ssklower 19537473Ssklower case SIOCAIFADDR: 19637473Ssklower dstIsNew = 0; hostIsNew = 1; 19737473Ssklower if (ia->ia_addr.sns_family == AF_NS) { 19837473Ssklower if (ifra->ifra_addr.sns_len == 0) { 19937473Ssklower ifra->ifra_addr = ia->ia_addr; 20037473Ssklower hostIsNew = 0; 20137473Ssklower } else if (ns_neteq(ifra->ifra_addr.sns_addr, 20237473Ssklower ia->ia_addr.sns_addr)) 20337473Ssklower hostIsNew = 0; 20437473Ssklower } 20537473Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) && 20637473Ssklower (ifra->ifra_dstaddr.sns_family == AF_NS)) { 20737473Ssklower if (hostIsNew == 0) 20837473Ssklower ns_ifscrub(ifp, ia); 20937473Ssklower ia->ia_dstaddr = ifra->ifra_dstaddr; 21037473Ssklower dstIsNew = 1; 21137473Ssklower } 21237473Ssklower if (ifra->ifra_addr.sns_family == AF_NS && 21337473Ssklower (hostIsNew || dstIsNew)) 21437473Ssklower error = ns_ifinit(ifp, ia, &ifra->ifra_addr, 0); 21537473Ssklower return (error); 21637473Ssklower 21721481Ssklower default: 21821481Ssklower if (ifp->if_ioctl == 0) 21921481Ssklower return (EOPNOTSUPP); 22021481Ssklower return ((*ifp->if_ioctl)(ifp, cmd, data)); 22121481Ssklower } 22221481Ssklower } 22321481Ssklower 22421481Ssklower /* 22537473Ssklower * Delete any previous route for an old address. 22637473Ssklower */ 22737473Ssklower ns_ifscrub(ifp, ia) 22837473Ssklower register struct ifnet *ifp; 22937473Ssklower register struct ns_ifaddr *ia; 23037473Ssklower { 23137473Ssklower if (ia->ia_flags & IFA_ROUTE) { 23237473Ssklower if (ifp->if_flags & IFF_POINTOPOINT) { 23337473Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 23437473Ssklower } else 23537473Ssklower rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0); 23637473Ssklower ia->ia_flags &= ~IFA_ROUTE; 23737473Ssklower } 23837473Ssklower } 23937473Ssklower /* 24021481Ssklower * Initialize an interface's internet address 24121481Ssklower * and routing table entry. 24221481Ssklower */ 24337473Ssklower ns_ifinit(ifp, ia, sns, scrub) 24421481Ssklower register struct ifnet *ifp; 24521481Ssklower register struct ns_ifaddr *ia; 24637473Ssklower register struct sockaddr_ns *sns; 24721481Ssklower { 24837473Ssklower struct sockaddr_ns oldaddr; 24937473Ssklower register union ns_host *h = &ia->ia_addr.sns_addr.x_host; 25021481Ssklower int s = splimp(), error; 25121481Ssklower 25221481Ssklower /* 25337473Ssklower * Set up new addresses. 25437473Ssklower */ 25537473Ssklower oldaddr = ia->ia_addr; 25637473Ssklower ia->ia_addr = *sns; 25737473Ssklower /* 25821481Ssklower * The convention we shall adopt for naming is that 25921481Ssklower * a supplied address of zero means that "we don't care". 26021481Ssklower * if there is a single interface, use the address of that 26121481Ssklower * interface as our 6 byte host address. 26221481Ssklower * if there are multiple interfaces, use any address already 26321481Ssklower * used. 26421481Ssklower * 26521481Ssklower * Give the interface a chance to initialize 26621481Ssklower * if this is its first address, 26721481Ssklower * and to validate the address if necessary. 26821481Ssklower */ 26921481Ssklower if (ns_hosteqnh(ns_thishost, ns_zerohost)) { 27021481Ssklower if (ifp->if_ioctl && 27121481Ssklower (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { 27237473Ssklower ia->ia_addr = oldaddr; 27321481Ssklower splx(s); 27421481Ssklower return (error); 27521481Ssklower } 27621481Ssklower ns_thishost = *h; 27721481Ssklower } else if (ns_hosteqnh(sns->sns_addr.x_host, ns_zerohost) 27821481Ssklower || ns_hosteqnh(sns->sns_addr.x_host, ns_thishost)) { 27921481Ssklower *h = ns_thishost; 28021481Ssklower if (ifp->if_ioctl && 28121481Ssklower (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { 28237473Ssklower ia->ia_addr = oldaddr; 28321481Ssklower splx(s); 28421481Ssklower return (error); 28521481Ssklower } 28625453Ssklower if (!ns_hosteqnh(ns_thishost,*h)) { 28737473Ssklower ia->ia_addr = oldaddr; 28821481Ssklower splx(s); 28921481Ssklower return (EINVAL); 29021481Ssklower } 29121481Ssklower } else { 29237473Ssklower ia->ia_addr = oldaddr; 29321481Ssklower splx(s); 29425453Ssklower return (EINVAL); 29521481Ssklower } 29652618Ssklower ia->ia_ifa.ifa_metric = ifp->if_metric; 29721481Ssklower /* 29821481Ssklower * Add route for the network. 29921481Ssklower */ 30037473Ssklower if (scrub) { 30137473Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr; 30237473Ssklower ns_ifscrub(ifp, ia); 30337473Ssklower ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 30437473Ssklower } 30525453Ssklower if (ifp->if_flags & IFF_POINTOPOINT) 30637473Ssklower rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 30737473Ssklower else { 308*53397Ssklower ia->ia_broadaddr.sns_addr.x_net = ia->ia_addr.sns_addr.x_net; 30937473Ssklower rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP); 31037473Ssklower } 31121481Ssklower ia->ia_flags |= IFA_ROUTE; 31225453Ssklower return (0); 31321481Ssklower } 31421481Ssklower 31521481Ssklower /* 31621481Ssklower * Return address info for specified internet network. 31721481Ssklower */ 31821481Ssklower struct ns_ifaddr * 31925045Ssklower ns_iaonnetof(dst) 32025045Ssklower register struct ns_addr *dst; 32121481Ssklower { 32221481Ssklower register struct ns_ifaddr *ia; 32325045Ssklower register struct ns_addr *compare; 32425453Ssklower register struct ifnet *ifp; 32525453Ssklower struct ns_ifaddr *ia_maybe = 0; 32626055Ssklower union ns_net net = dst->x_net; 32721481Ssklower 32825045Ssklower for (ia = ns_ifaddr; ia; ia = ia->ia_next) { 32925453Ssklower if (ifp = ia->ia_ifp) { 33025453Ssklower if (ifp->if_flags & IFF_POINTOPOINT) { 33125453Ssklower compare = &satons_addr(ia->ia_dstaddr); 33225453Ssklower if (ns_hosteq(*dst, *compare)) 33325045Ssklower return (ia); 334*53397Ssklower if (ns_neteqnn(net, ia->ia_addr.sns_addr.x_net)) 33525453Ssklower ia_maybe = ia; 33625453Ssklower } else { 337*53397Ssklower if (ns_neteqnn(net, ia->ia_addr.sns_addr.x_net)) 33825453Ssklower return (ia); 33925045Ssklower } 34025045Ssklower } 34125045Ssklower } 34225045Ssklower return (ia_maybe); 34321481Ssklower } 34421481Ssklower #endif 345