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.19 (Berkeley) 12/19/91 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 ; 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 ; 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 default: 311 return (EOPNOTSUPP); 312 break; 313 } 314 switch (cmd) { 315 316 case SIOCGIFADDR: 317 *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr; 318 break; 319 320 case SIOCGIFBRDADDR: 321 if ((ifp->if_flags & IFF_BROADCAST) == 0) 322 return (EINVAL); 323 *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr; 324 break; 325 326 case SIOCGIFDSTADDR: 327 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 328 return (EINVAL); 329 *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr; 330 break; 331 332 case SIOCGIFNETMASK: 333 *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask; 334 break; 335 336 case SIOCSIFDSTADDR: 337 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 338 return (EINVAL); 339 oldaddr = ia->ia_dstaddr; 340 ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr; 341 if (ifp->if_ioctl && 342 (error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia))) { 343 ia->ia_dstaddr = oldaddr; 344 return (error); 345 } 346 if (ia->ia_flags & IFA_ROUTE) { 347 ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr; 348 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 349 ia->ia_ifa.ifa_dstaddr = 350 (struct sockaddr *)&ia->ia_dstaddr; 351 rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 352 } 353 break; 354 355 case SIOCSIFBRDADDR: 356 if ((ifp->if_flags & IFF_BROADCAST) == 0) 357 return (EINVAL); 358 ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr; 359 break; 360 361 case SIOCSIFADDR: 362 return (in_ifinit(ifp, ia, 363 (struct sockaddr_in *) &ifr->ifr_addr, 1)); 364 365 case SIOCSIFNETMASK: 366 i = ifra->ifra_addr.sin_addr.s_addr; 367 ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr = i); 368 break; 369 370 case SIOCAIFADDR: 371 maskIsNew = 0; 372 hostIsNew = 1; 373 error = 0; 374 if (ia->ia_addr.sin_family == AF_INET) { 375 if (ifra->ifra_addr.sin_len == 0) { 376 ifra->ifra_addr = ia->ia_addr; 377 hostIsNew = 0; 378 } else if (ifra->ifra_addr.sin_addr.s_addr == 379 ia->ia_addr.sin_addr.s_addr) 380 hostIsNew = 0; 381 } 382 if (ifra->ifra_mask.sin_len) { 383 in_ifscrub(ifp, ia); 384 ia->ia_sockmask = ifra->ifra_mask; 385 ia->ia_subnetmask = 386 ntohl(ia->ia_sockmask.sin_addr.s_addr); 387 maskIsNew = 1; 388 } 389 if ((ifp->if_flags & IFF_POINTOPOINT) && 390 (ifra->ifra_dstaddr.sin_family == AF_INET)) { 391 in_ifscrub(ifp, ia); 392 ia->ia_dstaddr = ifra->ifra_dstaddr; 393 maskIsNew = 1; /* We lie; but the effect's the same */ 394 } 395 if (ifra->ifra_addr.sin_family == AF_INET && 396 (hostIsNew || maskIsNew)) 397 error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0); 398 if ((ifp->if_flags & IFF_BROADCAST) && 399 (ifra->ifra_broadaddr.sin_family == AF_INET)) 400 ia->ia_broadaddr = ifra->ifra_broadaddr; 401 return (error); 402 403 case SIOCDIFADDR: 404 in_ifscrub(ifp, ia); 405 if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia) 406 ifp->if_addrlist = ifa->ifa_next; 407 else { 408 while (ifa->ifa_next && 409 (ifa->ifa_next != (struct ifaddr *)ia)) 410 ifa = ifa->ifa_next; 411 if (ifa->ifa_next) 412 ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next; 413 else 414 printf("Couldn't unlink inifaddr from ifp\n"); 415 } 416 oia = ia; 417 if (oia == (ia = in_ifaddr)) 418 in_ifaddr = ia->ia_next; 419 else { 420 while (ia->ia_next && (ia->ia_next != oia)) 421 ia = ia->ia_next; 422 if (ia->ia_next) 423 ia->ia_next = oia->ia_next; 424 else 425 printf("Didn't unlink inifadr from list\n"); 426 } 427 IFAFREE((&oia->ia_ifa)); 428 break; 429 430 default: 431 if (ifp == 0 || ifp->if_ioctl == 0) 432 return (EOPNOTSUPP); 433 return ((*ifp->if_ioctl)(ifp, cmd, data)); 434 } 435 return (0); 436 } 437 438 /* 439 * Delete any existing route for an interface. 440 */ 441 in_ifscrub(ifp, ia) 442 register struct ifnet *ifp; 443 register struct in_ifaddr *ia; 444 { 445 446 if ((ia->ia_flags & IFA_ROUTE) == 0) 447 return; 448 if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT)) 449 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 450 else 451 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0); 452 ia->ia_flags &= ~IFA_ROUTE; 453 } 454 455 /* 456 * Initialize an interface's internet address 457 * and routing table entry. 458 */ 459 in_ifinit(ifp, ia, sin, scrub) 460 register struct ifnet *ifp; 461 register struct in_ifaddr *ia; 462 struct sockaddr_in *sin; 463 { 464 register u_long i = ntohl(sin->sin_addr.s_addr); 465 struct sockaddr_in oldaddr; 466 int s = splimp(), error, flags = RTF_UP; 467 int ether_output(), arp_rtrequest(); 468 469 oldaddr = ia->ia_addr; 470 ia->ia_addr = *sin; 471 /* 472 * Give the interface a chance to initialize 473 * if this is its first address, 474 * and to validate the address if necessary. 475 */ 476 if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { 477 splx(s); 478 ia->ia_addr = oldaddr; 479 return (error); 480 } 481 if (ifp->if_output == ether_output) { /* XXX: Another Kludge */ 482 ia->ia_ifa.ifa_rtrequest = arp_rtrequest; 483 ia->ia_ifa.ifa_flags |= RTF_CLONING; 484 } 485 splx(s); 486 if (scrub) { 487 ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr; 488 in_ifscrub(ifp, ia); 489 ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 490 } 491 if (IN_CLASSA(i)) 492 ia->ia_netmask = IN_CLASSA_NET; 493 else if (IN_CLASSB(i)) 494 ia->ia_netmask = IN_CLASSB_NET; 495 else 496 ia->ia_netmask = IN_CLASSC_NET; 497 ia->ia_net = i & ia->ia_netmask; 498 /* 499 * The subnet mask includes at least the standard network part, 500 * but may already have been set to a larger value. 501 */ 502 ia->ia_subnetmask |= ia->ia_netmask; 503 ia->ia_subnet = i & ia->ia_subnetmask; 504 ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask); 505 { 506 register char *cp = (char *) (1 + &(ia->ia_sockmask.sin_addr)); 507 register char *cpbase = (char *) &(ia->ia_sockmask.sin_addr); 508 while (--cp >= cpbase) 509 if (*cp) { 510 ia->ia_sockmask.sin_len = 511 1 + cp - (char *) &(ia->ia_sockmask); 512 break; 513 } 514 } 515 /* 516 * Add route for the network. 517 */ 518 if (ifp->if_flags & IFF_BROADCAST) { 519 ia->ia_broadaddr.sin_addr = 520 in_makeaddr(ia->ia_subnet, INADDR_BROADCAST); 521 ia->ia_netbroadcast.s_addr = 522 htonl(ia->ia_net | (INADDR_BROADCAST &~ ia->ia_netmask)); 523 } else if (ifp->if_flags & IFF_LOOPBACK) { 524 ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr; 525 flags |= RTF_HOST; 526 } else if (ifp->if_flags & IFF_POINTOPOINT) { 527 if (ia->ia_dstaddr.sin_family != AF_INET) 528 return (0); 529 flags |= RTF_HOST; 530 } 531 if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, flags)) == 0) 532 ia->ia_flags |= IFA_ROUTE; 533 return (error); 534 } 535 536 /* 537 * Return address info for specified internet network. 538 */ 539 struct in_ifaddr * 540 in_iaonnetof(net) 541 u_long net; 542 { 543 register struct in_ifaddr *ia; 544 545 for (ia = in_ifaddr; ia; ia = ia->ia_next) 546 if (ia->ia_subnet == net) 547 return (ia); 548 return ((struct in_ifaddr *)0); 549 } 550 551 /* 552 * Return 1 if the address might be a local broadcast address. 553 */ 554 in_broadcast(in) 555 struct in_addr in; 556 { 557 register struct in_ifaddr *ia; 558 u_long t; 559 560 /* 561 * Look through the list of addresses for a match 562 * with a broadcast address. 563 */ 564 for (ia = in_ifaddr; ia; ia = ia->ia_next) 565 if (ia->ia_ifp->if_flags & IFF_BROADCAST) { 566 if (ia->ia_broadaddr.sin_addr.s_addr == in.s_addr) 567 return (1); 568 /* 569 * Check for old-style (host 0) broadcast. 570 */ 571 if ((t = ntohl(in.s_addr)) == ia->ia_subnet || t == ia->ia_net) 572 return (1); 573 } 574 if (in.s_addr == INADDR_BROADCAST || in.s_addr == INADDR_ANY) 575 return (1); 576 return (0); 577 } 578 #endif 579