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