xref: /csrg-svn/lib/libc/net/gethostnamadr.c (revision 33500)
121374Sdist /*
225302Skjd  * Copyright (c) 1985 Regents of the University of California.
321374Sdist  * All rights reserved.  The Berkeley software License Agreement
421374Sdist  * specifies the terms and conditions for redistribution.
521374Sdist  */
615662Sralph 
726630Sdonn #if defined(LIBC_SCCS) && !defined(lint)
8*33500Skarels static char sccsid[] = "@(#)gethostnamadr.c	6.28 (Berkeley) 02/18/88";
926630Sdonn #endif LIBC_SCCS and not lint
1021374Sdist 
1130468Skjd #include <sys/param.h>
1218505Sralph #include <sys/socket.h>
1318505Sralph #include <netinet/in.h>
1426887Skjd #include <ctype.h>
1518505Sralph #include <netdb.h>
1615662Sralph #include <stdio.h>
1726887Skjd #include <errno.h>
1827034Skjd #include <arpa/inet.h>
1924508Sbloom #include <arpa/nameser.h>
2026894Skjd #include <resolv.h>
2115662Sralph 
2215662Sralph #define	MAXALIASES	35
2324687Sbloom #define MAXADDRS	35
2415662Sralph 
2524687Sbloom static char *h_addr_ptrs[MAXADDRS + 1];
2624687Sbloom 
2724687Sbloom static struct hostent host;
2815662Sralph static char *host_aliases[MAXALIASES];
2915912Sralph static char hostbuf[BUFSIZ+1];
3025153Sbloom static struct in_addr host_addr;
3126887Skjd static char HOSTDB[] = "/etc/hosts";
3226887Skjd static FILE *hostf = NULL;
3326887Skjd static char line[BUFSIZ+1];
3426887Skjd static char hostaddr[MAXADDRS];
3526887Skjd static char *host_addrs[2];
3626887Skjd static int stayopen = 0;
3726887Skjd static char *any();
3815662Sralph 
3932648Skarels #if PACKETSZ > 1024
4032648Skarels #define MAXPACKET	PACKETSZ
4132648Skarels #else
4232648Skarels #define MAXPACKET	1024
4332648Skarels #endif
4432648Skarels 
4525302Skjd typedef union {
4625302Skjd     HEADER qb1;
4732648Skarels     char qb2[MAXPACKET];
4825302Skjd } querybuf;
4924509Sbloom 
5025302Skjd static union {
5125302Skjd     long al;
5225302Skjd     char ac;
5325302Skjd } align;
5425302Skjd 
5525302Skjd 
5625484Skjd int h_errno;
5726887Skjd extern errno;
5825484Skjd 
5915662Sralph static struct hostent *
6018505Sralph getanswer(msg, msglen, iquery)
6118505Sralph 	char *msg;
6218505Sralph 	int msglen, iquery;
6315662Sralph {
6418505Sralph 	register HEADER *hp;
6518505Sralph 	register char *cp;
6618505Sralph 	register int n;
6725302Skjd 	querybuf answer;
6818505Sralph 	char *eom, *bp, **ap;
6927034Skjd 	int type, class, buflen, ancount, qdcount;
7027034Skjd 	int haveanswer, getclass = C_ANY;
7124687Sbloom 	char **hap;
7215662Sralph 
7325302Skjd 	n = res_send(msg, msglen, (char *)&answer, sizeof(answer));
7418505Sralph 	if (n < 0) {
7524733Sbloom #ifdef DEBUG
7626887Skjd 		int terrno;
7726887Skjd 		terrno = errno;
7818505Sralph 		if (_res.options & RES_DEBUG)
7918531Sralph 			printf("res_send failed\n");
8026887Skjd 		errno = terrno;
8124733Sbloom #endif
8225484Skjd 		h_errno = TRY_AGAIN;
83*33500Skarels 		return ((struct hostent *) NULL);
8415662Sralph 	}
8525302Skjd 	eom = (char *)&answer + n;
8618505Sralph 	/*
8718505Sralph 	 * find first satisfactory answer
8818505Sralph 	 */
8925302Skjd 	hp = (HEADER *) &answer;
9018505Sralph 	ancount = ntohs(hp->ancount);
9125153Sbloom 	qdcount = ntohs(hp->qdcount);
9218505Sralph 	if (hp->rcode != NOERROR || ancount == 0) {
9324733Sbloom #ifdef DEBUG
9418505Sralph 		if (_res.options & RES_DEBUG)
9518505Sralph 			printf("rcode = %d, ancount=%d\n", hp->rcode, ancount);
9624733Sbloom #endif
9725484Skjd 		switch (hp->rcode) {
9825484Skjd 			case NXDOMAIN:
9925484Skjd 				/* Check if it's an authoritive answer */
10025484Skjd 				if (hp->aa)
10125484Skjd 					h_errno = HOST_NOT_FOUND;
10225484Skjd 				else
10325484Skjd 					h_errno = TRY_AGAIN;
10425484Skjd 				break;
10525484Skjd 			case SERVFAIL:
10625484Skjd 				h_errno = TRY_AGAIN;
10725484Skjd 				break;
10825484Skjd 			case NOERROR:
10932648Skarels 				if (hp->aa)
11032648Skarels 					h_errno = NO_ADDRESS;
11132648Skarels 				else
11232648Skarels 					h_errno = TRY_AGAIN;
11325484Skjd 				break;
11425484Skjd 			case FORMERR:
11525484Skjd 			case NOTIMP:
11625484Skjd 			case REFUSED:
11725484Skjd 				h_errno = NO_RECOVERY;
11825484Skjd 		}
119*33500Skarels 		return ((struct hostent *) NULL);
12018505Sralph 	}
12118505Sralph 	bp = hostbuf;
12218505Sralph 	buflen = sizeof(hostbuf);
12325302Skjd 	cp = (char *)&answer + sizeof(HEADER);
12425153Sbloom 	if (qdcount) {
12518505Sralph 		if (iquery) {
12626066Skjd 			if ((n = dn_expand((char *)&answer, eom,
12726066Skjd 			     cp, bp, buflen)) < 0) {
12825484Skjd 				h_errno = NO_RECOVERY;
129*33500Skarels 				return ((struct hostent *) NULL);
13025484Skjd 			}
13118505Sralph 			cp += n + QFIXEDSZ;
13218505Sralph 			host.h_name = bp;
13318505Sralph 			n = strlen(bp) + 1;
13418505Sralph 			bp += n;
13518505Sralph 			buflen -= n;
13618505Sralph 		} else
13732648Skarels 			cp += dn_skipname(cp, eom) + QFIXEDSZ;
13825153Sbloom 		while (--qdcount > 0)
13932648Skarels 			cp += dn_skipname(cp, eom) + QFIXEDSZ;
14025484Skjd 	} else if (iquery) {
14125484Skjd 		if (hp->aa)
14225484Skjd 			h_errno = HOST_NOT_FOUND;
14325484Skjd 		else
14425484Skjd 			h_errno = TRY_AGAIN;
145*33500Skarels 		return ((struct hostent *) NULL);
14625484Skjd 	}
14724687Sbloom 	ap = host_aliases;
14824687Sbloom 	host.h_aliases = host_aliases;
14924687Sbloom 	hap = h_addr_ptrs;
15030468Skjd #if BSD >= 43
15124687Sbloom 	host.h_addr_list = h_addr_ptrs;
15230460Skjd #endif
15324687Sbloom 	haveanswer = 0;
15418505Sralph 	while (--ancount >= 0 && cp < eom) {
15526066Skjd 		if ((n = dn_expand((char *)&answer, eom, cp, bp, buflen)) < 0)
15624687Sbloom 			break;
15718505Sralph 		cp += n;
15830440Skjd 		type = _getshort(cp);
15918505Sralph  		cp += sizeof(u_short);
16030440Skjd 		class = _getshort(cp);
16118505Sralph  		cp += sizeof(u_short) + sizeof(u_long);
16230440Skjd 		n = _getshort(cp);
16318505Sralph 		cp += sizeof(u_short);
16418505Sralph 		if (type == T_CNAME) {
16518505Sralph 			cp += n;
16618505Sralph 			if (ap >= &host_aliases[MAXALIASES-1])
16718505Sralph 				continue;
16818505Sralph 			*ap++ = bp;
16918505Sralph 			n = strlen(bp) + 1;
17018505Sralph 			bp += n;
17118505Sralph 			buflen -= n;
17218505Sralph 			continue;
17318505Sralph 		}
17425153Sbloom 		if (type == T_PTR) {
17527034Skjd 			if ((n = dn_expand((char *)&answer, eom,
17627034Skjd 			    cp, bp, buflen)) < 0) {
17725153Sbloom 				cp += n;
17825153Sbloom 				continue;
17925153Sbloom 			}
18025153Sbloom 			cp += n;
18125153Sbloom 			host.h_name = bp;
18225153Sbloom 			return(&host);
18325153Sbloom 		}
18424687Sbloom 		if (type != T_A)  {
18524733Sbloom #ifdef DEBUG
18618505Sralph 			if (_res.options & RES_DEBUG)
18718505Sralph 				printf("unexpected answer type %d, size %d\n",
18818505Sralph 					type, n);
18924733Sbloom #endif
19024687Sbloom 			cp += n;
19118505Sralph 			continue;
19218505Sralph 		}
19324687Sbloom 		if (haveanswer) {
19424687Sbloom 			if (n != host.h_length) {
19524687Sbloom 				cp += n;
19624687Sbloom 				continue;
19724687Sbloom 			}
19824687Sbloom 			if (class != getclass) {
19924687Sbloom 				cp += n;
20024687Sbloom 				continue;
20124687Sbloom 			}
20224687Sbloom 		} else {
20324687Sbloom 			host.h_length = n;
20424687Sbloom 			getclass = class;
20525386Skjd 			host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC;
20624687Sbloom 			if (!iquery) {
20724687Sbloom 				host.h_name = bp;
20824687Sbloom 				bp += strlen(bp) + 1;
20924687Sbloom 			}
21018505Sralph 		}
21125302Skjd 
21231902Skarels 		bp += sizeof(align) - ((u_long)bp % sizeof(align));
21325302Skjd 
21418505Sralph 		if (bp + n >= &hostbuf[sizeof(hostbuf)]) {
21524733Sbloom #ifdef DEBUG
21618505Sralph 			if (_res.options & RES_DEBUG)
21718505Sralph 				printf("size (%d) too big\n", n);
21824733Sbloom #endif
21924687Sbloom 			break;
22018505Sralph 		}
22124687Sbloom 		bcopy(cp, *hap++ = bp, n);
22224687Sbloom 		bp +=n;
22324687Sbloom 		cp += n;
22424687Sbloom 		haveanswer++;
22524687Sbloom 	}
22624687Sbloom 	if (haveanswer) {
22724687Sbloom 		*ap = NULL;
22831902Skarels #if BSD >= 43
22924687Sbloom 		*hap = NULL;
23031902Skarels #else
23131902Skarels 		host.h_addr = h_addr_ptrs[0];
23231902Skarels #endif
23318505Sralph 		return (&host);
23425484Skjd 	} else {
23525484Skjd 		h_errno = TRY_AGAIN;
236*33500Skarels 		return ((struct hostent *) NULL);
23725484Skjd 	}
23815662Sralph }
23915662Sralph 
24015662Sralph struct hostent *
24118505Sralph gethostbyname(name)
24218505Sralph 	char *name;
24315662Sralph {
24431111Skarels 	register char *cp, **domain;
24518505Sralph 	int n;
24631111Skarels 	struct hostent *hp, *gethostdomain();
24731111Skarels 	char *hostalias();
24826887Skjd 	extern struct hostent *_gethtbyname();
24915662Sralph 
25031111Skarels 	if (!(_res.options & RES_INIT) && res_init() == -1)
251*33500Skarels 		return ((struct hostent *) NULL);
25232976Sbostic 	/*
25332976Sbostic 	 * disallow names consisting only of digits/dots, unless
25432976Sbostic 	 * they end in a dot.
25532976Sbostic 	 */
25632976Sbostic 	if (isdigit(name[0]))
25732976Sbostic 		for (cp = name;; ++cp) {
25832976Sbostic 			if (!*cp) {
25932976Sbostic 				if (*--cp == '.')
26032976Sbostic 					break;
26132976Sbostic 				h_errno = HOST_NOT_FOUND;
262*33500Skarels 				return ((struct hostent *) NULL);
26332976Sbostic 			}
26432976Sbostic 			if (!isdigit(*cp) && *cp != '.')
26532976Sbostic 				break;
26632976Sbostic 		}
26729930Skjd 	errno = 0;
26831111Skarels 	for (cp = name, n = 0; *cp; cp++)
26931111Skarels 		if (*cp == '.')
27031111Skarels 			n++;
27131111Skarels 	if (n == 0 && (cp = hostalias(name)))
27231111Skarels 		return (gethostdomain(cp, (char *)NULL));
273*33500Skarels 	if ((n == 0 || *--cp != '.') && (_res.options & RES_DEFNAMES))
274*33500Skarels 	    for (domain = _res.dnsrch; *domain; domain++) {
27531111Skarels 		hp = gethostdomain(name, *domain);
27631111Skarels 		if (hp)
27731111Skarels 			return (hp);
27831960Sbostic 		/*
27931960Sbostic 		 * If no server present, use host table.
28031960Sbostic 		 * If host isn't found in this domain,
28131960Sbostic 		 * keep trying higher domains in the search list
28231960Sbostic 		 * (if that's enabled).
283*33500Skarels 		 * On a NO_ADDRESS error, keep trying, otherwise
284*33500Skarels 		 * a wildcard MX entry could keep us from finding
28531960Sbostic 		 * host entries higher in the domain.
286*33500Skarels 		 * If we get some other error (non-authoritative negative
287*33500Skarels 		 * answer or server failure), then stop searching up,
288*33500Skarels 		 * but try the input name below in case it's fully-qualified.
28931960Sbostic 		 */
29031111Skarels 		if (errno == ECONNREFUSED)
29131111Skarels 			return (_gethtbyname(name));
292*33500Skarels 		if ((h_errno != HOST_NOT_FOUND && h_errno != NO_ADDRESS) ||
29331111Skarels 		    (_res.options & RES_DNSRCH) == 0)
294*33500Skarels 			break;
29531709Skarels 		h_errno = 0;
29631111Skarels 	}
297*33500Skarels 	/*
298*33500Skarels 	 * If the search/default failed, try the name as fully-qualified,
299*33500Skarels 	 * but only if it contained at least one dot (even trailing).
300*33500Skarels 	 */
301*33500Skarels 	if (n)
302*33500Skarels 		return (gethostdomain(name, (char *)NULL));
303*33500Skarels 	return ((struct hostent *) NULL);
30431111Skarels }
30531111Skarels 
30631111Skarels static struct hostent *
30731111Skarels gethostdomain(name, domain)
30831111Skarels 	char *name, *domain;
30931111Skarels {
31031111Skarels 	querybuf buf;
31131111Skarels 	char nbuf[2*MAXDNAME+2];
312*33500Skarels 	char *longname = nbuf;
31331111Skarels 	int n;
31431111Skarels 
315*33500Skarels 	if (domain == NULL) {
316*33500Skarels 		/*
317*33500Skarels 		 * Check for trailing '.';
318*33500Skarels 		 * copy without '.' if present.
319*33500Skarels 		 */
320*33500Skarels 		n = strlen(name) - 1;
321*33500Skarels 		if (name[n] == '.' && n < sizeof(nbuf) - 1) {
322*33500Skarels 			bcopy(name, nbuf, n);
323*33500Skarels 			nbuf[n] = '\0';
324*33500Skarels 		} else
325*33500Skarels 			longname = name;
326*33500Skarels 	} else
32732648Skarels 		(void)sprintf(nbuf, "%.*s.%.*s",
32832648Skarels 		    MAXDNAME, name, MAXDNAME, domain);
329*33500Skarels 	n = res_mkquery(QUERY, longname, C_IN, T_A, (char *)NULL, 0, NULL,
33025302Skjd 		(char *)&buf, sizeof(buf));
33118505Sralph 	if (n < 0) {
33224733Sbloom #ifdef DEBUG
33318505Sralph 		if (_res.options & RES_DEBUG)
33418531Sralph 			printf("res_mkquery failed\n");
33524733Sbloom #endif
336*33500Skarels 		return ((struct hostent *) NULL);
33717761Sserge 	}
33831111Skarels 	return (getanswer((char *)&buf, n, 0));
33915662Sralph }
34015662Sralph 
34115662Sralph struct hostent *
34218505Sralph gethostbyaddr(addr, len, type)
34315662Sralph 	char *addr;
34418505Sralph 	int len, type;
34515662Sralph {
34618505Sralph 	int n;
34725302Skjd 	querybuf buf;
34825153Sbloom 	register struct hostent *hp;
34925153Sbloom 	char qbuf[MAXDNAME];
35026887Skjd 	extern struct hostent *_gethtbyaddr();
35126887Skjd 
35218505Sralph 	if (type != AF_INET)
353*33500Skarels 		return ((struct hostent *) NULL);
35425153Sbloom 	(void)sprintf(qbuf, "%d.%d.%d.%d.in-addr.arpa",
35525484Skjd 		((unsigned)addr[3] & 0xff),
35625484Skjd 		((unsigned)addr[2] & 0xff),
35725484Skjd 		((unsigned)addr[1] & 0xff),
35825484Skjd 		((unsigned)addr[0] & 0xff));
35927034Skjd 	n = res_mkquery(QUERY, qbuf, C_IN, T_PTR, (char *)NULL, 0, NULL,
36025302Skjd 		(char *)&buf, sizeof(buf));
36118505Sralph 	if (n < 0) {
36224733Sbloom #ifdef DEBUG
36318505Sralph 		if (_res.options & RES_DEBUG)
36418531Sralph 			printf("res_mkquery failed\n");
36524733Sbloom #endif
366*33500Skarels 		return ((struct hostent *) NULL);
36717761Sserge 	}
36826887Skjd 	hp = getanswer((char *)&buf, n, 1);
36926887Skjd 	if (hp == NULL && errno == ECONNREFUSED)
37026887Skjd 		hp = _gethtbyaddr(addr, len, type);
37126887Skjd 	if (hp == NULL)
372*33500Skarels 		return ((struct hostent *) NULL);
37325153Sbloom 	hp->h_addrtype = type;
37425153Sbloom 	hp->h_length = len;
37525282Sbloom 	h_addr_ptrs[0] = (char *)&host_addr;
37625153Sbloom 	h_addr_ptrs[1] = (char *)0;
37725153Sbloom 	host_addr = *(struct in_addr *)addr;
37825153Sbloom 	return(hp);
37915662Sralph }
38025302Skjd 
38131111Skarels char *
38231111Skarels hostalias(name)
38331111Skarels 	register char *name;
38431111Skarels {
38531780Sbostic 	register char *C1, *C2;
38631111Skarels 	FILE *fp;
38731780Sbostic 	char *file, *getenv(), *strcpy(), *strncpy();
38831780Sbostic 	char buf[BUFSIZ];
38931111Skarels 	static char abuf[MAXDNAME];
39026887Skjd 
39131111Skarels 	file = getenv("HOSTALIASES");
39231111Skarels 	if (file == NULL || (fp = fopen(file, "r")) == NULL)
39331111Skarels 		return (NULL);
39431780Sbostic 	buf[sizeof(buf) - 1] = '\0';
39531780Sbostic 	while (fgets(buf, sizeof(buf), fp)) {
39631780Sbostic 		for (C1 = buf; *C1 && !isspace(*C1); ++C1);
39732169Sbostic 		if (!*C1)
39831780Sbostic 			break;
39932169Sbostic 		*C1 = '\0';
40032169Sbostic 		if (!strcasecmp(buf, name)) {
40131780Sbostic 			while (isspace(*++C1));
40231780Sbostic 			if (!*C1)
40331780Sbostic 				break;
40431780Sbostic 			for (C2 = C1 + 1; *C2 && !isspace(*C2); ++C2);
40531780Sbostic 			abuf[sizeof(abuf) - 1] = *C2 = '\0';
40631780Sbostic 			(void)strncpy(abuf, C1, sizeof(abuf) - 1);
40731111Skarels 			fclose(fp);
40831111Skarels 			return (abuf);
40931111Skarels 		}
41031780Sbostic 	}
41131111Skarels 	fclose(fp);
41231111Skarels 	return (NULL);
41331111Skarels }
41431111Skarels 
41526887Skjd _sethtent(f)
41626887Skjd 	int f;
41726887Skjd {
41826887Skjd 	if (hostf == NULL)
41926887Skjd 		hostf = fopen(HOSTDB, "r" );
42026887Skjd 	else
42126887Skjd 		rewind(hostf);
42226887Skjd 	stayopen |= f;
42326887Skjd }
42426887Skjd 
42526887Skjd _endhtent()
42626887Skjd {
42726887Skjd 	if (hostf && !stayopen) {
42827034Skjd 		(void) fclose(hostf);
42926887Skjd 		hostf = NULL;
43026887Skjd 	}
43126887Skjd }
43226887Skjd 
43326887Skjd struct hostent *
43426887Skjd _gethtent()
43526887Skjd {
43626887Skjd 	char *p;
43726887Skjd 	register char *cp, **q;
43826887Skjd 
43926887Skjd 	if (hostf == NULL && (hostf = fopen(HOSTDB, "r" )) == NULL)
44026887Skjd 		return (NULL);
44126887Skjd again:
44226887Skjd 	if ((p = fgets(line, BUFSIZ, hostf)) == NULL)
44326887Skjd 		return (NULL);
44426887Skjd 	if (*p == '#')
44526887Skjd 		goto again;
44626887Skjd 	cp = any(p, "#\n");
44726887Skjd 	if (cp == NULL)
44826887Skjd 		goto again;
44926887Skjd 	*cp = '\0';
45026887Skjd 	cp = any(p, " \t");
45126887Skjd 	if (cp == NULL)
45226887Skjd 		goto again;
45326887Skjd 	*cp++ = '\0';
45426887Skjd 	/* THIS STUFF IS INTERNET SPECIFIC */
45530468Skjd #if	BSD >= 43
45626887Skjd 	host.h_addr_list = host_addrs;
45730460Skjd #endif
45826887Skjd 	host.h_addr = hostaddr;
45926887Skjd 	*((u_long *)host.h_addr) = inet_addr(p);
46026887Skjd 	host.h_length = sizeof (u_long);
46126887Skjd 	host.h_addrtype = AF_INET;
46226887Skjd 	while (*cp == ' ' || *cp == '\t')
46326887Skjd 		cp++;
46426887Skjd 	host.h_name = cp;
46526887Skjd 	q = host.h_aliases = host_aliases;
46626887Skjd 	cp = any(cp, " \t");
46726887Skjd 	if (cp != NULL)
46826887Skjd 		*cp++ = '\0';
46926887Skjd 	while (cp && *cp) {
47026887Skjd 		if (*cp == ' ' || *cp == '\t') {
47126887Skjd 			cp++;
47226887Skjd 			continue;
47326887Skjd 		}
47426887Skjd 		if (q < &host_aliases[MAXALIASES - 1])
47526887Skjd 			*q++ = cp;
47626887Skjd 		cp = any(cp, " \t");
47726887Skjd 		if (cp != NULL)
47826887Skjd 			*cp++ = '\0';
47926887Skjd 	}
48026887Skjd 	*q = NULL;
48126887Skjd 	return (&host);
48226887Skjd }
48326887Skjd 
48426887Skjd static char *
48526887Skjd any(cp, match)
48626887Skjd 	register char *cp;
48726887Skjd 	char *match;
48826887Skjd {
48926887Skjd 	register char *mp, c;
49026887Skjd 
49126887Skjd 	while (c = *cp) {
49226887Skjd 		for (mp = match; *mp; mp++)
49326887Skjd 			if (*mp == c)
49426887Skjd 				return (cp);
49526887Skjd 		cp++;
49626887Skjd 	}
49726887Skjd 	return ((char *)0);
49826887Skjd }
49926887Skjd 
50026887Skjd struct hostent *
50126887Skjd _gethtbyname(name)
50226887Skjd 	char *name;
50326887Skjd {
50426887Skjd 	register struct hostent *p;
50526887Skjd 	register char **cp;
50628307Skarels 
50726887Skjd 	_sethtent(0);
50826887Skjd 	while (p = _gethtent()) {
50931960Sbostic 		if (strcasecmp(p->h_name, name) == 0)
51026887Skjd 			break;
51126887Skjd 		for (cp = p->h_aliases; *cp != 0; cp++)
51231960Sbostic 			if (strcasecmp(*cp, name) == 0)
51326887Skjd 				goto found;
51426887Skjd 	}
51526887Skjd found:
51626887Skjd 	_endhtent();
51726887Skjd 	return (p);
51826887Skjd }
51926887Skjd 
52026887Skjd struct hostent *
52126887Skjd _gethtbyaddr(addr, len, type)
52226887Skjd 	char *addr;
52326887Skjd 	int len, type;
52426887Skjd {
52526887Skjd 	register struct hostent *p;
52626887Skjd 
52726887Skjd 	_sethtent(0);
52826887Skjd 	while (p = _gethtent())
52926909Skjd 		if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len))
53026887Skjd 			break;
53126887Skjd 	_endhtent();
53226887Skjd 	return (p);
53326887Skjd }
534