121374Sdist /* 2*33734Sbostic * Copyright (c) 1985, 1988 Regents of the University of California. 3*33734Sbostic * All rights reserved. 4*33734Sbostic * 5*33734Sbostic * Redistribution and use in source and binary forms are permitted 6*33734Sbostic * provided that this notice is preserved and that due credit is given 7*33734Sbostic * to the University of California at Berkeley. The name of the University 8*33734Sbostic * may not be used to endorse or promote products derived from this 9*33734Sbostic * software without specific prior written permission. This software 10*33734Sbostic * is provided ``as is'' without express or implied warranty. 1121374Sdist */ 1215662Sralph 1326630Sdonn #if defined(LIBC_SCCS) && !defined(lint) 14*33734Sbostic static char sccsid[] = "@(#)gethostnamadr.c 6.30 (Berkeley) 03/14/88"; 15*33734Sbostic #endif /* LIBC_SCCS and not lint */ 1621374Sdist 1730468Skjd #include <sys/param.h> 1818505Sralph #include <sys/socket.h> 1918505Sralph #include <netinet/in.h> 2026887Skjd #include <ctype.h> 2118505Sralph #include <netdb.h> 2215662Sralph #include <stdio.h> 2326887Skjd #include <errno.h> 2427034Skjd #include <arpa/inet.h> 2524508Sbloom #include <arpa/nameser.h> 2626894Skjd #include <resolv.h> 2715662Sralph 2815662Sralph #define MAXALIASES 35 2924687Sbloom #define MAXADDRS 35 3015662Sralph 3124687Sbloom static char *h_addr_ptrs[MAXADDRS + 1]; 3224687Sbloom 3324687Sbloom static struct hostent host; 3415662Sralph static char *host_aliases[MAXALIASES]; 3515912Sralph static char hostbuf[BUFSIZ+1]; 3625153Sbloom static struct in_addr host_addr; 3726887Skjd static char HOSTDB[] = "/etc/hosts"; 3826887Skjd static FILE *hostf = NULL; 3926887Skjd static char line[BUFSIZ+1]; 4026887Skjd static char hostaddr[MAXADDRS]; 4126887Skjd static char *host_addrs[2]; 4226887Skjd static int stayopen = 0; 4326887Skjd static char *any(); 4415662Sralph 4532648Skarels #if PACKETSZ > 1024 4632648Skarels #define MAXPACKET PACKETSZ 4732648Skarels #else 4832648Skarels #define MAXPACKET 1024 4932648Skarels #endif 5032648Skarels 5125302Skjd typedef union { 5225302Skjd HEADER qb1; 5332648Skarels char qb2[MAXPACKET]; 5425302Skjd } querybuf; 5524509Sbloom 5625302Skjd static union { 5725302Skjd long al; 5825302Skjd char ac; 5925302Skjd } align; 6025302Skjd 6125302Skjd 6225484Skjd int h_errno; 6326887Skjd extern errno; 6425484Skjd 6515662Sralph static struct hostent * 6618505Sralph getanswer(msg, msglen, iquery) 6718505Sralph char *msg; 6818505Sralph int msglen, iquery; 6915662Sralph { 7018505Sralph register HEADER *hp; 7118505Sralph register char *cp; 7218505Sralph register int n; 7325302Skjd querybuf answer; 7418505Sralph char *eom, *bp, **ap; 7527034Skjd int type, class, buflen, ancount, qdcount; 7627034Skjd int haveanswer, getclass = C_ANY; 7724687Sbloom char **hap; 7815662Sralph 7925302Skjd n = res_send(msg, msglen, (char *)&answer, sizeof(answer)); 8018505Sralph if (n < 0) { 8124733Sbloom #ifdef DEBUG 8226887Skjd int terrno; 8326887Skjd terrno = errno; 8418505Sralph if (_res.options & RES_DEBUG) 8518531Sralph printf("res_send failed\n"); 8626887Skjd errno = terrno; 8724733Sbloom #endif 8825484Skjd h_errno = TRY_AGAIN; 8933500Skarels return ((struct hostent *) NULL); 9015662Sralph } 9125302Skjd eom = (char *)&answer + n; 9218505Sralph /* 9318505Sralph * find first satisfactory answer 9418505Sralph */ 9525302Skjd hp = (HEADER *) &answer; 9618505Sralph ancount = ntohs(hp->ancount); 9725153Sbloom qdcount = ntohs(hp->qdcount); 9818505Sralph if (hp->rcode != NOERROR || ancount == 0) { 9924733Sbloom #ifdef DEBUG 10018505Sralph if (_res.options & RES_DEBUG) 10118505Sralph printf("rcode = %d, ancount=%d\n", hp->rcode, ancount); 10224733Sbloom #endif 10325484Skjd switch (hp->rcode) { 10425484Skjd case NXDOMAIN: 10525484Skjd /* Check if it's an authoritive answer */ 10625484Skjd if (hp->aa) 10725484Skjd h_errno = HOST_NOT_FOUND; 10825484Skjd else 10925484Skjd h_errno = TRY_AGAIN; 11025484Skjd break; 11125484Skjd case SERVFAIL: 11225484Skjd h_errno = TRY_AGAIN; 11325484Skjd break; 11425484Skjd case NOERROR: 11532648Skarels if (hp->aa) 11632648Skarels h_errno = NO_ADDRESS; 11732648Skarels else 11832648Skarels h_errno = TRY_AGAIN; 11925484Skjd break; 12025484Skjd case FORMERR: 12125484Skjd case NOTIMP: 12225484Skjd case REFUSED: 12325484Skjd h_errno = NO_RECOVERY; 12425484Skjd } 12533500Skarels return ((struct hostent *) NULL); 12618505Sralph } 12718505Sralph bp = hostbuf; 12818505Sralph buflen = sizeof(hostbuf); 12925302Skjd cp = (char *)&answer + sizeof(HEADER); 13025153Sbloom if (qdcount) { 13118505Sralph if (iquery) { 13226066Skjd if ((n = dn_expand((char *)&answer, eom, 13326066Skjd cp, bp, buflen)) < 0) { 13425484Skjd h_errno = NO_RECOVERY; 13533500Skarels return ((struct hostent *) NULL); 13625484Skjd } 13718505Sralph cp += n + QFIXEDSZ; 13818505Sralph host.h_name = bp; 13918505Sralph n = strlen(bp) + 1; 14018505Sralph bp += n; 14118505Sralph buflen -= n; 14218505Sralph } else 14332648Skarels cp += dn_skipname(cp, eom) + QFIXEDSZ; 14425153Sbloom while (--qdcount > 0) 14532648Skarels cp += dn_skipname(cp, eom) + QFIXEDSZ; 14625484Skjd } else if (iquery) { 14725484Skjd if (hp->aa) 14825484Skjd h_errno = HOST_NOT_FOUND; 14925484Skjd else 15025484Skjd h_errno = TRY_AGAIN; 15133500Skarels return ((struct hostent *) NULL); 15225484Skjd } 15324687Sbloom ap = host_aliases; 15424687Sbloom host.h_aliases = host_aliases; 15524687Sbloom hap = h_addr_ptrs; 15633600Skarels #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ 15724687Sbloom host.h_addr_list = h_addr_ptrs; 15830460Skjd #endif 15924687Sbloom haveanswer = 0; 16018505Sralph while (--ancount >= 0 && cp < eom) { 16126066Skjd if ((n = dn_expand((char *)&answer, eom, cp, bp, buflen)) < 0) 16224687Sbloom break; 16318505Sralph cp += n; 16430440Skjd type = _getshort(cp); 16518505Sralph cp += sizeof(u_short); 16630440Skjd class = _getshort(cp); 16718505Sralph cp += sizeof(u_short) + sizeof(u_long); 16830440Skjd n = _getshort(cp); 16918505Sralph cp += sizeof(u_short); 17018505Sralph if (type == T_CNAME) { 17118505Sralph cp += n; 17218505Sralph if (ap >= &host_aliases[MAXALIASES-1]) 17318505Sralph continue; 17418505Sralph *ap++ = bp; 17518505Sralph n = strlen(bp) + 1; 17618505Sralph bp += n; 17718505Sralph buflen -= n; 17818505Sralph continue; 17918505Sralph } 18025153Sbloom if (type == T_PTR) { 18127034Skjd if ((n = dn_expand((char *)&answer, eom, 18227034Skjd cp, bp, buflen)) < 0) { 18325153Sbloom cp += n; 18425153Sbloom continue; 18525153Sbloom } 18625153Sbloom cp += n; 18725153Sbloom host.h_name = bp; 18825153Sbloom return(&host); 18925153Sbloom } 19024687Sbloom if (type != T_A) { 19124733Sbloom #ifdef DEBUG 19218505Sralph if (_res.options & RES_DEBUG) 19318505Sralph printf("unexpected answer type %d, size %d\n", 19418505Sralph type, n); 19524733Sbloom #endif 19624687Sbloom cp += n; 19718505Sralph continue; 19818505Sralph } 19924687Sbloom if (haveanswer) { 20024687Sbloom if (n != host.h_length) { 20124687Sbloom cp += n; 20224687Sbloom continue; 20324687Sbloom } 20424687Sbloom if (class != getclass) { 20524687Sbloom cp += n; 20624687Sbloom continue; 20724687Sbloom } 20824687Sbloom } else { 20924687Sbloom host.h_length = n; 21024687Sbloom getclass = class; 21125386Skjd host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC; 21224687Sbloom if (!iquery) { 21324687Sbloom host.h_name = bp; 21424687Sbloom bp += strlen(bp) + 1; 21524687Sbloom } 21618505Sralph } 21725302Skjd 21831902Skarels bp += sizeof(align) - ((u_long)bp % sizeof(align)); 21925302Skjd 22018505Sralph if (bp + n >= &hostbuf[sizeof(hostbuf)]) { 22124733Sbloom #ifdef DEBUG 22218505Sralph if (_res.options & RES_DEBUG) 22318505Sralph printf("size (%d) too big\n", n); 22424733Sbloom #endif 22524687Sbloom break; 22618505Sralph } 22724687Sbloom bcopy(cp, *hap++ = bp, n); 22824687Sbloom bp +=n; 22924687Sbloom cp += n; 23024687Sbloom haveanswer++; 23124687Sbloom } 23224687Sbloom if (haveanswer) { 23324687Sbloom *ap = NULL; 23433600Skarels #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ 23524687Sbloom *hap = NULL; 23631902Skarels #else 23731902Skarels host.h_addr = h_addr_ptrs[0]; 23831902Skarels #endif 23918505Sralph return (&host); 24025484Skjd } else { 24125484Skjd h_errno = TRY_AGAIN; 24233500Skarels return ((struct hostent *) NULL); 24325484Skjd } 24415662Sralph } 24515662Sralph 24615662Sralph struct hostent * 24718505Sralph gethostbyname(name) 24818505Sralph char *name; 24915662Sralph { 25031111Skarels register char *cp, **domain; 25118505Sralph int n; 25231111Skarels struct hostent *hp, *gethostdomain(); 25331111Skarels char *hostalias(); 25426887Skjd extern struct hostent *_gethtbyname(); 25515662Sralph 25631111Skarels if (!(_res.options & RES_INIT) && res_init() == -1) 25733500Skarels return ((struct hostent *) NULL); 25832976Sbostic /* 25932976Sbostic * disallow names consisting only of digits/dots, unless 26032976Sbostic * they end in a dot. 26132976Sbostic */ 26232976Sbostic if (isdigit(name[0])) 26332976Sbostic for (cp = name;; ++cp) { 26432976Sbostic if (!*cp) { 26532976Sbostic if (*--cp == '.') 26632976Sbostic break; 26732976Sbostic h_errno = HOST_NOT_FOUND; 26833500Skarels return ((struct hostent *) NULL); 26932976Sbostic } 27032976Sbostic if (!isdigit(*cp) && *cp != '.') 27132976Sbostic break; 27232976Sbostic } 27329930Skjd errno = 0; 27431111Skarels for (cp = name, n = 0; *cp; cp++) 27531111Skarels if (*cp == '.') 27631111Skarels n++; 27731111Skarels if (n == 0 && (cp = hostalias(name))) 27831111Skarels return (gethostdomain(cp, (char *)NULL)); 27933500Skarels if ((n == 0 || *--cp != '.') && (_res.options & RES_DEFNAMES)) 28033500Skarels for (domain = _res.dnsrch; *domain; domain++) { 28131111Skarels hp = gethostdomain(name, *domain); 28231111Skarels if (hp) 28331111Skarels return (hp); 28431960Sbostic /* 28531960Sbostic * If no server present, use host table. 28631960Sbostic * If host isn't found in this domain, 28731960Sbostic * keep trying higher domains in the search list 28831960Sbostic * (if that's enabled). 28933500Skarels * On a NO_ADDRESS error, keep trying, otherwise 29033500Skarels * a wildcard MX entry could keep us from finding 29131960Sbostic * host entries higher in the domain. 29233500Skarels * If we get some other error (non-authoritative negative 29333500Skarels * answer or server failure), then stop searching up, 29433500Skarels * but try the input name below in case it's fully-qualified. 29531960Sbostic */ 29631111Skarels if (errno == ECONNREFUSED) 29731111Skarels return (_gethtbyname(name)); 29833500Skarels if ((h_errno != HOST_NOT_FOUND && h_errno != NO_ADDRESS) || 29931111Skarels (_res.options & RES_DNSRCH) == 0) 30033500Skarels break; 30131709Skarels h_errno = 0; 30231111Skarels } 30333500Skarels /* 30433500Skarels * If the search/default failed, try the name as fully-qualified, 30533500Skarels * but only if it contained at least one dot (even trailing). 30633500Skarels */ 30733500Skarels if (n) 30833500Skarels return (gethostdomain(name, (char *)NULL)); 30933500Skarels return ((struct hostent *) NULL); 31031111Skarels } 31131111Skarels 31231111Skarels static struct hostent * 31331111Skarels gethostdomain(name, domain) 31431111Skarels char *name, *domain; 31531111Skarels { 31631111Skarels querybuf buf; 31731111Skarels char nbuf[2*MAXDNAME+2]; 31833500Skarels char *longname = nbuf; 31931111Skarels int n; 32031111Skarels 32133500Skarels if (domain == NULL) { 32233500Skarels /* 32333500Skarels * Check for trailing '.'; 32433500Skarels * copy without '.' if present. 32533500Skarels */ 32633500Skarels n = strlen(name) - 1; 32733500Skarels if (name[n] == '.' && n < sizeof(nbuf) - 1) { 32833500Skarels bcopy(name, nbuf, n); 32933500Skarels nbuf[n] = '\0'; 33033500Skarels } else 33133500Skarels longname = name; 33233500Skarels } else 33332648Skarels (void)sprintf(nbuf, "%.*s.%.*s", 33432648Skarels MAXDNAME, name, MAXDNAME, domain); 33533500Skarels n = res_mkquery(QUERY, longname, C_IN, T_A, (char *)NULL, 0, NULL, 33625302Skjd (char *)&buf, sizeof(buf)); 33718505Sralph if (n < 0) { 33824733Sbloom #ifdef DEBUG 33918505Sralph if (_res.options & RES_DEBUG) 34018531Sralph printf("res_mkquery failed\n"); 34124733Sbloom #endif 34233500Skarels return ((struct hostent *) NULL); 34317761Sserge } 34431111Skarels return (getanswer((char *)&buf, n, 0)); 34515662Sralph } 34615662Sralph 34715662Sralph struct hostent * 34818505Sralph gethostbyaddr(addr, len, type) 34915662Sralph char *addr; 35018505Sralph int len, type; 35115662Sralph { 35218505Sralph int n; 35325302Skjd querybuf buf; 35425153Sbloom register struct hostent *hp; 35525153Sbloom char qbuf[MAXDNAME]; 35626887Skjd extern struct hostent *_gethtbyaddr(); 35726887Skjd 35818505Sralph if (type != AF_INET) 35933500Skarels return ((struct hostent *) NULL); 36025153Sbloom (void)sprintf(qbuf, "%d.%d.%d.%d.in-addr.arpa", 36125484Skjd ((unsigned)addr[3] & 0xff), 36225484Skjd ((unsigned)addr[2] & 0xff), 36325484Skjd ((unsigned)addr[1] & 0xff), 36425484Skjd ((unsigned)addr[0] & 0xff)); 36527034Skjd n = res_mkquery(QUERY, qbuf, C_IN, T_PTR, (char *)NULL, 0, NULL, 36625302Skjd (char *)&buf, sizeof(buf)); 36718505Sralph if (n < 0) { 36824733Sbloom #ifdef DEBUG 36918505Sralph if (_res.options & RES_DEBUG) 37018531Sralph printf("res_mkquery failed\n"); 37124733Sbloom #endif 37233500Skarels return ((struct hostent *) NULL); 37317761Sserge } 37426887Skjd hp = getanswer((char *)&buf, n, 1); 37526887Skjd if (hp == NULL && errno == ECONNREFUSED) 37626887Skjd hp = _gethtbyaddr(addr, len, type); 37726887Skjd if (hp == NULL) 37833500Skarels return ((struct hostent *) NULL); 37925153Sbloom hp->h_addrtype = type; 38025153Sbloom hp->h_length = len; 38125282Sbloom h_addr_ptrs[0] = (char *)&host_addr; 38225153Sbloom h_addr_ptrs[1] = (char *)0; 38325153Sbloom host_addr = *(struct in_addr *)addr; 38425153Sbloom return(hp); 38515662Sralph } 38625302Skjd 38731111Skarels char * 38831111Skarels hostalias(name) 38931111Skarels register char *name; 39031111Skarels { 39131780Sbostic register char *C1, *C2; 39231111Skarels FILE *fp; 39331780Sbostic char *file, *getenv(), *strcpy(), *strncpy(); 39431780Sbostic char buf[BUFSIZ]; 39531111Skarels static char abuf[MAXDNAME]; 39626887Skjd 39731111Skarels file = getenv("HOSTALIASES"); 39831111Skarels if (file == NULL || (fp = fopen(file, "r")) == NULL) 39931111Skarels return (NULL); 40031780Sbostic buf[sizeof(buf) - 1] = '\0'; 40131780Sbostic while (fgets(buf, sizeof(buf), fp)) { 40231780Sbostic for (C1 = buf; *C1 && !isspace(*C1); ++C1); 40332169Sbostic if (!*C1) 40431780Sbostic break; 40532169Sbostic *C1 = '\0'; 40632169Sbostic if (!strcasecmp(buf, name)) { 40731780Sbostic while (isspace(*++C1)); 40831780Sbostic if (!*C1) 40931780Sbostic break; 41031780Sbostic for (C2 = C1 + 1; *C2 && !isspace(*C2); ++C2); 41131780Sbostic abuf[sizeof(abuf) - 1] = *C2 = '\0'; 41231780Sbostic (void)strncpy(abuf, C1, sizeof(abuf) - 1); 41331111Skarels fclose(fp); 41431111Skarels return (abuf); 41531111Skarels } 41631780Sbostic } 41731111Skarels fclose(fp); 41831111Skarels return (NULL); 41931111Skarels } 42031111Skarels 42126887Skjd _sethtent(f) 42226887Skjd int f; 42326887Skjd { 42426887Skjd if (hostf == NULL) 42526887Skjd hostf = fopen(HOSTDB, "r" ); 42626887Skjd else 42726887Skjd rewind(hostf); 42826887Skjd stayopen |= f; 42926887Skjd } 43026887Skjd 43126887Skjd _endhtent() 43226887Skjd { 43326887Skjd if (hostf && !stayopen) { 43427034Skjd (void) fclose(hostf); 43526887Skjd hostf = NULL; 43626887Skjd } 43726887Skjd } 43826887Skjd 43926887Skjd struct hostent * 44026887Skjd _gethtent() 44126887Skjd { 44226887Skjd char *p; 44326887Skjd register char *cp, **q; 44426887Skjd 44526887Skjd if (hostf == NULL && (hostf = fopen(HOSTDB, "r" )) == NULL) 44626887Skjd return (NULL); 44726887Skjd again: 44826887Skjd if ((p = fgets(line, BUFSIZ, hostf)) == NULL) 44926887Skjd return (NULL); 45026887Skjd if (*p == '#') 45126887Skjd goto again; 45226887Skjd cp = any(p, "#\n"); 45326887Skjd if (cp == NULL) 45426887Skjd goto again; 45526887Skjd *cp = '\0'; 45626887Skjd cp = any(p, " \t"); 45726887Skjd if (cp == NULL) 45826887Skjd goto again; 45926887Skjd *cp++ = '\0'; 46026887Skjd /* THIS STUFF IS INTERNET SPECIFIC */ 46133600Skarels #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ 46226887Skjd host.h_addr_list = host_addrs; 46330460Skjd #endif 46426887Skjd host.h_addr = hostaddr; 46526887Skjd *((u_long *)host.h_addr) = inet_addr(p); 46626887Skjd host.h_length = sizeof (u_long); 46726887Skjd host.h_addrtype = AF_INET; 46826887Skjd while (*cp == ' ' || *cp == '\t') 46926887Skjd cp++; 47026887Skjd host.h_name = cp; 47126887Skjd q = host.h_aliases = host_aliases; 47226887Skjd cp = any(cp, " \t"); 47326887Skjd if (cp != NULL) 47426887Skjd *cp++ = '\0'; 47526887Skjd while (cp && *cp) { 47626887Skjd if (*cp == ' ' || *cp == '\t') { 47726887Skjd cp++; 47826887Skjd continue; 47926887Skjd } 48026887Skjd if (q < &host_aliases[MAXALIASES - 1]) 48126887Skjd *q++ = cp; 48226887Skjd cp = any(cp, " \t"); 48326887Skjd if (cp != NULL) 48426887Skjd *cp++ = '\0'; 48526887Skjd } 48626887Skjd *q = NULL; 48726887Skjd return (&host); 48826887Skjd } 48926887Skjd 49026887Skjd static char * 49126887Skjd any(cp, match) 49226887Skjd register char *cp; 49326887Skjd char *match; 49426887Skjd { 49526887Skjd register char *mp, c; 49626887Skjd 49726887Skjd while (c = *cp) { 49826887Skjd for (mp = match; *mp; mp++) 49926887Skjd if (*mp == c) 50026887Skjd return (cp); 50126887Skjd cp++; 50226887Skjd } 50326887Skjd return ((char *)0); 50426887Skjd } 50526887Skjd 50626887Skjd struct hostent * 50726887Skjd _gethtbyname(name) 50826887Skjd char *name; 50926887Skjd { 51026887Skjd register struct hostent *p; 51126887Skjd register char **cp; 51228307Skarels 51326887Skjd _sethtent(0); 51426887Skjd while (p = _gethtent()) { 51531960Sbostic if (strcasecmp(p->h_name, name) == 0) 51626887Skjd break; 51726887Skjd for (cp = p->h_aliases; *cp != 0; cp++) 51831960Sbostic if (strcasecmp(*cp, name) == 0) 51926887Skjd goto found; 52026887Skjd } 52126887Skjd found: 52226887Skjd _endhtent(); 52326887Skjd return (p); 52426887Skjd } 52526887Skjd 52626887Skjd struct hostent * 52726887Skjd _gethtbyaddr(addr, len, type) 52826887Skjd char *addr; 52926887Skjd int len, type; 53026887Skjd { 53126887Skjd register struct hostent *p; 53226887Skjd 53326887Skjd _sethtent(0); 53426887Skjd while (p = _gethtent()) 53526909Skjd if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len)) 53626887Skjd break; 53726887Skjd _endhtent(); 53826887Skjd return (p); 53926887Skjd } 540