121374Sdist /* 233734Sbostic * Copyright (c) 1985, 1988 Regents of the University of California. 333734Sbostic * All rights reserved. 433734Sbostic * 533734Sbostic * Redistribution and use in source and binary forms are permitted 634812Sbostic * provided that the above copyright notice and this paragraph are 734812Sbostic * duplicated in all such forms and that any documentation, 834812Sbostic * advertising materials, and other materials related to such 934812Sbostic * distribution and use acknowledge that the software was developed 1034812Sbostic * by the University of California, Berkeley. The name of the 1134812Sbostic * University may not be used to endorse or promote products derived 1234812Sbostic * from this software without specific prior written permission. 1334812Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434812Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1534812Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1621374Sdist */ 1715662Sralph 1826630Sdonn #if defined(LIBC_SCCS) && !defined(lint) 19*42266Sbostic static char sccsid[] = "@(#)gethostnamadr.c 6.40 (Berkeley) 05/21/90"; 2033734Sbostic #endif /* LIBC_SCCS and not lint */ 2121374Sdist 2230468Skjd #include <sys/param.h> 2318505Sralph #include <sys/socket.h> 2418505Sralph #include <netinet/in.h> 2526887Skjd #include <ctype.h> 2618505Sralph #include <netdb.h> 2715662Sralph #include <stdio.h> 2826887Skjd #include <errno.h> 2927034Skjd #include <arpa/inet.h> 3024508Sbloom #include <arpa/nameser.h> 3126894Skjd #include <resolv.h> 3215662Sralph 3315662Sralph #define MAXALIASES 35 3433735Sbostic #define MAXADDRS 35 3515662Sralph 3624687Sbloom static char *h_addr_ptrs[MAXADDRS + 1]; 3724687Sbloom 3824687Sbloom static struct hostent host; 3915662Sralph static char *host_aliases[MAXALIASES]; 4015912Sralph static char hostbuf[BUFSIZ+1]; 4125153Sbloom static struct in_addr host_addr; 4226887Skjd static FILE *hostf = NULL; 4326887Skjd static char hostaddr[MAXADDRS]; 4426887Skjd static char *host_addrs[2]; 4526887Skjd static int stayopen = 0; 4637108Sbostic char *strpbrk(); 4715662Sralph 4832648Skarels #if PACKETSZ > 1024 4933735Sbostic #define MAXPACKET PACKETSZ 5032648Skarels #else 5133735Sbostic #define MAXPACKET 1024 5232648Skarels #endif 5332648Skarels 5425302Skjd typedef union { 5533735Sbostic HEADER hdr; 5633735Sbostic u_char buf[MAXPACKET]; 5725302Skjd } querybuf; 5824509Sbloom 5935765Skarels typedef union { 6025302Skjd long al; 6125302Skjd char ac; 6225302Skjd } align; 6325302Skjd 6425302Skjd 6525484Skjd int h_errno; 6626887Skjd extern errno; 6725484Skjd 6815662Sralph static struct hostent * 6933735Sbostic getanswer(answer, anslen, iquery) 7033735Sbostic querybuf *answer; 7133735Sbostic int anslen; 7233735Sbostic int iquery; 7315662Sralph { 7418505Sralph register HEADER *hp; 7533735Sbostic register u_char *cp; 7618505Sralph register int n; 7733735Sbostic u_char *eom; 7833735Sbostic char *bp, **ap; 7927034Skjd int type, class, buflen, ancount, qdcount; 8027034Skjd int haveanswer, getclass = C_ANY; 8124687Sbloom char **hap; 8215662Sralph 8333735Sbostic eom = answer->buf + anslen; 8418505Sralph /* 8518505Sralph * find first satisfactory answer 8618505Sralph */ 8733735Sbostic hp = &answer->hdr; 8818505Sralph ancount = ntohs(hp->ancount); 8925153Sbloom qdcount = ntohs(hp->qdcount); 9018505Sralph bp = hostbuf; 9118505Sralph buflen = sizeof(hostbuf); 9233735Sbostic cp = answer->buf + sizeof(HEADER); 9325153Sbloom if (qdcount) { 9418505Sralph if (iquery) { 9533735Sbostic if ((n = dn_expand((char *)answer->buf, eom, 9626066Skjd cp, bp, buflen)) < 0) { 9725484Skjd h_errno = NO_RECOVERY; 9833500Skarels return ((struct hostent *) NULL); 9925484Skjd } 10018505Sralph cp += n + QFIXEDSZ; 10118505Sralph host.h_name = bp; 10218505Sralph n = strlen(bp) + 1; 10318505Sralph bp += n; 10418505Sralph buflen -= n; 10518505Sralph } else 10632648Skarels cp += dn_skipname(cp, eom) + QFIXEDSZ; 10725153Sbloom while (--qdcount > 0) 10832648Skarels cp += dn_skipname(cp, eom) + QFIXEDSZ; 10925484Skjd } else if (iquery) { 11025484Skjd if (hp->aa) 11125484Skjd h_errno = HOST_NOT_FOUND; 11225484Skjd else 11325484Skjd h_errno = TRY_AGAIN; 11433500Skarels return ((struct hostent *) NULL); 11525484Skjd } 11624687Sbloom ap = host_aliases; 11739862Skarels *ap = NULL; 11824687Sbloom host.h_aliases = host_aliases; 11924687Sbloom hap = h_addr_ptrs; 12039862Skarels *hap = NULL; 12133600Skarels #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ 12224687Sbloom host.h_addr_list = h_addr_ptrs; 12330460Skjd #endif 12424687Sbloom haveanswer = 0; 12518505Sralph while (--ancount >= 0 && cp < eom) { 12633735Sbostic if ((n = dn_expand((char *)answer->buf, eom, cp, bp, buflen)) < 0) 12724687Sbloom break; 12818505Sralph cp += n; 12930440Skjd type = _getshort(cp); 13018505Sralph cp += sizeof(u_short); 13130440Skjd class = _getshort(cp); 13218505Sralph cp += sizeof(u_short) + sizeof(u_long); 13330440Skjd n = _getshort(cp); 13418505Sralph cp += sizeof(u_short); 13518505Sralph if (type == T_CNAME) { 13618505Sralph cp += n; 13718505Sralph if (ap >= &host_aliases[MAXALIASES-1]) 13818505Sralph continue; 13918505Sralph *ap++ = bp; 14018505Sralph n = strlen(bp) + 1; 14118505Sralph bp += n; 14218505Sralph buflen -= n; 14318505Sralph continue; 14418505Sralph } 14533735Sbostic if (iquery && type == T_PTR) { 14633735Sbostic if ((n = dn_expand((char *)answer->buf, eom, 14727034Skjd cp, bp, buflen)) < 0) { 14825153Sbloom cp += n; 14925153Sbloom continue; 15025153Sbloom } 15125153Sbloom cp += n; 15225153Sbloom host.h_name = bp; 15325153Sbloom return(&host); 15425153Sbloom } 15533735Sbostic if (iquery || type != T_A) { 15624733Sbloom #ifdef DEBUG 15718505Sralph if (_res.options & RES_DEBUG) 15818505Sralph printf("unexpected answer type %d, size %d\n", 15918505Sralph type, n); 16024733Sbloom #endif 16124687Sbloom cp += n; 16218505Sralph continue; 16318505Sralph } 16424687Sbloom if (haveanswer) { 16524687Sbloom if (n != host.h_length) { 16624687Sbloom cp += n; 16724687Sbloom continue; 16824687Sbloom } 16924687Sbloom if (class != getclass) { 17024687Sbloom cp += n; 17124687Sbloom continue; 17224687Sbloom } 17324687Sbloom } else { 17424687Sbloom host.h_length = n; 17524687Sbloom getclass = class; 17625386Skjd host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC; 17724687Sbloom if (!iquery) { 17824687Sbloom host.h_name = bp; 17924687Sbloom bp += strlen(bp) + 1; 18024687Sbloom } 18118505Sralph } 18225302Skjd 18331902Skarels bp += sizeof(align) - ((u_long)bp % sizeof(align)); 18425302Skjd 18518505Sralph if (bp + n >= &hostbuf[sizeof(hostbuf)]) { 18624733Sbloom #ifdef DEBUG 18718505Sralph if (_res.options & RES_DEBUG) 18818505Sralph printf("size (%d) too big\n", n); 18924733Sbloom #endif 19024687Sbloom break; 19118505Sralph } 19224687Sbloom bcopy(cp, *hap++ = bp, n); 19324687Sbloom bp +=n; 19424687Sbloom cp += n; 19524687Sbloom haveanswer++; 19624687Sbloom } 19724687Sbloom if (haveanswer) { 19824687Sbloom *ap = NULL; 19933600Skarels #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ 20024687Sbloom *hap = NULL; 20131902Skarels #else 20231902Skarels host.h_addr = h_addr_ptrs[0]; 20331902Skarels #endif 20418505Sralph return (&host); 20525484Skjd } else { 20625484Skjd h_errno = TRY_AGAIN; 20733500Skarels return ((struct hostent *) NULL); 20825484Skjd } 20915662Sralph } 21015662Sralph 21115662Sralph struct hostent * 21218505Sralph gethostbyname(name) 21318505Sralph char *name; 21415662Sralph { 21533735Sbostic querybuf buf; 21633735Sbostic register char *cp; 21718505Sralph int n; 21826887Skjd extern struct hostent *_gethtbyname(); 21915662Sralph 22032976Sbostic /* 22132976Sbostic * disallow names consisting only of digits/dots, unless 22232976Sbostic * they end in a dot. 22332976Sbostic */ 22432976Sbostic if (isdigit(name[0])) 22532976Sbostic for (cp = name;; ++cp) { 22632976Sbostic if (!*cp) { 22732976Sbostic if (*--cp == '.') 22832976Sbostic break; 22939710Sbloom /* 23039710Sbloom * All-numeric, no dot at the end. 23139710Sbloom * Fake up a hostent as if we'd actually 23239710Sbloom * done a lookup. What if someone types 23339710Sbloom * 255.255.255.255? The test below will 23439710Sbloom * succeed spuriously... ??? 23539710Sbloom */ 23639710Sbloom if ((host_addr.s_addr = inet_addr(name)) == -1) { 23739710Sbloom h_errno = HOST_NOT_FOUND; 23839710Sbloom return((struct hostent *) NULL); 23939710Sbloom } 24039710Sbloom host.h_name = name; 24139710Sbloom host.h_aliases = host_aliases; 24239710Sbloom host_aliases[0] = NULL; 24339710Sbloom host.h_addrtype = AF_INET; 24439710Sbloom host.h_length = sizeof(u_long); 24539710Sbloom h_addr_ptrs[0] = (char *)&host_addr; 24639710Sbloom h_addr_ptrs[1] = (char *)0; 24739710Sbloom #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ 24839710Sbloom host.h_addr_list = h_addr_ptrs; 24939710Sbloom #else 25039710Sbloom host.h_addr = h_addr_ptrs[0]; 25139710Sbloom #endif 25239710Sbloom return (&host); 25332976Sbostic } 25432976Sbostic if (!isdigit(*cp) && *cp != '.') 25532976Sbostic break; 25632976Sbostic } 25731111Skarels 25833735Sbostic if ((n = res_search(name, C_IN, T_A, buf.buf, sizeof(buf))) < 0) { 25924733Sbloom #ifdef DEBUG 26018505Sralph if (_res.options & RES_DEBUG) 26133735Sbostic printf("res_search failed\n"); 26224733Sbloom #endif 26333735Sbostic if (errno == ECONNREFUSED) 26433735Sbostic return (_gethtbyname(name)); 26533735Sbostic else 26633735Sbostic return ((struct hostent *) NULL); 26717761Sserge } 26833735Sbostic return (getanswer(&buf, n, 0)); 26915662Sralph } 27015662Sralph 27115662Sralph struct hostent * 27218505Sralph gethostbyaddr(addr, len, type) 27315662Sralph char *addr; 27418505Sralph int len, type; 27515662Sralph { 27618505Sralph int n; 27725302Skjd querybuf buf; 27825153Sbloom register struct hostent *hp; 27925153Sbloom char qbuf[MAXDNAME]; 28026887Skjd extern struct hostent *_gethtbyaddr(); 28126887Skjd 28218505Sralph if (type != AF_INET) 28333500Skarels return ((struct hostent *) NULL); 28435395Sbostic (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", 28525484Skjd ((unsigned)addr[3] & 0xff), 28625484Skjd ((unsigned)addr[2] & 0xff), 28725484Skjd ((unsigned)addr[1] & 0xff), 28825484Skjd ((unsigned)addr[0] & 0xff)); 28933735Sbostic n = res_query(qbuf, C_IN, T_PTR, (char *)&buf, sizeof(buf)); 29018505Sralph if (n < 0) { 29124733Sbloom #ifdef DEBUG 29218505Sralph if (_res.options & RES_DEBUG) 29333735Sbostic printf("res_query failed\n"); 29424733Sbloom #endif 29533735Sbostic if (errno == ECONNREFUSED) 29633990Skarels return (_gethtbyaddr(addr, len, type)); 29733500Skarels return ((struct hostent *) NULL); 29817761Sserge } 29933735Sbostic hp = getanswer(&buf, n, 1); 30026887Skjd if (hp == NULL) 30133500Skarels return ((struct hostent *) NULL); 30225153Sbloom hp->h_addrtype = type; 30325153Sbloom hp->h_length = len; 30425282Sbloom h_addr_ptrs[0] = (char *)&host_addr; 30525153Sbloom h_addr_ptrs[1] = (char *)0; 30625153Sbloom host_addr = *(struct in_addr *)addr; 30739710Sbloom #if BSD < 43 && !defined(h_addr) /* new-style hostent structure */ 30839710Sbloom hp->h_addr = h_addr_ptrs[0]; 30939710Sbloom #endif 31025153Sbloom return(hp); 31115662Sralph } 31225302Skjd 31326887Skjd _sethtent(f) 31426887Skjd int f; 31526887Skjd { 31626887Skjd if (hostf == NULL) 317*42266Sbostic hostf = fopen(_PATH_HOSTS, "r" ); 31826887Skjd else 31926887Skjd rewind(hostf); 32026887Skjd stayopen |= f; 32126887Skjd } 32226887Skjd 32326887Skjd _endhtent() 32426887Skjd { 32526887Skjd if (hostf && !stayopen) { 32627034Skjd (void) fclose(hostf); 32726887Skjd hostf = NULL; 32826887Skjd } 32926887Skjd } 33026887Skjd 33126887Skjd struct hostent * 33226887Skjd _gethtent() 33326887Skjd { 33426887Skjd char *p; 33526887Skjd register char *cp, **q; 33626887Skjd 337*42266Sbostic if (hostf == NULL && (hostf = fopen(_PATH_HOSTS, "r" )) == NULL) 33826887Skjd return (NULL); 33926887Skjd again: 34033735Sbostic if ((p = fgets(hostbuf, BUFSIZ, hostf)) == NULL) 34126887Skjd return (NULL); 34226887Skjd if (*p == '#') 34326887Skjd goto again; 34437108Sbostic cp = strpbrk(p, "#\n"); 34526887Skjd if (cp == NULL) 34626887Skjd goto again; 34726887Skjd *cp = '\0'; 34837108Sbostic cp = strpbrk(p, " \t"); 34926887Skjd if (cp == NULL) 35026887Skjd goto again; 35126887Skjd *cp++ = '\0'; 35226887Skjd /* THIS STUFF IS INTERNET SPECIFIC */ 35333600Skarels #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ 35426887Skjd host.h_addr_list = host_addrs; 35530460Skjd #endif 35626887Skjd host.h_addr = hostaddr; 35726887Skjd *((u_long *)host.h_addr) = inet_addr(p); 35826887Skjd host.h_length = sizeof (u_long); 35926887Skjd host.h_addrtype = AF_INET; 36026887Skjd while (*cp == ' ' || *cp == '\t') 36126887Skjd cp++; 36226887Skjd host.h_name = cp; 36326887Skjd q = host.h_aliases = host_aliases; 36437108Sbostic cp = strpbrk(cp, " \t"); 36526887Skjd if (cp != NULL) 36626887Skjd *cp++ = '\0'; 36726887Skjd while (cp && *cp) { 36826887Skjd if (*cp == ' ' || *cp == '\t') { 36926887Skjd cp++; 37026887Skjd continue; 37126887Skjd } 37226887Skjd if (q < &host_aliases[MAXALIASES - 1]) 37326887Skjd *q++ = cp; 37437108Sbostic cp = strpbrk(cp, " \t"); 37526887Skjd if (cp != NULL) 37626887Skjd *cp++ = '\0'; 37726887Skjd } 37826887Skjd *q = NULL; 37926887Skjd return (&host); 38026887Skjd } 38126887Skjd 38226887Skjd struct hostent * 38326887Skjd _gethtbyname(name) 38426887Skjd char *name; 38526887Skjd { 38626887Skjd register struct hostent *p; 38726887Skjd register char **cp; 38828307Skarels 38926887Skjd _sethtent(0); 39026887Skjd while (p = _gethtent()) { 39131960Sbostic if (strcasecmp(p->h_name, name) == 0) 39226887Skjd break; 39326887Skjd for (cp = p->h_aliases; *cp != 0; cp++) 39431960Sbostic if (strcasecmp(*cp, name) == 0) 39526887Skjd goto found; 39626887Skjd } 39726887Skjd found: 39826887Skjd _endhtent(); 39926887Skjd return (p); 40026887Skjd } 40126887Skjd 40226887Skjd struct hostent * 40326887Skjd _gethtbyaddr(addr, len, type) 40426887Skjd char *addr; 40526887Skjd int len, type; 40626887Skjd { 40726887Skjd register struct hostent *p; 40826887Skjd 40926887Skjd _sethtent(0); 41026887Skjd while (p = _gethtent()) 41126909Skjd if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len)) 41226887Skjd break; 41326887Skjd _endhtent(); 41426887Skjd return (p); 41526887Skjd } 416