1 /* 2 * Copyright (c) 1982, 1986 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)in.c 7.15 (Berkeley) 06/28/90 8 */ 9 10 #include "param.h" 11 #include "ioctl.h" 12 #include "mbuf.h" 13 #include "protosw.h" 14 #include "socket.h" 15 #include "socketvar.h" 16 #include "user.h" 17 #include "in_systm.h" 18 #include "../net/if.h" 19 #include "../net/route.h" 20 #include "../net/af.h" 21 #include "in.h" 22 #include "in_var.h" 23 24 #ifdef INET 25 /* 26 * Formulate an Internet address from network + host. 27 */ 28 struct in_addr 29 in_makeaddr(net, host) 30 u_long net, host; 31 { 32 register struct in_ifaddr *ia; 33 register u_long mask; 34 u_long addr; 35 36 if (IN_CLASSA(net)) 37 mask = IN_CLASSA_HOST; 38 else if (IN_CLASSB(net)) 39 mask = IN_CLASSB_HOST; 40 else 41 mask = IN_CLASSC_HOST; 42 for (ia = in_ifaddr; ia; ia = ia->ia_next) 43 if ((ia->ia_netmask & net) == ia->ia_net) { 44 mask = ~ia->ia_subnetmask; 45 break; 46 } 47 addr = htonl(net | (host & mask)); 48 return (*(struct in_addr *)&addr); 49 } 50 51 /* 52 * Return the network number from an internet address. 53 */ 54 u_long 55 in_netof(in) 56 struct in_addr in; 57 { 58 register u_long i = ntohl(in.s_addr); 59 register u_long net; 60 register struct in_ifaddr *ia; 61 62 if (IN_CLASSA(i)) 63 net = i & IN_CLASSA_NET; 64 else if (IN_CLASSB(i)) 65 net = i & IN_CLASSB_NET; 66 else if (IN_CLASSC(i)) 67 net = i & IN_CLASSC_NET; 68 else 69 return (0); 70 71 /* 72 * Check whether network is a subnet; 73 * if so, return subnet number. 74 */ 75 for (ia = in_ifaddr; ia; ia = ia->ia_next) 76 if (net == ia->ia_net) 77 return (i & ia->ia_subnetmask); 78 return (net); 79 } 80 81 /* 82 * Compute and save network mask as sockaddr from an internet address. 83 */ 84 in_sockmaskof(in, sockmask) 85 struct in_addr in; 86 register struct sockaddr_in *sockmask; 87 { 88 register u_long net; 89 register u_long mask; 90 { 91 register u_long i = ntohl(in.s_addr); 92 93 if (i == 0) 94 net = 0, mask = 0; 95 else if (IN_CLASSA(i)) 96 net = i & IN_CLASSA_NET, mask = IN_CLASSA_NET; 97 else if (IN_CLASSB(i)) 98 net = i & IN_CLASSB_NET, mask = IN_CLASSB_NET; 99 else if (IN_CLASSC(i)) 100 net = i & IN_CLASSC_NET, mask = IN_CLASSC_NET; 101 else 102 net = i, mask = -1; 103 } 104 { 105 register struct in_ifaddr *ia; 106 /* 107 * Check whether network is a subnet; 108 * if so, return subnet number. 109 */ 110 for (ia = in_ifaddr; ia; ia = ia->ia_next) 111 if (net == ia->ia_net) 112 mask = ia->ia_subnetmask; 113 } 114 { 115 register char *cpbase = (char *)&(sockmask->sin_addr); 116 register char *cp = (char *)(1 + &(sockmask->sin_addr)); 117 118 sockmask->sin_addr.s_addr = htonl(mask); 119 sockmask->sin_len = 0; 120 while (--cp >= cpbase) 121 if (*cp) { 122 sockmask->sin_len = 1 + cp - (caddr_t)sockmask; 123 break; 124 } 125 } 126 } 127 128 /* 129 * Return the host portion of an internet address. 130 */ 131 u_long 132 in_lnaof(in) 133 struct in_addr in; 134 { 135 register u_long i = ntohl(in.s_addr); 136 register u_long net, host; 137 register struct in_ifaddr *ia; 138 139 if (IN_CLASSA(i)) { 140 net = i & IN_CLASSA_NET; 141 host = i & IN_CLASSA_HOST; 142 } else if (IN_CLASSB(i)) { 143 net = i & IN_CLASSB_NET; 144 host = i & IN_CLASSB_HOST; 145 } else if (IN_CLASSC(i)) { 146 net = i & IN_CLASSC_NET; 147 host = i & IN_CLASSC_HOST; 148 } else 149 return (i); 150 151 /* 152 * Check whether network is a subnet; 153 * if so, use the modified interpretation of `host'. 154 */ 155 for (ia = in_ifaddr; ia; ia = ia->ia_next) 156 if (net == ia->ia_net) 157 return (host &~ ia->ia_subnetmask); 158 return (host); 159 } 160 161 #ifndef SUBNETSARELOCAL 162 #define SUBNETSARELOCAL 1 163 #endif 164 int subnetsarelocal = SUBNETSARELOCAL; 165 /* 166 * Return 1 if an internet address is for a ``local'' host 167 * (one to which we have a connection). If subnetsarelocal 168 * is true, this includes other subnets of the local net. 169 * Otherwise, it includes only the directly-connected (sub)nets. 170 */ 171 in_localaddr(in) 172 struct in_addr in; 173 { 174 register u_long i = ntohl(in.s_addr); 175 register struct in_ifaddr *ia; 176 177 if (subnetsarelocal) { 178 for (ia = in_ifaddr; ia; ia = ia->ia_next) 179 if ((i & ia->ia_netmask) == ia->ia_net) 180 return (1); 181 } else { 182 for (ia = in_ifaddr; ia; ia = ia->ia_next) 183 if ((i & ia->ia_subnetmask) == ia->ia_subnet) 184 return (1); 185 } 186 return (0); 187 } 188 189 /* 190 * Determine whether an IP address is in a reserved set of addresses 191 * that may not be forwarded, or whether datagrams to that destination 192 * may be forwarded. 193 */ 194 in_canforward(in) 195 struct in_addr in; 196 { 197 register u_long i = ntohl(in.s_addr); 198 register u_long net; 199 200 if (IN_EXPERIMENTAL(i)) 201 return (0); 202 if (IN_CLASSA(i)) { 203 net = i & IN_CLASSA_NET; 204 if (net == 0 || net == IN_LOOPBACKNET) 205 return (0); 206 } 207 return (1); 208 } 209 210 int in_interfaces; /* number of external internet interfaces */ 211 extern struct ifnet loif; 212 213 /* 214 * Generic internet control operations (ioctl's). 215 * Ifp is 0 if not an interface-specific ioctl. 216 */ 217 /* ARGSUSED */ 218 in_control(so, cmd, data, ifp) 219 struct socket *so; 220 int cmd; 221 caddr_t data; 222 register struct ifnet *ifp; 223 { 224 register struct ifreq *ifr = (struct ifreq *)data; 225 register struct in_ifaddr *ia = 0; 226 register struct ifaddr *ifa; 227 struct in_ifaddr *oia; 228 struct in_aliasreq *ifra = (struct in_aliasreq *)data; 229 struct mbuf *m; 230 struct sockaddr_in oldaddr; 231 int error, hostIsNew, maskIsNew; 232 u_long i; 233 234 /* 235 * Find address for this interface, if it exists. 236 */ 237 if (ifp) 238 for (ia = in_ifaddr; ia; ia = ia->ia_next) 239 if (ia->ia_ifp == ifp) 240 break; 241 242 switch (cmd) { 243 244 case SIOCAIFADDR: 245 case SIOCDIFADDR: 246 if (ifra->ifra_addr.sin_family == AF_INET) 247 for (oia = ia; ia; ia = ia->ia_next) { 248 if (ia->ia_ifp == ifp && 249 ia->ia_addr.sin_addr.s_addr == 250 ifra->ifra_addr.sin_addr.s_addr) 251 break; 252 } 253 if (cmd == SIOCDIFADDR && ia == 0) 254 return (EADDRNOTAVAIL); 255 /* FALLTHROUGH */ 256 case SIOCSIFADDR: 257 case SIOCSIFNETMASK: 258 case SIOCSIFDSTADDR: 259 if (error = suser(u.u_cred, &u.u_acflag)) 260 return (error); 261 262 if (ifp == 0) 263 panic("in_control"); 264 if (ia == (struct in_ifaddr *)0) { 265 m = m_getclr(M_WAIT, MT_IFADDR); 266 if (m == (struct mbuf *)NULL) 267 return (ENOBUFS); 268 if (ia = in_ifaddr) { 269 for ( ; ia->ia_next; ia = ia->ia_next) 270 ; 271 ia->ia_next = mtod(m, struct in_ifaddr *); 272 } else 273 in_ifaddr = mtod(m, struct in_ifaddr *); 274 ia = mtod(m, struct in_ifaddr *); 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 (error = suser(u.u_cred, &u.u_acflag)) 299 return (error); 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 = (struct sockaddr *)&ia->ia_addr; 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; 466 467 oldaddr = ia->ia_addr; 468 ia->ia_addr = *sin; 469 /* 470 * Give the interface a chance to initialize 471 * if this is its first address, 472 * and to validate the address if necessary. 473 */ 474 if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { 475 splx(s); 476 ia->ia_addr = oldaddr; 477 return (error); 478 } 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 if (ifp->if_flags & IFF_BROADCAST) { 509 ia->ia_broadaddr.sin_addr = 510 in_makeaddr(ia->ia_subnet, INADDR_BROADCAST); 511 ia->ia_netbroadcast.s_addr = 512 htonl(ia->ia_net | (INADDR_BROADCAST &~ ia->ia_netmask)); 513 } 514 /* 515 * Add route for the network. 516 */ 517 if (ifp->if_flags & IFF_LOOPBACK) { 518 ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr; 519 rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 520 } else if (ifp->if_flags & IFF_POINTOPOINT && 521 ia->ia_dstaddr.sin_family == AF_INET) 522 rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 523 else { 524 rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP); 525 } 526 ia->ia_flags |= IFA_ROUTE; 527 splx(s); 528 return (0); 529 } 530 531 /* 532 * Return address info for specified internet network. 533 */ 534 struct in_ifaddr * 535 in_iaonnetof(net) 536 u_long net; 537 { 538 register struct in_ifaddr *ia; 539 540 for (ia = in_ifaddr; ia; ia = ia->ia_next) 541 if (ia->ia_subnet == net) 542 return (ia); 543 return ((struct in_ifaddr *)0); 544 } 545 546 /* 547 * Return 1 if the address might be a local broadcast address. 548 */ 549 in_broadcast(in) 550 struct in_addr in; 551 { 552 register struct in_ifaddr *ia; 553 u_long t; 554 555 /* 556 * Look through the list of addresses for a match 557 * with a broadcast address. 558 */ 559 for (ia = in_ifaddr; ia; ia = ia->ia_next) 560 if (ia->ia_ifp->if_flags & IFF_BROADCAST) { 561 if (ia->ia_broadaddr.sin_addr.s_addr == in.s_addr) 562 return (1); 563 /* 564 * Check for old-style (host 0) broadcast. 565 */ 566 if ((t = ntohl(in.s_addr)) == ia->ia_subnet || t == ia->ia_net) 567 return (1); 568 } 569 if (in.s_addr == INADDR_BROADCAST || in.s_addr == INADDR_ANY) 570 return (1); 571 return (0); 572 } 573 #endif 574