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.16 (Berkeley) 10/31/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 = 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 (void) m_free(dtom(oia)); 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 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 splx(s); 481 if (scrub) { 482 ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr; 483 in_ifscrub(ifp, ia); 484 ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 485 } 486 if (IN_CLASSA(i)) 487 ia->ia_netmask = IN_CLASSA_NET; 488 else if (IN_CLASSB(i)) 489 ia->ia_netmask = IN_CLASSB_NET; 490 else 491 ia->ia_netmask = IN_CLASSC_NET; 492 ia->ia_net = i & ia->ia_netmask; 493 /* 494 * The subnet mask includes at least the standard network part, 495 * but may already have been set to a larger value. 496 */ 497 ia->ia_subnetmask |= ia->ia_netmask; 498 ia->ia_subnet = i & ia->ia_subnetmask; 499 ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask); 500 { 501 register char *cp = (char *) (1 + &(ia->ia_sockmask.sin_addr)); 502 register char *cpbase = (char *) &(ia->ia_sockmask.sin_addr); 503 while (--cp >= cpbase) 504 if (*cp) { 505 ia->ia_sockmask.sin_len = 506 1 + cp - (char *) &(ia->ia_sockmask); 507 break; 508 } 509 } 510 /* 511 * Add route for the network. 512 */ 513 if (ifp->if_flags & IFF_BROADCAST) { 514 ia->ia_broadaddr.sin_addr = 515 in_makeaddr(ia->ia_subnet, INADDR_BROADCAST); 516 ia->ia_netbroadcast.s_addr = 517 htonl(ia->ia_net | (INADDR_BROADCAST &~ ia->ia_netmask)); 518 } else if (ifp->if_flags & IFF_LOOPBACK) { 519 ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr; 520 flags |= RTF_HOST; 521 } else if (ifp->if_flags & IFF_POINTOPOINT) { 522 if (ia->ia_dstaddr.sin_family != AF_INET) 523 return (0); 524 flags |= RTF_HOST; 525 } 526 if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, flags)) == 0) 527 ia->ia_flags |= IFA_ROUTE; 528 return (error); 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