1 /* 2 * Copyright (c) 1982, 1986, 1991 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)in.c 7.24 (Berkeley) 03/11/92 8 */ 9 10 #include "param.h" 11 #include "ioctl.h" 12 #include "errno.h" 13 #include "mbuf.h" 14 #include "socket.h" 15 #include "socketvar.h" 16 #include "in_systm.h" 17 #include "net/if.h" 18 #include "net/route.h" 19 #include "net/af.h" 20 #include "in.h" 21 #include "in_var.h" 22 23 #ifdef INET 24 /* 25 * Formulate an Internet address from network + host. 26 */ 27 struct in_addr 28 in_makeaddr(net, host) 29 u_long net, host; 30 { 31 register struct in_ifaddr *ia; 32 register u_long mask; 33 u_long addr; 34 35 if (IN_CLASSA(net)) 36 mask = IN_CLASSA_HOST; 37 else if (IN_CLASSB(net)) 38 mask = IN_CLASSB_HOST; 39 else 40 mask = IN_CLASSC_HOST; 41 for (ia = in_ifaddr; ia; ia = ia->ia_next) 42 if ((ia->ia_netmask & net) == ia->ia_net) { 43 mask = ~ia->ia_subnetmask; 44 break; 45 } 46 addr = htonl(net | (host & mask)); 47 return (*(struct in_addr *)&addr); 48 } 49 50 /* 51 * Return the network number from an internet address. 52 */ 53 u_long 54 in_netof(in) 55 struct in_addr in; 56 { 57 register u_long i = ntohl(in.s_addr); 58 register u_long net; 59 register struct in_ifaddr *ia; 60 61 if (IN_CLASSA(i)) 62 net = i & IN_CLASSA_NET; 63 else if (IN_CLASSB(i)) 64 net = i & IN_CLASSB_NET; 65 else if (IN_CLASSC(i)) 66 net = i & IN_CLASSC_NET; 67 else 68 return (0); 69 70 /* 71 * Check whether network is a subnet; 72 * if so, return subnet number. 73 */ 74 for (ia = in_ifaddr; ia; ia = ia->ia_next) 75 if (net == ia->ia_net) 76 return (i & ia->ia_subnetmask); 77 return (net); 78 } 79 80 /* 81 * Compute and save network mask as sockaddr from an internet address. 82 */ 83 in_sockmaskof(in, sockmask) 84 struct in_addr in; 85 register struct sockaddr_in *sockmask; 86 { 87 register u_long net; 88 register u_long mask; 89 { 90 register u_long i = ntohl(in.s_addr); 91 92 if (i == 0) 93 net = 0, mask = 0; 94 else if (IN_CLASSA(i)) 95 net = i & IN_CLASSA_NET, mask = IN_CLASSA_NET; 96 else if (IN_CLASSB(i)) 97 net = i & IN_CLASSB_NET, mask = IN_CLASSB_NET; 98 else if (IN_CLASSC(i)) 99 net = i & IN_CLASSC_NET, mask = IN_CLASSC_NET; 100 else 101 net = i, mask = -1; 102 } 103 { 104 register struct in_ifaddr *ia; 105 /* 106 * Check whether network is a subnet; 107 * if so, return subnet number. 108 */ 109 for (ia = in_ifaddr; ia; ia = ia->ia_next) 110 if (net == ia->ia_net) 111 mask = ia->ia_subnetmask; 112 } 113 { 114 register char *cpbase = (char *)&(sockmask->sin_addr); 115 register char *cp = (char *)(1 + &(sockmask->sin_addr)); 116 117 sockmask->sin_addr.s_addr = htonl(mask); 118 sockmask->sin_len = 0; 119 while (--cp >= cpbase) 120 if (*cp) { 121 sockmask->sin_len = 1 + cp - (caddr_t)sockmask; 122 break; 123 } 124 } 125 } 126 127 /* 128 * Return the host portion of an internet address. 129 */ 130 u_long 131 in_lnaof(in) 132 struct in_addr in; 133 { 134 register u_long i = ntohl(in.s_addr); 135 register u_long net, host; 136 register struct in_ifaddr *ia; 137 138 if (IN_CLASSA(i)) { 139 net = i & IN_CLASSA_NET; 140 host = i & IN_CLASSA_HOST; 141 } else if (IN_CLASSB(i)) { 142 net = i & IN_CLASSB_NET; 143 host = i & IN_CLASSB_HOST; 144 } else if (IN_CLASSC(i)) { 145 net = i & IN_CLASSC_NET; 146 host = i & IN_CLASSC_HOST; 147 } else 148 return (i); 149 150 /* 151 * Check whether network is a subnet; 152 * if so, use the modified interpretation of `host'. 153 */ 154 for (ia = in_ifaddr; ia; ia = ia->ia_next) 155 if (net == ia->ia_net) 156 return (host &~ ia->ia_subnetmask); 157 return (host); 158 } 159 160 #ifndef SUBNETSARELOCAL 161 #define SUBNETSARELOCAL 1 162 #endif 163 int subnetsarelocal = SUBNETSARELOCAL; 164 /* 165 * Return 1 if an internet address is for a ``local'' host 166 * (one to which we have a connection). If subnetsarelocal 167 * is true, this includes other subnets of the local net. 168 * Otherwise, it includes only the directly-connected (sub)nets. 169 */ 170 in_localaddr(in) 171 struct in_addr in; 172 { 173 register u_long i = ntohl(in.s_addr); 174 register struct in_ifaddr *ia; 175 176 if (subnetsarelocal) { 177 for (ia = in_ifaddr; ia; ia = ia->ia_next) 178 if ((i & ia->ia_netmask) == ia->ia_net) 179 return (1); 180 } else { 181 for (ia = in_ifaddr; ia; ia = ia->ia_next) 182 if ((i & ia->ia_subnetmask) == ia->ia_subnet) 183 return (1); 184 } 185 return (0); 186 } 187 188 /* 189 * Determine whether an IP address is in a reserved set of addresses 190 * that may not be forwarded, or whether datagrams to that destination 191 * may be forwarded. 192 */ 193 in_canforward(in) 194 struct in_addr in; 195 { 196 register u_long i = ntohl(in.s_addr); 197 register u_long net; 198 199 if (IN_EXPERIMENTAL(i)) 200 return (0); 201 if (IN_CLASSA(i)) { 202 net = i & IN_CLASSA_NET; 203 if (net == 0 || net == IN_LOOPBACKNET) 204 return (0); 205 } 206 return (1); 207 } 208 209 int in_interfaces; /* number of external internet interfaces */ 210 extern struct ifnet loif; 211 212 /* 213 * Generic internet control operations (ioctl's). 214 * Ifp is 0 if not an interface-specific ioctl. 215 */ 216 /* ARGSUSED */ 217 in_control(so, cmd, data, ifp) 218 struct socket *so; 219 int cmd; 220 caddr_t data; 221 register struct ifnet *ifp; 222 { 223 register struct ifreq *ifr = (struct ifreq *)data; 224 register struct in_ifaddr *ia = 0; 225 register struct ifaddr *ifa; 226 struct in_ifaddr *oia; 227 struct in_aliasreq *ifra = (struct in_aliasreq *)data; 228 struct sockaddr_in oldaddr; 229 int error, hostIsNew, maskIsNew; 230 u_long i; 231 232 /* 233 * Find address for this interface, if it exists. 234 */ 235 if (ifp) 236 for (ia = in_ifaddr; ia; ia = ia->ia_next) 237 if (ia->ia_ifp == ifp) 238 break; 239 240 switch (cmd) { 241 242 case SIOCAIFADDR: 243 case SIOCDIFADDR: 244 if (ifra->ifra_addr.sin_family == AF_INET) 245 for (oia = ia; ia; ia = ia->ia_next) { 246 if (ia->ia_ifp == ifp && 247 ia->ia_addr.sin_addr.s_addr == 248 ifra->ifra_addr.sin_addr.s_addr) 249 break; 250 } 251 if (cmd == SIOCDIFADDR && ia == 0) 252 return (EADDRNOTAVAIL); 253 /* FALLTHROUGH */ 254 case SIOCSIFADDR: 255 case SIOCSIFNETMASK: 256 case SIOCSIFDSTADDR: 257 if ((so->so_state & SS_PRIV) == 0) 258 return (EPERM); 259 260 if (ifp == 0) 261 panic("in_control"); 262 if (ia == (struct in_ifaddr *)0) { 263 oia = (struct in_ifaddr *) 264 malloc(sizeof *oia, M_IFADDR, M_WAITOK); 265 if (oia == (struct in_ifaddr *)NULL) 266 return (ENOBUFS); 267 bzero((caddr_t)oia, sizeof *oia); 268 if (ia = in_ifaddr) { 269 for ( ; ia->ia_next; ia = ia->ia_next) 270 continue; 271 ia->ia_next = oia; 272 } else 273 in_ifaddr = oia; 274 ia = oia; 275 if (ifa = ifp->if_addrlist) { 276 for ( ; ifa->ifa_next; ifa = ifa->ifa_next) 277 continue; 278 ifa->ifa_next = (struct ifaddr *) ia; 279 } else 280 ifp->if_addrlist = (struct ifaddr *) ia; 281 ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 282 ia->ia_ifa.ifa_dstaddr 283 = (struct sockaddr *)&ia->ia_dstaddr; 284 ia->ia_ifa.ifa_netmask 285 = (struct sockaddr *)&ia->ia_sockmask; 286 ia->ia_sockmask.sin_len = 8; 287 if (ifp->if_flags & IFF_BROADCAST) { 288 ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr); 289 ia->ia_broadaddr.sin_family = AF_INET; 290 } 291 ia->ia_ifp = ifp; 292 if (ifp != &loif) 293 in_interfaces++; 294 } 295 break; 296 297 case SIOCSIFBRDADDR: 298 if ((so->so_state & SS_PRIV) == 0) 299 return (EPERM); 300 /* FALLTHROUGH */ 301 302 case SIOCGIFADDR: 303 case SIOCGIFNETMASK: 304 case SIOCGIFDSTADDR: 305 case SIOCGIFBRDADDR: 306 if (ia == (struct in_ifaddr *)0) 307 return (EADDRNOTAVAIL); 308 break; 309 } 310 switch (cmd) { 311 312 case SIOCGIFADDR: 313 *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr; 314 break; 315 316 case SIOCGIFBRDADDR: 317 if ((ifp->if_flags & IFF_BROADCAST) == 0) 318 return (EINVAL); 319 *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr; 320 break; 321 322 case SIOCGIFDSTADDR: 323 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 324 return (EINVAL); 325 *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr; 326 break; 327 328 case SIOCGIFNETMASK: 329 *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask; 330 break; 331 332 case SIOCSIFDSTADDR: 333 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 334 return (EINVAL); 335 oldaddr = ia->ia_dstaddr; 336 ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr; 337 if (ifp->if_ioctl && (error = (*ifp->if_ioctl) 338 (ifp, SIOCSIFDSTADDR, (caddr_t)ia))) { 339 ia->ia_dstaddr = oldaddr; 340 return (error); 341 } 342 if (ia->ia_flags & IFA_ROUTE) { 343 ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr; 344 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 345 ia->ia_ifa.ifa_dstaddr = 346 (struct sockaddr *)&ia->ia_dstaddr; 347 rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 348 } 349 break; 350 351 case SIOCSIFBRDADDR: 352 if ((ifp->if_flags & IFF_BROADCAST) == 0) 353 return (EINVAL); 354 ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr; 355 break; 356 357 case SIOCSIFADDR: 358 return (in_ifinit(ifp, ia, 359 (struct sockaddr_in *) &ifr->ifr_addr, 1)); 360 361 case SIOCSIFNETMASK: 362 i = ifra->ifra_addr.sin_addr.s_addr; 363 ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr = i); 364 break; 365 366 case SIOCAIFADDR: 367 maskIsNew = 0; 368 hostIsNew = 1; 369 error = 0; 370 if (ia->ia_addr.sin_family == AF_INET) { 371 if (ifra->ifra_addr.sin_len == 0) { 372 ifra->ifra_addr = ia->ia_addr; 373 hostIsNew = 0; 374 } else if (ifra->ifra_addr.sin_addr.s_addr == 375 ia->ia_addr.sin_addr.s_addr) 376 hostIsNew = 0; 377 } 378 if (ifra->ifra_mask.sin_len) { 379 in_ifscrub(ifp, ia); 380 ia->ia_sockmask = ifra->ifra_mask; 381 ia->ia_subnetmask = 382 ntohl(ia->ia_sockmask.sin_addr.s_addr); 383 maskIsNew = 1; 384 } 385 if ((ifp->if_flags & IFF_POINTOPOINT) && 386 (ifra->ifra_dstaddr.sin_family == AF_INET)) { 387 in_ifscrub(ifp, ia); 388 ia->ia_dstaddr = ifra->ifra_dstaddr; 389 maskIsNew = 1; /* We lie; but the effect's the same */ 390 } 391 if (ifra->ifra_addr.sin_family == AF_INET && 392 (hostIsNew || maskIsNew)) 393 error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0); 394 if ((ifp->if_flags & IFF_BROADCAST) && 395 (ifra->ifra_broadaddr.sin_family == AF_INET)) 396 ia->ia_broadaddr = ifra->ifra_broadaddr; 397 return (error); 398 399 case SIOCDIFADDR: 400 in_ifscrub(ifp, ia); 401 if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia) 402 ifp->if_addrlist = ifa->ifa_next; 403 else { 404 while (ifa->ifa_next && 405 (ifa->ifa_next != (struct ifaddr *)ia)) 406 ifa = ifa->ifa_next; 407 if (ifa->ifa_next) 408 ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next; 409 else 410 printf("Couldn't unlink inifaddr from ifp\n"); 411 } 412 oia = ia; 413 if (oia == (ia = in_ifaddr)) 414 in_ifaddr = ia->ia_next; 415 else { 416 while (ia->ia_next && (ia->ia_next != oia)) 417 ia = ia->ia_next; 418 if (ia->ia_next) 419 ia->ia_next = oia->ia_next; 420 else 421 printf("Didn't unlink inifadr from list\n"); 422 } 423 IFAFREE((&oia->ia_ifa)); 424 break; 425 426 default: 427 if (ifp == 0 || ifp->if_ioctl == 0) 428 return (EOPNOTSUPP); 429 return ((*ifp->if_ioctl)(ifp, cmd, data)); 430 } 431 return (0); 432 } 433 434 /* 435 * Delete any existing route for an interface. 436 */ 437 in_ifscrub(ifp, ia) 438 register struct ifnet *ifp; 439 register struct in_ifaddr *ia; 440 { 441 442 if ((ia->ia_flags & IFA_ROUTE) == 0) 443 return; 444 if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT)) 445 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 446 else 447 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0); 448 ia->ia_flags &= ~IFA_ROUTE; 449 } 450 451 /* 452 * Initialize an interface's internet address 453 * and routing table entry. 454 */ 455 in_ifinit(ifp, ia, sin, scrub) 456 register struct ifnet *ifp; 457 register struct in_ifaddr *ia; 458 struct sockaddr_in *sin; 459 int scrub; 460 { 461 register u_long i = ntohl(sin->sin_addr.s_addr); 462 struct sockaddr_in oldaddr; 463 int s = splimp(), error, flags = RTF_UP; 464 int ether_output(), arp_rtrequest(); 465 466 oldaddr = ia->ia_addr; 467 ia->ia_addr = *sin; 468 /* 469 * Give the interface a chance to initialize 470 * if this is its first address, 471 * and to validate the address if necessary. 472 */ 473 if (ifp->if_ioctl && 474 (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) { 475 splx(s); 476 ia->ia_addr = oldaddr; 477 return (error); 478 } 479 if (ifp->if_output == ether_output) { /* XXX: Another Kludge */ 480 ia->ia_ifa.ifa_rtrequest = arp_rtrequest; 481 ia->ia_ifa.ifa_flags |= RTF_CLONING; 482 } 483 splx(s); 484 if (scrub) { 485 ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr; 486 in_ifscrub(ifp, ia); 487 ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 488 } 489 if (IN_CLASSA(i)) 490 ia->ia_netmask = IN_CLASSA_NET; 491 else if (IN_CLASSB(i)) 492 ia->ia_netmask = IN_CLASSB_NET; 493 else 494 ia->ia_netmask = IN_CLASSC_NET; 495 ia->ia_net = i & ia->ia_netmask; 496 /* 497 * The subnet mask includes at least the standard network part, 498 * but may already have been set to a larger value. 499 */ 500 ia->ia_subnetmask |= ia->ia_netmask; 501 ia->ia_subnet = i & ia->ia_subnetmask; 502 ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask); 503 { 504 register char *cp = (char *) (1 + &(ia->ia_sockmask.sin_addr)); 505 register char *cpbase = (char *) &(ia->ia_sockmask.sin_addr); 506 while (--cp >= cpbase) 507 if (*cp) { 508 ia->ia_sockmask.sin_len = 509 1 + cp - (char *) &(ia->ia_sockmask); 510 break; 511 } 512 } 513 /* 514 * Add route for the network. 515 */ 516 ia->ia_ifa.ifa_metric = ifp->if_metric; 517 if (ifp->if_flags & IFF_BROADCAST) { 518 ia->ia_broadaddr.sin_addr = 519 in_makeaddr(ia->ia_subnet, INADDR_BROADCAST); 520 ia->ia_netbroadcast.s_addr = 521 htonl(ia->ia_net | (INADDR_BROADCAST &~ ia->ia_netmask)); 522 } else if (ifp->if_flags & IFF_LOOPBACK) { 523 ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr; 524 flags |= RTF_HOST; 525 } else if (ifp->if_flags & IFF_POINTOPOINT) { 526 if (ia->ia_dstaddr.sin_family != AF_INET) 527 return (0); 528 flags |= RTF_HOST; 529 } 530 if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, flags)) == 0) 531 ia->ia_flags |= IFA_ROUTE; 532 return (error); 533 } 534 535 /* 536 * Return address info for specified internet network. 537 */ 538 struct in_ifaddr * 539 in_iaonnetof(net) 540 u_long net; 541 { 542 register struct in_ifaddr *ia; 543 544 for (ia = in_ifaddr; ia; ia = ia->ia_next) 545 if (ia->ia_subnet == net) 546 return (ia); 547 return ((struct in_ifaddr *)0); 548 } 549 550 /* 551 * Return 1 if the address might be a local broadcast address. 552 */ 553 in_broadcast(in) 554 struct in_addr in; 555 { 556 register struct in_ifaddr *ia; 557 u_long t; 558 559 /* 560 * Look through the list of addresses for a match 561 * with a broadcast address. 562 */ 563 for (ia = in_ifaddr; ia; ia = ia->ia_next) 564 if (ia->ia_ifp->if_flags & IFF_BROADCAST) { 565 if (ia->ia_broadaddr.sin_addr.s_addr == in.s_addr) 566 return (1); 567 /* 568 * Check for old-style (host 0) broadcast. 569 */ 570 if ((t = ntohl(in.s_addr)) == ia->ia_subnet || t == ia->ia_net) 571 return (1); 572 } 573 if (in.s_addr == INADDR_BROADCAST || in.s_addr == INADDR_ANY) 574 return (1); 575 return (0); 576 } 577 #endif 578