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