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