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*27034Skjd static char sccsid[] = "@(#)gethostnamadr.c 6.10 (Berkeley) 04/10/86"; 926630Sdonn #endif LIBC_SCCS and not lint 1021374Sdist 1125386Skjd #include <sys/param.h> 1218505Sralph #include <sys/socket.h> 1318505Sralph #include <netinet/in.h> 1426887Skjd #include <sys/types.h> 1526887Skjd #include <ctype.h> 1618505Sralph #include <netdb.h> 1715662Sralph #include <stdio.h> 1826887Skjd #include <errno.h> 19*27034Skjd #include <arpa/inet.h> 2024508Sbloom #include <arpa/nameser.h> 2126894Skjd #include <resolv.h> 2215662Sralph 2315662Sralph #define MAXALIASES 35 2424687Sbloom #define MAXADDRS 35 2515662Sralph 2624687Sbloom static char *h_addr_ptrs[MAXADDRS + 1]; 2724687Sbloom 2824687Sbloom static struct hostent host; 2915662Sralph static char *host_aliases[MAXALIASES]; 3015912Sralph static char hostbuf[BUFSIZ+1]; 3125153Sbloom static struct in_addr host_addr; 3226887Skjd static char HOSTDB[] = "/etc/hosts"; 3326887Skjd static FILE *hostf = NULL; 3426887Skjd static char line[BUFSIZ+1]; 3526887Skjd static char hostaddr[MAXADDRS]; 3626887Skjd static char *host_addrs[2]; 3726887Skjd static int stayopen = 0; 3826887Skjd static char *any(); 3915662Sralph 4025302Skjd typedef union { 4125302Skjd HEADER qb1; 4225302Skjd char qb2[PACKETSZ]; 4325302Skjd } querybuf; 4424509Sbloom 4525302Skjd static union { 4625302Skjd long al; 4725302Skjd char ac; 4825302Skjd } align; 4925302Skjd 5025302Skjd 5125484Skjd int h_errno; 5226887Skjd extern errno; 5325484Skjd 5415662Sralph static struct hostent * 5518505Sralph getanswer(msg, msglen, iquery) 5618505Sralph char *msg; 5718505Sralph int msglen, iquery; 5815662Sralph { 5918505Sralph register HEADER *hp; 6018505Sralph register char *cp; 6118505Sralph register int n; 6225302Skjd querybuf answer; 6318505Sralph char *eom, *bp, **ap; 64*27034Skjd int type, class, buflen, ancount, qdcount; 65*27034Skjd int haveanswer, getclass = C_ANY; 6624687Sbloom char **hap; 6715662Sralph 6825302Skjd n = res_send(msg, msglen, (char *)&answer, sizeof(answer)); 6918505Sralph if (n < 0) { 7024733Sbloom #ifdef DEBUG 7126887Skjd int terrno; 7226887Skjd terrno = errno; 7318505Sralph if (_res.options & RES_DEBUG) 7418531Sralph printf("res_send failed\n"); 7526887Skjd errno = terrno; 7624733Sbloom #endif 7725484Skjd h_errno = TRY_AGAIN; 7818505Sralph return (NULL); 7915662Sralph } 8025302Skjd eom = (char *)&answer + n; 8118505Sralph /* 8218505Sralph * find first satisfactory answer 8318505Sralph */ 8425302Skjd hp = (HEADER *) &answer; 8518505Sralph ancount = ntohs(hp->ancount); 8625153Sbloom qdcount = ntohs(hp->qdcount); 8718505Sralph if (hp->rcode != NOERROR || ancount == 0) { 8824733Sbloom #ifdef DEBUG 8918505Sralph if (_res.options & RES_DEBUG) 9018505Sralph printf("rcode = %d, ancount=%d\n", hp->rcode, ancount); 9124733Sbloom #endif 9225484Skjd switch (hp->rcode) { 9325484Skjd case NXDOMAIN: 9425484Skjd /* Check if it's an authoritive answer */ 9525484Skjd if (hp->aa) 9625484Skjd h_errno = HOST_NOT_FOUND; 9725484Skjd else 9825484Skjd h_errno = TRY_AGAIN; 9925484Skjd break; 10025484Skjd case SERVFAIL: 10125484Skjd h_errno = TRY_AGAIN; 10225484Skjd break; 10325484Skjd case NOERROR: 10425484Skjd h_errno = NO_ADDRESS; 10525484Skjd break; 10625484Skjd case FORMERR: 10725484Skjd case NOTIMP: 10825484Skjd case REFUSED: 10925484Skjd h_errno = NO_RECOVERY; 11025484Skjd } 11118505Sralph return (NULL); 11218505Sralph } 11318505Sralph bp = hostbuf; 11418505Sralph buflen = sizeof(hostbuf); 11525302Skjd cp = (char *)&answer + sizeof(HEADER); 11625153Sbloom if (qdcount) { 11718505Sralph if (iquery) { 11826066Skjd if ((n = dn_expand((char *)&answer, eom, 11926066Skjd cp, bp, buflen)) < 0) { 12025484Skjd h_errno = NO_RECOVERY; 12118505Sralph return (NULL); 12225484Skjd } 12318505Sralph cp += n + QFIXEDSZ; 12418505Sralph host.h_name = bp; 12518505Sralph n = strlen(bp) + 1; 12618505Sralph bp += n; 12718505Sralph buflen -= n; 12818505Sralph } else 12918505Sralph cp += dn_skip(cp) + QFIXEDSZ; 13025153Sbloom while (--qdcount > 0) 13125153Sbloom cp += dn_skip(cp) + QFIXEDSZ; 13225484Skjd } else if (iquery) { 13325484Skjd if (hp->aa) 13425484Skjd h_errno = HOST_NOT_FOUND; 13525484Skjd else 13625484Skjd h_errno = TRY_AGAIN; 13718505Sralph return (NULL); 13825484Skjd } 13924687Sbloom ap = host_aliases; 14024687Sbloom host.h_aliases = host_aliases; 14124687Sbloom hap = h_addr_ptrs; 14224687Sbloom host.h_addr_list = h_addr_ptrs; 14324687Sbloom haveanswer = 0; 14418505Sralph while (--ancount >= 0 && cp < eom) { 14526066Skjd if ((n = dn_expand((char *)&answer, eom, cp, bp, buflen)) < 0) 14624687Sbloom break; 14718505Sralph cp += n; 14818505Sralph type = getshort(cp); 14918505Sralph cp += sizeof(u_short); 15018505Sralph class = getshort(cp); 15118505Sralph cp += sizeof(u_short) + sizeof(u_long); 15218505Sralph n = getshort(cp); 15318505Sralph cp += sizeof(u_short); 15418505Sralph if (type == T_CNAME) { 15518505Sralph cp += n; 15618505Sralph if (ap >= &host_aliases[MAXALIASES-1]) 15718505Sralph continue; 15818505Sralph *ap++ = bp; 15918505Sralph n = strlen(bp) + 1; 16018505Sralph bp += n; 16118505Sralph buflen -= n; 16218505Sralph continue; 16318505Sralph } 16425153Sbloom if (type == T_PTR) { 165*27034Skjd if ((n = dn_expand((char *)&answer, eom, 166*27034Skjd cp, bp, buflen)) < 0) { 16725153Sbloom cp += n; 16825153Sbloom continue; 16925153Sbloom } 17025153Sbloom cp += n; 17125153Sbloom host.h_name = bp; 17225153Sbloom return(&host); 17325153Sbloom } 17424687Sbloom if (type != T_A) { 17524733Sbloom #ifdef DEBUG 17618505Sralph if (_res.options & RES_DEBUG) 17718505Sralph printf("unexpected answer type %d, size %d\n", 17818505Sralph type, n); 17924733Sbloom #endif 18024687Sbloom cp += n; 18118505Sralph continue; 18218505Sralph } 18324687Sbloom if (haveanswer) { 18424687Sbloom if (n != host.h_length) { 18524687Sbloom cp += n; 18624687Sbloom continue; 18724687Sbloom } 18824687Sbloom if (class != getclass) { 18924687Sbloom cp += n; 19024687Sbloom continue; 19124687Sbloom } 19224687Sbloom } else { 19324687Sbloom host.h_length = n; 19424687Sbloom getclass = class; 19525386Skjd host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC; 19624687Sbloom if (!iquery) { 19724687Sbloom host.h_name = bp; 19824687Sbloom bp += strlen(bp) + 1; 19924687Sbloom } 20018505Sralph } 20125302Skjd 20225302Skjd bp += ((u_long)bp % sizeof(align)); 20325302Skjd 20418505Sralph if (bp + n >= &hostbuf[sizeof(hostbuf)]) { 20524733Sbloom #ifdef DEBUG 20618505Sralph if (_res.options & RES_DEBUG) 20718505Sralph printf("size (%d) too big\n", n); 20824733Sbloom #endif 20924687Sbloom break; 21018505Sralph } 21124687Sbloom bcopy(cp, *hap++ = bp, n); 21224687Sbloom bp +=n; 21324687Sbloom cp += n; 21424687Sbloom haveanswer++; 21524687Sbloom } 21624687Sbloom if (haveanswer) { 21724687Sbloom *ap = NULL; 21824687Sbloom *hap = NULL; 21918505Sralph return (&host); 22025484Skjd } else { 22125484Skjd h_errno = TRY_AGAIN; 22224687Sbloom return (NULL); 22325484Skjd } 22415662Sralph } 22515662Sralph 22615662Sralph struct hostent * 22718505Sralph gethostbyname(name) 22818505Sralph char *name; 22915662Sralph { 23018505Sralph int n; 23125302Skjd querybuf buf; 23226887Skjd register struct hostent *hp; 23326887Skjd extern struct hostent *_gethtbyname(); 23415662Sralph 23526908Skjd n = res_mkquery(QUERY, name, C_IN, T_A, (char *)NULL, 0, NULL, 23625302Skjd (char *)&buf, sizeof(buf)); 23718505Sralph if (n < 0) { 23824733Sbloom #ifdef DEBUG 23918505Sralph if (_res.options & RES_DEBUG) 24018531Sralph printf("res_mkquery failed\n"); 24124733Sbloom #endif 24218505Sralph return (NULL); 24317761Sserge } 24426887Skjd hp = getanswer((char *)&buf, n, 0); 24526887Skjd if (hp == NULL && errno == ECONNREFUSED) 24626887Skjd hp = _gethtbyname(name); 24726887Skjd return(hp); 24815662Sralph } 24915662Sralph 25015662Sralph struct hostent * 25118505Sralph gethostbyaddr(addr, len, type) 25215662Sralph char *addr; 25318505Sralph int len, type; 25415662Sralph { 25518505Sralph int n; 25625302Skjd querybuf buf; 25725153Sbloom register struct hostent *hp; 25825153Sbloom char qbuf[MAXDNAME]; 25926887Skjd extern struct hostent *_gethtbyaddr(); 26026887Skjd 26118505Sralph if (type != AF_INET) 26218505Sralph return (NULL); 26325153Sbloom (void)sprintf(qbuf, "%d.%d.%d.%d.in-addr.arpa", 26425484Skjd ((unsigned)addr[3] & 0xff), 26525484Skjd ((unsigned)addr[2] & 0xff), 26625484Skjd ((unsigned)addr[1] & 0xff), 26725484Skjd ((unsigned)addr[0] & 0xff)); 268*27034Skjd n = res_mkquery(QUERY, qbuf, C_IN, T_PTR, (char *)NULL, 0, NULL, 26925302Skjd (char *)&buf, sizeof(buf)); 27018505Sralph if (n < 0) { 27124733Sbloom #ifdef DEBUG 27218505Sralph if (_res.options & RES_DEBUG) 27318531Sralph printf("res_mkquery failed\n"); 27424733Sbloom #endif 27518505Sralph return (NULL); 27617761Sserge } 27726887Skjd hp = getanswer((char *)&buf, n, 1); 27826887Skjd if (hp == NULL && errno == ECONNREFUSED) 27926887Skjd hp = _gethtbyaddr(addr, len, type); 28026887Skjd if (hp == NULL) 28125153Sbloom return(NULL); 28225153Sbloom hp->h_addrtype = type; 28325153Sbloom hp->h_length = len; 28425282Sbloom h_addr_ptrs[0] = (char *)&host_addr; 28525153Sbloom h_addr_ptrs[1] = (char *)0; 28625153Sbloom host_addr = *(struct in_addr *)addr; 28725153Sbloom return(hp); 28815662Sralph } 28925302Skjd 29026887Skjd 29126887Skjd _sethtent(f) 29226887Skjd int f; 29326887Skjd { 29426887Skjd if (hostf == NULL) 29526887Skjd hostf = fopen(HOSTDB, "r" ); 29626887Skjd else 29726887Skjd rewind(hostf); 29826887Skjd stayopen |= f; 29926887Skjd } 30026887Skjd 30126887Skjd _endhtent() 30226887Skjd { 30326887Skjd if (hostf && !stayopen) { 304*27034Skjd (void) fclose(hostf); 30526887Skjd hostf = NULL; 30626887Skjd } 30726887Skjd } 30826887Skjd 30926887Skjd struct hostent * 31026887Skjd _gethtent() 31126887Skjd { 31226887Skjd char *p; 31326887Skjd register char *cp, **q; 31426887Skjd 31526887Skjd if (hostf == NULL && (hostf = fopen(HOSTDB, "r" )) == NULL) 31626887Skjd return (NULL); 31726887Skjd again: 31826887Skjd if ((p = fgets(line, BUFSIZ, hostf)) == NULL) 31926887Skjd return (NULL); 32026887Skjd if (*p == '#') 32126887Skjd goto again; 32226887Skjd cp = any(p, "#\n"); 32326887Skjd if (cp == NULL) 32426887Skjd goto again; 32526887Skjd *cp = '\0'; 32626887Skjd cp = any(p, " \t"); 32726887Skjd if (cp == NULL) 32826887Skjd goto again; 32926887Skjd *cp++ = '\0'; 33026887Skjd /* THIS STUFF IS INTERNET SPECIFIC */ 33126887Skjd host.h_addr_list = host_addrs; 33226887Skjd host.h_addr = hostaddr; 33326887Skjd *((u_long *)host.h_addr) = inet_addr(p); 33426887Skjd host.h_length = sizeof (u_long); 33526887Skjd host.h_addrtype = AF_INET; 33626887Skjd while (*cp == ' ' || *cp == '\t') 33726887Skjd cp++; 33826887Skjd host.h_name = cp; 33926887Skjd q = host.h_aliases = host_aliases; 34026887Skjd cp = any(cp, " \t"); 34126887Skjd if (cp != NULL) 34226887Skjd *cp++ = '\0'; 34326887Skjd while (cp && *cp) { 34426887Skjd if (*cp == ' ' || *cp == '\t') { 34526887Skjd cp++; 34626887Skjd continue; 34726887Skjd } 34826887Skjd if (q < &host_aliases[MAXALIASES - 1]) 34926887Skjd *q++ = cp; 35026887Skjd cp = any(cp, " \t"); 35126887Skjd if (cp != NULL) 35226887Skjd *cp++ = '\0'; 35326887Skjd } 35426887Skjd *q = NULL; 35526887Skjd return (&host); 35626887Skjd } 35726887Skjd 35826887Skjd static char * 35926887Skjd any(cp, match) 36026887Skjd register char *cp; 36126887Skjd char *match; 36226887Skjd { 36326887Skjd register char *mp, c; 36426887Skjd 36526887Skjd while (c = *cp) { 36626887Skjd for (mp = match; *mp; mp++) 36726887Skjd if (*mp == c) 36826887Skjd return (cp); 36926887Skjd cp++; 37026887Skjd } 37126887Skjd return ((char *)0); 37226887Skjd } 37326887Skjd 37426887Skjd struct hostent * 37526887Skjd _gethtbyname(name) 37626887Skjd char *name; 37726887Skjd { 37826887Skjd register struct hostent *p; 37926887Skjd register char **cp; 38026887Skjd 38126887Skjd _sethtent(0); 38226887Skjd while (p = _gethtent()) { 38326887Skjd if (strcmp(p->h_name, name) == 0) 38426887Skjd break; 38526887Skjd for (cp = p->h_aliases; *cp != 0; cp++) 38626887Skjd if (strcmp(*cp, name) == 0) 38726887Skjd goto found; 38826887Skjd } 38926887Skjd found: 39026887Skjd _endhtent(); 39126887Skjd return (p); 39226887Skjd } 39326887Skjd 39426887Skjd struct hostent * 39526887Skjd _gethtbyaddr(addr, len, type) 39626887Skjd 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