123204Smckusick /* 223204Smckusick * Copyright (c) 1982 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*24109Ssklower * @(#)ns.c 6.3 (Berkeley) 07/31/85 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; 3721481Ssklower 3821481Ssklower hp->afh_nethash = ns_netof(sns->sns_addr); 3921481Ssklower hash = *s++; hash <<= 8; hash += *s++; hash <<= 8; hash += *s; 4021481Ssklower hp->afh_hosthash = hash; 4121481Ssklower } 4221481Ssklower 4321481Ssklower 4421481Ssklower ns_netmatch(sns1, sns2) 4521481Ssklower struct sockaddr_ns *sns1, *sns2; 4621481Ssklower { 4721481Ssklower 4821481Ssklower return (ns_netof(sns1->sns_addr) == ns_netof(sns2->sns_addr)); 4921481Ssklower } 5021481Ssklower 5121481Ssklower /* 5221481Ssklower * Generic internet control operations (ioctl's). 5321481Ssklower */ 5421481Ssklower ns_control(so, cmd, data, ifp) 5521481Ssklower struct socket *so; 5621481Ssklower int cmd; 5721481Ssklower caddr_t data; 5821481Ssklower register struct ifnet *ifp; 5921481Ssklower { 6021481Ssklower register struct ifreq *ifr = (struct ifreq *)data; 6121481Ssklower register struct ns_ifaddr *ia; 6221481Ssklower struct ifaddr *ifa; 6321481Ssklower struct mbuf *m; 6421481Ssklower int error; 6521481Ssklower 6621481Ssklower /* 6721481Ssklower * Find address for this interface, if it exists. 6821481Ssklower */ 69*24109Ssklower if (ifp==0) 70*24109Ssklower return (EADDRNOTAVAIL); 7121481Ssklower for (ia = ns_ifaddr; ia; ia = ia->ia_next) 7221481Ssklower if (ia->ia_ifp == ifp) 7321481Ssklower break; 7421481Ssklower 7521481Ssklower switch (cmd) { 7621481Ssklower 7721481Ssklower case SIOCGIFADDR: 78*24109Ssklower if (ia == (struct ns_ifaddr *)0) 79*24109Ssklower return (EADDRNOTAVAIL); 80*24109Ssklower ifr->ifr_addr = ia->ia_addr; 81*24109Ssklower return (0); 82*24109Ssklower 83*24109Ssklower 8421481Ssklower case SIOCGIFBRDADDR: 85*24109Ssklower if (ia == (struct ns_ifaddr *)0) 86*24109Ssklower return (EADDRNOTAVAIL); 87*24109Ssklower if ((ifp->if_flags & IFF_BROADCAST) == 0) 88*24109Ssklower return (EINVAL); 89*24109Ssklower ifr->ifr_dstaddr = ia->ia_broadaddr; 90*24109Ssklower return (0); 91*24109Ssklower 9221481Ssklower case SIOCGIFDSTADDR: 9321481Ssklower if (ia == (struct ns_ifaddr *)0) 9421481Ssklower return (EADDRNOTAVAIL); 95*24109Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 96*24109Ssklower return (EINVAL); 97*24109Ssklower ifr->ifr_dstaddr = ia->ia_dstaddr; 98*24109Ssklower return (0); 99*24109Ssklower } 10021481Ssklower 101*24109Ssklower if (!suser()) 102*24109Ssklower return (u.u_error); 103*24109Ssklower 104*24109Ssklower switch (cmd) { 105*24109Ssklower 10621481Ssklower case SIOCSIFDSTADDR: 10721481Ssklower return (EOPNOTSUPP); 10821481Ssklower 10921481Ssklower case SIOCSIFADDR: 11021481Ssklower if (ia == (struct ns_ifaddr *)0) { 11121481Ssklower m = m_getclr(M_WAIT, MT_IFADDR); 11221481Ssklower if (m == (struct mbuf *)NULL) 11321481Ssklower return (ENOBUFS); 11421481Ssklower if (ia = ns_ifaddr) { 11521481Ssklower for ( ; ia->ia_next; ia = ia->ia_next) 11621481Ssklower ; 11721481Ssklower ia->ia_next = mtod(m, struct ns_ifaddr *); 11821481Ssklower } else 11921481Ssklower ns_ifaddr = mtod(m, struct ns_ifaddr *); 12021481Ssklower ia = mtod(m, struct ns_ifaddr *); 12121481Ssklower if (ifa = ifp->if_addrlist) { 12221481Ssklower for ( ; ifa->ifa_next; ifa = ifa->ifa_next) 12321481Ssklower ; 12421481Ssklower ifa->ifa_next = (struct ifaddr *) ia; 12521481Ssklower } else 12621481Ssklower ifp->if_addrlist = (struct ifaddr *) ia; 12721481Ssklower ia->ia_ifp = ifp; 12821481Ssklower IA_SNS(ia)->sns_family = AF_NS; 12921481Ssklower } 13021481Ssklower return 13121481Ssklower (ns_ifinit(ifp, ia, (struct sockaddr_ns *)&ifr->ifr_addr)); 13221481Ssklower 13321481Ssklower default: 13421481Ssklower if (ifp->if_ioctl == 0) 13521481Ssklower return (EOPNOTSUPP); 13621481Ssklower return ((*ifp->if_ioctl)(ifp, cmd, data)); 13721481Ssklower } 13821481Ssklower } 13921481Ssklower 14021481Ssklower /* 14121481Ssklower * Initialize an interface's internet address 14221481Ssklower * and routing table entry. 14321481Ssklower */ 14421481Ssklower ns_ifinit(ifp, ia, sns) 14521481Ssklower register struct ifnet *ifp; 14621481Ssklower register struct ns_ifaddr *ia; 14721481Ssklower struct sockaddr_ns *sns; 14821481Ssklower { 14921481Ssklower struct sockaddr_ns netaddr; 15021481Ssklower register union ns_host *h = &(IA_SNS(ia)->sns_addr.x_host); 15121481Ssklower int s = splimp(), error; 15221481Ssklower 15321481Ssklower /* 15421481Ssklower * The convention we shall adopt for naming is that 15521481Ssklower * a supplied address of zero means that "we don't care". 15621481Ssklower * if there is a single interface, use the address of that 15721481Ssklower * interface as our 6 byte host address. 15821481Ssklower * if there are multiple interfaces, use any address already 15921481Ssklower * used. 16021481Ssklower * 16121481Ssklower * If we have gotten into trouble and want to reset back to 16221481Ssklower * virginity, we recognize a request of the broadcast address. 16321481Ssklower */ 16421481Ssklower if (ns_hosteqnh(sns->sns_addr.x_host, ns_broadhost)) { 16521481Ssklower ns_thishost = ns_zerohost; 16621481Ssklower splx(s); 16721481Ssklower return(EINVAL); 16821481Ssklower } 16921481Ssklower 17021481Ssklower /* 17121481Ssklower * Delete any previous route for an old address. 17221481Ssklower */ 17321481Ssklower 17421481Ssklower bzero((caddr_t)&netaddr, sizeof (netaddr)); 17521481Ssklower netaddr.sns_family = AF_NS; 17621481Ssklower netaddr.sns_addr.x_host = ns_broadhost; 17721481Ssklower netaddr.sns_addr.x_net = ia->ia_net; 17821481Ssklower if (ia->ia_flags & IFA_ROUTE) { 17921481Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) == 0) { 18021481Ssklower rtinit((struct sockaddr *)&netaddr, &ia->ia_addr, -1); 18121481Ssklower } else 18221481Ssklower rtinit((struct sockaddr *)&ia->ia_dstaddr, &ia->ia_addr, -1); 18321481Ssklower } 18421481Ssklower 18521481Ssklower /* 18621481Ssklower * Set up new addresses. 18721481Ssklower */ 18821481Ssklower ia->ia_addr = *(struct sockaddr *)sns; 18921481Ssklower ia->ia_net = sns->sns_addr.x_net; 19021481Ssklower netaddr.sns_addr.x_net = ia->ia_net; 19121481Ssklower if (ifp->if_flags & IFF_BROADCAST) { 19221481Ssklower ia->ia_broadaddr = * (struct sockaddr *) &netaddr; 19321481Ssklower } 19421481Ssklower /* 19521481Ssklower * Point to point links are a little touchier -- 19621481Ssklower * We have to have an address of our own first, 19721481Ssklower * and will use the supplied address as that of the other end. 19821481Ssklower */ 19921481Ssklower if (ifp->if_flags & IFF_POINTOPOINT) { 20021481Ssklower struct sockaddr_ns *sns2 = IA_SNS(ia); 20121481Ssklower if (ns_hosteqnh(ns_zerohost,ns_thishost)) 20221481Ssklower return(EINVAL); 20321481Ssklower ia->ia_dstaddr = ia->ia_addr; 20421481Ssklower sns2->sns_addr.x_host = ns_thishost; 20521481Ssklower sns->sns_addr.x_host = ns_thishost; 20621481Ssklower } 20721481Ssklower /* 20821481Ssklower * Give the interface a chance to initialize 20921481Ssklower * if this is its first address, 21021481Ssklower * and to validate the address if necessary. 21121481Ssklower */ 21221481Ssklower 21321481Ssklower if (ns_hosteqnh(ns_thishost, ns_zerohost)) { 21421481Ssklower if (ifp->if_ioctl && 21521481Ssklower (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { 21621481Ssklower splx(s); 21721481Ssklower return (error); 21821481Ssklower } 21921481Ssklower ns_thishost = *h; 22021481Ssklower } else if (ns_hosteqnh(sns->sns_addr.x_host, ns_zerohost) 22121481Ssklower || ns_hosteqnh(sns->sns_addr.x_host, ns_thishost)) { 22221481Ssklower *h = ns_thishost; 22321481Ssklower if (ifp->if_ioctl && 22421481Ssklower (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { 22521481Ssklower splx(s); 22621481Ssklower return (error); 22721481Ssklower } 22821481Ssklower if(!ns_hosteqnh(ns_thishost,*h)) { 22921481Ssklower splx(s); 23021481Ssklower return (EINVAL); 23121481Ssklower } 23221481Ssklower } else { 23321481Ssklower splx(s); 23421481Ssklower return(EINVAL); 23521481Ssklower } 23621481Ssklower /* 23721481Ssklower * Add route for the network. 23821481Ssklower */ 23921481Ssklower if ((ifp->if_flags & IFF_POINTOPOINT) == 0) { 24021481Ssklower rtinit((struct sockaddr *)&netaddr, &ia->ia_addr, RTF_UP); 24121481Ssklower } else 24221481Ssklower rtinit((struct sockaddr *)&ia->ia_dstaddr, &ia->ia_addr, 24321481Ssklower RTF_HOST|RTF_UP); 24421481Ssklower ia->ia_flags |= IFA_ROUTE; 24521481Ssklower return(0); 24621481Ssklower } 24721481Ssklower 24821481Ssklower /* 24921481Ssklower * Return address info for specified internet network. 25021481Ssklower */ 25121481Ssklower struct ns_ifaddr * 25221481Ssklower ns_iaonnetof(net) 25321481Ssklower union ns_net net; 25421481Ssklower { 25521481Ssklower register struct ns_ifaddr *ia; 25621481Ssklower 25721481Ssklower #define NtoL(x) (*(long *)(&(x))) 25821481Ssklower for (ia = ns_ifaddr; ia; ia = ia->ia_next) 25921481Ssklower if (NtoL(ia->ia_net) == NtoL(net)) 26021481Ssklower return (ia); 26121481Ssklower return ((struct ns_ifaddr *)0); 26221481Ssklower } 26321481Ssklower #endif 264