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