1 /* 2 * Copyright (c) 1982 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 * 6 * @(#)ns.c 6.4 (Berkeley) 08/09/85 7 */ 8 9 #include "param.h" 10 #include "mbuf.h" 11 #include "ioctl.h" 12 #include "protosw.h" 13 #include "socket.h" 14 #include "socketvar.h" 15 #include "uio.h" 16 #include "dir.h" 17 #include "user.h" 18 19 20 #include "../net/if.h" 21 #include "../net/route.h" 22 #include "../net/af.h" 23 24 #include "ns.h" 25 #include "ns_if.h" 26 27 #ifdef NS 28 29 struct ns_ifaddr *ns_ifaddr; 30 31 ns_hash(sns, hp) 32 register struct sockaddr_ns *sns; 33 struct afhash *hp; 34 { 35 register long hash = 0; 36 register u_short *s = sns->sns_addr.x_host.s_host; 37 38 hp->afh_nethash = ns_netof(sns->sns_addr); 39 hash = *s++; hash <<= 8; hash += *s++; hash <<= 8; hash += *s; 40 hp->afh_hosthash = hash; 41 } 42 43 44 ns_netmatch(sns1, sns2) 45 struct sockaddr_ns *sns1, *sns2; 46 { 47 48 return (ns_netof(sns1->sns_addr) == ns_netof(sns2->sns_addr)); 49 } 50 51 /* 52 * Generic internet control operations (ioctl's). 53 */ 54 /* ARGSUSED */ 55 ns_control(so, cmd, data, ifp) 56 struct socket *so; 57 int cmd; 58 caddr_t data; 59 register struct ifnet *ifp; 60 { 61 register struct ifreq *ifr = (struct ifreq *)data; 62 register struct ns_ifaddr *ia; 63 struct ifaddr *ifa; 64 struct mbuf *m; 65 66 /* 67 * Find address for this interface, if it exists. 68 */ 69 if (ifp==0) 70 return (EADDRNOTAVAIL); 71 for (ia = ns_ifaddr; ia; ia = ia->ia_next) 72 if (ia->ia_ifp == ifp) 73 break; 74 75 switch (cmd) { 76 77 case SIOCGIFADDR: 78 if (ia == (struct ns_ifaddr *)0) 79 return (EADDRNOTAVAIL); 80 ifr->ifr_addr = ia->ia_addr; 81 return (0); 82 83 84 case SIOCGIFBRDADDR: 85 if (ia == (struct ns_ifaddr *)0) 86 return (EADDRNOTAVAIL); 87 if ((ifp->if_flags & IFF_BROADCAST) == 0) 88 return (EINVAL); 89 ifr->ifr_dstaddr = ia->ia_broadaddr; 90 return (0); 91 92 case SIOCGIFDSTADDR: 93 if (ia == (struct ns_ifaddr *)0) 94 return (EADDRNOTAVAIL); 95 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 96 return (EINVAL); 97 ifr->ifr_dstaddr = ia->ia_dstaddr; 98 return (0); 99 } 100 101 if (!suser()) 102 return (u.u_error); 103 104 switch (cmd) { 105 106 case SIOCSIFDSTADDR: 107 return (EOPNOTSUPP); 108 109 case SIOCSIFADDR: 110 if (ia == (struct ns_ifaddr *)0) { 111 m = m_getclr(M_WAIT, MT_IFADDR); 112 if (m == (struct mbuf *)NULL) 113 return (ENOBUFS); 114 if (ia = ns_ifaddr) { 115 for ( ; ia->ia_next; ia = ia->ia_next) 116 ; 117 ia->ia_next = mtod(m, struct ns_ifaddr *); 118 } else 119 ns_ifaddr = mtod(m, struct ns_ifaddr *); 120 ia = mtod(m, struct ns_ifaddr *); 121 if (ifa = ifp->if_addrlist) { 122 for ( ; ifa->ifa_next; ifa = ifa->ifa_next) 123 ; 124 ifa->ifa_next = (struct ifaddr *) ia; 125 } else 126 ifp->if_addrlist = (struct ifaddr *) ia; 127 ia->ia_ifp = ifp; 128 IA_SNS(ia)->sns_family = AF_NS; 129 } 130 return 131 (ns_ifinit(ifp, ia, (struct sockaddr_ns *)&ifr->ifr_addr)); 132 133 default: 134 if (ifp->if_ioctl == 0) 135 return (EOPNOTSUPP); 136 return ((*ifp->if_ioctl)(ifp, cmd, data)); 137 } 138 } 139 140 /* 141 * Initialize an interface's internet address 142 * and routing table entry. 143 */ 144 ns_ifinit(ifp, ia, sns) 145 register struct ifnet *ifp; 146 register struct ns_ifaddr *ia; 147 struct sockaddr_ns *sns; 148 { 149 struct sockaddr_ns netaddr; 150 register union ns_host *h = &(IA_SNS(ia)->sns_addr.x_host); 151 int s = splimp(), error; 152 153 /* 154 * The convention we shall adopt for naming is that 155 * a supplied address of zero means that "we don't care". 156 * if there is a single interface, use the address of that 157 * interface as our 6 byte host address. 158 * if there are multiple interfaces, use any address already 159 * used. 160 * 161 * If we have gotten into trouble and want to reset back to 162 * virginity, we recognize a request of the broadcast address. 163 */ 164 if (ns_hosteqnh(sns->sns_addr.x_host, ns_broadhost)) { 165 ns_thishost = ns_zerohost; 166 splx(s); 167 return(EINVAL); 168 } 169 170 /* 171 * Delete any previous route for an old address. 172 */ 173 174 bzero((caddr_t)&netaddr, sizeof (netaddr)); 175 netaddr.sns_family = AF_NS; 176 netaddr.sns_addr.x_host = ns_broadhost; 177 netaddr.sns_addr.x_net = ia->ia_net; 178 if (ia->ia_flags & IFA_ROUTE) { 179 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) { 180 rtinit((struct sockaddr *)&netaddr, &ia->ia_addr, -1); 181 } else 182 rtinit((struct sockaddr *)&ia->ia_dstaddr, &ia->ia_addr, -1); 183 } 184 185 /* 186 * Set up new addresses. 187 */ 188 ia->ia_addr = *(struct sockaddr *)sns; 189 ia->ia_net = sns->sns_addr.x_net; 190 netaddr.sns_addr.x_net = ia->ia_net; 191 if (ifp->if_flags & IFF_BROADCAST) { 192 ia->ia_broadaddr = * (struct sockaddr *) &netaddr; 193 } 194 /* 195 * Point to point links are a little touchier -- 196 * We have to have an address of our own first, 197 * and will use the supplied address as that of the other end. 198 */ 199 if (ifp->if_flags & IFF_POINTOPOINT) { 200 struct sockaddr_ns *sns2 = IA_SNS(ia); 201 if (ns_hosteqnh(ns_zerohost,ns_thishost)) 202 return(EINVAL); 203 ia->ia_dstaddr = ia->ia_addr; 204 sns2->sns_addr.x_host = ns_thishost; 205 sns->sns_addr.x_host = ns_thishost; 206 } 207 /* 208 * Give the interface a chance to initialize 209 * if this is its first address, 210 * and to validate the address if necessary. 211 */ 212 213 if (ns_hosteqnh(ns_thishost, ns_zerohost)) { 214 if (ifp->if_ioctl && 215 (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { 216 splx(s); 217 return (error); 218 } 219 ns_thishost = *h; 220 } else if (ns_hosteqnh(sns->sns_addr.x_host, ns_zerohost) 221 || ns_hosteqnh(sns->sns_addr.x_host, ns_thishost)) { 222 *h = ns_thishost; 223 if (ifp->if_ioctl && 224 (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { 225 splx(s); 226 return (error); 227 } 228 if(!ns_hosteqnh(ns_thishost,*h)) { 229 splx(s); 230 return (EINVAL); 231 } 232 } else { 233 splx(s); 234 return(EINVAL); 235 } 236 /* 237 * Add route for the network. 238 */ 239 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) { 240 rtinit((struct sockaddr *)&netaddr, &ia->ia_addr, RTF_UP); 241 } else 242 rtinit((struct sockaddr *)&ia->ia_dstaddr, &ia->ia_addr, 243 RTF_HOST|RTF_UP); 244 ia->ia_flags |= IFA_ROUTE; 245 return(0); 246 } 247 248 /* 249 * Return address info for specified internet network. 250 */ 251 struct ns_ifaddr * 252 ns_iaonnetof(net) 253 union ns_net net; 254 { 255 register struct ns_ifaddr *ia; 256 257 #define NtoL(x) (*(long *)(&(x))) 258 for (ia = ns_ifaddr; ia; ia = ia->ia_next) 259 if (NtoL(ia->ia_net) == NtoL(net)) 260 return (ia); 261 return ((struct ns_ifaddr *)0); 262 } 263 #endif 264