|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1985, 1988 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: (1) source distributions retain this entire copyright ! 7: * notice and comment, and (2) distributions including binaries display ! 8: * the following acknowledgement: ``This product includes software ! 9: * developed by the University of California, Berkeley and its contributors'' ! 10: * in the documentation or other materials provided with the distribution ! 11: * and in all advertising materials mentioning features or use of this ! 12: * software. Neither the name of the University nor the names of its ! 13: * contributors may be used to endorse or promote products derived ! 14: * from this software without specific prior written permission. ! 15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ! 16: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ! 17: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 18: */ ! 19: ! 20: #if defined(LIBC_SCCS) && !defined(lint) ! 21: static char sccsid[] = "@(#)gethostnamadr.c 6.41 (Berkeley) 6/1/90"; ! 22: #endif /* LIBC_SCCS and not lint */ ! 23: ! 24: #include <sys/param.h> ! 25: #include <sys/socket.h> ! 26: #include <netinet/in.h> ! 27: #include <ctype.h> ! 28: #include <netdb.h> ! 29: #include <stdio.h> ! 30: #include <errno.h> ! 31: #include <arpa/inet.h> ! 32: #include <arpa/nameser.h> ! 33: #include <resolv.h> ! 34: ! 35: #define MAXALIASES 35 ! 36: #define MAXADDRS 35 ! 37: ! 38: static char *h_addr_ptrs[MAXADDRS + 1]; ! 39: ! 40: static struct hostent host; ! 41: static char *host_aliases[MAXALIASES]; ! 42: static char hostbuf[BUFSIZ+1]; ! 43: static struct in_addr host_addr; ! 44: static FILE *hostf = NULL; ! 45: static char hostaddr[MAXADDRS]; ! 46: static char *host_addrs[2]; ! 47: static int stayopen = 0; ! 48: char *strpbrk(); ! 49: ! 50: #if PACKETSZ > 1024 ! 51: #define MAXPACKET PACKETSZ ! 52: #else ! 53: #define MAXPACKET 1024 ! 54: #endif ! 55: ! 56: typedef union { ! 57: HEADER hdr; ! 58: u_char buf[MAXPACKET]; ! 59: } querybuf; ! 60: ! 61: typedef union { ! 62: long al; ! 63: char ac; ! 64: } align; ! 65: ! 66: ! 67: int h_errno; ! 68: extern errno; ! 69: ! 70: static struct hostent * ! 71: getanswer(answer, anslen, iquery) ! 72: querybuf *answer; ! 73: int anslen; ! 74: int iquery; ! 75: { ! 76: register HEADER *hp; ! 77: register u_char *cp; ! 78: register int n; ! 79: u_char *eom; ! 80: char *bp, **ap; ! 81: int type, class, buflen, ancount, qdcount; ! 82: int haveanswer, getclass = C_ANY; ! 83: char **hap; ! 84: ! 85: eom = answer->buf + anslen; ! 86: /* ! 87: * find first satisfactory answer ! 88: */ ! 89: hp = &answer->hdr; ! 90: ancount = ntohs(hp->ancount); ! 91: qdcount = ntohs(hp->qdcount); ! 92: bp = hostbuf; ! 93: buflen = sizeof(hostbuf); ! 94: cp = answer->buf + sizeof(HEADER); ! 95: if (qdcount) { ! 96: if (iquery) { ! 97: if ((n = dn_expand((char *)answer->buf, eom, ! 98: cp, bp, buflen)) < 0) { ! 99: h_errno = NO_RECOVERY; ! 100: return ((struct hostent *) NULL); ! 101: } ! 102: cp += n + QFIXEDSZ; ! 103: host.h_name = bp; ! 104: n = strlen(bp) + 1; ! 105: bp += n; ! 106: buflen -= n; ! 107: } else ! 108: cp += dn_skipname(cp, eom) + QFIXEDSZ; ! 109: while (--qdcount > 0) ! 110: cp += dn_skipname(cp, eom) + QFIXEDSZ; ! 111: } else if (iquery) { ! 112: if (hp->aa) ! 113: h_errno = HOST_NOT_FOUND; ! 114: else ! 115: h_errno = TRY_AGAIN; ! 116: return ((struct hostent *) NULL); ! 117: } ! 118: ap = host_aliases; ! 119: *ap = NULL; ! 120: host.h_aliases = host_aliases; ! 121: hap = h_addr_ptrs; ! 122: *hap = NULL; ! 123: #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ ! 124: host.h_addr_list = h_addr_ptrs; ! 125: #endif ! 126: haveanswer = 0; ! 127: while (--ancount >= 0 && cp < eom) { ! 128: if ((n = dn_expand((char *)answer->buf, eom, cp, bp, buflen)) < 0) ! 129: break; ! 130: cp += n; ! 131: type = _getshort(cp); ! 132: cp += sizeof(u_short); ! 133: class = _getshort(cp); ! 134: cp += sizeof(u_short) + sizeof(u_long); ! 135: n = _getshort(cp); ! 136: cp += sizeof(u_short); ! 137: if (type == T_CNAME) { ! 138: cp += n; ! 139: if (ap >= &host_aliases[MAXALIASES-1]) ! 140: continue; ! 141: *ap++ = bp; ! 142: n = strlen(bp) + 1; ! 143: bp += n; ! 144: buflen -= n; ! 145: continue; ! 146: } ! 147: if (iquery && type == T_PTR) { ! 148: if ((n = dn_expand((char *)answer->buf, eom, ! 149: cp, bp, buflen)) < 0) { ! 150: cp += n; ! 151: continue; ! 152: } ! 153: cp += n; ! 154: host.h_name = bp; ! 155: return(&host); ! 156: } ! 157: if (iquery || type != T_A) { ! 158: #ifdef DEBUG ! 159: if (_res.options & RES_DEBUG) ! 160: printf("unexpected answer type %d, size %d\n", ! 161: type, n); ! 162: #endif ! 163: cp += n; ! 164: continue; ! 165: } ! 166: if (haveanswer) { ! 167: if (n != host.h_length) { ! 168: cp += n; ! 169: continue; ! 170: } ! 171: if (class != getclass) { ! 172: cp += n; ! 173: continue; ! 174: } ! 175: } else { ! 176: host.h_length = n; ! 177: getclass = class; ! 178: host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC; ! 179: if (!iquery) { ! 180: host.h_name = bp; ! 181: bp += strlen(bp) + 1; ! 182: } ! 183: } ! 184: ! 185: bp += sizeof(align) - ((u_long)bp % sizeof(align)); ! 186: ! 187: if (bp + n >= &hostbuf[sizeof(hostbuf)]) { ! 188: #ifdef DEBUG ! 189: if (_res.options & RES_DEBUG) ! 190: printf("size (%d) too big\n", n); ! 191: #endif ! 192: break; ! 193: } ! 194: bcopy(cp, *hap++ = bp, n); ! 195: bp +=n; ! 196: cp += n; ! 197: haveanswer++; ! 198: } ! 199: if (haveanswer) { ! 200: *ap = NULL; ! 201: #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ ! 202: *hap = NULL; ! 203: #else ! 204: host.h_addr = h_addr_ptrs[0]; ! 205: #endif ! 206: return (&host); ! 207: } else { ! 208: h_errno = TRY_AGAIN; ! 209: return ((struct hostent *) NULL); ! 210: } ! 211: } ! 212: ! 213: struct hostent * ! 214: gethostbyname(name) ! 215: char *name; ! 216: { ! 217: querybuf buf; ! 218: register char *cp; ! 219: int n; ! 220: extern struct hostent *_gethtbyname(); ! 221: ! 222: /* ! 223: * disallow names consisting only of digits/dots, unless ! 224: * they end in a dot. ! 225: */ ! 226: if (isdigit(name[0])) ! 227: for (cp = name;; ++cp) { ! 228: if (!*cp) { ! 229: if (*--cp == '.') ! 230: break; ! 231: /* ! 232: * All-numeric, no dot at the end. ! 233: * Fake up a hostent as if we'd actually ! 234: * done a lookup. What if someone types ! 235: * 255.255.255.255? The test below will ! 236: * succeed spuriously... ??? ! 237: */ ! 238: if ((host_addr.s_addr = inet_addr(name)) == -1) { ! 239: h_errno = HOST_NOT_FOUND; ! 240: return((struct hostent *) NULL); ! 241: } ! 242: host.h_name = name; ! 243: host.h_aliases = host_aliases; ! 244: host_aliases[0] = NULL; ! 245: host.h_addrtype = AF_INET; ! 246: host.h_length = sizeof(u_long); ! 247: h_addr_ptrs[0] = (char *)&host_addr; ! 248: h_addr_ptrs[1] = (char *)0; ! 249: #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ ! 250: host.h_addr_list = h_addr_ptrs; ! 251: #else ! 252: host.h_addr = h_addr_ptrs[0]; ! 253: #endif ! 254: return (&host); ! 255: } ! 256: if (!isdigit(*cp) && *cp != '.') ! 257: break; ! 258: } ! 259: ! 260: if ((n = res_search(name, C_IN, T_A, buf.buf, sizeof(buf))) < 0) { ! 261: #ifdef DEBUG ! 262: if (_res.options & RES_DEBUG) ! 263: printf("res_search failed\n"); ! 264: #endif ! 265: if (errno == ECONNREFUSED) ! 266: return (_gethtbyname(name)); ! 267: else ! 268: return ((struct hostent *) NULL); ! 269: } ! 270: return (getanswer(&buf, n, 0)); ! 271: } ! 272: ! 273: struct hostent * ! 274: gethostbyaddr(addr, len, type) ! 275: char *addr; ! 276: int len, type; ! 277: { ! 278: int n; ! 279: querybuf buf; ! 280: register struct hostent *hp; ! 281: char qbuf[MAXDNAME]; ! 282: extern struct hostent *_gethtbyaddr(); ! 283: ! 284: if (type != AF_INET) ! 285: return ((struct hostent *) NULL); ! 286: (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", ! 287: ((unsigned)addr[3] & 0xff), ! 288: ((unsigned)addr[2] & 0xff), ! 289: ((unsigned)addr[1] & 0xff), ! 290: ((unsigned)addr[0] & 0xff)); ! 291: n = res_query(qbuf, C_IN, T_PTR, (char *)&buf, sizeof(buf)); ! 292: if (n < 0) { ! 293: #ifdef DEBUG ! 294: if (_res.options & RES_DEBUG) ! 295: printf("res_query failed\n"); ! 296: #endif ! 297: if (errno == ECONNREFUSED) ! 298: return (_gethtbyaddr(addr, len, type)); ! 299: return ((struct hostent *) NULL); ! 300: } ! 301: hp = getanswer(&buf, n, 1); ! 302: if (hp == NULL) ! 303: return ((struct hostent *) NULL); ! 304: hp->h_addrtype = type; ! 305: hp->h_length = len; ! 306: h_addr_ptrs[0] = (char *)&host_addr; ! 307: h_addr_ptrs[1] = (char *)0; ! 308: host_addr = *(struct in_addr *)addr; ! 309: #if BSD < 43 && !defined(h_addr) /* new-style hostent structure */ ! 310: hp->h_addr = h_addr_ptrs[0]; ! 311: #endif ! 312: return(hp); ! 313: } ! 314: ! 315: _sethtent(f) ! 316: int f; ! 317: { ! 318: if (hostf == NULL) ! 319: hostf = fopen(_PATH_HOSTS, "r" ); ! 320: else ! 321: rewind(hostf); ! 322: stayopen |= f; ! 323: } ! 324: ! 325: _endhtent() ! 326: { ! 327: if (hostf && !stayopen) { ! 328: (void) fclose(hostf); ! 329: hostf = NULL; ! 330: } ! 331: } ! 332: ! 333: struct hostent * ! 334: _gethtent() ! 335: { ! 336: char *p; ! 337: register char *cp, **q; ! 338: ! 339: if (hostf == NULL && (hostf = fopen(_PATH_HOSTS, "r" )) == NULL) ! 340: return (NULL); ! 341: again: ! 342: if ((p = fgets(hostbuf, BUFSIZ, hostf)) == NULL) ! 343: return (NULL); ! 344: if (*p == '#') ! 345: goto again; ! 346: cp = strpbrk(p, "#\n"); ! 347: if (cp == NULL) ! 348: goto again; ! 349: *cp = '\0'; ! 350: cp = strpbrk(p, " \t"); ! 351: if (cp == NULL) ! 352: goto again; ! 353: *cp++ = '\0'; ! 354: /* THIS STUFF IS INTERNET SPECIFIC */ ! 355: #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ ! 356: host.h_addr_list = host_addrs; ! 357: #endif ! 358: host.h_addr = hostaddr; ! 359: *((u_long *)host.h_addr) = inet_addr(p); ! 360: host.h_length = sizeof (u_long); ! 361: host.h_addrtype = AF_INET; ! 362: while (*cp == ' ' || *cp == '\t') ! 363: cp++; ! 364: host.h_name = cp; ! 365: q = host.h_aliases = host_aliases; ! 366: cp = strpbrk(cp, " \t"); ! 367: if (cp != NULL) ! 368: *cp++ = '\0'; ! 369: while (cp && *cp) { ! 370: if (*cp == ' ' || *cp == '\t') { ! 371: cp++; ! 372: continue; ! 373: } ! 374: if (q < &host_aliases[MAXALIASES - 1]) ! 375: *q++ = cp; ! 376: cp = strpbrk(cp, " \t"); ! 377: if (cp != NULL) ! 378: *cp++ = '\0'; ! 379: } ! 380: *q = NULL; ! 381: return (&host); ! 382: } ! 383: ! 384: struct hostent * ! 385: _gethtbyname(name) ! 386: char *name; ! 387: { ! 388: register struct hostent *p; ! 389: register char **cp; ! 390: ! 391: _sethtent(0); ! 392: while (p = _gethtent()) { ! 393: if (strcasecmp(p->h_name, name) == 0) ! 394: break; ! 395: for (cp = p->h_aliases; *cp != 0; cp++) ! 396: if (strcasecmp(*cp, name) == 0) ! 397: goto found; ! 398: } ! 399: found: ! 400: _endhtent(); ! 401: return (p); ! 402: } ! 403: ! 404: struct hostent * ! 405: _gethtbyaddr(addr, len, type) ! 406: char *addr; ! 407: int len, type; ! 408: { ! 409: register struct hostent *p; ! 410: ! 411: _sethtent(0); ! 412: while (p = _gethtent()) ! 413: if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len)) ! 414: break; ! 415: _endhtent(); ! 416: return (p); ! 417: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.