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*33500Skarels static char sccsid[] = "@(#)gethostnamadr.c 6.28 (Berkeley) 02/18/88"; 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 3932648Skarels #if PACKETSZ > 1024 4032648Skarels #define MAXPACKET PACKETSZ 4132648Skarels #else 4232648Skarels #define MAXPACKET 1024 4332648Skarels #endif 4432648Skarels 4525302Skjd typedef union { 4625302Skjd HEADER qb1; 4732648Skarels char qb2[MAXPACKET]; 4825302Skjd } querybuf; 4924509Sbloom 5025302Skjd static union { 5125302Skjd long al; 5225302Skjd char ac; 5325302Skjd } align; 5425302Skjd 5525302Skjd 5625484Skjd int h_errno; 5726887Skjd extern errno; 5825484Skjd 5915662Sralph static struct hostent * 6018505Sralph getanswer(msg, msglen, iquery) 6118505Sralph char *msg; 6218505Sralph int msglen, iquery; 6315662Sralph { 6418505Sralph register HEADER *hp; 6518505Sralph register char *cp; 6618505Sralph register int n; 6725302Skjd querybuf answer; 6818505Sralph char *eom, *bp, **ap; 6927034Skjd int type, class, buflen, ancount, qdcount; 7027034Skjd int haveanswer, getclass = C_ANY; 7124687Sbloom char **hap; 7215662Sralph 7325302Skjd n = res_send(msg, msglen, (char *)&answer, sizeof(answer)); 7418505Sralph if (n < 0) { 7524733Sbloom #ifdef DEBUG 7626887Skjd int terrno; 7726887Skjd terrno = errno; 7818505Sralph if (_res.options & RES_DEBUG) 7918531Sralph printf("res_send failed\n"); 8026887Skjd errno = terrno; 8124733Sbloom #endif 8225484Skjd h_errno = TRY_AGAIN; 83*33500Skarels return ((struct hostent *) NULL); 8415662Sralph } 8525302Skjd eom = (char *)&answer + n; 8618505Sralph /* 8718505Sralph * find first satisfactory answer 8818505Sralph */ 8925302Skjd hp = (HEADER *) &answer; 9018505Sralph ancount = ntohs(hp->ancount); 9125153Sbloom qdcount = ntohs(hp->qdcount); 9218505Sralph if (hp->rcode != NOERROR || ancount == 0) { 9324733Sbloom #ifdef DEBUG 9418505Sralph if (_res.options & RES_DEBUG) 9518505Sralph printf("rcode = %d, ancount=%d\n", hp->rcode, ancount); 9624733Sbloom #endif 9725484Skjd switch (hp->rcode) { 9825484Skjd case NXDOMAIN: 9925484Skjd /* Check if it's an authoritive answer */ 10025484Skjd if (hp->aa) 10125484Skjd h_errno = HOST_NOT_FOUND; 10225484Skjd else 10325484Skjd h_errno = TRY_AGAIN; 10425484Skjd break; 10525484Skjd case SERVFAIL: 10625484Skjd h_errno = TRY_AGAIN; 10725484Skjd break; 10825484Skjd case NOERROR: 10932648Skarels if (hp->aa) 11032648Skarels h_errno = NO_ADDRESS; 11132648Skarels else 11232648Skarels h_errno = TRY_AGAIN; 11325484Skjd break; 11425484Skjd case FORMERR: 11525484Skjd case NOTIMP: 11625484Skjd case REFUSED: 11725484Skjd h_errno = NO_RECOVERY; 11825484Skjd } 119*33500Skarels return ((struct hostent *) NULL); 12018505Sralph } 12118505Sralph bp = hostbuf; 12218505Sralph buflen = sizeof(hostbuf); 12325302Skjd cp = (char *)&answer + sizeof(HEADER); 12425153Sbloom if (qdcount) { 12518505Sralph if (iquery) { 12626066Skjd if ((n = dn_expand((char *)&answer, eom, 12726066Skjd cp, bp, buflen)) < 0) { 12825484Skjd h_errno = NO_RECOVERY; 129*33500Skarels return ((struct hostent *) NULL); 13025484Skjd } 13118505Sralph cp += n + QFIXEDSZ; 13218505Sralph host.h_name = bp; 13318505Sralph n = strlen(bp) + 1; 13418505Sralph bp += n; 13518505Sralph buflen -= n; 13618505Sralph } else 13732648Skarels cp += dn_skipname(cp, eom) + QFIXEDSZ; 13825153Sbloom while (--qdcount > 0) 13932648Skarels cp += dn_skipname(cp, eom) + QFIXEDSZ; 14025484Skjd } else if (iquery) { 14125484Skjd if (hp->aa) 14225484Skjd h_errno = HOST_NOT_FOUND; 14325484Skjd else 14425484Skjd h_errno = TRY_AGAIN; 145*33500Skarels return ((struct hostent *) NULL); 14625484Skjd } 14724687Sbloom ap = host_aliases; 14824687Sbloom host.h_aliases = host_aliases; 14924687Sbloom hap = h_addr_ptrs; 15030468Skjd #if BSD >= 43 15124687Sbloom host.h_addr_list = h_addr_ptrs; 15230460Skjd #endif 15324687Sbloom haveanswer = 0; 15418505Sralph while (--ancount >= 0 && cp < eom) { 15526066Skjd if ((n = dn_expand((char *)&answer, eom, cp, bp, buflen)) < 0) 15624687Sbloom break; 15718505Sralph cp += n; 15830440Skjd type = _getshort(cp); 15918505Sralph cp += sizeof(u_short); 16030440Skjd class = _getshort(cp); 16118505Sralph cp += sizeof(u_short) + sizeof(u_long); 16230440Skjd n = _getshort(cp); 16318505Sralph cp += sizeof(u_short); 16418505Sralph if (type == T_CNAME) { 16518505Sralph cp += n; 16618505Sralph if (ap >= &host_aliases[MAXALIASES-1]) 16718505Sralph continue; 16818505Sralph *ap++ = bp; 16918505Sralph n = strlen(bp) + 1; 17018505Sralph bp += n; 17118505Sralph buflen -= n; 17218505Sralph continue; 17318505Sralph } 17425153Sbloom if (type == T_PTR) { 17527034Skjd if ((n = dn_expand((char *)&answer, eom, 17627034Skjd cp, bp, buflen)) < 0) { 17725153Sbloom cp += n; 17825153Sbloom continue; 17925153Sbloom } 18025153Sbloom cp += n; 18125153Sbloom host.h_name = bp; 18225153Sbloom return(&host); 18325153Sbloom } 18424687Sbloom if (type != T_A) { 18524733Sbloom #ifdef DEBUG 18618505Sralph if (_res.options & RES_DEBUG) 18718505Sralph printf("unexpected answer type %d, size %d\n", 18818505Sralph type, n); 18924733Sbloom #endif 19024687Sbloom cp += n; 19118505Sralph continue; 19218505Sralph } 19324687Sbloom if (haveanswer) { 19424687Sbloom if (n != host.h_length) { 19524687Sbloom cp += n; 19624687Sbloom continue; 19724687Sbloom } 19824687Sbloom if (class != getclass) { 19924687Sbloom cp += n; 20024687Sbloom continue; 20124687Sbloom } 20224687Sbloom } else { 20324687Sbloom host.h_length = n; 20424687Sbloom getclass = class; 20525386Skjd host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC; 20624687Sbloom if (!iquery) { 20724687Sbloom host.h_name = bp; 20824687Sbloom bp += strlen(bp) + 1; 20924687Sbloom } 21018505Sralph } 21125302Skjd 21231902Skarels bp += sizeof(align) - ((u_long)bp % sizeof(align)); 21325302Skjd 21418505Sralph if (bp + n >= &hostbuf[sizeof(hostbuf)]) { 21524733Sbloom #ifdef DEBUG 21618505Sralph if (_res.options & RES_DEBUG) 21718505Sralph printf("size (%d) too big\n", n); 21824733Sbloom #endif 21924687Sbloom break; 22018505Sralph } 22124687Sbloom bcopy(cp, *hap++ = bp, n); 22224687Sbloom bp +=n; 22324687Sbloom cp += n; 22424687Sbloom haveanswer++; 22524687Sbloom } 22624687Sbloom if (haveanswer) { 22724687Sbloom *ap = NULL; 22831902Skarels #if BSD >= 43 22924687Sbloom *hap = NULL; 23031902Skarels #else 23131902Skarels host.h_addr = h_addr_ptrs[0]; 23231902Skarels #endif 23318505Sralph return (&host); 23425484Skjd } else { 23525484Skjd h_errno = TRY_AGAIN; 236*33500Skarels return ((struct hostent *) NULL); 23725484Skjd } 23815662Sralph } 23915662Sralph 24015662Sralph struct hostent * 24118505Sralph gethostbyname(name) 24218505Sralph char *name; 24315662Sralph { 24431111Skarels register char *cp, **domain; 24518505Sralph int n; 24631111Skarels struct hostent *hp, *gethostdomain(); 24731111Skarels char *hostalias(); 24826887Skjd extern struct hostent *_gethtbyname(); 24915662Sralph 25031111Skarels if (!(_res.options & RES_INIT) && res_init() == -1) 251*33500Skarels return ((struct hostent *) NULL); 25232976Sbostic /* 25332976Sbostic * disallow names consisting only of digits/dots, unless 25432976Sbostic * they end in a dot. 25532976Sbostic */ 25632976Sbostic if (isdigit(name[0])) 25732976Sbostic for (cp = name;; ++cp) { 25832976Sbostic if (!*cp) { 25932976Sbostic if (*--cp == '.') 26032976Sbostic break; 26132976Sbostic h_errno = HOST_NOT_FOUND; 262*33500Skarels return ((struct hostent *) NULL); 26332976Sbostic } 26432976Sbostic if (!isdigit(*cp) && *cp != '.') 26532976Sbostic break; 26632976Sbostic } 26729930Skjd errno = 0; 26831111Skarels for (cp = name, n = 0; *cp; cp++) 26931111Skarels if (*cp == '.') 27031111Skarels n++; 27131111Skarels if (n == 0 && (cp = hostalias(name))) 27231111Skarels return (gethostdomain(cp, (char *)NULL)); 273*33500Skarels if ((n == 0 || *--cp != '.') && (_res.options & RES_DEFNAMES)) 274*33500Skarels for (domain = _res.dnsrch; *domain; domain++) { 27531111Skarels hp = gethostdomain(name, *domain); 27631111Skarels if (hp) 27731111Skarels return (hp); 27831960Sbostic /* 27931960Sbostic * If no server present, use host table. 28031960Sbostic * If host isn't found in this domain, 28131960Sbostic * keep trying higher domains in the search list 28231960Sbostic * (if that's enabled). 283*33500Skarels * On a NO_ADDRESS error, keep trying, otherwise 284*33500Skarels * a wildcard MX entry could keep us from finding 28531960Sbostic * host entries higher in the domain. 286*33500Skarels * If we get some other error (non-authoritative negative 287*33500Skarels * answer or server failure), then stop searching up, 288*33500Skarels * but try the input name below in case it's fully-qualified. 28931960Sbostic */ 29031111Skarels if (errno == ECONNREFUSED) 29131111Skarels return (_gethtbyname(name)); 292*33500Skarels if ((h_errno != HOST_NOT_FOUND && h_errno != NO_ADDRESS) || 29331111Skarels (_res.options & RES_DNSRCH) == 0) 294*33500Skarels break; 29531709Skarels h_errno = 0; 29631111Skarels } 297*33500Skarels /* 298*33500Skarels * If the search/default failed, try the name as fully-qualified, 299*33500Skarels * but only if it contained at least one dot (even trailing). 300*33500Skarels */ 301*33500Skarels if (n) 302*33500Skarels return (gethostdomain(name, (char *)NULL)); 303*33500Skarels return ((struct hostent *) NULL); 30431111Skarels } 30531111Skarels 30631111Skarels static struct hostent * 30731111Skarels gethostdomain(name, domain) 30831111Skarels char *name, *domain; 30931111Skarels { 31031111Skarels querybuf buf; 31131111Skarels char nbuf[2*MAXDNAME+2]; 312*33500Skarels char *longname = nbuf; 31331111Skarels int n; 31431111Skarels 315*33500Skarels if (domain == NULL) { 316*33500Skarels /* 317*33500Skarels * Check for trailing '.'; 318*33500Skarels * copy without '.' if present. 319*33500Skarels */ 320*33500Skarels n = strlen(name) - 1; 321*33500Skarels if (name[n] == '.' && n < sizeof(nbuf) - 1) { 322*33500Skarels bcopy(name, nbuf, n); 323*33500Skarels nbuf[n] = '\0'; 324*33500Skarels } else 325*33500Skarels longname = name; 326*33500Skarels } else 32732648Skarels (void)sprintf(nbuf, "%.*s.%.*s", 32832648Skarels MAXDNAME, name, MAXDNAME, domain); 329*33500Skarels n = res_mkquery(QUERY, longname, C_IN, T_A, (char *)NULL, 0, NULL, 33025302Skjd (char *)&buf, sizeof(buf)); 33118505Sralph if (n < 0) { 33224733Sbloom #ifdef DEBUG 33318505Sralph if (_res.options & RES_DEBUG) 33418531Sralph printf("res_mkquery failed\n"); 33524733Sbloom #endif 336*33500Skarels return ((struct hostent *) NULL); 33717761Sserge } 33831111Skarels return (getanswer((char *)&buf, n, 0)); 33915662Sralph } 34015662Sralph 34115662Sralph struct hostent * 34218505Sralph gethostbyaddr(addr, len, type) 34315662Sralph char *addr; 34418505Sralph int len, type; 34515662Sralph { 34618505Sralph int n; 34725302Skjd querybuf buf; 34825153Sbloom register struct hostent *hp; 34925153Sbloom char qbuf[MAXDNAME]; 35026887Skjd extern struct hostent *_gethtbyaddr(); 35126887Skjd 35218505Sralph if (type != AF_INET) 353*33500Skarels return ((struct hostent *) NULL); 35425153Sbloom (void)sprintf(qbuf, "%d.%d.%d.%d.in-addr.arpa", 35525484Skjd ((unsigned)addr[3] & 0xff), 35625484Skjd ((unsigned)addr[2] & 0xff), 35725484Skjd ((unsigned)addr[1] & 0xff), 35825484Skjd ((unsigned)addr[0] & 0xff)); 35927034Skjd n = res_mkquery(QUERY, qbuf, C_IN, T_PTR, (char *)NULL, 0, NULL, 36025302Skjd (char *)&buf, sizeof(buf)); 36118505Sralph if (n < 0) { 36224733Sbloom #ifdef DEBUG 36318505Sralph if (_res.options & RES_DEBUG) 36418531Sralph printf("res_mkquery failed\n"); 36524733Sbloom #endif 366*33500Skarels return ((struct hostent *) NULL); 36717761Sserge } 36826887Skjd hp = getanswer((char *)&buf, n, 1); 36926887Skjd if (hp == NULL && errno == ECONNREFUSED) 37026887Skjd hp = _gethtbyaddr(addr, len, type); 37126887Skjd if (hp == NULL) 372*33500Skarels return ((struct hostent *) NULL); 37325153Sbloom hp->h_addrtype = type; 37425153Sbloom hp->h_length = len; 37525282Sbloom h_addr_ptrs[0] = (char *)&host_addr; 37625153Sbloom h_addr_ptrs[1] = (char *)0; 37725153Sbloom host_addr = *(struct in_addr *)addr; 37825153Sbloom return(hp); 37915662Sralph } 38025302Skjd 38131111Skarels char * 38231111Skarels hostalias(name) 38331111Skarels register char *name; 38431111Skarels { 38531780Sbostic register char *C1, *C2; 38631111Skarels FILE *fp; 38731780Sbostic char *file, *getenv(), *strcpy(), *strncpy(); 38831780Sbostic char buf[BUFSIZ]; 38931111Skarels static char abuf[MAXDNAME]; 39026887Skjd 39131111Skarels file = getenv("HOSTALIASES"); 39231111Skarels if (file == NULL || (fp = fopen(file, "r")) == NULL) 39331111Skarels return (NULL); 39431780Sbostic buf[sizeof(buf) - 1] = '\0'; 39531780Sbostic while (fgets(buf, sizeof(buf), fp)) { 39631780Sbostic for (C1 = buf; *C1 && !isspace(*C1); ++C1); 39732169Sbostic if (!*C1) 39831780Sbostic break; 39932169Sbostic *C1 = '\0'; 40032169Sbostic if (!strcasecmp(buf, name)) { 40131780Sbostic while (isspace(*++C1)); 40231780Sbostic if (!*C1) 40331780Sbostic break; 40431780Sbostic for (C2 = C1 + 1; *C2 && !isspace(*C2); ++C2); 40531780Sbostic abuf[sizeof(abuf) - 1] = *C2 = '\0'; 40631780Sbostic (void)strncpy(abuf, C1, sizeof(abuf) - 1); 40731111Skarels fclose(fp); 40831111Skarels return (abuf); 40931111Skarels } 41031780Sbostic } 41131111Skarels fclose(fp); 41231111Skarels return (NULL); 41331111Skarels } 41431111Skarels 41526887Skjd _sethtent(f) 41626887Skjd int f; 41726887Skjd { 41826887Skjd if (hostf == NULL) 41926887Skjd hostf = fopen(HOSTDB, "r" ); 42026887Skjd else 42126887Skjd rewind(hostf); 42226887Skjd stayopen |= f; 42326887Skjd } 42426887Skjd 42526887Skjd _endhtent() 42626887Skjd { 42726887Skjd if (hostf && !stayopen) { 42827034Skjd (void) fclose(hostf); 42926887Skjd hostf = NULL; 43026887Skjd } 43126887Skjd } 43226887Skjd 43326887Skjd struct hostent * 43426887Skjd _gethtent() 43526887Skjd { 43626887Skjd char *p; 43726887Skjd register char *cp, **q; 43826887Skjd 43926887Skjd if (hostf == NULL && (hostf = fopen(HOSTDB, "r" )) == NULL) 44026887Skjd return (NULL); 44126887Skjd again: 44226887Skjd if ((p = fgets(line, BUFSIZ, hostf)) == NULL) 44326887Skjd return (NULL); 44426887Skjd if (*p == '#') 44526887Skjd goto again; 44626887Skjd cp = any(p, "#\n"); 44726887Skjd if (cp == NULL) 44826887Skjd goto again; 44926887Skjd *cp = '\0'; 45026887Skjd cp = any(p, " \t"); 45126887Skjd if (cp == NULL) 45226887Skjd goto again; 45326887Skjd *cp++ = '\0'; 45426887Skjd /* THIS STUFF IS INTERNET SPECIFIC */ 45530468Skjd #if BSD >= 43 45626887Skjd host.h_addr_list = host_addrs; 45730460Skjd #endif 45826887Skjd host.h_addr = hostaddr; 45926887Skjd *((u_long *)host.h_addr) = inet_addr(p); 46026887Skjd host.h_length = sizeof (u_long); 46126887Skjd host.h_addrtype = AF_INET; 46226887Skjd while (*cp == ' ' || *cp == '\t') 46326887Skjd cp++; 46426887Skjd host.h_name = cp; 46526887Skjd q = host.h_aliases = host_aliases; 46626887Skjd cp = any(cp, " \t"); 46726887Skjd if (cp != NULL) 46826887Skjd *cp++ = '\0'; 46926887Skjd while (cp && *cp) { 47026887Skjd if (*cp == ' ' || *cp == '\t') { 47126887Skjd cp++; 47226887Skjd continue; 47326887Skjd } 47426887Skjd if (q < &host_aliases[MAXALIASES - 1]) 47526887Skjd *q++ = cp; 47626887Skjd cp = any(cp, " \t"); 47726887Skjd if (cp != NULL) 47826887Skjd *cp++ = '\0'; 47926887Skjd } 48026887Skjd *q = NULL; 48126887Skjd return (&host); 48226887Skjd } 48326887Skjd 48426887Skjd static char * 48526887Skjd any(cp, match) 48626887Skjd register char *cp; 48726887Skjd char *match; 48826887Skjd { 48926887Skjd register char *mp, c; 49026887Skjd 49126887Skjd while (c = *cp) { 49226887Skjd for (mp = match; *mp; mp++) 49326887Skjd if (*mp == c) 49426887Skjd return (cp); 49526887Skjd cp++; 49626887Skjd } 49726887Skjd return ((char *)0); 49826887Skjd } 49926887Skjd 50026887Skjd struct hostent * 50126887Skjd _gethtbyname(name) 50226887Skjd char *name; 50326887Skjd { 50426887Skjd register struct hostent *p; 50526887Skjd register char **cp; 50628307Skarels 50726887Skjd _sethtent(0); 50826887Skjd while (p = _gethtent()) { 50931960Sbostic if (strcasecmp(p->h_name, name) == 0) 51026887Skjd break; 51126887Skjd for (cp = p->h_aliases; *cp != 0; cp++) 51231960Sbostic if (strcasecmp(*cp, name) == 0) 51326887Skjd goto found; 51426887Skjd } 51526887Skjd found: 51626887Skjd _endhtent(); 51726887Skjd return (p); 51826887Skjd } 51926887Skjd 52026887Skjd struct hostent * 52126887Skjd _gethtbyaddr(addr, len, type) 52226887Skjd char *addr; 52326887Skjd int len, type; 52426887Skjd { 52526887Skjd register struct hostent *p; 52626887Skjd 52726887Skjd _sethtent(0); 52826887Skjd while (p = _gethtent()) 52926909Skjd if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len)) 53026887Skjd break; 53126887Skjd _endhtent(); 53226887Skjd return (p); 53326887Skjd } 534