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*32075Skarels static char sccsid[] = "@(#)gethostnamadr.c 6.24 (Berkeley) 08/27/87"; 926630Sdonn #endif LIBC_SCCS and not lint 1021374Sdist 1130468Skjd #include <sys/param.h> 1218505Sralph #include <sys/socket.h> 1318505Sralph #include <netinet/in.h> 1426887Skjd #include <ctype.h> 1518505Sralph #include <netdb.h> 1615662Sralph #include <stdio.h> 1726887Skjd #include <errno.h> 1827034Skjd #include <arpa/inet.h> 1924508Sbloom #include <arpa/nameser.h> 2026894Skjd #include <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; 3126887Skjd static char HOSTDB[] = "/etc/hosts"; 3226887Skjd static FILE *hostf = NULL; 3326887Skjd static char line[BUFSIZ+1]; 3426887Skjd static char hostaddr[MAXADDRS]; 3526887Skjd static char *host_addrs[2]; 3626887Skjd static int stayopen = 0; 3726887Skjd 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; 5126887Skjd 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; 6327034Skjd int type, class, buflen, ancount, qdcount; 6427034Skjd int haveanswer, getclass = C_ANY; 6524687Sbloom char **hap; 6615662Sralph 6725302Skjd n = res_send(msg, msglen, (char *)&answer, sizeof(answer)); 6818505Sralph if (n < 0) { 6924733Sbloom #ifdef DEBUG 7026887Skjd int terrno; 7126887Skjd terrno = errno; 7218505Sralph if (_res.options & RES_DEBUG) 7318531Sralph printf("res_send failed\n"); 7426887Skjd 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; 14130468Skjd #if BSD >= 43 14224687Sbloom host.h_addr_list = h_addr_ptrs; 14330460Skjd #endif 14424687Sbloom haveanswer = 0; 14518505Sralph while (--ancount >= 0 && cp < eom) { 14626066Skjd if ((n = dn_expand((char *)&answer, eom, cp, bp, buflen)) < 0) 14724687Sbloom break; 14818505Sralph cp += n; 14930440Skjd type = _getshort(cp); 15018505Sralph cp += sizeof(u_short); 15130440Skjd class = _getshort(cp); 15218505Sralph cp += sizeof(u_short) + sizeof(u_long); 15330440Skjd n = _getshort(cp); 15418505Sralph cp += sizeof(u_short); 15518505Sralph if (type == T_CNAME) { 15618505Sralph cp += n; 15718505Sralph if (ap >= &host_aliases[MAXALIASES-1]) 15818505Sralph continue; 15918505Sralph *ap++ = bp; 16018505Sralph n = strlen(bp) + 1; 16118505Sralph bp += n; 16218505Sralph buflen -= n; 16318505Sralph continue; 16418505Sralph } 16525153Sbloom if (type == T_PTR) { 16627034Skjd if ((n = dn_expand((char *)&answer, eom, 16727034Skjd cp, bp, buflen)) < 0) { 16825153Sbloom cp += n; 16925153Sbloom continue; 17025153Sbloom } 17125153Sbloom cp += n; 17225153Sbloom host.h_name = bp; 17325153Sbloom return(&host); 17425153Sbloom } 17524687Sbloom if (type != T_A) { 17624733Sbloom #ifdef DEBUG 17718505Sralph if (_res.options & RES_DEBUG) 17818505Sralph printf("unexpected answer type %d, size %d\n", 17918505Sralph type, n); 18024733Sbloom #endif 18124687Sbloom cp += n; 18218505Sralph continue; 18318505Sralph } 18424687Sbloom if (haveanswer) { 18524687Sbloom if (n != host.h_length) { 18624687Sbloom cp += n; 18724687Sbloom continue; 18824687Sbloom } 18924687Sbloom if (class != getclass) { 19024687Sbloom cp += n; 19124687Sbloom continue; 19224687Sbloom } 19324687Sbloom } else { 19424687Sbloom host.h_length = n; 19524687Sbloom getclass = class; 19625386Skjd host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC; 19724687Sbloom if (!iquery) { 19824687Sbloom host.h_name = bp; 19924687Sbloom bp += strlen(bp) + 1; 20024687Sbloom } 20118505Sralph } 20225302Skjd 20331902Skarels bp += sizeof(align) - ((u_long)bp % sizeof(align)); 20425302Skjd 20518505Sralph if (bp + n >= &hostbuf[sizeof(hostbuf)]) { 20624733Sbloom #ifdef DEBUG 20718505Sralph if (_res.options & RES_DEBUG) 20818505Sralph printf("size (%d) too big\n", n); 20924733Sbloom #endif 21024687Sbloom break; 21118505Sralph } 21224687Sbloom bcopy(cp, *hap++ = bp, n); 21324687Sbloom bp +=n; 21424687Sbloom cp += n; 21524687Sbloom haveanswer++; 21624687Sbloom } 21724687Sbloom if (haveanswer) { 21824687Sbloom *ap = NULL; 21931902Skarels #if BSD >= 43 22024687Sbloom *hap = NULL; 22131902Skarels #else 22231902Skarels host.h_addr = h_addr_ptrs[0]; 22331902Skarels #endif 22418505Sralph return (&host); 22525484Skjd } else { 22625484Skjd h_errno = TRY_AGAIN; 22724687Sbloom return (NULL); 22825484Skjd } 22915662Sralph } 23015662Sralph 23115662Sralph struct hostent * 23218505Sralph gethostbyname(name) 23318505Sralph char *name; 23415662Sralph { 23531111Skarels register char *cp, **domain; 23618505Sralph int n; 23731111Skarels struct hostent *hp, *gethostdomain(); 23831111Skarels char *hostalias(); 23926887Skjd extern struct hostent *_gethtbyname(); 24015662Sralph 24131111Skarels if (!(_res.options & RES_INIT) && res_init() == -1) 24231111Skarels return (NULL); 24331994Skarels if (isdigit(name[0])) { 24431994Skarels h_errno = HOST_NOT_FOUND; 24531994Skarels return (NULL); 24631994Skarels 24731994Skarels } 24829930Skjd errno = 0; 24931111Skarels for (cp = name, n = 0; *cp; cp++) 25031111Skarels if (*cp == '.') 25131111Skarels n++; 25231902Skarels if ((n && *--cp == '.') || (_res.options & RES_DEFNAMES) == 0) { 253*32075Skarels int defflag = _res.options & RES_DEFNAMES; 254*32075Skarels 255*32075Skarels _res.options &= ~RES_DEFNAMES; /* XXX */ 25631902Skarels if (n && *cp == '.') 25731902Skarels *cp = 0; 25831111Skarels hp = gethostdomain(name, (char *)NULL); 259*32075Skarels if (n && *cp == 0) 26031902Skarels *cp = '.'; 261*32075Skarels if (defflag) 262*32075Skarels _res.options |= RES_DEFNAMES; 26331111Skarels return (hp); 26431111Skarels } 26531111Skarels if (n == 0 && (cp = hostalias(name))) 26631111Skarels return (gethostdomain(cp, (char *)NULL)); 26731111Skarels for (domain = _res.dnsrch; *domain; domain++) { 26831111Skarels hp = gethostdomain(name, *domain); 26931111Skarels if (hp) 27031111Skarels return (hp); 27131960Sbostic /* 27231960Sbostic * If no server present, use host table. 27331960Sbostic * If host isn't found in this domain, 27431960Sbostic * keep trying higher domains in the search list 27531960Sbostic * (if that's enabled). 27631960Sbostic * On a NO_ADDRESS error, keep trying, 27731960Sbostic * or a wildcard MX entry could keep us from finding 27831960Sbostic * host entries higher in the domain. 27931960Sbostic */ 28031111Skarels if (errno == ECONNREFUSED) 28131111Skarels return (_gethtbyname(name)); 28231960Sbostic if ((h_errno != HOST_NOT_FOUND && 28331960Sbostic h_errno != NO_ADDRESS) || 28431111Skarels (_res.options & RES_DNSRCH) == 0) 28531111Skarels return (NULL); 28631709Skarels h_errno = 0; 28731111Skarels } 28831111Skarels return (gethostdomain(name, (char *)NULL)); 28931111Skarels } 29031111Skarels 29131111Skarels static struct hostent * 29231111Skarels gethostdomain(name, domain) 29331111Skarels char *name, *domain; 29431111Skarels { 29531111Skarels querybuf buf; 29631111Skarels char nbuf[2*MAXDNAME+2]; 29731111Skarels int n; 29831111Skarels 29931902Skarels if (domain == NULL) 30031902Skarels sprintf(nbuf, "%.*s", MAXDNAME, name); 30131902Skarels else 30231902Skarels sprintf(nbuf, "%.*s.%.*s", MAXDNAME, name, MAXDNAME, domain); 30331111Skarels n = res_mkquery(QUERY, nbuf, C_IN, T_A, (char *)NULL, 0, NULL, 30425302Skjd (char *)&buf, sizeof(buf)); 30518505Sralph if (n < 0) { 30624733Sbloom #ifdef DEBUG 30718505Sralph if (_res.options & RES_DEBUG) 30818531Sralph printf("res_mkquery failed\n"); 30924733Sbloom #endif 31018505Sralph return (NULL); 31117761Sserge } 31231111Skarels return (getanswer((char *)&buf, n, 0)); 31315662Sralph } 31415662Sralph 31515662Sralph struct hostent * 31618505Sralph gethostbyaddr(addr, len, type) 31715662Sralph char *addr; 31818505Sralph int len, type; 31915662Sralph { 32018505Sralph int n; 32125302Skjd querybuf buf; 32225153Sbloom register struct hostent *hp; 32325153Sbloom char qbuf[MAXDNAME]; 32426887Skjd extern struct hostent *_gethtbyaddr(); 32526887Skjd 32618505Sralph if (type != AF_INET) 32718505Sralph return (NULL); 32825153Sbloom (void)sprintf(qbuf, "%d.%d.%d.%d.in-addr.arpa", 32925484Skjd ((unsigned)addr[3] & 0xff), 33025484Skjd ((unsigned)addr[2] & 0xff), 33125484Skjd ((unsigned)addr[1] & 0xff), 33225484Skjd ((unsigned)addr[0] & 0xff)); 33327034Skjd n = res_mkquery(QUERY, qbuf, C_IN, T_PTR, (char *)NULL, 0, NULL, 33425302Skjd (char *)&buf, sizeof(buf)); 33518505Sralph if (n < 0) { 33624733Sbloom #ifdef DEBUG 33718505Sralph if (_res.options & RES_DEBUG) 33818531Sralph printf("res_mkquery failed\n"); 33924733Sbloom #endif 34018505Sralph return (NULL); 34117761Sserge } 34226887Skjd hp = getanswer((char *)&buf, n, 1); 34326887Skjd if (hp == NULL && errno == ECONNREFUSED) 34426887Skjd hp = _gethtbyaddr(addr, len, type); 34526887Skjd if (hp == NULL) 34625153Sbloom return(NULL); 34725153Sbloom hp->h_addrtype = type; 34825153Sbloom hp->h_length = len; 34925282Sbloom h_addr_ptrs[0] = (char *)&host_addr; 35025153Sbloom h_addr_ptrs[1] = (char *)0; 35125153Sbloom host_addr = *(struct in_addr *)addr; 35225153Sbloom return(hp); 35315662Sralph } 35425302Skjd 35531111Skarels char * 35631111Skarels hostalias(name) 35731111Skarels register char *name; 35831111Skarels { 35931780Sbostic register char *C1, *C2; 36031111Skarels FILE *fp; 36131780Sbostic char *file, *getenv(), *strcpy(), *strncpy(); 36231780Sbostic char buf[BUFSIZ]; 36331111Skarels static char abuf[MAXDNAME]; 36426887Skjd 36531111Skarels file = getenv("HOSTALIASES"); 36631111Skarels if (file == NULL || (fp = fopen(file, "r")) == NULL) 36731111Skarels return (NULL); 36831780Sbostic buf[sizeof(buf) - 1] = '\0'; 36931780Sbostic while (fgets(buf, sizeof(buf), fp)) { 37031780Sbostic for (C1 = buf; *C1 && !isspace(*C1); ++C1); 37131780Sbostic if (!*C1 || *C1 == '\n') 37231780Sbostic break; 37331994Skarels if (!strncasecmp(buf, name, C1 - buf)) { 37431780Sbostic while (isspace(*++C1)); 37531780Sbostic if (!*C1) 37631780Sbostic break; 37731780Sbostic for (C2 = C1 + 1; *C2 && !isspace(*C2); ++C2); 37831780Sbostic abuf[sizeof(abuf) - 1] = *C2 = '\0'; 37931780Sbostic (void)strncpy(abuf, C1, sizeof(abuf) - 1); 38031111Skarels fclose(fp); 38131111Skarels return (abuf); 38231111Skarels } 38331780Sbostic } 38431111Skarels fclose(fp); 38531111Skarels return (NULL); 38631111Skarels } 38731111Skarels 38826887Skjd _sethtent(f) 38926887Skjd int f; 39026887Skjd { 39126887Skjd if (hostf == NULL) 39226887Skjd hostf = fopen(HOSTDB, "r" ); 39326887Skjd else 39426887Skjd rewind(hostf); 39526887Skjd stayopen |= f; 39626887Skjd } 39726887Skjd 39826887Skjd _endhtent() 39926887Skjd { 40026887Skjd if (hostf && !stayopen) { 40127034Skjd (void) fclose(hostf); 40226887Skjd hostf = NULL; 40326887Skjd } 40426887Skjd } 40526887Skjd 40626887Skjd struct hostent * 40726887Skjd _gethtent() 40826887Skjd { 40926887Skjd char *p; 41026887Skjd register char *cp, **q; 41126887Skjd 41226887Skjd if (hostf == NULL && (hostf = fopen(HOSTDB, "r" )) == NULL) 41326887Skjd return (NULL); 41426887Skjd again: 41526887Skjd if ((p = fgets(line, BUFSIZ, hostf)) == NULL) 41626887Skjd return (NULL); 41726887Skjd if (*p == '#') 41826887Skjd goto again; 41926887Skjd cp = any(p, "#\n"); 42026887Skjd if (cp == NULL) 42126887Skjd goto again; 42226887Skjd *cp = '\0'; 42326887Skjd cp = any(p, " \t"); 42426887Skjd if (cp == NULL) 42526887Skjd goto again; 42626887Skjd *cp++ = '\0'; 42726887Skjd /* THIS STUFF IS INTERNET SPECIFIC */ 42830468Skjd #if BSD >= 43 42926887Skjd host.h_addr_list = host_addrs; 43030460Skjd #endif 43126887Skjd host.h_addr = hostaddr; 43226887Skjd *((u_long *)host.h_addr) = inet_addr(p); 43326887Skjd host.h_length = sizeof (u_long); 43426887Skjd host.h_addrtype = AF_INET; 43526887Skjd while (*cp == ' ' || *cp == '\t') 43626887Skjd cp++; 43726887Skjd host.h_name = cp; 43826887Skjd q = host.h_aliases = host_aliases; 43926887Skjd cp = any(cp, " \t"); 44026887Skjd if (cp != NULL) 44126887Skjd *cp++ = '\0'; 44226887Skjd while (cp && *cp) { 44326887Skjd if (*cp == ' ' || *cp == '\t') { 44426887Skjd cp++; 44526887Skjd continue; 44626887Skjd } 44726887Skjd if (q < &host_aliases[MAXALIASES - 1]) 44826887Skjd *q++ = cp; 44926887Skjd cp = any(cp, " \t"); 45026887Skjd if (cp != NULL) 45126887Skjd *cp++ = '\0'; 45226887Skjd } 45326887Skjd *q = NULL; 45426887Skjd return (&host); 45526887Skjd } 45626887Skjd 45726887Skjd static char * 45826887Skjd any(cp, match) 45926887Skjd register char *cp; 46026887Skjd char *match; 46126887Skjd { 46226887Skjd register char *mp, c; 46326887Skjd 46426887Skjd while (c = *cp) { 46526887Skjd for (mp = match; *mp; mp++) 46626887Skjd if (*mp == c) 46726887Skjd return (cp); 46826887Skjd cp++; 46926887Skjd } 47026887Skjd return ((char *)0); 47126887Skjd } 47226887Skjd 47326887Skjd struct hostent * 47426887Skjd _gethtbyname(name) 47526887Skjd char *name; 47626887Skjd { 47726887Skjd register struct hostent *p; 47826887Skjd register char **cp; 47928307Skarels 48026887Skjd _sethtent(0); 48126887Skjd while (p = _gethtent()) { 48231960Sbostic if (strcasecmp(p->h_name, name) == 0) 48326887Skjd break; 48426887Skjd for (cp = p->h_aliases; *cp != 0; cp++) 48531960Sbostic if (strcasecmp(*cp, name) == 0) 48626887Skjd goto found; 48726887Skjd } 48826887Skjd found: 48926887Skjd _endhtent(); 49026887Skjd return (p); 49126887Skjd } 49226887Skjd 49326887Skjd struct hostent * 49426887Skjd _gethtbyaddr(addr, len, type) 49526887Skjd char *addr; 49626887Skjd int len, type; 49726887Skjd { 49826887Skjd register struct hostent *p; 49926887Skjd 50026887Skjd _sethtent(0); 50126887Skjd while (p = _gethtent()) 50226909Skjd if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len)) 50326887Skjd break; 50426887Skjd _endhtent(); 50526887Skjd return (p); 50626887Skjd } 507