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