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