121374Sdist /* 233734Sbostic * Copyright (c) 1985, 1988 Regents of the University of California. 333734Sbostic * All rights reserved. 433734Sbostic * 542625Sbostic * %sccs.include.redist.c% 621374Sdist */ 715662Sralph 826630Sdonn #if defined(LIBC_SCCS) && !defined(lint) 9*53078Sbostic static char sccsid[] = "@(#)gethostnamadr.c 6.46 (Berkeley) 03/29/92"; 1033734Sbostic #endif /* LIBC_SCCS and not lint */ 1121374Sdist 1230468Skjd #include <sys/param.h> 1318505Sralph #include <sys/socket.h> 1418505Sralph #include <netinet/in.h> 1546604Sbostic #include <arpa/inet.h> 1646604Sbostic #include <arpa/nameser.h> 1746604Sbostic #include <netdb.h> 1846604Sbostic #include <resolv.h> 1915662Sralph #include <stdio.h> 2046606Sbostic #include <ctype.h> 2126887Skjd #include <errno.h> 2246604Sbostic #include <string.h> 2315662Sralph 2415662Sralph #define MAXALIASES 35 2533735Sbostic #define MAXADDRS 35 2615662Sralph 2724687Sbloom static char *h_addr_ptrs[MAXADDRS + 1]; 2824687Sbloom 2924687Sbloom static struct hostent host; 3015662Sralph static char *host_aliases[MAXALIASES]; 3115912Sralph static char hostbuf[BUFSIZ+1]; 3225153Sbloom static struct in_addr host_addr; 3326887Skjd static FILE *hostf = NULL; 3426887Skjd static char hostaddr[MAXADDRS]; 3526887Skjd static char *host_addrs[2]; 3626887Skjd static int stayopen = 0; 3737108Sbostic char *strpbrk(); 3815662Sralph 3932648Skarels #if PACKETSZ > 1024 4033735Sbostic #define MAXPACKET PACKETSZ 4132648Skarels #else 4233735Sbostic #define MAXPACKET 1024 4332648Skarels #endif 4432648Skarels 4525302Skjd typedef union { 4633735Sbostic HEADER hdr; 4733735Sbostic u_char buf[MAXPACKET]; 4825302Skjd } querybuf; 4924509Sbloom 5035765Skarels typedef union { 5125302Skjd long al; 5225302Skjd char ac; 5325302Skjd } align; 5425302Skjd 5525484Skjd int h_errno; 5625484Skjd 5715662Sralph static struct hostent * 5833735Sbostic getanswer(answer, anslen, iquery) 5933735Sbostic querybuf *answer; 6033735Sbostic int anslen; 6133735Sbostic int iquery; 6215662Sralph { 6318505Sralph register HEADER *hp; 6433735Sbostic register u_char *cp; 6518505Sralph register int n; 6633735Sbostic u_char *eom; 6733735Sbostic char *bp, **ap; 6827034Skjd int type, class, buflen, ancount, qdcount; 6927034Skjd int haveanswer, getclass = C_ANY; 7024687Sbloom char **hap; 7115662Sralph 7233735Sbostic eom = answer->buf + anslen; 7318505Sralph /* 7418505Sralph * find first satisfactory answer 7518505Sralph */ 7633735Sbostic hp = &answer->hdr; 7718505Sralph ancount = ntohs(hp->ancount); 7825153Sbloom qdcount = ntohs(hp->qdcount); 7918505Sralph bp = hostbuf; 8018505Sralph buflen = sizeof(hostbuf); 8133735Sbostic cp = answer->buf + sizeof(HEADER); 8225153Sbloom if (qdcount) { 8318505Sralph if (iquery) { 8446604Sbostic if ((n = dn_expand((u_char *)answer->buf, 8546604Sbostic (u_char *)eom, (u_char *)cp, (u_char *)bp, 8646604Sbostic buflen)) < 0) { 8725484Skjd h_errno = NO_RECOVERY; 8833500Skarels return ((struct hostent *) NULL); 8925484Skjd } 9018505Sralph cp += n + QFIXEDSZ; 9118505Sralph host.h_name = bp; 9218505Sralph n = strlen(bp) + 1; 9318505Sralph bp += n; 9418505Sralph buflen -= n; 9518505Sralph } else 9646496Sbostic cp += __dn_skipname(cp, eom) + QFIXEDSZ; 9725153Sbloom while (--qdcount > 0) 9846496Sbostic cp += __dn_skipname(cp, eom) + QFIXEDSZ; 9925484Skjd } else if (iquery) { 10025484Skjd if (hp->aa) 10125484Skjd h_errno = HOST_NOT_FOUND; 10225484Skjd else 10325484Skjd h_errno = TRY_AGAIN; 10433500Skarels return ((struct hostent *) NULL); 10525484Skjd } 10624687Sbloom ap = host_aliases; 10739862Skarels *ap = NULL; 10824687Sbloom host.h_aliases = host_aliases; 10924687Sbloom hap = h_addr_ptrs; 11039862Skarels *hap = NULL; 11133600Skarels #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ 11224687Sbloom host.h_addr_list = h_addr_ptrs; 11330460Skjd #endif 11424687Sbloom haveanswer = 0; 11518505Sralph while (--ancount >= 0 && cp < eom) { 11646604Sbostic if ((n = dn_expand((u_char *)answer->buf, (u_char *)eom, 11746604Sbostic (u_char *)cp, (u_char *)bp, buflen)) < 0) 11824687Sbloom break; 11918505Sralph cp += n; 12030440Skjd type = _getshort(cp); 12118505Sralph cp += sizeof(u_short); 12230440Skjd class = _getshort(cp); 12318505Sralph cp += sizeof(u_short) + sizeof(u_long); 12430440Skjd n = _getshort(cp); 12518505Sralph cp += sizeof(u_short); 12618505Sralph if (type == T_CNAME) { 12718505Sralph cp += n; 12818505Sralph if (ap >= &host_aliases[MAXALIASES-1]) 12918505Sralph continue; 13018505Sralph *ap++ = bp; 13118505Sralph n = strlen(bp) + 1; 13218505Sralph bp += n; 13318505Sralph buflen -= n; 13418505Sralph continue; 13518505Sralph } 13633735Sbostic if (iquery && type == T_PTR) { 13746604Sbostic if ((n = dn_expand((u_char *)answer->buf, 13846604Sbostic (u_char *)eom, (u_char *)cp, (u_char *)bp, 13946604Sbostic buflen)) < 0) { 14025153Sbloom cp += n; 14125153Sbloom continue; 14225153Sbloom } 14325153Sbloom cp += n; 14425153Sbloom host.h_name = bp; 14525153Sbloom return(&host); 14625153Sbloom } 14733735Sbostic if (iquery || type != T_A) { 14824733Sbloom #ifdef DEBUG 14918505Sralph if (_res.options & RES_DEBUG) 15018505Sralph printf("unexpected answer type %d, size %d\n", 15118505Sralph type, n); 15224733Sbloom #endif 15324687Sbloom cp += n; 15418505Sralph continue; 15518505Sralph } 15624687Sbloom if (haveanswer) { 15724687Sbloom if (n != host.h_length) { 15824687Sbloom cp += n; 15924687Sbloom continue; 16024687Sbloom } 16124687Sbloom if (class != getclass) { 16224687Sbloom cp += n; 16324687Sbloom continue; 16424687Sbloom } 16524687Sbloom } else { 16624687Sbloom host.h_length = n; 16724687Sbloom getclass = class; 16825386Skjd host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC; 16924687Sbloom if (!iquery) { 17024687Sbloom host.h_name = bp; 17124687Sbloom bp += strlen(bp) + 1; 17224687Sbloom } 17318505Sralph } 17425302Skjd 17531902Skarels bp += sizeof(align) - ((u_long)bp % sizeof(align)); 17625302Skjd 17718505Sralph if (bp + n >= &hostbuf[sizeof(hostbuf)]) { 17824733Sbloom #ifdef DEBUG 17918505Sralph if (_res.options & RES_DEBUG) 18018505Sralph printf("size (%d) too big\n", n); 18124733Sbloom #endif 18224687Sbloom break; 18318505Sralph } 18424687Sbloom bcopy(cp, *hap++ = bp, n); 18524687Sbloom bp +=n; 18624687Sbloom cp += n; 18724687Sbloom haveanswer++; 18824687Sbloom } 18924687Sbloom if (haveanswer) { 19024687Sbloom *ap = NULL; 19133600Skarels #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ 19224687Sbloom *hap = NULL; 19331902Skarels #else 19431902Skarels host.h_addr = h_addr_ptrs[0]; 19531902Skarels #endif 19618505Sralph return (&host); 19725484Skjd } else { 19825484Skjd h_errno = TRY_AGAIN; 19933500Skarels return ((struct hostent *) NULL); 20025484Skjd } 20115662Sralph } 20215662Sralph 20315662Sralph struct hostent * 20418505Sralph gethostbyname(name) 205*53078Sbostic const char *name; 20615662Sralph { 20733735Sbostic querybuf buf; 208*53078Sbostic register const char *cp; 20918505Sralph int n; 21026887Skjd extern struct hostent *_gethtbyname(); 21115662Sralph 21232976Sbostic /* 21332976Sbostic * disallow names consisting only of digits/dots, unless 21432976Sbostic * they end in a dot. 21532976Sbostic */ 21632976Sbostic if (isdigit(name[0])) 21732976Sbostic for (cp = name;; ++cp) { 21832976Sbostic if (!*cp) { 21932976Sbostic if (*--cp == '.') 22032976Sbostic break; 22139710Sbloom /* 22239710Sbloom * All-numeric, no dot at the end. 22339710Sbloom * Fake up a hostent as if we'd actually 22439710Sbloom * done a lookup. What if someone types 22539710Sbloom * 255.255.255.255? The test below will 22639710Sbloom * succeed spuriously... ??? 22739710Sbloom */ 22839710Sbloom if ((host_addr.s_addr = inet_addr(name)) == -1) { 22939710Sbloom h_errno = HOST_NOT_FOUND; 23039710Sbloom return((struct hostent *) NULL); 23139710Sbloom } 232*53078Sbostic host.h_name = (char *)name; 23339710Sbloom host.h_aliases = host_aliases; 23439710Sbloom host_aliases[0] = NULL; 23539710Sbloom host.h_addrtype = AF_INET; 23639710Sbloom host.h_length = sizeof(u_long); 23739710Sbloom h_addr_ptrs[0] = (char *)&host_addr; 23839710Sbloom h_addr_ptrs[1] = (char *)0; 23939710Sbloom #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ 24039710Sbloom host.h_addr_list = h_addr_ptrs; 24139710Sbloom #else 24239710Sbloom host.h_addr = h_addr_ptrs[0]; 24339710Sbloom #endif 24439710Sbloom return (&host); 24532976Sbostic } 24632976Sbostic if (!isdigit(*cp) && *cp != '.') 24732976Sbostic break; 24832976Sbostic } 24931111Skarels 25033735Sbostic if ((n = res_search(name, C_IN, T_A, buf.buf, sizeof(buf))) < 0) { 25124733Sbloom #ifdef DEBUG 25218505Sralph if (_res.options & RES_DEBUG) 25333735Sbostic printf("res_search failed\n"); 25424733Sbloom #endif 25533735Sbostic if (errno == ECONNREFUSED) 25633735Sbostic return (_gethtbyname(name)); 25733735Sbostic else 25833735Sbostic return ((struct hostent *) NULL); 25917761Sserge } 26033735Sbostic return (getanswer(&buf, n, 0)); 26115662Sralph } 26215662Sralph 26315662Sralph struct hostent * 26418505Sralph gethostbyaddr(addr, len, type) 26546604Sbostic const char *addr; 26618505Sralph int len, type; 26715662Sralph { 26818505Sralph int n; 26925302Skjd querybuf buf; 27025153Sbloom register struct hostent *hp; 27125153Sbloom char qbuf[MAXDNAME]; 27226887Skjd extern struct hostent *_gethtbyaddr(); 27326887Skjd 27418505Sralph if (type != AF_INET) 27533500Skarels return ((struct hostent *) NULL); 27635395Sbostic (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", 27725484Skjd ((unsigned)addr[3] & 0xff), 27825484Skjd ((unsigned)addr[2] & 0xff), 27925484Skjd ((unsigned)addr[1] & 0xff), 28025484Skjd ((unsigned)addr[0] & 0xff)); 28133735Sbostic n = res_query(qbuf, C_IN, T_PTR, (char *)&buf, sizeof(buf)); 28218505Sralph if (n < 0) { 28324733Sbloom #ifdef DEBUG 28418505Sralph if (_res.options & RES_DEBUG) 28533735Sbostic printf("res_query failed\n"); 28624733Sbloom #endif 28733735Sbostic if (errno == ECONNREFUSED) 28833990Skarels return (_gethtbyaddr(addr, len, type)); 28933500Skarels return ((struct hostent *) NULL); 29017761Sserge } 29133735Sbostic hp = getanswer(&buf, n, 1); 29226887Skjd if (hp == NULL) 29333500Skarels return ((struct hostent *) NULL); 29425153Sbloom hp->h_addrtype = type; 29525153Sbloom hp->h_length = len; 29625282Sbloom h_addr_ptrs[0] = (char *)&host_addr; 29725153Sbloom h_addr_ptrs[1] = (char *)0; 29825153Sbloom host_addr = *(struct in_addr *)addr; 29939710Sbloom #if BSD < 43 && !defined(h_addr) /* new-style hostent structure */ 30039710Sbloom hp->h_addr = h_addr_ptrs[0]; 30139710Sbloom #endif 30225153Sbloom return(hp); 30315662Sralph } 30425302Skjd 30526887Skjd _sethtent(f) 30626887Skjd int f; 30726887Skjd { 30826887Skjd if (hostf == NULL) 30942266Sbostic hostf = fopen(_PATH_HOSTS, "r" ); 31026887Skjd else 31126887Skjd rewind(hostf); 31226887Skjd stayopen |= f; 31326887Skjd } 31426887Skjd 31526887Skjd _endhtent() 31626887Skjd { 31726887Skjd if (hostf && !stayopen) { 31827034Skjd (void) fclose(hostf); 31926887Skjd hostf = NULL; 32026887Skjd } 32126887Skjd } 32226887Skjd 32326887Skjd struct hostent * 32426887Skjd _gethtent() 32526887Skjd { 32626887Skjd char *p; 32726887Skjd register char *cp, **q; 32826887Skjd 32942266Sbostic if (hostf == NULL && (hostf = fopen(_PATH_HOSTS, "r" )) == NULL) 33026887Skjd return (NULL); 33126887Skjd again: 33233735Sbostic if ((p = fgets(hostbuf, BUFSIZ, hostf)) == NULL) 33326887Skjd return (NULL); 33426887Skjd if (*p == '#') 33526887Skjd goto again; 33637108Sbostic cp = strpbrk(p, "#\n"); 33726887Skjd if (cp == NULL) 33826887Skjd goto again; 33926887Skjd *cp = '\0'; 34037108Sbostic cp = strpbrk(p, " \t"); 34126887Skjd if (cp == NULL) 34226887Skjd goto again; 34326887Skjd *cp++ = '\0'; 34426887Skjd /* THIS STUFF IS INTERNET SPECIFIC */ 34533600Skarels #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ 34626887Skjd host.h_addr_list = host_addrs; 34730460Skjd #endif 34826887Skjd host.h_addr = hostaddr; 34926887Skjd *((u_long *)host.h_addr) = inet_addr(p); 35026887Skjd host.h_length = sizeof (u_long); 35126887Skjd host.h_addrtype = AF_INET; 35226887Skjd while (*cp == ' ' || *cp == '\t') 35326887Skjd cp++; 35426887Skjd host.h_name = cp; 35526887Skjd q = host.h_aliases = host_aliases; 35637108Sbostic cp = strpbrk(cp, " \t"); 35726887Skjd if (cp != NULL) 35826887Skjd *cp++ = '\0'; 35926887Skjd while (cp && *cp) { 36026887Skjd if (*cp == ' ' || *cp == '\t') { 36126887Skjd cp++; 36226887Skjd continue; 36326887Skjd } 36426887Skjd if (q < &host_aliases[MAXALIASES - 1]) 36526887Skjd *q++ = cp; 36637108Sbostic cp = strpbrk(cp, " \t"); 36726887Skjd if (cp != NULL) 36826887Skjd *cp++ = '\0'; 36926887Skjd } 37026887Skjd *q = NULL; 37126887Skjd return (&host); 37226887Skjd } 37326887Skjd 37426887Skjd struct hostent * 37526887Skjd _gethtbyname(name) 37626887Skjd char *name; 37726887Skjd { 37826887Skjd register struct hostent *p; 37926887Skjd register char **cp; 38028307Skarels 38126887Skjd _sethtent(0); 38226887Skjd while (p = _gethtent()) { 38331960Sbostic if (strcasecmp(p->h_name, name) == 0) 38426887Skjd break; 38526887Skjd for (cp = p->h_aliases; *cp != 0; cp++) 38631960Sbostic if (strcasecmp(*cp, name) == 0) 38726887Skjd goto found; 38826887Skjd } 38926887Skjd found: 39026887Skjd _endhtent(); 39126887Skjd return (p); 39226887Skjd } 39326887Skjd 39426887Skjd struct hostent * 39526887Skjd _gethtbyaddr(addr, len, type) 39646604Sbostic const char *addr; 39726887Skjd int len, type; 39826887Skjd { 39926887Skjd register struct hostent *p; 40026887Skjd 40126887Skjd _sethtent(0); 40226887Skjd while (p = _gethtent()) 40326909Skjd if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len)) 40426887Skjd break; 40526887Skjd _endhtent(); 40626887Skjd return (p); 40726887Skjd } 408