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 633734Sbostic * provided that this notice is preserved and that due credit is given 733734Sbostic * to the University of California at Berkeley. The name of the University 833734Sbostic * may not be used to endorse or promote products derived from this 933734Sbostic * software without specific prior written permission. This software 1033734Sbostic * is provided ``as is'' without express or implied warranty. 1121374Sdist */ 1215662Sralph 1326630Sdonn #if defined(LIBC_SCCS) && !defined(lint) 14*33990Skarels static char sccsid[] = "@(#)gethostnamadr.c 6.32 (Berkeley) 04/12/88"; 1533734Sbostic #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 2933735Sbostic #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 hostaddr[MAXADDRS]; 4026887Skjd static char *host_addrs[2]; 4126887Skjd static int stayopen = 0; 4226887Skjd static char *any(); 4315662Sralph 4432648Skarels #if PACKETSZ > 1024 4533735Sbostic #define MAXPACKET PACKETSZ 4632648Skarels #else 4733735Sbostic #define MAXPACKET 1024 4832648Skarels #endif 4932648Skarels 5025302Skjd typedef union { 5133735Sbostic HEADER hdr; 5233735Sbostic u_char buf[MAXPACKET]; 5325302Skjd } querybuf; 5424509Sbloom 5525302Skjd static union { 5625302Skjd long al; 5725302Skjd char ac; 5825302Skjd } align; 5925302Skjd 6025302Skjd 6125484Skjd int h_errno; 6226887Skjd extern errno; 6325484Skjd 6415662Sralph static struct hostent * 6533735Sbostic getanswer(answer, anslen, iquery) 6633735Sbostic querybuf *answer; 6733735Sbostic int anslen; 6833735Sbostic int iquery; 6915662Sralph { 7018505Sralph register HEADER *hp; 7133735Sbostic register u_char *cp; 7218505Sralph register int n; 7333735Sbostic u_char *eom; 7433735Sbostic char *bp, **ap; 7527034Skjd int type, class, buflen, ancount, qdcount; 7627034Skjd int haveanswer, getclass = C_ANY; 7724687Sbloom char **hap; 7815662Sralph 7933735Sbostic eom = answer->buf + anslen; 8018505Sralph /* 8118505Sralph * find first satisfactory answer 8218505Sralph */ 8333735Sbostic hp = &answer->hdr; 8418505Sralph ancount = ntohs(hp->ancount); 8525153Sbloom qdcount = ntohs(hp->qdcount); 8618505Sralph bp = hostbuf; 8718505Sralph buflen = sizeof(hostbuf); 8833735Sbostic cp = answer->buf + sizeof(HEADER); 8925153Sbloom if (qdcount) { 9018505Sralph if (iquery) { 9133735Sbostic if ((n = dn_expand((char *)answer->buf, eom, 9226066Skjd cp, bp, buflen)) < 0) { 9325484Skjd h_errno = NO_RECOVERY; 9433500Skarels return ((struct hostent *) NULL); 9525484Skjd } 9618505Sralph cp += n + QFIXEDSZ; 9718505Sralph host.h_name = bp; 9818505Sralph n = strlen(bp) + 1; 9918505Sralph bp += n; 10018505Sralph buflen -= n; 10118505Sralph } else 10232648Skarels cp += dn_skipname(cp, eom) + QFIXEDSZ; 10325153Sbloom while (--qdcount > 0) 10432648Skarels cp += dn_skipname(cp, eom) + QFIXEDSZ; 10525484Skjd } else if (iquery) { 10625484Skjd if (hp->aa) 10725484Skjd h_errno = HOST_NOT_FOUND; 10825484Skjd else 10925484Skjd h_errno = TRY_AGAIN; 11033500Skarels return ((struct hostent *) NULL); 11125484Skjd } 11224687Sbloom ap = host_aliases; 11324687Sbloom host.h_aliases = host_aliases; 11424687Sbloom hap = h_addr_ptrs; 11533600Skarels #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ 11624687Sbloom host.h_addr_list = h_addr_ptrs; 11730460Skjd #endif 11824687Sbloom haveanswer = 0; 11918505Sralph while (--ancount >= 0 && cp < eom) { 12033735Sbostic if ((n = dn_expand((char *)answer->buf, eom, cp, bp, buflen)) < 0) 12124687Sbloom break; 12218505Sralph cp += n; 12330440Skjd type = _getshort(cp); 12418505Sralph cp += sizeof(u_short); 12530440Skjd class = _getshort(cp); 12618505Sralph cp += sizeof(u_short) + sizeof(u_long); 12730440Skjd n = _getshort(cp); 12818505Sralph cp += sizeof(u_short); 12918505Sralph if (type == T_CNAME) { 13018505Sralph cp += n; 13118505Sralph if (ap >= &host_aliases[MAXALIASES-1]) 13218505Sralph continue; 13318505Sralph *ap++ = bp; 13418505Sralph n = strlen(bp) + 1; 13518505Sralph bp += n; 13618505Sralph buflen -= n; 13718505Sralph continue; 13818505Sralph } 13933735Sbostic if (iquery && type == T_PTR) { 14033735Sbostic if ((n = dn_expand((char *)answer->buf, eom, 14127034Skjd cp, bp, buflen)) < 0) { 14225153Sbloom cp += n; 14325153Sbloom continue; 14425153Sbloom } 14525153Sbloom cp += n; 14625153Sbloom host.h_name = bp; 14725153Sbloom return(&host); 14825153Sbloom } 14933735Sbostic if (iquery || type != T_A) { 15024733Sbloom #ifdef DEBUG 15118505Sralph if (_res.options & RES_DEBUG) 15218505Sralph printf("unexpected answer type %d, size %d\n", 15318505Sralph type, n); 15424733Sbloom #endif 15524687Sbloom cp += n; 15618505Sralph continue; 15718505Sralph } 15824687Sbloom if (haveanswer) { 15924687Sbloom if (n != host.h_length) { 16024687Sbloom cp += n; 16124687Sbloom continue; 16224687Sbloom } 16324687Sbloom if (class != getclass) { 16424687Sbloom cp += n; 16524687Sbloom continue; 16624687Sbloom } 16724687Sbloom } else { 16824687Sbloom host.h_length = n; 16924687Sbloom getclass = class; 17025386Skjd host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC; 17124687Sbloom if (!iquery) { 17224687Sbloom host.h_name = bp; 17324687Sbloom bp += strlen(bp) + 1; 17424687Sbloom } 17518505Sralph } 17625302Skjd 17731902Skarels bp += sizeof(align) - ((u_long)bp % sizeof(align)); 17825302Skjd 17918505Sralph if (bp + n >= &hostbuf[sizeof(hostbuf)]) { 18024733Sbloom #ifdef DEBUG 18118505Sralph if (_res.options & RES_DEBUG) 18218505Sralph printf("size (%d) too big\n", n); 18324733Sbloom #endif 18424687Sbloom break; 18518505Sralph } 18624687Sbloom bcopy(cp, *hap++ = bp, n); 18724687Sbloom bp +=n; 18824687Sbloom cp += n; 18924687Sbloom haveanswer++; 19024687Sbloom } 19124687Sbloom if (haveanswer) { 19224687Sbloom *ap = NULL; 19333600Skarels #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ 19424687Sbloom *hap = NULL; 19531902Skarels #else 19631902Skarels host.h_addr = h_addr_ptrs[0]; 19731902Skarels #endif 19818505Sralph return (&host); 19925484Skjd } else { 20025484Skjd h_errno = TRY_AGAIN; 20133500Skarels return ((struct hostent *) NULL); 20225484Skjd } 20315662Sralph } 20415662Sralph 20515662Sralph struct hostent * 20618505Sralph gethostbyname(name) 20718505Sralph char *name; 20815662Sralph { 20933735Sbostic querybuf buf; 21033735Sbostic register char *cp; 21118505Sralph int n; 21231111Skarels struct hostent *hp, *gethostdomain(); 21326887Skjd extern struct hostent *_gethtbyname(); 21415662Sralph 21532976Sbostic /* 21632976Sbostic * disallow names consisting only of digits/dots, unless 21732976Sbostic * they end in a dot. 21832976Sbostic */ 21932976Sbostic if (isdigit(name[0])) 22032976Sbostic for (cp = name;; ++cp) { 22132976Sbostic if (!*cp) { 22232976Sbostic if (*--cp == '.') 22332976Sbostic break; 22432976Sbostic h_errno = HOST_NOT_FOUND; 22533500Skarels return ((struct hostent *) NULL); 22632976Sbostic } 22732976Sbostic if (!isdigit(*cp) && *cp != '.') 22832976Sbostic break; 22932976Sbostic } 23031111Skarels 23133735Sbostic if ((n = res_search(name, C_IN, T_A, buf.buf, sizeof(buf))) < 0) { 23224733Sbloom #ifdef DEBUG 23318505Sralph if (_res.options & RES_DEBUG) 23433735Sbostic printf("res_search failed\n"); 23524733Sbloom #endif 23633735Sbostic if (errno == ECONNREFUSED) 23733735Sbostic return (_gethtbyname(name)); 23833735Sbostic else 23933735Sbostic return ((struct hostent *) NULL); 24017761Sserge } 24133735Sbostic return (getanswer(&buf, n, 0)); 24215662Sralph } 24315662Sralph 24415662Sralph struct hostent * 24518505Sralph gethostbyaddr(addr, len, type) 24615662Sralph char *addr; 24718505Sralph int len, type; 24815662Sralph { 24918505Sralph int n; 25025302Skjd querybuf buf; 25125153Sbloom register struct hostent *hp; 25225153Sbloom char qbuf[MAXDNAME]; 25326887Skjd extern struct hostent *_gethtbyaddr(); 25426887Skjd 25518505Sralph if (type != AF_INET) 25633500Skarels return ((struct hostent *) NULL); 25725153Sbloom (void)sprintf(qbuf, "%d.%d.%d.%d.in-addr.arpa", 25825484Skjd ((unsigned)addr[3] & 0xff), 25925484Skjd ((unsigned)addr[2] & 0xff), 26025484Skjd ((unsigned)addr[1] & 0xff), 26125484Skjd ((unsigned)addr[0] & 0xff)); 26233735Sbostic n = res_query(qbuf, C_IN, T_PTR, (char *)&buf, sizeof(buf)); 26318505Sralph if (n < 0) { 26424733Sbloom #ifdef DEBUG 26518505Sralph if (_res.options & RES_DEBUG) 26633735Sbostic printf("res_query failed\n"); 26724733Sbloom #endif 26833735Sbostic if (errno == ECONNREFUSED) 269*33990Skarels return (_gethtbyaddr(addr, len, type)); 27033500Skarels return ((struct hostent *) NULL); 27117761Sserge } 27233735Sbostic hp = getanswer(&buf, n, 1); 27326887Skjd if (hp == NULL) 27433500Skarels return ((struct hostent *) NULL); 27525153Sbloom hp->h_addrtype = type; 27625153Sbloom hp->h_length = len; 27725282Sbloom h_addr_ptrs[0] = (char *)&host_addr; 27825153Sbloom h_addr_ptrs[1] = (char *)0; 27925153Sbloom host_addr = *(struct in_addr *)addr; 28025153Sbloom return(hp); 28115662Sralph } 28225302Skjd 28326887Skjd _sethtent(f) 28426887Skjd int f; 28526887Skjd { 28626887Skjd if (hostf == NULL) 28726887Skjd hostf = fopen(HOSTDB, "r" ); 28826887Skjd else 28926887Skjd rewind(hostf); 29026887Skjd stayopen |= f; 29126887Skjd } 29226887Skjd 29326887Skjd _endhtent() 29426887Skjd { 29526887Skjd if (hostf && !stayopen) { 29627034Skjd (void) fclose(hostf); 29726887Skjd hostf = NULL; 29826887Skjd } 29926887Skjd } 30026887Skjd 30126887Skjd struct hostent * 30226887Skjd _gethtent() 30326887Skjd { 30426887Skjd char *p; 30526887Skjd register char *cp, **q; 30626887Skjd 30726887Skjd if (hostf == NULL && (hostf = fopen(HOSTDB, "r" )) == NULL) 30826887Skjd return (NULL); 30926887Skjd again: 31033735Sbostic if ((p = fgets(hostbuf, BUFSIZ, hostf)) == NULL) 31126887Skjd return (NULL); 31226887Skjd if (*p == '#') 31326887Skjd goto again; 31426887Skjd cp = any(p, "#\n"); 31526887Skjd if (cp == NULL) 31626887Skjd goto again; 31726887Skjd *cp = '\0'; 31826887Skjd cp = any(p, " \t"); 31926887Skjd if (cp == NULL) 32026887Skjd goto again; 32126887Skjd *cp++ = '\0'; 32226887Skjd /* THIS STUFF IS INTERNET SPECIFIC */ 32333600Skarels #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ 32426887Skjd host.h_addr_list = host_addrs; 32530460Skjd #endif 32626887Skjd host.h_addr = hostaddr; 32726887Skjd *((u_long *)host.h_addr) = inet_addr(p); 32826887Skjd host.h_length = sizeof (u_long); 32926887Skjd host.h_addrtype = AF_INET; 33026887Skjd while (*cp == ' ' || *cp == '\t') 33126887Skjd cp++; 33226887Skjd host.h_name = cp; 33326887Skjd q = host.h_aliases = host_aliases; 33426887Skjd cp = any(cp, " \t"); 33526887Skjd if (cp != NULL) 33626887Skjd *cp++ = '\0'; 33726887Skjd while (cp && *cp) { 33826887Skjd if (*cp == ' ' || *cp == '\t') { 33926887Skjd cp++; 34026887Skjd continue; 34126887Skjd } 34226887Skjd if (q < &host_aliases[MAXALIASES - 1]) 34326887Skjd *q++ = cp; 34426887Skjd cp = any(cp, " \t"); 34526887Skjd if (cp != NULL) 34626887Skjd *cp++ = '\0'; 34726887Skjd } 34826887Skjd *q = NULL; 34926887Skjd return (&host); 35026887Skjd } 35126887Skjd 35226887Skjd static char * 35326887Skjd any(cp, match) 35426887Skjd register char *cp; 35526887Skjd char *match; 35626887Skjd { 35726887Skjd register char *mp, c; 35826887Skjd 35926887Skjd while (c = *cp) { 36026887Skjd for (mp = match; *mp; mp++) 36126887Skjd if (*mp == c) 36226887Skjd return (cp); 36326887Skjd cp++; 36426887Skjd } 36526887Skjd return ((char *)0); 36626887Skjd } 36726887Skjd 36826887Skjd struct hostent * 36926887Skjd _gethtbyname(name) 37026887Skjd char *name; 37126887Skjd { 37226887Skjd register struct hostent *p; 37326887Skjd register char **cp; 37428307Skarels 37526887Skjd _sethtent(0); 37626887Skjd while (p = _gethtent()) { 37731960Sbostic if (strcasecmp(p->h_name, name) == 0) 37826887Skjd break; 37926887Skjd for (cp = p->h_aliases; *cp != 0; cp++) 38031960Sbostic if (strcasecmp(*cp, name) == 0) 38126887Skjd goto found; 38226887Skjd } 38326887Skjd found: 38426887Skjd _endhtent(); 38526887Skjd return (p); 38626887Skjd } 38726887Skjd 38826887Skjd struct hostent * 38926887Skjd _gethtbyaddr(addr, len, type) 39026887Skjd char *addr; 39126887Skjd int len, type; 39226887Skjd { 39326887Skjd register struct hostent *p; 39426887Skjd 39526887Skjd _sethtent(0); 39626887Skjd while (p = _gethtent()) 39726909Skjd if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len)) 39826887Skjd break; 39926887Skjd _endhtent(); 40026887Skjd return (p); 40126887Skjd } 402