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