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: }