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