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*37108Sbostic static char sccsid[] = "@(#)gethostnamadr.c 6.37 (Berkeley) 03/09/89"; 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 char HOSTDB[] = "/etc/hosts"; 4326887Skjd static FILE *hostf = NULL; 4426887Skjd static char hostaddr[MAXADDRS]; 4526887Skjd static char *host_addrs[2]; 4626887Skjd static int stayopen = 0; 47*37108Sbostic char *strpbrk(); 4815662Sralph 4932648Skarels #if PACKETSZ > 1024 5033735Sbostic #define MAXPACKET PACKETSZ 5132648Skarels #else 5233735Sbostic #define MAXPACKET 1024 5332648Skarels #endif 5432648Skarels 5525302Skjd typedef union { 5633735Sbostic HEADER hdr; 5733735Sbostic u_char buf[MAXPACKET]; 5825302Skjd } querybuf; 5924509Sbloom 6035765Skarels typedef union { 6125302Skjd long al; 6225302Skjd char ac; 6325302Skjd } align; 6425302Skjd 6525302Skjd 6625484Skjd int h_errno; 6726887Skjd extern errno; 6825484Skjd 6915662Sralph static struct hostent * 7033735Sbostic getanswer(answer, anslen, iquery) 7133735Sbostic querybuf *answer; 7233735Sbostic int anslen; 7333735Sbostic int iquery; 7415662Sralph { 7518505Sralph register HEADER *hp; 7633735Sbostic register u_char *cp; 7718505Sralph register int n; 7833735Sbostic u_char *eom; 7933735Sbostic char *bp, **ap; 8027034Skjd int type, class, buflen, ancount, qdcount; 8127034Skjd int haveanswer, getclass = C_ANY; 8224687Sbloom char **hap; 8315662Sralph 8433735Sbostic eom = answer->buf + anslen; 8518505Sralph /* 8618505Sralph * find first satisfactory answer 8718505Sralph */ 8833735Sbostic hp = &answer->hdr; 8918505Sralph ancount = ntohs(hp->ancount); 9025153Sbloom qdcount = ntohs(hp->qdcount); 9118505Sralph bp = hostbuf; 9218505Sralph buflen = sizeof(hostbuf); 9333735Sbostic cp = answer->buf + sizeof(HEADER); 9425153Sbloom if (qdcount) { 9518505Sralph if (iquery) { 9633735Sbostic if ((n = dn_expand((char *)answer->buf, eom, 9726066Skjd cp, bp, buflen)) < 0) { 9825484Skjd h_errno = NO_RECOVERY; 9933500Skarels return ((struct hostent *) NULL); 10025484Skjd } 10118505Sralph cp += n + QFIXEDSZ; 10218505Sralph host.h_name = bp; 10318505Sralph n = strlen(bp) + 1; 10418505Sralph bp += n; 10518505Sralph buflen -= n; 10618505Sralph } else 10732648Skarels cp += dn_skipname(cp, eom) + QFIXEDSZ; 10825153Sbloom while (--qdcount > 0) 10932648Skarels cp += dn_skipname(cp, eom) + QFIXEDSZ; 11025484Skjd } else if (iquery) { 11125484Skjd if (hp->aa) 11225484Skjd h_errno = HOST_NOT_FOUND; 11325484Skjd else 11425484Skjd h_errno = TRY_AGAIN; 11533500Skarels return ((struct hostent *) NULL); 11625484Skjd } 11724687Sbloom ap = host_aliases; 11824687Sbloom host.h_aliases = host_aliases; 11924687Sbloom hap = h_addr_ptrs; 12033600Skarels #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ 12124687Sbloom host.h_addr_list = h_addr_ptrs; 12230460Skjd #endif 12324687Sbloom haveanswer = 0; 12418505Sralph while (--ancount >= 0 && cp < eom) { 12533735Sbostic if ((n = dn_expand((char *)answer->buf, eom, cp, bp, buflen)) < 0) 12624687Sbloom break; 12718505Sralph cp += n; 12830440Skjd type = _getshort(cp); 12918505Sralph cp += sizeof(u_short); 13030440Skjd class = _getshort(cp); 13118505Sralph cp += sizeof(u_short) + sizeof(u_long); 13230440Skjd n = _getshort(cp); 13318505Sralph cp += sizeof(u_short); 13418505Sralph if (type == T_CNAME) { 13518505Sralph cp += n; 13618505Sralph if (ap >= &host_aliases[MAXALIASES-1]) 13718505Sralph continue; 13818505Sralph *ap++ = bp; 13918505Sralph n = strlen(bp) + 1; 14018505Sralph bp += n; 14118505Sralph buflen -= n; 14218505Sralph continue; 14318505Sralph } 14433735Sbostic if (iquery && type == T_PTR) { 14533735Sbostic if ((n = dn_expand((char *)answer->buf, eom, 14627034Skjd cp, bp, buflen)) < 0) { 14725153Sbloom cp += n; 14825153Sbloom continue; 14925153Sbloom } 15025153Sbloom cp += n; 15125153Sbloom host.h_name = bp; 15225153Sbloom return(&host); 15325153Sbloom } 15433735Sbostic if (iquery || type != T_A) { 15524733Sbloom #ifdef DEBUG 15618505Sralph if (_res.options & RES_DEBUG) 15718505Sralph printf("unexpected answer type %d, size %d\n", 15818505Sralph type, n); 15924733Sbloom #endif 16024687Sbloom cp += n; 16118505Sralph continue; 16218505Sralph } 16324687Sbloom if (haveanswer) { 16424687Sbloom if (n != host.h_length) { 16524687Sbloom cp += n; 16624687Sbloom continue; 16724687Sbloom } 16824687Sbloom if (class != getclass) { 16924687Sbloom cp += n; 17024687Sbloom continue; 17124687Sbloom } 17224687Sbloom } else { 17324687Sbloom host.h_length = n; 17424687Sbloom getclass = class; 17525386Skjd host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC; 17624687Sbloom if (!iquery) { 17724687Sbloom host.h_name = bp; 17824687Sbloom bp += strlen(bp) + 1; 17924687Sbloom } 18018505Sralph } 18125302Skjd 18231902Skarels bp += sizeof(align) - ((u_long)bp % sizeof(align)); 18325302Skjd 18418505Sralph if (bp + n >= &hostbuf[sizeof(hostbuf)]) { 18524733Sbloom #ifdef DEBUG 18618505Sralph if (_res.options & RES_DEBUG) 18718505Sralph printf("size (%d) too big\n", n); 18824733Sbloom #endif 18924687Sbloom break; 19018505Sralph } 19124687Sbloom bcopy(cp, *hap++ = bp, n); 19224687Sbloom bp +=n; 19324687Sbloom cp += n; 19424687Sbloom haveanswer++; 19524687Sbloom } 19624687Sbloom if (haveanswer) { 19724687Sbloom *ap = NULL; 19833600Skarels #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ 19924687Sbloom *hap = NULL; 20031902Skarels #else 20131902Skarels host.h_addr = h_addr_ptrs[0]; 20231902Skarels #endif 20318505Sralph return (&host); 20425484Skjd } else { 20525484Skjd h_errno = TRY_AGAIN; 20633500Skarels return ((struct hostent *) NULL); 20725484Skjd } 20815662Sralph } 20915662Sralph 21015662Sralph struct hostent * 21118505Sralph gethostbyname(name) 21218505Sralph char *name; 21315662Sralph { 21433735Sbostic querybuf buf; 21533735Sbostic register char *cp; 21618505Sralph int n; 21726887Skjd extern struct hostent *_gethtbyname(); 21815662Sralph 21932976Sbostic /* 22032976Sbostic * disallow names consisting only of digits/dots, unless 22132976Sbostic * they end in a dot. 22232976Sbostic */ 22332976Sbostic if (isdigit(name[0])) 22432976Sbostic for (cp = name;; ++cp) { 22532976Sbostic if (!*cp) { 22632976Sbostic if (*--cp == '.') 22732976Sbostic break; 22832976Sbostic h_errno = HOST_NOT_FOUND; 22933500Skarels return ((struct hostent *) NULL); 23032976Sbostic } 23132976Sbostic if (!isdigit(*cp) && *cp != '.') 23232976Sbostic break; 23332976Sbostic } 23431111Skarels 23533735Sbostic if ((n = res_search(name, C_IN, T_A, buf.buf, sizeof(buf))) < 0) { 23624733Sbloom #ifdef DEBUG 23718505Sralph if (_res.options & RES_DEBUG) 23833735Sbostic printf("res_search failed\n"); 23924733Sbloom #endif 24033735Sbostic if (errno == ECONNREFUSED) 24133735Sbostic return (_gethtbyname(name)); 24233735Sbostic else 24333735Sbostic return ((struct hostent *) NULL); 24417761Sserge } 24533735Sbostic return (getanswer(&buf, n, 0)); 24615662Sralph } 24715662Sralph 24815662Sralph struct hostent * 24918505Sralph gethostbyaddr(addr, len, type) 25015662Sralph char *addr; 25118505Sralph int len, type; 25215662Sralph { 25318505Sralph int n; 25425302Skjd querybuf buf; 25525153Sbloom register struct hostent *hp; 25625153Sbloom char qbuf[MAXDNAME]; 25726887Skjd extern struct hostent *_gethtbyaddr(); 25826887Skjd 25918505Sralph if (type != AF_INET) 26033500Skarels return ((struct hostent *) NULL); 26135395Sbostic (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", 26225484Skjd ((unsigned)addr[3] & 0xff), 26325484Skjd ((unsigned)addr[2] & 0xff), 26425484Skjd ((unsigned)addr[1] & 0xff), 26525484Skjd ((unsigned)addr[0] & 0xff)); 26633735Sbostic n = res_query(qbuf, C_IN, T_PTR, (char *)&buf, sizeof(buf)); 26718505Sralph if (n < 0) { 26824733Sbloom #ifdef DEBUG 26918505Sralph if (_res.options & RES_DEBUG) 27033735Sbostic printf("res_query failed\n"); 27124733Sbloom #endif 27233735Sbostic if (errno == ECONNREFUSED) 27333990Skarels return (_gethtbyaddr(addr, len, type)); 27433500Skarels return ((struct hostent *) NULL); 27517761Sserge } 27633735Sbostic hp = getanswer(&buf, n, 1); 27726887Skjd if (hp == NULL) 27833500Skarels return ((struct hostent *) NULL); 27925153Sbloom hp->h_addrtype = type; 28025153Sbloom hp->h_length = len; 28125282Sbloom h_addr_ptrs[0] = (char *)&host_addr; 28225153Sbloom h_addr_ptrs[1] = (char *)0; 28325153Sbloom host_addr = *(struct in_addr *)addr; 28425153Sbloom return(hp); 28515662Sralph } 28625302Skjd 28726887Skjd _sethtent(f) 28826887Skjd int f; 28926887Skjd { 29026887Skjd if (hostf == NULL) 29126887Skjd hostf = fopen(HOSTDB, "r" ); 29226887Skjd else 29326887Skjd rewind(hostf); 29426887Skjd stayopen |= f; 29526887Skjd } 29626887Skjd 29726887Skjd _endhtent() 29826887Skjd { 29926887Skjd if (hostf && !stayopen) { 30027034Skjd (void) fclose(hostf); 30126887Skjd hostf = NULL; 30226887Skjd } 30326887Skjd } 30426887Skjd 30526887Skjd struct hostent * 30626887Skjd _gethtent() 30726887Skjd { 30826887Skjd char *p; 30926887Skjd register char *cp, **q; 31026887Skjd 31126887Skjd if (hostf == NULL && (hostf = fopen(HOSTDB, "r" )) == NULL) 31226887Skjd return (NULL); 31326887Skjd again: 31433735Sbostic if ((p = fgets(hostbuf, BUFSIZ, hostf)) == NULL) 31526887Skjd return (NULL); 31626887Skjd if (*p == '#') 31726887Skjd goto again; 318*37108Sbostic cp = strpbrk(p, "#\n"); 31926887Skjd if (cp == NULL) 32026887Skjd goto again; 32126887Skjd *cp = '\0'; 322*37108Sbostic cp = strpbrk(p, " \t"); 32326887Skjd if (cp == NULL) 32426887Skjd goto again; 32526887Skjd *cp++ = '\0'; 32626887Skjd /* THIS STUFF IS INTERNET SPECIFIC */ 32733600Skarels #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ 32826887Skjd host.h_addr_list = host_addrs; 32930460Skjd #endif 33026887Skjd host.h_addr = hostaddr; 33126887Skjd *((u_long *)host.h_addr) = inet_addr(p); 33226887Skjd host.h_length = sizeof (u_long); 33326887Skjd host.h_addrtype = AF_INET; 33426887Skjd while (*cp == ' ' || *cp == '\t') 33526887Skjd cp++; 33626887Skjd host.h_name = cp; 33726887Skjd q = host.h_aliases = host_aliases; 338*37108Sbostic cp = strpbrk(cp, " \t"); 33926887Skjd if (cp != NULL) 34026887Skjd *cp++ = '\0'; 34126887Skjd while (cp && *cp) { 34226887Skjd if (*cp == ' ' || *cp == '\t') { 34326887Skjd cp++; 34426887Skjd continue; 34526887Skjd } 34626887Skjd if (q < &host_aliases[MAXALIASES - 1]) 34726887Skjd *q++ = cp; 348*37108Sbostic cp = strpbrk(cp, " \t"); 34926887Skjd if (cp != NULL) 35026887Skjd *cp++ = '\0'; 35126887Skjd } 35226887Skjd *q = NULL; 35326887Skjd return (&host); 35426887Skjd } 35526887Skjd 35626887Skjd struct hostent * 35726887Skjd _gethtbyname(name) 35826887Skjd char *name; 35926887Skjd { 36026887Skjd register struct hostent *p; 36126887Skjd register char **cp; 36228307Skarels 36326887Skjd _sethtent(0); 36426887Skjd while (p = _gethtent()) { 36531960Sbostic if (strcasecmp(p->h_name, name) == 0) 36626887Skjd break; 36726887Skjd for (cp = p->h_aliases; *cp != 0; cp++) 36831960Sbostic if (strcasecmp(*cp, name) == 0) 36926887Skjd goto found; 37026887Skjd } 37126887Skjd found: 37226887Skjd _endhtent(); 37326887Skjd return (p); 37426887Skjd } 37526887Skjd 37626887Skjd struct hostent * 37726887Skjd _gethtbyaddr(addr, len, type) 37826887Skjd char *addr; 37926887Skjd int len, type; 38026887Skjd { 38126887Skjd register struct hostent *p; 38226887Skjd 38326887Skjd _sethtent(0); 38426887Skjd while (p = _gethtent()) 38526909Skjd if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len)) 38626887Skjd break; 38726887Skjd _endhtent(); 38826887Skjd return (p); 38926887Skjd } 390