xref: /csrg-svn/lib/libc/net/gethostnamadr.c (revision 61150)
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