|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1985 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #if defined(LIBC_SCCS) && !defined(lint) ! 8: static char sccsid[] = "@(#)gethostnamadr.c 6.12 (Berkeley) 5/19/86"; ! 9: #endif LIBC_SCCS and not lint ! 10: ! 11: #include <sys/types.h> ! 12: #include <sys/socket.h> ! 13: #include <netinet/in.h> ! 14: #include <ctype.h> ! 15: #include <netdb.h> ! 16: #include <stdio.h> ! 17: #include <errno.h> ! 18: #include <arpa/inet.h> ! 19: #include <arpa/nameser.h> ! 20: #include <resolv.h> ! 21: ! 22: #define MAXALIASES 35 ! 23: #define MAXADDRS 35 ! 24: ! 25: static char *h_addr_ptrs[MAXADDRS + 1]; ! 26: ! 27: static struct hostent host; ! 28: static char *host_aliases[MAXALIASES]; ! 29: static char hostbuf[BUFSIZ+1]; ! 30: static struct in_addr host_addr; ! 31: static char HOSTDB[] = "/etc/hosts"; ! 32: static FILE *hostf = NULL; ! 33: static char line[BUFSIZ+1]; ! 34: static char hostaddr[MAXADDRS]; ! 35: static char *host_addrs[2]; ! 36: static int stayopen = 0; ! 37: static char *any(); ! 38: ! 39: typedef union { ! 40: HEADER qb1; ! 41: char qb2[PACKETSZ]; ! 42: } querybuf; ! 43: ! 44: static union { ! 45: long al; ! 46: char ac; ! 47: } align; ! 48: ! 49: ! 50: int h_errno; ! 51: extern errno; ! 52: ! 53: static struct hostent * ! 54: getanswer(msg, msglen, iquery) ! 55: char *msg; ! 56: int msglen, iquery; ! 57: { ! 58: register HEADER *hp; ! 59: register char *cp; ! 60: register int n; ! 61: querybuf answer; ! 62: char *eom, *bp, **ap; ! 63: int type, class, buflen, ancount, qdcount; ! 64: int haveanswer, getclass = C_ANY; ! 65: char **hap; ! 66: ! 67: n = res_send(msg, msglen, (char *)&answer, sizeof(answer)); ! 68: if (n < 0) { ! 69: #ifdef DEBUG ! 70: int terrno; ! 71: terrno = errno; ! 72: if (_res.options & RES_DEBUG) ! 73: printf("res_send failed\n"); ! 74: errno = terrno; ! 75: #endif ! 76: h_errno = TRY_AGAIN; ! 77: return (NULL); ! 78: } ! 79: eom = (char *)&answer + n; ! 80: /* ! 81: * find first satisfactory answer ! 82: */ ! 83: hp = (HEADER *) &answer; ! 84: ancount = ntohs(hp->ancount); ! 85: qdcount = ntohs(hp->qdcount); ! 86: if (hp->rcode != NOERROR || ancount == 0) { ! 87: #ifdef DEBUG ! 88: if (_res.options & RES_DEBUG) ! 89: printf("rcode = %d, ancount=%d\n", hp->rcode, ancount); ! 90: #endif ! 91: switch (hp->rcode) { ! 92: case NXDOMAIN: ! 93: /* Check if it's an authoritive answer */ ! 94: if (hp->aa) ! 95: h_errno = HOST_NOT_FOUND; ! 96: else ! 97: h_errno = TRY_AGAIN; ! 98: break; ! 99: case SERVFAIL: ! 100: h_errno = TRY_AGAIN; ! 101: break; ! 102: case NOERROR: ! 103: h_errno = NO_ADDRESS; ! 104: break; ! 105: case FORMERR: ! 106: case NOTIMP: ! 107: case REFUSED: ! 108: h_errno = NO_RECOVERY; ! 109: } ! 110: return (NULL); ! 111: } ! 112: bp = hostbuf; ! 113: buflen = sizeof(hostbuf); ! 114: cp = (char *)&answer + sizeof(HEADER); ! 115: if (qdcount) { ! 116: if (iquery) { ! 117: if ((n = dn_expand((char *)&answer, eom, ! 118: cp, bp, buflen)) < 0) { ! 119: h_errno = NO_RECOVERY; ! 120: return (NULL); ! 121: } ! 122: cp += n + QFIXEDSZ; ! 123: host.h_name = bp; ! 124: n = strlen(bp) + 1; ! 125: bp += n; ! 126: buflen -= n; ! 127: } else ! 128: cp += dn_skip(cp) + QFIXEDSZ; ! 129: while (--qdcount > 0) ! 130: cp += dn_skip(cp) + QFIXEDSZ; ! 131: } else if (iquery) { ! 132: if (hp->aa) ! 133: h_errno = HOST_NOT_FOUND; ! 134: else ! 135: h_errno = TRY_AGAIN; ! 136: return (NULL); ! 137: } ! 138: ap = host_aliases; ! 139: host.h_aliases = host_aliases; ! 140: hap = h_addr_ptrs; ! 141: host.h_addr_list = h_addr_ptrs; ! 142: haveanswer = 0; ! 143: while (--ancount >= 0 && cp < eom) { ! 144: if ((n = dn_expand((char *)&answer, eom, cp, bp, buflen)) < 0) ! 145: break; ! 146: cp += n; ! 147: type = getshort(cp); ! 148: cp += sizeof(u_short); ! 149: class = getshort(cp); ! 150: cp += sizeof(u_short) + sizeof(u_long); ! 151: n = getshort(cp); ! 152: cp += sizeof(u_short); ! 153: if (type == T_CNAME) { ! 154: cp += n; ! 155: if (ap >= &host_aliases[MAXALIASES-1]) ! 156: continue; ! 157: *ap++ = bp; ! 158: n = strlen(bp) + 1; ! 159: bp += n; ! 160: buflen -= n; ! 161: continue; ! 162: } ! 163: if (type == T_PTR) { ! 164: if ((n = dn_expand((char *)&answer, eom, ! 165: cp, bp, buflen)) < 0) { ! 166: cp += n; ! 167: continue; ! 168: } ! 169: cp += n; ! 170: host.h_name = bp; ! 171: return(&host); ! 172: } ! 173: if (type != T_A) { ! 174: #ifdef DEBUG ! 175: if (_res.options & RES_DEBUG) ! 176: printf("unexpected answer type %d, size %d\n", ! 177: type, n); ! 178: #endif ! 179: cp += n; ! 180: continue; ! 181: } ! 182: if (haveanswer) { ! 183: if (n != host.h_length) { ! 184: cp += n; ! 185: continue; ! 186: } ! 187: if (class != getclass) { ! 188: cp += n; ! 189: continue; ! 190: } ! 191: } else { ! 192: host.h_length = n; ! 193: getclass = class; ! 194: host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC; ! 195: if (!iquery) { ! 196: host.h_name = bp; ! 197: bp += strlen(bp) + 1; ! 198: } ! 199: } ! 200: ! 201: bp += ((u_long)bp % sizeof(align)); ! 202: ! 203: if (bp + n >= &hostbuf[sizeof(hostbuf)]) { ! 204: #ifdef DEBUG ! 205: if (_res.options & RES_DEBUG) ! 206: printf("size (%d) too big\n", n); ! 207: #endif ! 208: break; ! 209: } ! 210: bcopy(cp, *hap++ = bp, n); ! 211: bp +=n; ! 212: cp += n; ! 213: haveanswer++; ! 214: } ! 215: if (haveanswer) { ! 216: *ap = NULL; ! 217: *hap = NULL; ! 218: return (&host); ! 219: } else { ! 220: h_errno = TRY_AGAIN; ! 221: return (NULL); ! 222: } ! 223: } ! 224: ! 225: struct hostent * ! 226: gethostbyname(name) ! 227: char *name; ! 228: { ! 229: int n; ! 230: querybuf buf; ! 231: register struct hostent *hp; ! 232: extern struct hostent *_gethtbyname(); ! 233: ! 234: n = res_mkquery(QUERY, name, C_IN, T_A, (char *)NULL, 0, NULL, ! 235: (char *)&buf, sizeof(buf)); ! 236: if (n < 0) { ! 237: #ifdef DEBUG ! 238: if (_res.options & RES_DEBUG) ! 239: printf("res_mkquery failed\n"); ! 240: #endif ! 241: return (NULL); ! 242: } ! 243: hp = getanswer((char *)&buf, n, 0); ! 244: if (hp == NULL && errno == ECONNREFUSED) ! 245: hp = _gethtbyname(name); ! 246: return(hp); ! 247: } ! 248: ! 249: struct hostent * ! 250: gethostbyaddr(addr, len, type) ! 251: char *addr; ! 252: int len, type; ! 253: { ! 254: int n; ! 255: querybuf buf; ! 256: register struct hostent *hp; ! 257: char qbuf[MAXDNAME]; ! 258: extern struct hostent *_gethtbyaddr(); ! 259: ! 260: if (type != AF_INET) ! 261: return (NULL); ! 262: (void)sprintf(qbuf, "%d.%d.%d.%d.in-addr.arpa", ! 263: ((unsigned)addr[3] & 0xff), ! 264: ((unsigned)addr[2] & 0xff), ! 265: ((unsigned)addr[1] & 0xff), ! 266: ((unsigned)addr[0] & 0xff)); ! 267: n = res_mkquery(QUERY, qbuf, C_IN, T_PTR, (char *)NULL, 0, NULL, ! 268: (char *)&buf, sizeof(buf)); ! 269: if (n < 0) { ! 270: #ifdef DEBUG ! 271: if (_res.options & RES_DEBUG) ! 272: printf("res_mkquery failed\n"); ! 273: #endif ! 274: return (NULL); ! 275: } ! 276: hp = getanswer((char *)&buf, n, 1); ! 277: if (hp == NULL && errno == ECONNREFUSED) ! 278: hp = _gethtbyaddr(addr, len, type); ! 279: if (hp == NULL) ! 280: return(NULL); ! 281: hp->h_addrtype = type; ! 282: hp->h_length = len; ! 283: h_addr_ptrs[0] = (char *)&host_addr; ! 284: h_addr_ptrs[1] = (char *)0; ! 285: host_addr = *(struct in_addr *)addr; ! 286: return(hp); ! 287: } ! 288: ! 289: ! 290: _sethtent(f) ! 291: int f; ! 292: { ! 293: if (hostf == NULL) ! 294: hostf = fopen(HOSTDB, "r" ); ! 295: else ! 296: rewind(hostf); ! 297: stayopen |= f; ! 298: } ! 299: ! 300: _endhtent() ! 301: { ! 302: if (hostf && !stayopen) { ! 303: (void) fclose(hostf); ! 304: hostf = NULL; ! 305: } ! 306: } ! 307: ! 308: struct hostent * ! 309: _gethtent() ! 310: { ! 311: char *p; ! 312: register char *cp, **q; ! 313: ! 314: if (hostf == NULL && (hostf = fopen(HOSTDB, "r" )) == NULL) ! 315: return (NULL); ! 316: again: ! 317: if ((p = fgets(line, BUFSIZ, hostf)) == NULL) ! 318: return (NULL); ! 319: if (*p == '#') ! 320: goto again; ! 321: cp = any(p, "#\n"); ! 322: if (cp == NULL) ! 323: goto again; ! 324: *cp = '\0'; ! 325: cp = any(p, " \t"); ! 326: if (cp == NULL) ! 327: goto again; ! 328: *cp++ = '\0'; ! 329: /* THIS STUFF IS INTERNET SPECIFIC */ ! 330: host.h_addr_list = host_addrs; ! 331: host.h_addr = hostaddr; ! 332: *((u_long *)host.h_addr) = inet_addr(p); ! 333: host.h_length = sizeof (u_long); ! 334: host.h_addrtype = AF_INET; ! 335: while (*cp == ' ' || *cp == '\t') ! 336: cp++; ! 337: host.h_name = cp; ! 338: q = host.h_aliases = host_aliases; ! 339: cp = any(cp, " \t"); ! 340: if (cp != NULL) ! 341: *cp++ = '\0'; ! 342: while (cp && *cp) { ! 343: if (*cp == ' ' || *cp == '\t') { ! 344: cp++; ! 345: continue; ! 346: } ! 347: if (q < &host_aliases[MAXALIASES - 1]) ! 348: *q++ = cp; ! 349: cp = any(cp, " \t"); ! 350: if (cp != NULL) ! 351: *cp++ = '\0'; ! 352: } ! 353: *q = NULL; ! 354: return (&host); ! 355: } ! 356: ! 357: static char * ! 358: any(cp, match) ! 359: register char *cp; ! 360: char *match; ! 361: { ! 362: register char *mp, c; ! 363: ! 364: while (c = *cp) { ! 365: for (mp = match; *mp; mp++) ! 366: if (*mp == c) ! 367: return (cp); ! 368: cp++; ! 369: } ! 370: return ((char *)0); ! 371: } ! 372: ! 373: struct hostent * ! 374: _gethtbyname(name) ! 375: char *name; ! 376: { ! 377: register struct hostent *p; ! 378: register char **cp; ! 379: char lowname[128]; ! 380: register char *lp = lowname; ! 381: ! 382: while (*name) ! 383: if (isupper(*name)) ! 384: *lp++ = tolower(*name++); ! 385: else ! 386: *lp++ = *name++; ! 387: *lp = '\0'; ! 388: ! 389: _sethtent(0); ! 390: while (p = _gethtent()) { ! 391: if (strcmp(p->h_name, lowname) == 0) ! 392: break; ! 393: for (cp = p->h_aliases; *cp != 0; cp++) ! 394: if (strcmp(*cp, lowname) == 0) ! 395: goto found; ! 396: } ! 397: found: ! 398: _endhtent(); ! 399: return (p); ! 400: } ! 401: ! 402: struct hostent * ! 403: _gethtbyaddr(addr, len, type) ! 404: char *addr; ! 405: int len, type; ! 406: { ! 407: register struct hostent *p; ! 408: ! 409: _sethtent(0); ! 410: while (p = _gethtent()) ! 411: if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len)) ! 412: break; ! 413: _endhtent(); ! 414: return (p); ! 415: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.