123204Smckusick /* 225453Ssklower * 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*26055Ssklower * @(#)ns.c 6.7 (Berkeley) 02/03/86 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; 37*26055Ssklower union { 38*26055Ssklower union ns_net net_e; 39*26055Ssklower long long_e; 40*26055Ssklower } net; 4121481Ssklower 42*26055Ssklower net.net_e = sns->sns_addr.x_net; 43*26055Ssklower hp->afh_nethash = net.long_e; 4421481Ssklower hash = *s++; hash <<= 8; hash += *s++; hash <<= 8; hash += *s; 4521481Ssklower hp->afh_hosthash = hash; 4621481Ssklower } 4721481Ssklower 4821481Ssklower 4921481Ssklower ns_netmatch(sns1, sns2) 5021481Ssklower struct sockaddr_ns *sns1, *sns2; 5121481Ssklower { 5221481Ssklower 53*26055Ssklower return (ns_neteq(sns1->sns_addr, sns2->sns_addr)); 5421481Ssklower } 5521481Ssklower 5621481Ssklower /* 5721481Ssklower * Generic internet control operations (ioctl's). 5821481Ssklower */ 5924226Ssklower /* ARGSUSED */ 6021481Ssklower ns_control(so, cmd, data, ifp) 6121481Ssklower struct socket *so; 6221481Ssklower int cmd; 6321481Ssklower caddr_t data; 6421481Ssklower register struct ifnet *ifp; 6521481Ssklower { 6621481Ssklower register struct ifreq *ifr = (struct ifreq *)data; 6721481Ssklower register struct ns_ifaddr *ia; 6821481Ssklower struct ifaddr *ifa; 6921481Ssklower struct mbuf *m; 7021481Ssklower 7121481Ssklower /* 7221481Ssklower * Find address for this interface, if it exists. 7321481Ssklower */ 7425453Ssklower if (ifp == 0) 7524109Ssklower return (EADDRNOTAVAIL); 7621481Ssklower for (ia = ns_ifaddr; ia; ia = ia->ia_next) 7721481Ssklower if (ia->ia_ifp == ifp) 7821481Ssklower break; 7921481Ssklower 8021481Ssklower switch (cmd) { 8121481Ssklower 8221481Ssklower case SIOCGIFADDR: 8324109Ssklower if (ia == (struct ns_ifaddr *)0) 8424109Ssklower return (EADDRNOTAVAIL); 8524109Ssklower ifr->ifr_addr = ia->ia_addr; 8624109Ssklower return (0); 8724109Ssklower 8824109Ssklower 8921481Ssklower case SIOCGIFBRDADDR: 9024109Ssklower if (ia == (struct ns_ifaddr *)0) 9124109Ssklower return (EADDRNOTAVAIL); 9224109Ssklower if ((ifp->if_flags & IFF_BROADCAST) == 0) 9324109Ssklower return (EINVAL); 9424109Ssklower ifr->ifr_dstaddr = ia->ia_broadaddr; 9524109Ssklower return (0); 9624109Ssklower 9721481Ssklower case SIOCGIFDSTADDR: 9821481Ssklower if (ia == (struct ns_ifaddr *)0) 9921481Ssklower return (EADDRNOTAVAIL); 10024109Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 10124109Ssklower return (EINVAL); 10224109Ssklower ifr->ifr_dstaddr = ia->ia_dstaddr; 10324109Ssklower return (0); 10424109Ssklower } 10521481Ssklower 10624109Ssklower if (!suser()) 10724109Ssklower return (u.u_error); 10824109Ssklower 10924109Ssklower switch (cmd) { 11024109Ssklower 11125453Ssklower case SIOCSIFADDR: 11221481Ssklower case SIOCSIFDSTADDR: 11321481Ssklower if (ia == (struct ns_ifaddr *)0) { 11421481Ssklower m = m_getclr(M_WAIT, MT_IFADDR); 11521481Ssklower if (m == (struct mbuf *)NULL) 11621481Ssklower return (ENOBUFS); 11721481Ssklower if (ia = ns_ifaddr) { 11821481Ssklower for ( ; ia->ia_next; ia = ia->ia_next) 11921481Ssklower ; 12021481Ssklower ia->ia_next = mtod(m, struct ns_ifaddr *); 12121481Ssklower } else 12221481Ssklower ns_ifaddr = mtod(m, struct ns_ifaddr *); 12321481Ssklower ia = mtod(m, struct ns_ifaddr *); 12421481Ssklower if (ifa = ifp->if_addrlist) { 12521481Ssklower for ( ; ifa->ifa_next; ifa = ifa->ifa_next) 12621481Ssklower ; 12721481Ssklower ifa->ifa_next = (struct ifaddr *) ia; 12821481Ssklower } else 12921481Ssklower ifp->if_addrlist = (struct ifaddr *) ia; 13021481Ssklower ia->ia_ifp = ifp; 13121481Ssklower IA_SNS(ia)->sns_family = AF_NS; 13221481Ssklower } 13325453Ssklower } 13425453Ssklower 13525453Ssklower switch (cmd) { 13625453Ssklower 13725453Ssklower case SIOCSIFDSTADDR: 13825453Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 13925453Ssklower return (EINVAL); 14025453Ssklower if (ia->ia_flags & IFA_ROUTE) { 14125453Ssklower rtinit(&ia->ia_dstaddr, &ia->ia_addr, 14225453Ssklower (int)SIOCDELRT, RTF_HOST); 14325453Ssklower ia->ia_flags &= ~IFA_ROUTE; 14425453Ssklower } 14525453Ssklower if (ifp->if_ioctl) { 14625453Ssklower int error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia); 14725453Ssklower if (error) 14825453Ssklower return (error); 14925453Ssklower } 15025453Ssklower ia->ia_dstaddr = ifr->ifr_dstaddr; 15125453Ssklower return (0); 15225453Ssklower 15325453Ssklower case SIOCSIFADDR: 15421481Ssklower return 15521481Ssklower (ns_ifinit(ifp, ia, (struct sockaddr_ns *)&ifr->ifr_addr)); 15621481Ssklower 15721481Ssklower default: 15821481Ssklower if (ifp->if_ioctl == 0) 15921481Ssklower return (EOPNOTSUPP); 16021481Ssklower return ((*ifp->if_ioctl)(ifp, cmd, data)); 16121481Ssklower } 16221481Ssklower } 16321481Ssklower 16421481Ssklower /* 16521481Ssklower * Initialize an interface's internet address 16621481Ssklower * and routing table entry. 16721481Ssklower */ 16821481Ssklower ns_ifinit(ifp, ia, sns) 16921481Ssklower register struct ifnet *ifp; 17021481Ssklower register struct ns_ifaddr *ia; 17121481Ssklower struct sockaddr_ns *sns; 17221481Ssklower { 17321481Ssklower struct sockaddr_ns netaddr; 17421481Ssklower register union ns_host *h = &(IA_SNS(ia)->sns_addr.x_host); 17521481Ssklower int s = splimp(), error; 17621481Ssklower 17721481Ssklower /* 17821481Ssklower * The convention we shall adopt for naming is that 17921481Ssklower * a supplied address of zero means that "we don't care". 18021481Ssklower * if there is a single interface, use the address of that 18121481Ssklower * interface as our 6 byte host address. 18221481Ssklower * if there are multiple interfaces, use any address already 18321481Ssklower * used. 18421481Ssklower * 18521481Ssklower * If we have gotten into trouble and want to reset back to 18621481Ssklower * virginity, we recognize a request of the broadcast address. 18721481Ssklower */ 18821481Ssklower if (ns_hosteqnh(sns->sns_addr.x_host, ns_broadhost)) { 18921481Ssklower ns_thishost = ns_zerohost; 19021481Ssklower splx(s); 19125453Ssklower return (0); 19221481Ssklower } 19321481Ssklower 19421481Ssklower /* 19521481Ssklower * Delete any previous route for an old address. 19621481Ssklower */ 19721481Ssklower bzero((caddr_t)&netaddr, sizeof (netaddr)); 19821481Ssklower netaddr.sns_family = AF_NS; 19921481Ssklower netaddr.sns_addr.x_host = ns_broadhost; 20021481Ssklower netaddr.sns_addr.x_net = ia->ia_net; 20121481Ssklower if (ia->ia_flags & IFA_ROUTE) { 20221481Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) == 0) { 20325453Ssklower rtinit((struct sockaddr *)&netaddr, &ia->ia_addr, 20425453Ssklower (int)SIOCDELRT, 0); 20521481Ssklower } else 20625453Ssklower rtinit(&ia->ia_dstaddr, &ia->ia_addr, 20725453Ssklower (int)SIOCDELRT, RTF_HOST); 20821481Ssklower } 20921481Ssklower 21021481Ssklower /* 21121481Ssklower * Set up new addresses. 21221481Ssklower */ 21321481Ssklower ia->ia_addr = *(struct sockaddr *)sns; 21421481Ssklower ia->ia_net = sns->sns_addr.x_net; 21521481Ssklower netaddr.sns_addr.x_net = ia->ia_net; 21621481Ssklower if (ifp->if_flags & IFF_BROADCAST) { 21721481Ssklower ia->ia_broadaddr = * (struct sockaddr *) &netaddr; 21821481Ssklower } 21925453Ssklower 22021481Ssklower /* 22121481Ssklower * Give the interface a chance to initialize 22221481Ssklower * if this is its first address, 22321481Ssklower * and to validate the address if necessary. 22421481Ssklower */ 22521481Ssklower if (ns_hosteqnh(ns_thishost, ns_zerohost)) { 22621481Ssklower if (ifp->if_ioctl && 22721481Ssklower (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { 22821481Ssklower splx(s); 22921481Ssklower return (error); 23021481Ssklower } 23121481Ssklower ns_thishost = *h; 23221481Ssklower } else if (ns_hosteqnh(sns->sns_addr.x_host, ns_zerohost) 23321481Ssklower || ns_hosteqnh(sns->sns_addr.x_host, ns_thishost)) { 23421481Ssklower *h = ns_thishost; 23521481Ssklower if (ifp->if_ioctl && 23621481Ssklower (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { 23721481Ssklower splx(s); 23821481Ssklower return (error); 23921481Ssklower } 24025453Ssklower if (!ns_hosteqnh(ns_thishost,*h)) { 24121481Ssklower splx(s); 24221481Ssklower return (EINVAL); 24321481Ssklower } 24421481Ssklower } else { 24521481Ssklower splx(s); 24625453Ssklower return (EINVAL); 24721481Ssklower } 24825453Ssklower 24921481Ssklower /* 25021481Ssklower * Add route for the network. 25121481Ssklower */ 25225453Ssklower if (ifp->if_flags & IFF_POINTOPOINT) 25325453Ssklower rtinit(&ia->ia_dstaddr, &ia->ia_addr, (int)SIOCADDRT, 25421481Ssklower RTF_HOST|RTF_UP); 25525453Ssklower else 25625453Ssklower rtinit(&ia->ia_broadaddr, &ia->ia_addr, (int)SIOCADDRT, 25725453Ssklower RTF_UP); 25821481Ssklower ia->ia_flags |= IFA_ROUTE; 25925453Ssklower return (0); 26021481Ssklower } 26121481Ssklower 26221481Ssklower /* 26321481Ssklower * Return address info for specified internet network. 26421481Ssklower */ 26521481Ssklower struct ns_ifaddr * 26625045Ssklower ns_iaonnetof(dst) 26725045Ssklower register struct ns_addr *dst; 26821481Ssklower { 26921481Ssklower register struct ns_ifaddr *ia; 27025045Ssklower register struct ns_addr *compare; 27125453Ssklower register struct ifnet *ifp; 27225453Ssklower struct ns_ifaddr *ia_maybe = 0; 273*26055Ssklower union ns_net net = dst->x_net; 27421481Ssklower 27525045Ssklower for (ia = ns_ifaddr; ia; ia = ia->ia_next) { 27625453Ssklower if (ifp = ia->ia_ifp) { 27725453Ssklower if (ifp->if_flags & IFF_POINTOPOINT) { 27825453Ssklower compare = &satons_addr(ia->ia_dstaddr); 27925453Ssklower if (ns_hosteq(*dst, *compare)) 28025045Ssklower return (ia); 281*26055Ssklower if (ns_neteqnn(net, ia->ia_net)) 28225453Ssklower ia_maybe = ia; 28325453Ssklower } else { 284*26055Ssklower if (ns_neteqnn(net, ia->ia_net)) 28525453Ssklower return (ia); 28625045Ssklower } 28725045Ssklower } 28825045Ssklower } 28925045Ssklower return (ia_maybe); 29021481Ssklower } 29121481Ssklower #endif 292