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.18 (Berkeley) 06/25/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 mbuf *m; 229 struct sockaddr_in oldaddr; 230 int error, hostIsNew, maskIsNew; 231 u_long i; 232 233 /* 234 * Find address for this interface, if it exists. 235 */ 236 if (ifp) 237 for (ia = in_ifaddr; ia; ia = ia->ia_next) 238 if (ia->ia_ifp == ifp) 239 break; 240 241 switch (cmd) { 242 243 case SIOCAIFADDR: 244 case SIOCDIFADDR: 245 if (ifra->ifra_addr.sin_family == AF_INET) 246 for (oia = ia; ia; ia = ia->ia_next) { 247 if (ia->ia_ifp == ifp && 248 ia->ia_addr.sin_addr.s_addr == 249 ifra->ifra_addr.sin_addr.s_addr) 250 break; 251 } 252 if (cmd == SIOCDIFADDR && ia == 0) 253 return (EADDRNOTAVAIL); 254 /* FALLTHROUGH */ 255 case SIOCSIFADDR: 256 case SIOCSIFNETMASK: 257 case SIOCSIFDSTADDR: 258 if ((so->so_state & SS_PRIV) == 0) 259 return (EPERM); 260 261 if (ifp == 0) 262 panic("in_control"); 263 if (ia == (struct in_ifaddr *)0) { 264 m = m_getclr(M_WAIT, MT_IFADDR); 265 if (m == (struct mbuf *)NULL) 266 return (ENOBUFS); 267 if (ia = in_ifaddr) { 268 for ( ; ia->ia_next; ia = ia->ia_next) 269 ; 270 ia->ia_next = mtod(m, struct in_ifaddr *); 271 } else 272 in_ifaddr = mtod(m, struct in_ifaddr *); 273 ia = mtod(m, struct in_ifaddr *); 274 if (ifa = ifp->if_addrlist) { 275 for ( ; ifa->ifa_next; ifa = ifa->ifa_next) 276 ; 277 ifa->ifa_next = (struct ifaddr *) ia; 278 } else 279 ifp->if_addrlist = (struct ifaddr *) ia; 280 ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 281 ia->ia_ifa.ifa_dstaddr 282 = (struct sockaddr *)&ia->ia_dstaddr; 283 ia->ia_ifa.ifa_netmask 284 = (struct sockaddr *)&ia->ia_sockmask; 285 ia->ia_sockmask.sin_len = 8; 286 if (ifp->if_flags & IFF_BROADCAST) { 287 ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr); 288 ia->ia_broadaddr.sin_family = AF_INET; 289 } 290 ia->ia_ifp = ifp; 291 if (ifp != &loif) 292 in_interfaces++; 293 } 294 break; 295 296 case SIOCSIFBRDADDR: 297 if ((so->so_state & SS_PRIV) == 0) 298 return (EPERM); 299 /* FALLTHROUGH */ 300 301 case SIOCGIFADDR: 302 case SIOCGIFNETMASK: 303 case SIOCGIFDSTADDR: 304 case SIOCGIFBRDADDR: 305 if (ia == (struct in_ifaddr *)0) 306 return (EADDRNOTAVAIL); 307 break; 308 309 default: 310 return (EOPNOTSUPP); 311 break; 312 } 313 switch (cmd) { 314 315 case SIOCGIFADDR: 316 *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr; 317 break; 318 319 case SIOCGIFBRDADDR: 320 if ((ifp->if_flags & IFF_BROADCAST) == 0) 321 return (EINVAL); 322 *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr; 323 break; 324 325 case SIOCGIFDSTADDR: 326 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 327 return (EINVAL); 328 *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr; 329 break; 330 331 case SIOCGIFNETMASK: 332 *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask; 333 break; 334 335 case SIOCSIFDSTADDR: 336 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 337 return (EINVAL); 338 oldaddr = ia->ia_dstaddr; 339 ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr; 340 if (ifp->if_ioctl && 341 (error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia))) { 342 ia->ia_dstaddr = oldaddr; 343 return (error); 344 } 345 if (ia->ia_flags & IFA_ROUTE) { 346 ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr; 347 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 348 ia->ia_ifa.ifa_dstaddr = 349 (struct sockaddr *)&ia->ia_dstaddr; 350 rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 351 } 352 break; 353 354 case SIOCSIFBRDADDR: 355 if ((ifp->if_flags & IFF_BROADCAST) == 0) 356 return (EINVAL); 357 ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr; 358 break; 359 360 case SIOCSIFADDR: 361 return (in_ifinit(ifp, ia, 362 (struct sockaddr_in *) &ifr->ifr_addr, 1)); 363 364 case SIOCSIFNETMASK: 365 i = ifra->ifra_addr.sin_addr.s_addr; 366 ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr = i); 367 break; 368 369 case SIOCAIFADDR: 370 maskIsNew = 0; 371 hostIsNew = 1; 372 error = 0; 373 if (ia->ia_addr.sin_family == AF_INET) { 374 if (ifra->ifra_addr.sin_len == 0) { 375 ifra->ifra_addr = ia->ia_addr; 376 hostIsNew = 0; 377 } else if (ifra->ifra_addr.sin_addr.s_addr == 378 ia->ia_addr.sin_addr.s_addr) 379 hostIsNew = 0; 380 } 381 if (ifra->ifra_mask.sin_len) { 382 in_ifscrub(ifp, ia); 383 ia->ia_sockmask = ifra->ifra_mask; 384 ia->ia_subnetmask = 385 ntohl(ia->ia_sockmask.sin_addr.s_addr); 386 maskIsNew = 1; 387 } 388 if ((ifp->if_flags & IFF_POINTOPOINT) && 389 (ifra->ifra_dstaddr.sin_family == AF_INET)) { 390 in_ifscrub(ifp, ia); 391 ia->ia_dstaddr = ifra->ifra_dstaddr; 392 maskIsNew = 1; /* We lie; but the effect's the same */ 393 } 394 if (ifra->ifra_addr.sin_family == AF_INET && 395 (hostIsNew || maskIsNew)) 396 error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0); 397 if ((ifp->if_flags & IFF_BROADCAST) && 398 (ifra->ifra_broadaddr.sin_family == AF_INET)) 399 ia->ia_broadaddr = ifra->ifra_broadaddr; 400 return (error); 401 402 case SIOCDIFADDR: 403 in_ifscrub(ifp, ia); 404 if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia) 405 ifp->if_addrlist = ifa->ifa_next; 406 else { 407 while (ifa->ifa_next && 408 (ifa->ifa_next != (struct ifaddr *)ia)) 409 ifa = ifa->ifa_next; 410 if (ifa->ifa_next) 411 ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next; 412 else 413 printf("Couldn't unlink inifaddr from ifp\n"); 414 } 415 oia = ia; 416 if (oia == (ia = in_ifaddr)) 417 in_ifaddr = ia->ia_next; 418 else { 419 while (ia->ia_next && (ia->ia_next != oia)) 420 ia = ia->ia_next; 421 if (ia->ia_next) 422 ia->ia_next = oia->ia_next; 423 else 424 printf("Didn't unlink inifadr from list\n"); 425 } 426 (void) m_free(dtom(oia)); 427 break; 428 429 default: 430 if (ifp == 0 || ifp->if_ioctl == 0) 431 return (EOPNOTSUPP); 432 return ((*ifp->if_ioctl)(ifp, cmd, data)); 433 } 434 return (0); 435 } 436 437 /* 438 * Delete any existing route for an interface. 439 */ 440 in_ifscrub(ifp, ia) 441 register struct ifnet *ifp; 442 register struct in_ifaddr *ia; 443 { 444 445 if ((ia->ia_flags & IFA_ROUTE) == 0) 446 return; 447 if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT)) 448 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 449 else 450 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0); 451 ia->ia_flags &= ~IFA_ROUTE; 452 } 453 454 /* 455 * Initialize an interface's internet address 456 * and routing table entry. 457 */ 458 in_ifinit(ifp, ia, sin, scrub) 459 register struct ifnet *ifp; 460 register struct in_ifaddr *ia; 461 struct sockaddr_in *sin; 462 { 463 register u_long i = ntohl(sin->sin_addr.s_addr); 464 struct sockaddr_in oldaddr; 465 int s = splimp(), error, flags = RTF_UP; 466 int ether_output(), arp_rtrequest(); 467 468 oldaddr = ia->ia_addr; 469 ia->ia_addr = *sin; 470 /* 471 * Give the interface a chance to initialize 472 * if this is its first address, 473 * and to validate the address if necessary. 474 */ 475 if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { 476 splx(s); 477 ia->ia_addr = oldaddr; 478 return (error); 479 } 480 if (ifp->if_output == ether_output) { /* XXX: Another Kludge */ 481 ia->ia_ifa.ifa_rtrequest = arp_rtrequest; 482 ia->ia_ifa.ifa_flags |= RTF_CLONING; 483 } 484 splx(s); 485 if (scrub) { 486 ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr; 487 in_ifscrub(ifp, ia); 488 ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 489 } 490 if (IN_CLASSA(i)) 491 ia->ia_netmask = IN_CLASSA_NET; 492 else if (IN_CLASSB(i)) 493 ia->ia_netmask = IN_CLASSB_NET; 494 else 495 ia->ia_netmask = IN_CLASSC_NET; 496 ia->ia_net = i & ia->ia_netmask; 497 /* 498 * The subnet mask includes at least the standard network part, 499 * but may already have been set to a larger value. 500 */ 501 ia->ia_subnetmask |= ia->ia_netmask; 502 ia->ia_subnet = i & ia->ia_subnetmask; 503 ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask); 504 { 505 register char *cp = (char *) (1 + &(ia->ia_sockmask.sin_addr)); 506 register char *cpbase = (char *) &(ia->ia_sockmask.sin_addr); 507 while (--cp >= cpbase) 508 if (*cp) { 509 ia->ia_sockmask.sin_len = 510 1 + cp - (char *) &(ia->ia_sockmask); 511 break; 512 } 513 } 514 /* 515 * Add route for the network. 516 */ 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