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