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.12 (Berkeley) 05/05/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 "user.h" 27 #include "in_systm.h" 28 #include "../net/if.h" 29 #include "../net/route.h" 30 #include "../net/af.h" 31 #include "in.h" 32 #include "in_var.h" 33 34 #ifdef INET 35 /* 36 * Formulate an Internet address from network + host. 37 */ 38 struct in_addr 39 in_makeaddr(net, host) 40 u_long net, host; 41 { 42 register struct in_ifaddr *ia; 43 register u_long mask; 44 u_long addr; 45 46 if (IN_CLASSA(net)) 47 mask = IN_CLASSA_HOST; 48 else if (IN_CLASSB(net)) 49 mask = IN_CLASSB_HOST; 50 else 51 mask = IN_CLASSC_HOST; 52 for (ia = in_ifaddr; ia; ia = ia->ia_next) 53 if ((ia->ia_netmask & net) == ia->ia_net) { 54 mask = ~ia->ia_subnetmask; 55 break; 56 } 57 addr = htonl(net | (host & mask)); 58 return (*(struct in_addr *)&addr); 59 } 60 61 /* 62 * Return the network number from an internet address. 63 */ 64 u_long 65 in_netof(in) 66 struct in_addr in; 67 { 68 register u_long i = ntohl(in.s_addr); 69 register u_long net; 70 register struct in_ifaddr *ia; 71 72 if (IN_CLASSA(i)) 73 net = i & IN_CLASSA_NET; 74 else if (IN_CLASSB(i)) 75 net = i & IN_CLASSB_NET; 76 else if (IN_CLASSC(i)) 77 net = i & IN_CLASSC_NET; 78 else 79 return (0); 80 81 /* 82 * Check whether network is a subnet; 83 * if so, return subnet number. 84 */ 85 for (ia = in_ifaddr; ia; ia = ia->ia_next) 86 if (net == ia->ia_net) 87 return (i & ia->ia_subnetmask); 88 return (net); 89 } 90 91 /* 92 * Compute and save network mask as sockaddr from an internet address. 93 */ 94 in_sockmaskof(in, sockmask) 95 struct in_addr in; 96 register struct sockaddr_in *sockmask; 97 { 98 register u_long net; 99 register u_long mask; 100 { 101 register u_long i = ntohl(in.s_addr); 102 103 if (i == 0) 104 net = 0, mask = 0; 105 else if (IN_CLASSA(i)) 106 net = i & IN_CLASSA_NET, mask = IN_CLASSA_NET; 107 else if (IN_CLASSB(i)) 108 net = i & IN_CLASSB_NET, mask = IN_CLASSB_NET; 109 else if (IN_CLASSC(i)) 110 net = i & IN_CLASSC_NET, mask = IN_CLASSC_NET; 111 else 112 net = i, mask = -1; 113 } 114 { 115 register struct in_ifaddr *ia; 116 /* 117 * Check whether network is a subnet; 118 * if so, return subnet number. 119 */ 120 for (ia = in_ifaddr; ia; ia = ia->ia_next) 121 if (net == ia->ia_net) 122 mask = ia->ia_subnetmask; 123 } 124 { 125 register char *cp = (char *)&(sockmask->sin_port); 126 register char *cpbase = (char *)&(sockmask->sin_addr); 127 128 sockmask->sin_addr.s_addr = htonl(mask); 129 sockmask->sin_len = 0; 130 while (--cp >= cpbase) 131 if (*cp) { 132 sockmask->sin_len = 1 + cp - (caddr_t)sockmask; 133 break; 134 } 135 } 136 } 137 138 /* 139 * Return the host portion of an internet address. 140 */ 141 u_long 142 in_lnaof(in) 143 struct in_addr in; 144 { 145 register u_long i = ntohl(in.s_addr); 146 register u_long net, host; 147 register struct in_ifaddr *ia; 148 149 if (IN_CLASSA(i)) { 150 net = i & IN_CLASSA_NET; 151 host = i & IN_CLASSA_HOST; 152 } else if (IN_CLASSB(i)) { 153 net = i & IN_CLASSB_NET; 154 host = i & IN_CLASSB_HOST; 155 } else if (IN_CLASSC(i)) { 156 net = i & IN_CLASSC_NET; 157 host = i & IN_CLASSC_HOST; 158 } else 159 return (i); 160 161 /* 162 * Check whether network is a subnet; 163 * if so, use the modified interpretation of `host'. 164 */ 165 for (ia = in_ifaddr; ia; ia = ia->ia_next) 166 if (net == ia->ia_net) 167 return (host &~ ia->ia_subnetmask); 168 return (host); 169 } 170 171 #ifndef SUBNETSARELOCAL 172 #define SUBNETSARELOCAL 1 173 #endif 174 int subnetsarelocal = SUBNETSARELOCAL; 175 /* 176 * Return 1 if an internet address is for a ``local'' host 177 * (one to which we have a connection). If subnetsarelocal 178 * is true, this includes other subnets of the local net. 179 * Otherwise, it includes only the directly-connected (sub)nets. 180 */ 181 in_localaddr(in) 182 struct in_addr in; 183 { 184 register u_long i = ntohl(in.s_addr); 185 register struct in_ifaddr *ia; 186 187 if (subnetsarelocal) { 188 for (ia = in_ifaddr; ia; ia = ia->ia_next) 189 if ((i & ia->ia_netmask) == ia->ia_net) 190 return (1); 191 } else { 192 for (ia = in_ifaddr; ia; ia = ia->ia_next) 193 if ((i & ia->ia_subnetmask) == ia->ia_subnet) 194 return (1); 195 } 196 return (0); 197 } 198 199 /* 200 * Determine whether an IP address is in a reserved set of addresses 201 * that may not be forwarded, or whether datagrams to that destination 202 * may be forwarded. 203 */ 204 in_canforward(in) 205 struct in_addr in; 206 { 207 register u_long i = ntohl(in.s_addr); 208 register u_long net; 209 210 if (IN_EXPERIMENTAL(i)) 211 return (0); 212 if (IN_CLASSA(i)) { 213 net = i & IN_CLASSA_NET; 214 if (net == 0 || net == IN_LOOPBACKNET) 215 return (0); 216 } 217 return (1); 218 } 219 220 int in_interfaces; /* number of external internet interfaces */ 221 extern struct ifnet loif; 222 223 /* 224 * Generic internet control operations (ioctl's). 225 * Ifp is 0 if not an interface-specific ioctl. 226 */ 227 /* ARGSUSED */ 228 in_control(so, cmd, data, ifp) 229 struct socket *so; 230 int cmd; 231 caddr_t data; 232 register struct ifnet *ifp; 233 { 234 register struct ifreq *ifr = (struct ifreq *)data; 235 register struct in_ifaddr *ia = 0; 236 register struct ifaddr *ifa; 237 struct in_ifaddr *oia; 238 struct in_aliasreq *ifra = (struct in_aliasreq *)data; 239 struct mbuf *m; 240 struct sockaddr_in oldaddr; 241 int error, hostIsNew, maskIsNew; 242 u_long i; 243 244 /* 245 * Find address for this interface, if it exists. 246 */ 247 if (ifp) 248 for (ia = in_ifaddr; ia; ia = ia->ia_next) 249 if (ia->ia_ifp == ifp) 250 break; 251 252 switch (cmd) { 253 254 case SIOCAIFADDR: 255 case SIOCDIFADDR: 256 if (ifra->ifra_addr.sin_family == AF_INET) 257 for (oia = ia; ia; ia = ia->ia_next) { 258 if (ia->ia_ifp == ifp && 259 ia->ia_addr.sin_addr.s_addr == 260 ifra->ifra_addr.sin_addr.s_addr) 261 break; 262 } 263 if (cmd == SIOCDIFADDR && ia == 0) 264 return (EADDRNOTAVAIL); 265 /* FALLTHROUGH */ 266 case SIOCSIFADDR: 267 case SIOCSIFNETMASK: 268 case SIOCSIFDSTADDR: 269 if (error = suser(u.u_cred, &u.u_acflag)) 270 return (error); 271 272 if (ifp == 0) 273 panic("in_control"); 274 if (ia == (struct in_ifaddr *)0) { 275 m = m_getclr(M_WAIT, MT_IFADDR); 276 if (m == (struct mbuf *)NULL) 277 return (ENOBUFS); 278 if (ia = in_ifaddr) { 279 for ( ; ia->ia_next; ia = ia->ia_next) 280 ; 281 ia->ia_next = mtod(m, struct in_ifaddr *); 282 } else 283 in_ifaddr = mtod(m, struct in_ifaddr *); 284 ia = mtod(m, struct in_ifaddr *); 285 if (ifa = ifp->if_addrlist) { 286 for ( ; ifa->ifa_next; ifa = ifa->ifa_next) 287 ; 288 ifa->ifa_next = (struct ifaddr *) ia; 289 } else 290 ifp->if_addrlist = (struct ifaddr *) ia; 291 ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; 292 ia->ia_ifa.ifa_dstaddr 293 = (struct sockaddr *)&ia->ia_dstaddr; 294 ia->ia_ifa.ifa_netmask 295 = (struct sockaddr *)&ia->ia_sockmask; 296 ia->ia_sockmask.sin_len = 8; 297 if (ifp->if_flags & IFF_BROADCAST) { 298 ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr); 299 ia->ia_broadaddr.sin_family = AF_INET; 300 } 301 ia->ia_ifp = ifp; 302 if (ifp != &loif) 303 in_interfaces++; 304 } 305 break; 306 307 case SIOCSIFBRDADDR: 308 if (error = suser(u.u_cred, &u.u_acflag)) 309 return (error); 310 /* FALLTHROUGH */ 311 312 default: 313 if (ia == (struct in_ifaddr *)0) 314 return (EADDRNOTAVAIL); 315 break; 316 } 317 switch (cmd) { 318 319 case SIOCGIFADDR: 320 *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr; 321 break; 322 323 case SIOCGIFBRDADDR: 324 if ((ifp->if_flags & IFF_BROADCAST) == 0) 325 return (EINVAL); 326 *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr; 327 break; 328 329 case SIOCGIFDSTADDR: 330 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 331 return (EINVAL); 332 *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr; 333 break; 334 335 case SIOCGIFNETMASK: 336 *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask; 337 break; 338 339 case SIOCSIFDSTADDR: 340 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 341 return (EINVAL); 342 oldaddr = ia->ia_dstaddr; 343 ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr; 344 if (ifp->if_ioctl && 345 (error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia))) { 346 ia->ia_dstaddr = oldaddr; 347 return (error); 348 } 349 if (ia->ia_flags & IFA_ROUTE) { 350 ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr; 351 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 352 ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&ia->ia_addr; 353 rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 354 } 355 break; 356 357 case SIOCSIFBRDADDR: 358 if ((ifp->if_flags & IFF_BROADCAST) == 0) 359 return (EINVAL); 360 ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr; 361 break; 362 363 case SIOCSIFADDR: 364 return (in_ifinit(ifp, ia, 365 (struct sockaddr_in *) &ifr->ifr_addr, 1)); 366 367 case SIOCSIFNETMASK: 368 i = ifra->ifra_addr.sin_addr.s_addr; 369 ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr = i); 370 break; 371 372 case SIOCAIFADDR: 373 maskIsNew = 0; hostIsNew = 1; error = u.u_error; 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 } 423 if (ia->ia_next) 424 ia->ia_next = oia->ia_next; 425 else 426 printf("Didn't unlink inifadr from list\n"); 427 } 428 (void) m_free(dtom(oia)); 429 break; 430 431 default: 432 if (ifp == 0 || ifp->if_ioctl == 0) 433 return (EOPNOTSUPP); 434 return ((*ifp->if_ioctl)(ifp, cmd, data)); 435 } 436 return (0); 437 } 438 439 /* 440 * Delete any existing route for an interface. 441 */ 442 in_ifscrub(ifp, ia) 443 register struct ifnet *ifp; 444 register struct in_ifaddr *ia; 445 { 446 447 if ((ia->ia_flags & IFA_ROUTE) == 0) 448 return; 449 if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT)) 450 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); 451 else 452 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0); 453 ia->ia_flags &= ~IFA_ROUTE; 454 } 455 456 /* 457 * Initialize an interface's internet address 458 * and routing table entry. 459 */ 460 in_ifinit(ifp, ia, sin, scrub) 461 register struct ifnet *ifp; 462 register struct in_ifaddr *ia; 463 struct sockaddr_in *sin; 464 { 465 register u_long i = ntohl(sin->sin_addr.s_addr); 466 struct sockaddr_in oldaddr; 467 int s = splimp(), error; 468 469 oldaddr = ia->ia_addr; 470 ia->ia_addr = *sin; 471 /* 472 * Give the interface a chance to initialize 473 * if this is its first address, 474 * and to validate the address if necessary. 475 */ 476 if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { 477 splx(s); 478 ia->ia_addr = oldaddr; 479 return (error); 480 } 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 if (ifp->if_flags & IFF_BROADCAST) { 501 ia->ia_broadaddr.sin_addr = 502 in_makeaddr(ia->ia_subnet, INADDR_BROADCAST); 503 ia->ia_netbroadcast.s_addr = 504 htonl(ia->ia_net | (INADDR_BROADCAST &~ ia->ia_netmask)); 505 } 506 /* 507 * Add route for the network. 508 */ 509 if (ifp->if_flags & IFF_LOOPBACK) { 510 ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr; 511 rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 512 } else if (ifp->if_flags & IFF_POINTOPOINT && 513 ia->ia_dstaddr.sin_family == AF_INET) 514 rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); 515 else { 516 rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP); 517 } 518 ia->ia_flags |= IFA_ROUTE; 519 splx(s); 520 return (0); 521 } 522 523 /* 524 * Return address info for specified internet network. 525 */ 526 struct in_ifaddr * 527 in_iaonnetof(net) 528 u_long net; 529 { 530 register struct in_ifaddr *ia; 531 532 for (ia = in_ifaddr; ia; ia = ia->ia_next) 533 if (ia->ia_subnet == net) 534 return (ia); 535 return ((struct in_ifaddr *)0); 536 } 537 538 /* 539 * Return 1 if the address might be a local broadcast address. 540 */ 541 in_broadcast(in) 542 struct in_addr in; 543 { 544 register struct in_ifaddr *ia; 545 u_long t; 546 547 /* 548 * Look through the list of addresses for a match 549 * with a broadcast address. 550 */ 551 for (ia = in_ifaddr; ia; ia = ia->ia_next) 552 if (ia->ia_ifp->if_flags & IFF_BROADCAST) { 553 if (ia->ia_broadaddr.sin_addr.s_addr == in.s_addr) 554 return (1); 555 /* 556 * Check for old-style (host 0) broadcast. 557 */ 558 if ((t = ntohl(in.s_addr)) == ia->ia_subnet || t == ia->ia_net) 559 return (1); 560 } 561 if (in.s_addr == INADDR_BROADCAST || in.s_addr == INADDR_ANY) 562 return (1); 563 return (0); 564 } 565 #endif 566