121374Sdist /* 225302Skjd * Copyright (c) 1985 Regents of the University of California. 321374Sdist * All rights reserved. The Berkeley software License Agreement 421374Sdist * specifies the terms and conditions for redistribution. 521374Sdist */ 615662Sralph 726630Sdonn #if defined(LIBC_SCCS) && !defined(lint) 8*26887Skjd static char sccsid[] = "@(#)gethostnamadr.c 6.6 (Berkeley) 03/14/86"; 926630Sdonn #endif LIBC_SCCS and not lint 1021374Sdist 1125386Skjd #include <sys/param.h> 1218505Sralph #include <sys/socket.h> 1318505Sralph #include <netinet/in.h> 14*26887Skjd #include <sys/types.h> 15*26887Skjd #include <ctype.h> 1618505Sralph #include <netdb.h> 1715662Sralph #include <stdio.h> 18*26887Skjd #include <errno.h> 1924508Sbloom #include <arpa/nameser.h> 2024508Sbloom #include <arpa/resolv.h> 2115662Sralph 2215662Sralph #define MAXALIASES 35 2324687Sbloom #define MAXADDRS 35 2415662Sralph 2524687Sbloom static char *h_addr_ptrs[MAXADDRS + 1]; 2624687Sbloom 2724687Sbloom static struct hostent host; 2815662Sralph static char *host_aliases[MAXALIASES]; 2915912Sralph static char hostbuf[BUFSIZ+1]; 3025153Sbloom static struct in_addr host_addr; 31*26887Skjd static char HOSTDB[] = "/etc/hosts"; 32*26887Skjd static FILE *hostf = NULL; 33*26887Skjd static char line[BUFSIZ+1]; 34*26887Skjd static char hostaddr[MAXADDRS]; 35*26887Skjd static char *host_addrs[2]; 36*26887Skjd static int stayopen = 0; 37*26887Skjd static char *any(); 3815662Sralph 3925302Skjd typedef union { 4025302Skjd HEADER qb1; 4125302Skjd char qb2[PACKETSZ]; 4225302Skjd } querybuf; 4324509Sbloom 4425302Skjd static union { 4525302Skjd long al; 4625302Skjd char ac; 4725302Skjd } align; 4825302Skjd 4925302Skjd 5025484Skjd int h_errno; 51*26887Skjd extern errno; 5225484Skjd 5315662Sralph static struct hostent * 5418505Sralph getanswer(msg, msglen, iquery) 5518505Sralph char *msg; 5618505Sralph int msglen, iquery; 5715662Sralph { 5818505Sralph register HEADER *hp; 5918505Sralph register char *cp; 6018505Sralph register int n; 6125302Skjd querybuf answer; 6218505Sralph char *eom, *bp, **ap; 6325153Sbloom int type, class, ancount, qdcount, buflen; 6424687Sbloom int haveanswer, getclass; 6524687Sbloom char **hap; 6615662Sralph 6725302Skjd n = res_send(msg, msglen, (char *)&answer, sizeof(answer)); 6818505Sralph if (n < 0) { 6924733Sbloom #ifdef DEBUG 70*26887Skjd int terrno; 71*26887Skjd terrno = errno; 7218505Sralph if (_res.options & RES_DEBUG) 7318531Sralph printf("res_send failed\n"); 74*26887Skjd errno = terrno; 7524733Sbloom #endif 7625484Skjd h_errno = TRY_AGAIN; 7718505Sralph return (NULL); 7815662Sralph } 7925302Skjd eom = (char *)&answer + n; 8018505Sralph /* 8118505Sralph * find first satisfactory answer 8218505Sralph */ 8325302Skjd hp = (HEADER *) &answer; 8418505Sralph ancount = ntohs(hp->ancount); 8525153Sbloom qdcount = ntohs(hp->qdcount); 8618505Sralph if (hp->rcode != NOERROR || ancount == 0) { 8724733Sbloom #ifdef DEBUG 8818505Sralph if (_res.options & RES_DEBUG) 8918505Sralph printf("rcode = %d, ancount=%d\n", hp->rcode, ancount); 9024733Sbloom #endif 9125484Skjd switch (hp->rcode) { 9225484Skjd case NXDOMAIN: 9325484Skjd /* Check if it's an authoritive answer */ 9425484Skjd if (hp->aa) 9525484Skjd h_errno = HOST_NOT_FOUND; 9625484Skjd else 9725484Skjd h_errno = TRY_AGAIN; 9825484Skjd break; 9925484Skjd case SERVFAIL: 10025484Skjd h_errno = TRY_AGAIN; 10125484Skjd break; 10225484Skjd case NOERROR: 10325484Skjd h_errno = NO_ADDRESS; 10425484Skjd break; 10525484Skjd case FORMERR: 10625484Skjd case NOTIMP: 10725484Skjd case REFUSED: 10825484Skjd h_errno = NO_RECOVERY; 10925484Skjd } 11018505Sralph return (NULL); 11118505Sralph } 11218505Sralph bp = hostbuf; 11318505Sralph buflen = sizeof(hostbuf); 11425302Skjd cp = (char *)&answer + sizeof(HEADER); 11525153Sbloom if (qdcount) { 11618505Sralph if (iquery) { 11726066Skjd if ((n = dn_expand((char *)&answer, eom, 11826066Skjd cp, bp, buflen)) < 0) { 11925484Skjd h_errno = NO_RECOVERY; 12018505Sralph return (NULL); 12125484Skjd } 12218505Sralph cp += n + QFIXEDSZ; 12318505Sralph host.h_name = bp; 12418505Sralph n = strlen(bp) + 1; 12518505Sralph bp += n; 12618505Sralph buflen -= n; 12718505Sralph } else 12818505Sralph cp += dn_skip(cp) + QFIXEDSZ; 12925153Sbloom while (--qdcount > 0) 13025153Sbloom cp += dn_skip(cp) + QFIXEDSZ; 13125484Skjd } else if (iquery) { 13225484Skjd if (hp->aa) 13325484Skjd h_errno = HOST_NOT_FOUND; 13425484Skjd else 13525484Skjd h_errno = TRY_AGAIN; 13618505Sralph return (NULL); 13725484Skjd } 13824687Sbloom ap = host_aliases; 13924687Sbloom host.h_aliases = host_aliases; 14024687Sbloom hap = h_addr_ptrs; 14124687Sbloom host.h_addr_list = h_addr_ptrs; 14224687Sbloom haveanswer = 0; 14318505Sralph while (--ancount >= 0 && cp < eom) { 14426066Skjd if ((n = dn_expand((char *)&answer, eom, cp, bp, buflen)) < 0) 14524687Sbloom break; 14618505Sralph cp += n; 14718505Sralph type = getshort(cp); 14818505Sralph cp += sizeof(u_short); 14918505Sralph class = getshort(cp); 15018505Sralph cp += sizeof(u_short) + sizeof(u_long); 15118505Sralph n = getshort(cp); 15218505Sralph cp += sizeof(u_short); 15318505Sralph if (type == T_CNAME) { 15418505Sralph cp += n; 15518505Sralph if (ap >= &host_aliases[MAXALIASES-1]) 15618505Sralph continue; 15718505Sralph *ap++ = bp; 15818505Sralph n = strlen(bp) + 1; 15918505Sralph bp += n; 16018505Sralph buflen -= n; 16118505Sralph continue; 16218505Sralph } 16325153Sbloom if (type == T_PTR) { 16426066Skjd if ((n = dn_expand((char *)&answer, eom, cp, bp, buflen)) < 16525302Skjd 0) { 16625153Sbloom cp += n; 16725153Sbloom continue; 16825153Sbloom } 16925153Sbloom cp += n; 17025153Sbloom host.h_name = bp; 17125153Sbloom return(&host); 17225153Sbloom } 17324687Sbloom if (type != T_A) { 17424733Sbloom #ifdef DEBUG 17518505Sralph if (_res.options & RES_DEBUG) 17618505Sralph printf("unexpected answer type %d, size %d\n", 17718505Sralph type, n); 17824733Sbloom #endif 17924687Sbloom cp += n; 18018505Sralph continue; 18118505Sralph } 18224687Sbloom if (haveanswer) { 18324687Sbloom if (n != host.h_length) { 18424687Sbloom cp += n; 18524687Sbloom continue; 18624687Sbloom } 18724687Sbloom if (class != getclass) { 18824687Sbloom cp += n; 18924687Sbloom continue; 19024687Sbloom } 19124687Sbloom } else { 19224687Sbloom host.h_length = n; 19324687Sbloom getclass = class; 19425386Skjd host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC; 19524687Sbloom if (!iquery) { 19624687Sbloom host.h_name = bp; 19724687Sbloom bp += strlen(bp) + 1; 19824687Sbloom } 19918505Sralph } 20025302Skjd 20125302Skjd bp += ((u_long)bp % sizeof(align)); 20225302Skjd 20318505Sralph if (bp + n >= &hostbuf[sizeof(hostbuf)]) { 20424733Sbloom #ifdef DEBUG 20518505Sralph if (_res.options & RES_DEBUG) 20618505Sralph printf("size (%d) too big\n", n); 20724733Sbloom #endif 20824687Sbloom break; 20918505Sralph } 21024687Sbloom bcopy(cp, *hap++ = bp, n); 21124687Sbloom bp +=n; 21224687Sbloom cp += n; 21324687Sbloom haveanswer++; 21424687Sbloom } 21524687Sbloom if (haveanswer) { 21624687Sbloom *ap = NULL; 21724687Sbloom *hap = NULL; 21818505Sralph return (&host); 21925484Skjd } else { 22025484Skjd h_errno = TRY_AGAIN; 22124687Sbloom return (NULL); 22225484Skjd } 22315662Sralph } 22415662Sralph 22515662Sralph struct hostent * 22618505Sralph gethostbyname(name) 22718505Sralph char *name; 22815662Sralph { 22918505Sralph int n; 23025302Skjd querybuf buf; 231*26887Skjd register struct hostent *hp; 232*26887Skjd extern struct hostent *_gethtbyname(); 23315662Sralph 23424687Sbloom n = res_mkquery(QUERY, name, C_ANY, T_A, (char *)NULL, 0, NULL, 23525302Skjd (char *)&buf, sizeof(buf)); 23618505Sralph if (n < 0) { 23724733Sbloom #ifdef DEBUG 23818505Sralph if (_res.options & RES_DEBUG) 23918531Sralph printf("res_mkquery failed\n"); 24024733Sbloom #endif 24118505Sralph return (NULL); 24217761Sserge } 243*26887Skjd hp = getanswer((char *)&buf, n, 0); 244*26887Skjd if (hp == NULL && errno == ECONNREFUSED) 245*26887Skjd hp = _gethtbyname(name); 246*26887Skjd return(hp); 24715662Sralph } 24815662Sralph 24915662Sralph struct hostent * 25018505Sralph gethostbyaddr(addr, len, type) 25115662Sralph char *addr; 25218505Sralph int len, type; 25315662Sralph { 25418505Sralph int n; 25525302Skjd querybuf buf; 25625153Sbloom register struct hostent *hp; 25725153Sbloom char qbuf[MAXDNAME]; 258*26887Skjd extern struct hostent *_gethtbyaddr(); 259*26887Skjd 26018505Sralph if (type != AF_INET) 26118505Sralph return (NULL); 26225153Sbloom (void)sprintf(qbuf, "%d.%d.%d.%d.in-addr.arpa", 26325484Skjd ((unsigned)addr[3] & 0xff), 26425484Skjd ((unsigned)addr[2] & 0xff), 26525484Skjd ((unsigned)addr[1] & 0xff), 26625484Skjd ((unsigned)addr[0] & 0xff)); 26725153Sbloom n = res_mkquery(QUERY, qbuf, C_IN, T_PTR, NULL, 0, NULL, 26825302Skjd (char *)&buf, sizeof(buf)); 26918505Sralph if (n < 0) { 27024733Sbloom #ifdef DEBUG 27118505Sralph if (_res.options & RES_DEBUG) 27218531Sralph printf("res_mkquery failed\n"); 27324733Sbloom #endif 27418505Sralph return (NULL); 27517761Sserge } 276*26887Skjd hp = getanswer((char *)&buf, n, 1); 277*26887Skjd if (hp == NULL && errno == ECONNREFUSED) 278*26887Skjd hp = _gethtbyaddr(addr, len, type); 279*26887Skjd if (hp == NULL) 28025153Sbloom return(NULL); 28125153Sbloom hp->h_addrtype = type; 28225153Sbloom hp->h_length = len; 28325282Sbloom h_addr_ptrs[0] = (char *)&host_addr; 28425153Sbloom h_addr_ptrs[1] = (char *)0; 28525153Sbloom host_addr = *(struct in_addr *)addr; 28625153Sbloom return(hp); 28715662Sralph } 28825302Skjd 289*26887Skjd 290*26887Skjd _sethtent(f) 291*26887Skjd int f; 292*26887Skjd { 293*26887Skjd if (hostf == NULL) 294*26887Skjd hostf = fopen(HOSTDB, "r" ); 295*26887Skjd else 296*26887Skjd rewind(hostf); 297*26887Skjd stayopen |= f; 298*26887Skjd } 299*26887Skjd 300*26887Skjd _endhtent() 301*26887Skjd { 302*26887Skjd if (hostf && !stayopen) { 303*26887Skjd fclose(hostf); 304*26887Skjd hostf = NULL; 305*26887Skjd } 306*26887Skjd } 307*26887Skjd 308*26887Skjd struct hostent * 309*26887Skjd _gethtent() 310*26887Skjd { 311*26887Skjd char *p; 312*26887Skjd register char *cp, **q; 313*26887Skjd 314*26887Skjd if (hostf == NULL && (hostf = fopen(HOSTDB, "r" )) == NULL) 315*26887Skjd return (NULL); 316*26887Skjd again: 317*26887Skjd if ((p = fgets(line, BUFSIZ, hostf)) == NULL) 318*26887Skjd return (NULL); 319*26887Skjd if (*p == '#') 320*26887Skjd goto again; 321*26887Skjd cp = any(p, "#\n"); 322*26887Skjd if (cp == NULL) 323*26887Skjd goto again; 324*26887Skjd *cp = '\0'; 325*26887Skjd cp = any(p, " \t"); 326*26887Skjd if (cp == NULL) 327*26887Skjd goto again; 328*26887Skjd *cp++ = '\0'; 329*26887Skjd /* THIS STUFF IS INTERNET SPECIFIC */ 330*26887Skjd host.h_addr_list = host_addrs; 331*26887Skjd host.h_addr = hostaddr; 332*26887Skjd *((u_long *)host.h_addr) = inet_addr(p); 333*26887Skjd host.h_length = sizeof (u_long); 334*26887Skjd host.h_addrtype = AF_INET; 335*26887Skjd while (*cp == ' ' || *cp == '\t') 336*26887Skjd cp++; 337*26887Skjd host.h_name = cp; 338*26887Skjd q = host.h_aliases = host_aliases; 339*26887Skjd cp = any(cp, " \t"); 340*26887Skjd if (cp != NULL) 341*26887Skjd *cp++ = '\0'; 342*26887Skjd while (cp && *cp) { 343*26887Skjd if (*cp == ' ' || *cp == '\t') { 344*26887Skjd cp++; 345*26887Skjd continue; 346*26887Skjd } 347*26887Skjd if (q < &host_aliases[MAXALIASES - 1]) 348*26887Skjd *q++ = cp; 349*26887Skjd cp = any(cp, " \t"); 350*26887Skjd if (cp != NULL) 351*26887Skjd *cp++ = '\0'; 352*26887Skjd } 353*26887Skjd *q = NULL; 354*26887Skjd return (&host); 355*26887Skjd } 356*26887Skjd 357*26887Skjd static char * 358*26887Skjd any(cp, match) 359*26887Skjd register char *cp; 360*26887Skjd char *match; 361*26887Skjd { 362*26887Skjd register char *mp, c; 363*26887Skjd 364*26887Skjd while (c = *cp) { 365*26887Skjd for (mp = match; *mp; mp++) 366*26887Skjd if (*mp == c) 367*26887Skjd return (cp); 368*26887Skjd cp++; 369*26887Skjd } 370*26887Skjd return ((char *)0); 371*26887Skjd } 372*26887Skjd 373*26887Skjd struct hostent * 374*26887Skjd _gethtbyname(name) 375*26887Skjd char *name; 376*26887Skjd { 377*26887Skjd register struct hostent *p; 378*26887Skjd register char **cp; 379*26887Skjd 380*26887Skjd _sethtent(0); 381*26887Skjd while (p = _gethtent()) { 382*26887Skjd if (strcmp(p->h_name, name) == 0) 383*26887Skjd break; 384*26887Skjd for (cp = p->h_aliases; *cp != 0; cp++) 385*26887Skjd if (strcmp(*cp, name) == 0) 386*26887Skjd goto found; 387*26887Skjd } 388*26887Skjd found: 389*26887Skjd _endhtent(); 390*26887Skjd return (p); 391*26887Skjd } 392*26887Skjd 393*26887Skjd struct hostent * 394*26887Skjd _gethtbyaddr(addr, len, type) 395*26887Skjd char *addr; 396*26887Skjd int len, type; 397*26887Skjd { 398*26887Skjd register struct hostent *p; 399*26887Skjd 400*26887Skjd _sethtent(0); 401*26887Skjd while (p = _gethtent()) 402*26887Skjd if (p->h_addrtype == type && bcmp(p->h_addr, addr, len)) 403*26887Skjd break; 404*26887Skjd _endhtent(); 405*26887Skjd return (p); 406*26887Skjd } 407