xref: /csrg-svn/lib/libc/net/gethostnamadr.c (revision 26887)
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*26887Skjd static char sccsid[] = "@(#)gethostnamadr.c	6.6 (Berkeley) 03/14/86";
926630Sdonn #endif LIBC_SCCS and not lint
1021374Sdist 
1125386Skjd #include <sys/param.h>
1218505Sralph #include <sys/socket.h>
1318505Sralph #include <netinet/in.h>
14*26887Skjd #include <sys/types.h>
15*26887Skjd #include <ctype.h>
1618505Sralph #include <netdb.h>
1715662Sralph #include <stdio.h>
18*26887Skjd #include <errno.h>
1924508Sbloom #include <arpa/nameser.h>
2024508Sbloom #include <arpa/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;
31*26887Skjd static char HOSTDB[] = "/etc/hosts";
32*26887Skjd static FILE *hostf = NULL;
33*26887Skjd static char line[BUFSIZ+1];
34*26887Skjd static char hostaddr[MAXADDRS];
35*26887Skjd static char *host_addrs[2];
36*26887Skjd static int stayopen = 0;
37*26887Skjd static char *any();
3815662Sralph 
3925302Skjd typedef union {
4025302Skjd     HEADER qb1;
4125302Skjd     char qb2[PACKETSZ];
4225302Skjd } querybuf;
4324509Sbloom 
4425302Skjd static union {
4525302Skjd     long al;
4625302Skjd     char ac;
4725302Skjd } align;
4825302Skjd 
4925302Skjd 
5025484Skjd int h_errno;
51*26887Skjd extern errno;
5225484Skjd 
5315662Sralph static struct hostent *
5418505Sralph getanswer(msg, msglen, iquery)
5518505Sralph 	char *msg;
5618505Sralph 	int msglen, iquery;
5715662Sralph {
5818505Sralph 	register HEADER *hp;
5918505Sralph 	register char *cp;
6018505Sralph 	register int n;
6125302Skjd 	querybuf answer;
6218505Sralph 	char *eom, *bp, **ap;
6325153Sbloom 	int type, class, ancount, qdcount, buflen;
6424687Sbloom 	int haveanswer, getclass;
6524687Sbloom 	char **hap;
6615662Sralph 
6725302Skjd 	n = res_send(msg, msglen, (char *)&answer, sizeof(answer));
6818505Sralph 	if (n < 0) {
6924733Sbloom #ifdef DEBUG
70*26887Skjd 		int terrno;
71*26887Skjd 		terrno = errno;
7218505Sralph 		if (_res.options & RES_DEBUG)
7318531Sralph 			printf("res_send failed\n");
74*26887Skjd 		errno = terrno;
7524733Sbloom #endif
7625484Skjd 		h_errno = TRY_AGAIN;
7718505Sralph 		return (NULL);
7815662Sralph 	}
7925302Skjd 	eom = (char *)&answer + n;
8018505Sralph 	/*
8118505Sralph 	 * find first satisfactory answer
8218505Sralph 	 */
8325302Skjd 	hp = (HEADER *) &answer;
8418505Sralph 	ancount = ntohs(hp->ancount);
8525153Sbloom 	qdcount = ntohs(hp->qdcount);
8618505Sralph 	if (hp->rcode != NOERROR || ancount == 0) {
8724733Sbloom #ifdef DEBUG
8818505Sralph 		if (_res.options & RES_DEBUG)
8918505Sralph 			printf("rcode = %d, ancount=%d\n", hp->rcode, ancount);
9024733Sbloom #endif
9125484Skjd 		switch (hp->rcode) {
9225484Skjd 			case NXDOMAIN:
9325484Skjd 				/* Check if it's an authoritive answer */
9425484Skjd 				if (hp->aa)
9525484Skjd 					h_errno = HOST_NOT_FOUND;
9625484Skjd 				else
9725484Skjd 					h_errno = TRY_AGAIN;
9825484Skjd 				break;
9925484Skjd 			case SERVFAIL:
10025484Skjd 				h_errno = TRY_AGAIN;
10125484Skjd 				break;
10225484Skjd 			case NOERROR:
10325484Skjd 				h_errno = NO_ADDRESS;
10425484Skjd 				break;
10525484Skjd 			case FORMERR:
10625484Skjd 			case NOTIMP:
10725484Skjd 			case REFUSED:
10825484Skjd 				h_errno = NO_RECOVERY;
10925484Skjd 		}
11018505Sralph 		return (NULL);
11118505Sralph 	}
11218505Sralph 	bp = hostbuf;
11318505Sralph 	buflen = sizeof(hostbuf);
11425302Skjd 	cp = (char *)&answer + sizeof(HEADER);
11525153Sbloom 	if (qdcount) {
11618505Sralph 		if (iquery) {
11726066Skjd 			if ((n = dn_expand((char *)&answer, eom,
11826066Skjd 			     cp, bp, buflen)) < 0) {
11925484Skjd 				h_errno = NO_RECOVERY;
12018505Sralph 				return (NULL);
12125484Skjd 			}
12218505Sralph 			cp += n + QFIXEDSZ;
12318505Sralph 			host.h_name = bp;
12418505Sralph 			n = strlen(bp) + 1;
12518505Sralph 			bp += n;
12618505Sralph 			buflen -= n;
12718505Sralph 		} else
12818505Sralph 			cp += dn_skip(cp) + QFIXEDSZ;
12925153Sbloom 		while (--qdcount > 0)
13025153Sbloom 			cp += dn_skip(cp) + QFIXEDSZ;
13125484Skjd 	} else if (iquery) {
13225484Skjd 		if (hp->aa)
13325484Skjd 			h_errno = HOST_NOT_FOUND;
13425484Skjd 		else
13525484Skjd 			h_errno = TRY_AGAIN;
13618505Sralph 		return (NULL);
13725484Skjd 	}
13824687Sbloom 	ap = host_aliases;
13924687Sbloom 	host.h_aliases = host_aliases;
14024687Sbloom 	hap = h_addr_ptrs;
14124687Sbloom 	host.h_addr_list = h_addr_ptrs;
14224687Sbloom 	haveanswer = 0;
14318505Sralph 	while (--ancount >= 0 && cp < eom) {
14426066Skjd 		if ((n = dn_expand((char *)&answer, eom, cp, bp, buflen)) < 0)
14524687Sbloom 			break;
14618505Sralph 		cp += n;
14718505Sralph 		type = getshort(cp);
14818505Sralph  		cp += sizeof(u_short);
14918505Sralph 		class = getshort(cp);
15018505Sralph  		cp += sizeof(u_short) + sizeof(u_long);
15118505Sralph 		n = getshort(cp);
15218505Sralph 		cp += sizeof(u_short);
15318505Sralph 		if (type == T_CNAME) {
15418505Sralph 			cp += n;
15518505Sralph 			if (ap >= &host_aliases[MAXALIASES-1])
15618505Sralph 				continue;
15718505Sralph 			*ap++ = bp;
15818505Sralph 			n = strlen(bp) + 1;
15918505Sralph 			bp += n;
16018505Sralph 			buflen -= n;
16118505Sralph 			continue;
16218505Sralph 		}
16325153Sbloom 		if (type == T_PTR) {
16426066Skjd 			if ((n = dn_expand((char *)&answer, eom, cp, bp, buflen)) <
16525302Skjd 0) {
16625153Sbloom 				cp += n;
16725153Sbloom 				continue;
16825153Sbloom 			}
16925153Sbloom 			cp += n;
17025153Sbloom 			host.h_name = bp;
17125153Sbloom 			return(&host);
17225153Sbloom 		}
17324687Sbloom 		if (type != T_A)  {
17424733Sbloom #ifdef DEBUG
17518505Sralph 			if (_res.options & RES_DEBUG)
17618505Sralph 				printf("unexpected answer type %d, size %d\n",
17718505Sralph 					type, n);
17824733Sbloom #endif
17924687Sbloom 			cp += n;
18018505Sralph 			continue;
18118505Sralph 		}
18224687Sbloom 		if (haveanswer) {
18324687Sbloom 			if (n != host.h_length) {
18424687Sbloom 				cp += n;
18524687Sbloom 				continue;
18624687Sbloom 			}
18724687Sbloom 			if (class != getclass) {
18824687Sbloom 				cp += n;
18924687Sbloom 				continue;
19024687Sbloom 			}
19124687Sbloom 		} else {
19224687Sbloom 			host.h_length = n;
19324687Sbloom 			getclass = class;
19425386Skjd 			host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC;
19524687Sbloom 			if (!iquery) {
19624687Sbloom 				host.h_name = bp;
19724687Sbloom 				bp += strlen(bp) + 1;
19824687Sbloom 			}
19918505Sralph 		}
20025302Skjd 
20125302Skjd 		bp += ((u_long)bp % sizeof(align));
20225302Skjd 
20318505Sralph 		if (bp + n >= &hostbuf[sizeof(hostbuf)]) {
20424733Sbloom #ifdef DEBUG
20518505Sralph 			if (_res.options & RES_DEBUG)
20618505Sralph 				printf("size (%d) too big\n", n);
20724733Sbloom #endif
20824687Sbloom 			break;
20918505Sralph 		}
21024687Sbloom 		bcopy(cp, *hap++ = bp, n);
21124687Sbloom 		bp +=n;
21224687Sbloom 		cp += n;
21324687Sbloom 		haveanswer++;
21424687Sbloom 	}
21524687Sbloom 	if (haveanswer) {
21624687Sbloom 		*ap = NULL;
21724687Sbloom 		*hap = NULL;
21818505Sralph 		return (&host);
21925484Skjd 	} else {
22025484Skjd 		h_errno = TRY_AGAIN;
22124687Sbloom 		return (NULL);
22225484Skjd 	}
22315662Sralph }
22415662Sralph 
22515662Sralph struct hostent *
22618505Sralph gethostbyname(name)
22718505Sralph 	char *name;
22815662Sralph {
22918505Sralph 	int n;
23025302Skjd 	querybuf buf;
231*26887Skjd 	register struct hostent *hp;
232*26887Skjd 	extern struct hostent *_gethtbyname();
23315662Sralph 
23424687Sbloom 	n = res_mkquery(QUERY, name, C_ANY, T_A, (char *)NULL, 0, NULL,
23525302Skjd 		(char *)&buf, sizeof(buf));
23618505Sralph 	if (n < 0) {
23724733Sbloom #ifdef DEBUG
23818505Sralph 		if (_res.options & RES_DEBUG)
23918531Sralph 			printf("res_mkquery failed\n");
24024733Sbloom #endif
24118505Sralph 		return (NULL);
24217761Sserge 	}
243*26887Skjd 	hp = getanswer((char *)&buf, n, 0);
244*26887Skjd 	if (hp == NULL && errno == ECONNREFUSED)
245*26887Skjd 		hp = _gethtbyname(name);
246*26887Skjd 	return(hp);
24715662Sralph }
24815662Sralph 
24915662Sralph struct hostent *
25018505Sralph gethostbyaddr(addr, len, type)
25115662Sralph 	char *addr;
25218505Sralph 	int len, type;
25315662Sralph {
25418505Sralph 	int n;
25525302Skjd 	querybuf buf;
25625153Sbloom 	register struct hostent *hp;
25725153Sbloom 	char qbuf[MAXDNAME];
258*26887Skjd 	extern struct hostent *_gethtbyaddr();
259*26887Skjd 
26018505Sralph 	if (type != AF_INET)
26118505Sralph 		return (NULL);
26225153Sbloom 	(void)sprintf(qbuf, "%d.%d.%d.%d.in-addr.arpa",
26325484Skjd 		((unsigned)addr[3] & 0xff),
26425484Skjd 		((unsigned)addr[2] & 0xff),
26525484Skjd 		((unsigned)addr[1] & 0xff),
26625484Skjd 		((unsigned)addr[0] & 0xff));
26725153Sbloom 	n = res_mkquery(QUERY, qbuf, C_IN, T_PTR, NULL, 0, NULL,
26825302Skjd 		(char *)&buf, sizeof(buf));
26918505Sralph 	if (n < 0) {
27024733Sbloom #ifdef DEBUG
27118505Sralph 		if (_res.options & RES_DEBUG)
27218531Sralph 			printf("res_mkquery failed\n");
27324733Sbloom #endif
27418505Sralph 		return (NULL);
27517761Sserge 	}
276*26887Skjd 	hp = getanswer((char *)&buf, n, 1);
277*26887Skjd 	if (hp == NULL && errno == ECONNREFUSED)
278*26887Skjd 		hp = _gethtbyaddr(addr, len, type);
279*26887Skjd 	if (hp == NULL)
28025153Sbloom 		return(NULL);
28125153Sbloom 	hp->h_addrtype = type;
28225153Sbloom 	hp->h_length = len;
28325282Sbloom 	h_addr_ptrs[0] = (char *)&host_addr;
28425153Sbloom 	h_addr_ptrs[1] = (char *)0;
28525153Sbloom 	host_addr = *(struct in_addr *)addr;
28625153Sbloom 	return(hp);
28715662Sralph }
28825302Skjd 
289*26887Skjd 
290*26887Skjd _sethtent(f)
291*26887Skjd 	int f;
292*26887Skjd {
293*26887Skjd 	if (hostf == NULL)
294*26887Skjd 		hostf = fopen(HOSTDB, "r" );
295*26887Skjd 	else
296*26887Skjd 		rewind(hostf);
297*26887Skjd 	stayopen |= f;
298*26887Skjd }
299*26887Skjd 
300*26887Skjd _endhtent()
301*26887Skjd {
302*26887Skjd 	if (hostf && !stayopen) {
303*26887Skjd 		fclose(hostf);
304*26887Skjd 		hostf = NULL;
305*26887Skjd 	}
306*26887Skjd }
307*26887Skjd 
308*26887Skjd struct hostent *
309*26887Skjd _gethtent()
310*26887Skjd {
311*26887Skjd 	char *p;
312*26887Skjd 	register char *cp, **q;
313*26887Skjd 
314*26887Skjd 	if (hostf == NULL && (hostf = fopen(HOSTDB, "r" )) == NULL)
315*26887Skjd 		return (NULL);
316*26887Skjd again:
317*26887Skjd 	if ((p = fgets(line, BUFSIZ, hostf)) == NULL)
318*26887Skjd 		return (NULL);
319*26887Skjd 	if (*p == '#')
320*26887Skjd 		goto again;
321*26887Skjd 	cp = any(p, "#\n");
322*26887Skjd 	if (cp == NULL)
323*26887Skjd 		goto again;
324*26887Skjd 	*cp = '\0';
325*26887Skjd 	cp = any(p, " \t");
326*26887Skjd 	if (cp == NULL)
327*26887Skjd 		goto again;
328*26887Skjd 	*cp++ = '\0';
329*26887Skjd 	/* THIS STUFF IS INTERNET SPECIFIC */
330*26887Skjd 	host.h_addr_list = host_addrs;
331*26887Skjd 	host.h_addr = hostaddr;
332*26887Skjd 	*((u_long *)host.h_addr) = inet_addr(p);
333*26887Skjd 	host.h_length = sizeof (u_long);
334*26887Skjd 	host.h_addrtype = AF_INET;
335*26887Skjd 	while (*cp == ' ' || *cp == '\t')
336*26887Skjd 		cp++;
337*26887Skjd 	host.h_name = cp;
338*26887Skjd 	q = host.h_aliases = host_aliases;
339*26887Skjd 	cp = any(cp, " \t");
340*26887Skjd 	if (cp != NULL)
341*26887Skjd 		*cp++ = '\0';
342*26887Skjd 	while (cp && *cp) {
343*26887Skjd 		if (*cp == ' ' || *cp == '\t') {
344*26887Skjd 			cp++;
345*26887Skjd 			continue;
346*26887Skjd 		}
347*26887Skjd 		if (q < &host_aliases[MAXALIASES - 1])
348*26887Skjd 			*q++ = cp;
349*26887Skjd 		cp = any(cp, " \t");
350*26887Skjd 		if (cp != NULL)
351*26887Skjd 			*cp++ = '\0';
352*26887Skjd 	}
353*26887Skjd 	*q = NULL;
354*26887Skjd 	return (&host);
355*26887Skjd }
356*26887Skjd 
357*26887Skjd static char *
358*26887Skjd any(cp, match)
359*26887Skjd 	register char *cp;
360*26887Skjd 	char *match;
361*26887Skjd {
362*26887Skjd 	register char *mp, c;
363*26887Skjd 
364*26887Skjd 	while (c = *cp) {
365*26887Skjd 		for (mp = match; *mp; mp++)
366*26887Skjd 			if (*mp == c)
367*26887Skjd 				return (cp);
368*26887Skjd 		cp++;
369*26887Skjd 	}
370*26887Skjd 	return ((char *)0);
371*26887Skjd }
372*26887Skjd 
373*26887Skjd struct hostent *
374*26887Skjd _gethtbyname(name)
375*26887Skjd 	char *name;
376*26887Skjd {
377*26887Skjd 	register struct hostent *p;
378*26887Skjd 	register char **cp;
379*26887Skjd 
380*26887Skjd 	_sethtent(0);
381*26887Skjd 	while (p = _gethtent()) {
382*26887Skjd 		if (strcmp(p->h_name, name) == 0)
383*26887Skjd 			break;
384*26887Skjd 		for (cp = p->h_aliases; *cp != 0; cp++)
385*26887Skjd 			if (strcmp(*cp, name) == 0)
386*26887Skjd 				goto found;
387*26887Skjd 	}
388*26887Skjd found:
389*26887Skjd 	_endhtent();
390*26887Skjd 	return (p);
391*26887Skjd }
392*26887Skjd 
393*26887Skjd struct hostent *
394*26887Skjd _gethtbyaddr(addr, len, type)
395*26887Skjd 	char *addr;
396*26887Skjd 	int len, type;
397*26887Skjd {
398*26887Skjd 	register struct hostent *p;
399*26887Skjd 
400*26887Skjd 	_sethtent(0);
401*26887Skjd 	while (p = _gethtent())
402*26887Skjd 		if (p->h_addrtype == type && bcmp(p->h_addr, addr, len))
403*26887Skjd 			break;
404*26887Skjd 	_endhtent();
405*26887Skjd 	return (p);
406*26887Skjd }
407