161023Skarels /*-
2*61150Sbostic * Copyright (c) 1985, 1988, 1993
3*61150Sbostic * The Regents of the University of California. All rights reserved.
433734Sbostic *
542625Sbostic * %sccs.include.redist.c%
661023Skarels * -
761023Skarels * Portions Copyright (c) 1993 by Digital Equipment Corporation.
861023Skarels *
961023Skarels * Permission to use, copy, modify, and distribute this software for any
1061023Skarels * purpose with or without fee is hereby granted, provided that the above
1161023Skarels * copyright notice and this permission notice appear in all copies, and that
1261023Skarels * the name of Digital Equipment Corporation not be used in advertising or
1361023Skarels * publicity pertaining to distribution of the document or software without
1461023Skarels * specific, written prior permission.
1561023Skarels *
1661023Skarels * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
1761023Skarels * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
1861023Skarels * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
1961023Skarels * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
2061023Skarels * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
2161023Skarels * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
2261023Skarels * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
2361023Skarels * SOFTWARE.
2461023Skarels * -
2561023Skarels * --Copyright--
2621374Sdist */
2715662Sralph
2826630Sdonn #if defined(LIBC_SCCS) && !defined(lint)
29*61150Sbostic static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 06/04/93";
3061023Skarels static char rcsid[] = "$Id: gethnamaddr.c,v 4.9.1.1 1993/05/02 22:43:03 vixie Rel $";
3133734Sbostic #endif /* LIBC_SCCS and not lint */
3221374Sdist
3330468Skjd #include <sys/param.h>
3418505Sralph #include <sys/socket.h>
3518505Sralph #include <netinet/in.h>
3646604Sbostic #include <arpa/inet.h>
3746604Sbostic #include <arpa/nameser.h>
3846604Sbostic #include <netdb.h>
3946604Sbostic #include <resolv.h>
4015662Sralph #include <stdio.h>
4146606Sbostic #include <ctype.h>
4226887Skjd #include <errno.h>
4346604Sbostic #include <string.h>
4415662Sralph
4515662Sralph #define MAXALIASES 35
4633735Sbostic #define MAXADDRS 35
4715662Sralph
4824687Sbloom static char *h_addr_ptrs[MAXADDRS + 1];
4924687Sbloom
5024687Sbloom static struct hostent host;
5115662Sralph static char *host_aliases[MAXALIASES];
5215912Sralph static char hostbuf[BUFSIZ+1];
5325153Sbloom static struct in_addr host_addr;
5426887Skjd static FILE *hostf = NULL;
5526887Skjd static char hostaddr[MAXADDRS];
5626887Skjd static char *host_addrs[2];
5726887Skjd static int stayopen = 0;
5837108Sbostic char *strpbrk();
5915662Sralph
6032648Skarels #if PACKETSZ > 1024
6133735Sbostic #define MAXPACKET PACKETSZ
6232648Skarels #else
6333735Sbostic #define MAXPACKET 1024
6432648Skarels #endif
6532648Skarels
6625302Skjd typedef union {
6733735Sbostic HEADER hdr;
6833735Sbostic u_char buf[MAXPACKET];
6925302Skjd } querybuf;
7024509Sbloom
7135765Skarels typedef union {
7261023Skarels int32_t al;
7325302Skjd char ac;
7425302Skjd } align;
7525302Skjd
7661023Skarels extern int h_errno;
7725484Skjd
7815662Sralph static struct hostent *
getanswer(answer,anslen,iquery)7933735Sbostic getanswer(answer, anslen, iquery)
8033735Sbostic querybuf *answer;
8133735Sbostic int anslen;
8233735Sbostic int iquery;
8315662Sralph {
8418505Sralph register HEADER *hp;
8533735Sbostic register u_char *cp;
8618505Sralph register int n;
8733735Sbostic u_char *eom;
8833735Sbostic char *bp, **ap;
8927034Skjd int type, class, buflen, ancount, qdcount;
9027034Skjd int haveanswer, getclass = C_ANY;
9124687Sbloom char **hap;
9215662Sralph
9333735Sbostic eom = answer->buf + anslen;
9418505Sralph /*
9518505Sralph * find first satisfactory answer
9618505Sralph */
9733735Sbostic hp = &answer->hdr;
9818505Sralph ancount = ntohs(hp->ancount);
9925153Sbloom qdcount = ntohs(hp->qdcount);
10018505Sralph bp = hostbuf;
10118505Sralph buflen = sizeof(hostbuf);
10233735Sbostic cp = answer->buf + sizeof(HEADER);
10325153Sbloom if (qdcount) {
10418505Sralph if (iquery) {
10546604Sbostic if ((n = dn_expand((u_char *)answer->buf,
10646604Sbostic (u_char *)eom, (u_char *)cp, (u_char *)bp,
10746604Sbostic buflen)) < 0) {
10825484Skjd h_errno = NO_RECOVERY;
10933500Skarels return ((struct hostent *) NULL);
11025484Skjd }
11118505Sralph cp += n + QFIXEDSZ;
11218505Sralph host.h_name = bp;
11318505Sralph n = strlen(bp) + 1;
11418505Sralph bp += n;
11518505Sralph buflen -= n;
11618505Sralph } else
11746496Sbostic cp += __dn_skipname(cp, eom) + QFIXEDSZ;
11825153Sbloom while (--qdcount > 0)
11946496Sbostic cp += __dn_skipname(cp, eom) + QFIXEDSZ;
12025484Skjd } else if (iquery) {
12125484Skjd if (hp->aa)
12225484Skjd h_errno = HOST_NOT_FOUND;
12325484Skjd else
12425484Skjd h_errno = TRY_AGAIN;
12533500Skarels return ((struct hostent *) NULL);
12625484Skjd }
12724687Sbloom ap = host_aliases;
12839862Skarels *ap = NULL;
12924687Sbloom host.h_aliases = host_aliases;
13024687Sbloom hap = h_addr_ptrs;
13139862Skarels *hap = NULL;
13233600Skarels #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */
13324687Sbloom host.h_addr_list = h_addr_ptrs;
13430460Skjd #endif
13524687Sbloom haveanswer = 0;
13618505Sralph while (--ancount >= 0 && cp < eom) {
13746604Sbostic if ((n = dn_expand((u_char *)answer->buf, (u_char *)eom,
13846604Sbostic (u_char *)cp, (u_char *)bp, buflen)) < 0)
13924687Sbloom break;
14018505Sralph cp += n;
14130440Skjd type = _getshort(cp);
14261023Skarels cp += sizeof(u_int16_t);
14330440Skjd class = _getshort(cp);
14461023Skarels cp += sizeof(u_int16_t) + sizeof(u_int32_t);
14530440Skjd n = _getshort(cp);
14661023Skarels cp += sizeof(u_int16_t);
14718505Sralph if (type == T_CNAME) {
14818505Sralph cp += n;
14918505Sralph if (ap >= &host_aliases[MAXALIASES-1])
15018505Sralph continue;
15118505Sralph *ap++ = bp;
15218505Sralph n = strlen(bp) + 1;
15318505Sralph bp += n;
15418505Sralph buflen -= n;
15518505Sralph continue;
15618505Sralph }
15733735Sbostic if (iquery && type == T_PTR) {
15846604Sbostic if ((n = dn_expand((u_char *)answer->buf,
15946604Sbostic (u_char *)eom, (u_char *)cp, (u_char *)bp,
16057465Sbostic buflen)) < 0)
16157465Sbostic break;
16225153Sbloom cp += n;
16325153Sbloom host.h_name = bp;
16425153Sbloom return(&host);
16525153Sbloom }
16633735Sbostic if (iquery || type != T_A) {
16724733Sbloom #ifdef DEBUG
16818505Sralph if (_res.options & RES_DEBUG)
16918505Sralph printf("unexpected answer type %d, size %d\n",
17018505Sralph type, n);
17124733Sbloom #endif
17224687Sbloom cp += n;
17318505Sralph continue;
17418505Sralph }
17524687Sbloom if (haveanswer) {
17624687Sbloom if (n != host.h_length) {
17724687Sbloom cp += n;
17824687Sbloom continue;
17924687Sbloom }
18024687Sbloom if (class != getclass) {
18124687Sbloom cp += n;
18224687Sbloom continue;
18324687Sbloom }
18424687Sbloom } else {
18524687Sbloom host.h_length = n;
18624687Sbloom getclass = class;
18725386Skjd host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC;
18824687Sbloom if (!iquery) {
18924687Sbloom host.h_name = bp;
19024687Sbloom bp += strlen(bp) + 1;
19124687Sbloom }
19218505Sralph }
19325302Skjd
19461023Skarels bp += sizeof(align) - ((u_int32_t)bp % sizeof(align));
19525302Skjd
19618505Sralph if (bp + n >= &hostbuf[sizeof(hostbuf)]) {
19724733Sbloom #ifdef DEBUG
19818505Sralph if (_res.options & RES_DEBUG)
19918505Sralph printf("size (%d) too big\n", n);
20024733Sbloom #endif
20124687Sbloom break;
20218505Sralph }
20324687Sbloom bcopy(cp, *hap++ = bp, n);
20424687Sbloom bp +=n;
20524687Sbloom cp += n;
20624687Sbloom haveanswer++;
20724687Sbloom }
20824687Sbloom if (haveanswer) {
20924687Sbloom *ap = NULL;
21033600Skarels #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */
21124687Sbloom *hap = NULL;
21231902Skarels #else
21331902Skarels host.h_addr = h_addr_ptrs[0];
21431902Skarels #endif
21518505Sralph return (&host);
21625484Skjd } else {
21725484Skjd h_errno = TRY_AGAIN;
21833500Skarels return ((struct hostent *) NULL);
21925484Skjd }
22015662Sralph }
22115662Sralph
22215662Sralph struct hostent *
gethostbyname(name)22318505Sralph gethostbyname(name)
22453078Sbostic const char *name;
22515662Sralph {
22633735Sbostic querybuf buf;
22753078Sbostic register const char *cp;
22818505Sralph int n;
22926887Skjd extern struct hostent *_gethtbyname();
23015662Sralph
23132976Sbostic /*
23232976Sbostic * disallow names consisting only of digits/dots, unless
23332976Sbostic * they end in a dot.
23432976Sbostic */
23532976Sbostic if (isdigit(name[0]))
23632976Sbostic for (cp = name;; ++cp) {
23732976Sbostic if (!*cp) {
23832976Sbostic if (*--cp == '.')
23932976Sbostic break;
24039710Sbloom /*
24139710Sbloom * All-numeric, no dot at the end.
24239710Sbloom * Fake up a hostent as if we'd actually
24354055Sandrew * done a lookup.
24439710Sbloom */
24554055Sandrew if (!inet_aton(name, &host_addr)) {
24639710Sbloom h_errno = HOST_NOT_FOUND;
24739710Sbloom return((struct hostent *) NULL);
24839710Sbloom }
24953078Sbostic host.h_name = (char *)name;
25039710Sbloom host.h_aliases = host_aliases;
25139710Sbloom host_aliases[0] = NULL;
25239710Sbloom host.h_addrtype = AF_INET;
25361023Skarels host.h_length = sizeof(u_int32_t);
25439710Sbloom h_addr_ptrs[0] = (char *)&host_addr;
25539710Sbloom h_addr_ptrs[1] = (char *)0;
25639710Sbloom #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */
25739710Sbloom host.h_addr_list = h_addr_ptrs;
25839710Sbloom #else
25939710Sbloom host.h_addr = h_addr_ptrs[0];
26039710Sbloom #endif
26139710Sbloom return (&host);
26232976Sbostic }
26332976Sbostic if (!isdigit(*cp) && *cp != '.')
26432976Sbostic break;
26532976Sbostic }
26631111Skarels
26733735Sbostic if ((n = res_search(name, C_IN, T_A, buf.buf, sizeof(buf))) < 0) {
26824733Sbloom #ifdef DEBUG
26918505Sralph if (_res.options & RES_DEBUG)
27033735Sbostic printf("res_search failed\n");
27124733Sbloom #endif
27233735Sbostic if (errno == ECONNREFUSED)
27333735Sbostic return (_gethtbyname(name));
27433735Sbostic else
27533735Sbostic return ((struct hostent *) NULL);
27617761Sserge }
27733735Sbostic return (getanswer(&buf, n, 0));
27815662Sralph }
27915662Sralph
28015662Sralph struct hostent *
gethostbyaddr(addr,len,type)28118505Sralph gethostbyaddr(addr, len, type)
28246604Sbostic const char *addr;
28318505Sralph int len, type;
28415662Sralph {
28518505Sralph int n;
28625302Skjd querybuf buf;
28725153Sbloom register struct hostent *hp;
28825153Sbloom char qbuf[MAXDNAME];
28926887Skjd extern struct hostent *_gethtbyaddr();
29026887Skjd
29118505Sralph if (type != AF_INET)
29233500Skarels return ((struct hostent *) NULL);
29335395Sbostic (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
29425484Skjd ((unsigned)addr[3] & 0xff),
29525484Skjd ((unsigned)addr[2] & 0xff),
29625484Skjd ((unsigned)addr[1] & 0xff),
29725484Skjd ((unsigned)addr[0] & 0xff));
29833735Sbostic n = res_query(qbuf, C_IN, T_PTR, (char *)&buf, sizeof(buf));
29918505Sralph if (n < 0) {
30024733Sbloom #ifdef DEBUG
30118505Sralph if (_res.options & RES_DEBUG)
30233735Sbostic printf("res_query failed\n");
30324733Sbloom #endif
30433735Sbostic if (errno == ECONNREFUSED)
30533990Skarels return (_gethtbyaddr(addr, len, type));
30633500Skarels return ((struct hostent *) NULL);
30717761Sserge }
30833735Sbostic hp = getanswer(&buf, n, 1);
30926887Skjd if (hp == NULL)
31033500Skarels return ((struct hostent *) NULL);
31125153Sbloom hp->h_addrtype = type;
31225153Sbloom hp->h_length = len;
31325282Sbloom h_addr_ptrs[0] = (char *)&host_addr;
31425153Sbloom h_addr_ptrs[1] = (char *)0;
31525153Sbloom host_addr = *(struct in_addr *)addr;
31639710Sbloom #if BSD < 43 && !defined(h_addr) /* new-style hostent structure */
31739710Sbloom hp->h_addr = h_addr_ptrs[0];
31839710Sbloom #endif
31925153Sbloom return(hp);
32015662Sralph }
32125302Skjd
32261023Skarels void
_sethtent(f)32326887Skjd _sethtent(f)
32426887Skjd int f;
32526887Skjd {
32626887Skjd if (hostf == NULL)
32742266Sbostic hostf = fopen(_PATH_HOSTS, "r" );
32826887Skjd else
32926887Skjd rewind(hostf);
33026887Skjd stayopen |= f;
33126887Skjd }
33226887Skjd
33361023Skarels void
_endhtent()33426887Skjd _endhtent()
33526887Skjd {
33626887Skjd if (hostf && !stayopen) {
33727034Skjd (void) fclose(hostf);
33826887Skjd hostf = NULL;
33926887Skjd }
34026887Skjd }
34126887Skjd
34226887Skjd struct hostent *
_gethtent()34326887Skjd _gethtent()
34426887Skjd {
34526887Skjd char *p;
34626887Skjd register char *cp, **q;
34726887Skjd
34842266Sbostic if (hostf == NULL && (hostf = fopen(_PATH_HOSTS, "r" )) == NULL)
34926887Skjd return (NULL);
35026887Skjd again:
35133735Sbostic if ((p = fgets(hostbuf, BUFSIZ, hostf)) == NULL)
35226887Skjd return (NULL);
35326887Skjd if (*p == '#')
35426887Skjd goto again;
35537108Sbostic cp = strpbrk(p, "#\n");
35626887Skjd if (cp == NULL)
35726887Skjd goto again;
35826887Skjd *cp = '\0';
35937108Sbostic cp = strpbrk(p, " \t");
36026887Skjd if (cp == NULL)
36126887Skjd goto again;
36226887Skjd *cp++ = '\0';
36326887Skjd /* THIS STUFF IS INTERNET SPECIFIC */
36433600Skarels #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */
36526887Skjd host.h_addr_list = host_addrs;
36630460Skjd #endif
36726887Skjd host.h_addr = hostaddr;
36861023Skarels *((u_int32_t *)host.h_addr) = inet_addr(p);
36961023Skarels host.h_length = sizeof (u_int32_t);
37026887Skjd host.h_addrtype = AF_INET;
37126887Skjd while (*cp == ' ' || *cp == '\t')
37226887Skjd cp++;
37326887Skjd host.h_name = cp;
37426887Skjd q = host.h_aliases = host_aliases;
37537108Sbostic cp = strpbrk(cp, " \t");
37626887Skjd if (cp != NULL)
37726887Skjd *cp++ = '\0';
37826887Skjd while (cp && *cp) {
37926887Skjd if (*cp == ' ' || *cp == '\t') {
38026887Skjd cp++;
38126887Skjd continue;
38226887Skjd }
38326887Skjd if (q < &host_aliases[MAXALIASES - 1])
38426887Skjd *q++ = cp;
38537108Sbostic cp = strpbrk(cp, " \t");
38626887Skjd if (cp != NULL)
38726887Skjd *cp++ = '\0';
38826887Skjd }
38926887Skjd *q = NULL;
39026887Skjd return (&host);
39126887Skjd }
39226887Skjd
39326887Skjd struct hostent *
_gethtbyname(name)39426887Skjd _gethtbyname(name)
39526887Skjd char *name;
39626887Skjd {
39726887Skjd register struct hostent *p;
39826887Skjd register char **cp;
39928307Skarels
40026887Skjd _sethtent(0);
40126887Skjd while (p = _gethtent()) {
40231960Sbostic if (strcasecmp(p->h_name, name) == 0)
40326887Skjd break;
40426887Skjd for (cp = p->h_aliases; *cp != 0; cp++)
40531960Sbostic if (strcasecmp(*cp, name) == 0)
40626887Skjd goto found;
40726887Skjd }
40826887Skjd found:
40926887Skjd _endhtent();
41026887Skjd return (p);
41126887Skjd }
41226887Skjd
41326887Skjd struct hostent *
_gethtbyaddr(addr,len,type)41426887Skjd _gethtbyaddr(addr, len, type)
41546604Sbostic const char *addr;
41626887Skjd int len, type;
41726887Skjd {
41826887Skjd register struct hostent *p;
41926887Skjd
42026887Skjd _sethtent(0);
42126887Skjd while (p = _gethtent())
42226909Skjd if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len))
42326887Skjd break;
42426887Skjd _endhtent();
42526887Skjd return (p);
42626887Skjd }
427