1 /* 2 * Copyright (c) 1984, 1985, 1986, 1987 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)ns.c 7.12 (Berkeley) 05/08/92 8 */ 9 10 #include "param.h" 11 #include "mbuf.h" 12 #include "ioctl.h" 13 #include "protosw.h" 14 #include "errno.h" 15 #include "socket.h" 16 #include "socketvar.h" 17 18 19 #include "../net/if.h" 20 #include "../net/route.h" 21 #include "../net/af.h" 22 23 #include "ns.h" 24 #include "ns_if.h" 25 26 #ifdef NS 27 28 struct ns_ifaddr *ns_ifaddr; 29 int ns_interfaces; 30 extern struct sockaddr_ns ns_netmask, ns_hostmask; 31 32 /* 33 * Generic internet control operations (ioctl's). 34 */ 35 /* ARGSUSED */ 36 ns_control(so, cmd, data, ifp) 37 struct socket *so; 38 int cmd; 39 caddr_t data; 40 register struct ifnet *ifp; 41 { 42 register struct ifreq *ifr = (struct ifreq *)data; 43 register struct ns_aliasreq *ifra = (struct ns_aliasreq *)data; 44 register struct ns_ifaddr *ia; 45 struct ifaddr *ifa; 46 struct ns_ifaddr *oia; 47 int error, dstIsNew, hostIsNew; 48 49 /* 50 * Find address for this interface, if it exists. 51 */ 52 if (ifp == 0) 53 return (EADDRNOTAVAIL); 54 for (ia = ns_ifaddr; ia; ia = ia->ia_next) 55 if (ia->ia_ifp == ifp) 56 break; 57 58 switch (cmd) { 59 60 case SIOCGIFADDR: 61 if (ia == (struct ns_ifaddr *)0) 62 return (EADDRNOTAVAIL); 63 *(struct sockaddr_ns *)&ifr->ifr_addr = ia->ia_addr; 64 return (0); 65 66 67 case SIOCGIFBRDADDR: 68 if (ia == (struct ns_ifaddr *)0) 69 return (EADDRNOTAVAIL); 70 if ((ifp->if_flags & IFF_BROADCAST) == 0) 71 return (EINVAL); 72 *(struct sockaddr_ns *)&ifr->ifr_dstaddr = ia->ia_broadaddr; 73 return (0); 74 75 case SIOCGIFDSTADDR: 76 if (ia == (struct ns_ifaddr *)0) 77 return (EADDRNOTAVAIL); 78 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 79 return (EINVAL); 80 *(struct sockaddr_ns *)&ifr->ifr_dstaddr = ia->ia_dstaddr; 81 return (0); 82 } 83 84 if ((so->so_state & SS_PRIV) == 0) 85 return (EPERM); 86 87 switch (cmd) { 88 case SIOCAIFADDR: 89 case SIOCDIFADDR: 90 if (ifra->ifra_addr.sns_family == AF_NS) 91 for (oia = ia; ia; ia = ia->ia_next) { 92 if (ia->ia_ifp == ifp && 93 ns_neteq(ia->ia_addr.sns_addr, 94 ifra->ifra_addr.sns_addr)) 95 break; 96 } 97 if (cmd == SIOCDIFADDR && ia == 0) 98 return (EADDRNOTAVAIL); 99 /* FALLTHROUGH */ 100 101 case SIOCSIFADDR: 102 case SIOCSIFDSTADDR: 103 if (ia == (struct ns_ifaddr *)0) { 104 oia = (struct ns_ifaddr *) 105 malloc(sizeof *ia, M_IFADDR, M_WAITOK); 106 if (oia == (struct ns_ifaddr *)NULL) 107 return (ENOBUFS); 108 bzero((caddr_t)oia, sizeof(*oia)); 109 if (ia = ns_ifaddr) { 110 for ( ; ia->ia_next; ia = ia->ia_next) 111 ; 112 ia->ia_next = oia; 113 } else 114 ns_ifaddr = oia; 115 ia = oia; 116 if (ifa = ifp->if_addrlist) { 117 for ( ; ifa->ifa_next; ifa = ifa->ifa_next) 118 ; 119 ifa->ifa_next = (struct ifaddr *) ia; 120 } else 121 ifp->if_addrlist = (struct ifaddr *) ia; 122 ia->ia_ifp = ifp; 123 ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 124 125 ia->ia_ifa.ifa_netmask = 126 (struct sockaddr *)&ns_netmask; 127 128 ia->ia_ifa.ifa_dstaddr = 129 (struct sockaddr *)&ia->ia_dstaddr; 130 if (ifp->if_flags & IFF_BROADCAST) { 131 ia->ia_broadaddr.sns_family = AF_NS; 132 ia->ia_broadaddr.sns_len = sizeof(ia->ia_addr); 133 ia->ia_broadaddr.sns_addr.x_host = ns_broadhost; 134 } 135 ns_interfaces++; 136 } 137 } 138 139 switch (cmd) { 140 int error; 141 142 case SIOCSIFDSTADDR: 143 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 144 return (EINVAL); 145 if (ia->ia_flags & IFA_ROUTE) { 146 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 147 ia->ia_flags &= ~IFA_ROUTE; 148 } 149 if (ifp->if_ioctl) { 150 error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia); 151 if (error) 152 return (error); 153 } 154 *(struct sockaddr *)&ia->ia_dstaddr = ifr->ifr_dstaddr; 155 return (0); 156 157 case SIOCSIFADDR: 158 return (ns_ifinit(ifp, ia, 159 (struct sockaddr_ns *)&ifr->ifr_addr, 1)); 160 161 case SIOCDIFADDR: 162 ns_ifscrub(ifp, ia); 163 if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia) 164 ifp->if_addrlist = ifa->ifa_next; 165 else { 166 while (ifa->ifa_next && 167 (ifa->ifa_next != (struct ifaddr *)ia)) 168 ifa = ifa->ifa_next; 169 if (ifa->ifa_next) 170 ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next; 171 else 172 printf("Couldn't unlink nsifaddr from ifp\n"); 173 } 174 oia = ia; 175 if (oia == (ia = ns_ifaddr)) { 176 ns_ifaddr = ia->ia_next; 177 } else { 178 while (ia->ia_next && (ia->ia_next != oia)) { 179 ia = ia->ia_next; 180 } 181 if (ia->ia_next) 182 ia->ia_next = oia->ia_next; 183 else 184 printf("Didn't unlink nsifadr from list\n"); 185 } 186 IFAFREE((&oia->ia_ifa)); 187 if (0 == --ns_interfaces) { 188 /* 189 * We reset to virginity and start all over again 190 */ 191 ns_thishost = ns_zerohost; 192 } 193 return (0); 194 195 case SIOCAIFADDR: 196 dstIsNew = 0; hostIsNew = 1; 197 if (ia->ia_addr.sns_family == AF_NS) { 198 if (ifra->ifra_addr.sns_len == 0) { 199 ifra->ifra_addr = ia->ia_addr; 200 hostIsNew = 0; 201 } else if (ns_neteq(ifra->ifra_addr.sns_addr, 202 ia->ia_addr.sns_addr)) 203 hostIsNew = 0; 204 } 205 if ((ifp->if_flags & IFF_POINTOPOINT) && 206 (ifra->ifra_dstaddr.sns_family == AF_NS)) { 207 if (hostIsNew == 0) 208 ns_ifscrub(ifp, ia); 209 ia->ia_dstaddr = ifra->ifra_dstaddr; 210 dstIsNew = 1; 211 } 212 if (ifra->ifra_addr.sns_family == AF_NS && 213 (hostIsNew || dstIsNew)) 214 error = ns_ifinit(ifp, ia, &ifra->ifra_addr, 0); 215 return (error); 216 217 default: 218 if (ifp->if_ioctl == 0) 219 return (EOPNOTSUPP); 220 return ((*ifp->if_ioctl)(ifp, cmd, data)); 221 } 222 } 223 224 /* 225 * Delete any previous route for an old address. 226 */ 227 ns_ifscrub(ifp, ia) 228 register struct ifnet *ifp; 229 register struct ns_ifaddr *ia; 230 { 231 if (ia->ia_flags & IFA_ROUTE) { 232 if (ifp->if_flags & IFF_POINTOPOINT) { 233 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 234 } else 235 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0); 236 ia->ia_flags &= ~IFA_ROUTE; 237 } 238 } 239 /* 240 * Initialize an interface's internet address 241 * and routing table entry. 242 */ 243 ns_ifinit(ifp, ia, sns, scrub) 244 register struct ifnet *ifp; 245 register struct ns_ifaddr *ia; 246 register struct sockaddr_ns *sns; 247 { 248 struct sockaddr_ns oldaddr; 249 register union ns_host *h = &ia->ia_addr.sns_addr.x_host; 250 int s = splimp(), error; 251 252 /* 253 * Set up new addresses. 254 */ 255 oldaddr = ia->ia_addr; 256 ia->ia_addr = *sns; 257 /* 258 * The convention we shall adopt for naming is that 259 * a supplied address of zero means that "we don't care". 260 * if there is a single interface, use the address of that 261 * interface as our 6 byte host address. 262 * if there are multiple interfaces, use any address already 263 * used. 264 * 265 * Give the interface a chance to initialize 266 * if this is its first address, 267 * and to validate the address if necessary. 268 */ 269 if (ns_hosteqnh(ns_thishost, ns_zerohost)) { 270 if (ifp->if_ioctl && 271 (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { 272 ia->ia_addr = oldaddr; 273 splx(s); 274 return (error); 275 } 276 ns_thishost = *h; 277 } else if (ns_hosteqnh(sns->sns_addr.x_host, ns_zerohost) 278 || ns_hosteqnh(sns->sns_addr.x_host, ns_thishost)) { 279 *h = ns_thishost; 280 if (ifp->if_ioctl && 281 (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { 282 ia->ia_addr = oldaddr; 283 splx(s); 284 return (error); 285 } 286 if (!ns_hosteqnh(ns_thishost,*h)) { 287 ia->ia_addr = oldaddr; 288 splx(s); 289 return (EINVAL); 290 } 291 } else { 292 ia->ia_addr = oldaddr; 293 splx(s); 294 return (EINVAL); 295 } 296 ia->ia_ifa.ifa_metric = ifp->if_metric; 297 /* 298 * Add route for the network. 299 */ 300 if (scrub) { 301 ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr; 302 ns_ifscrub(ifp, ia); 303 ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 304 } 305 if (ifp->if_flags & IFF_POINTOPOINT) 306 rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 307 else { 308 ia->ia_broadaddr.sns_addr.x_net = ia->ia_addr.sns_addr.x_net; 309 rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP); 310 } 311 ia->ia_flags |= IFA_ROUTE; 312 return (0); 313 } 314 315 /* 316 * Return address info for specified internet network. 317 */ 318 struct ns_ifaddr * 319 ns_iaonnetof(dst) 320 register struct ns_addr *dst; 321 { 322 register struct ns_ifaddr *ia; 323 register struct ns_addr *compare; 324 register struct ifnet *ifp; 325 struct ns_ifaddr *ia_maybe = 0; 326 union ns_net net = dst->x_net; 327 328 for (ia = ns_ifaddr; ia; ia = ia->ia_next) { 329 if (ifp = ia->ia_ifp) { 330 if (ifp->if_flags & IFF_POINTOPOINT) { 331 compare = &satons_addr(ia->ia_dstaddr); 332 if (ns_hosteq(*dst, *compare)) 333 return (ia); 334 if (ns_neteqnn(net, ia->ia_addr.sns_addr.x_net)) 335 ia_maybe = ia; 336 } else { 337 if (ns_neteqnn(net, ia->ia_addr.sns_addr.x_net)) 338 return (ia); 339 } 340 } 341 } 342 return (ia_maybe); 343 } 344 #endif 345