xref: /csrg-svn/lib/libc/net/gethostnamadr.c (revision 24509)
121374Sdist /*
2*24509Sbloom  * 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 
721374Sdist #ifndef lint
8*24509Sbloom static char sccsid[] = "@(#)gethostnamadr.c	5.3 (Berkeley) 09/03/85";
921374Sdist #endif not lint
1021374Sdist 
1118505Sralph #include <sys/types.h>
1218505Sralph #include <sys/socket.h>
1318505Sralph #include <netinet/in.h>
1418505Sralph #include <netdb.h>
1515662Sralph #include <stdio.h>
1624508Sbloom #include <arpa/nameser.h>
1724508Sbloom #include <arpa/resolv.h>
1815662Sralph 
1915662Sralph #define	MAXALIASES	35
2015662Sralph 
21*24509Sbloom #define XX 2
22*24509Sbloom static char h_addr_buf[sizeof(struct in_addr) * XX];
23*24509Sbloom static char *h_addr_ptr[XX] = {
24*24509Sbloom 	&h_addr_buf[0],
25*24509Sbloom 	&h_addr_buf[sizeof(struct in_addr)]
26*24509Sbloom };
27*24509Sbloom static struct hostent host = {
28*24509Sbloom 	NULL,		/* official name of host */
29*24509Sbloom 	NULL,		/* alias list */
30*24509Sbloom 	0,		/* host address type */
31*24509Sbloom 	0,		/* length of address */
32*24509Sbloom 	h_addr_ptr	/* list of addresses from name server */
33*24509Sbloom };
3415662Sralph static char *host_aliases[MAXALIASES];
3515912Sralph static char hostbuf[BUFSIZ+1];
3615662Sralph 
37*24509Sbloom #ifdef BOMBPROOFING
38*24509Sbloom #include <ndbm.h>
39*24509Sbloom DBM *_host_db = NULL;
40*24509Sbloom int	_host_stayopen = 0;
41*24509Sbloom int	_host_bombed;
42*24509Sbloom struct hostent *_oldgethostbyname(), *_oldgethostbyaddr();
43*24509Sbloom #endif BOMBPROOFING
44*24509Sbloom 
4515662Sralph static struct hostent *
4618505Sralph getanswer(msg, msglen, iquery)
4718505Sralph 	char *msg;
4818505Sralph 	int msglen, iquery;
4915662Sralph {
5018505Sralph 	register HEADER *hp;
5118505Sralph 	register char *cp;
5218505Sralph 	register int n;
5318505Sralph 	char answer[PACKETSZ];
5418505Sralph 	char *eom, *bp, **ap;
5518505Sralph 	int type, class, ancount, buflen;
5615662Sralph 
57*24509Sbloom #ifdef BOMBPROOFING
58*24509Sbloom 	_host_bombed = 0;
59*24509Sbloom #endif BOMBPROOFING
6018531Sralph 	n = res_send(msg, msglen, answer, sizeof(answer));
6118505Sralph 	if (n < 0) {
6218505Sralph 		if (_res.options & RES_DEBUG)
6318531Sralph 			printf("res_send failed\n");
64*24509Sbloom #ifdef BOMBPROOFING
65*24509Sbloom 		_host_bombed++;
66*24509Sbloom #endif BOMBPROOFING
6718505Sralph 		return (NULL);
6815662Sralph 	}
6918505Sralph 	eom = answer + n;
7018505Sralph 	/*
7118505Sralph 	 * find first satisfactory answer
7218505Sralph 	 */
7318505Sralph 	hp = (HEADER *) answer;
7418505Sralph 	ancount = ntohs(hp->ancount);
7518505Sralph 	if (hp->rcode != NOERROR || ancount == 0) {
7618505Sralph 		if (_res.options & RES_DEBUG)
7718505Sralph 			printf("rcode = %d, ancount=%d\n", hp->rcode, ancount);
78*24509Sbloom #ifdef BOMBPROOFING
79*24509Sbloom 		if (!(hp->rcode == NOERROR && ancount == 0))
80*24509Sbloom 			_host_bombed++;
81*24509Sbloom #endif BOMBPROOFING
8218505Sralph 		return (NULL);
8318505Sralph 	}
8418505Sralph 	bp = hostbuf;
8518505Sralph 	buflen = sizeof(hostbuf);
8618505Sralph 	ap = host_aliases;
8718505Sralph 	cp = answer + sizeof(HEADER);
8818505Sralph 	if (hp->qdcount) {
8918505Sralph 		if (iquery) {
9018505Sralph 			if ((n = dn_expand(answer, cp, bp, buflen)) < 0)
9118505Sralph 				return (NULL);
9218505Sralph 			cp += n + QFIXEDSZ;
9318505Sralph 			host.h_name = bp;
9418505Sralph 			n = strlen(bp) + 1;
9518505Sralph 			bp += n;
9618505Sralph 			buflen -= n;
9718505Sralph 		} else
9818505Sralph 			cp += dn_skip(cp) + QFIXEDSZ;
9918505Sralph 	} else if (iquery)
10018505Sralph 		return (NULL);
10118505Sralph 	while (--ancount >= 0 && cp < eom) {
10218505Sralph 		if ((n = dn_expand(answer, cp, bp, buflen)) < 0)
10318505Sralph 			return (NULL);
10418505Sralph 		cp += n;
10518505Sralph 		type = getshort(cp);
10618505Sralph  		cp += sizeof(u_short);
10718505Sralph 		class = getshort(cp);
10818505Sralph  		cp += sizeof(u_short) + sizeof(u_long);
10918505Sralph 		n = getshort(cp);
11018505Sralph 		cp += sizeof(u_short);
11118505Sralph 		if (type == T_CNAME) {
11218505Sralph 			cp += n;
11318505Sralph 			if (ap >= &host_aliases[MAXALIASES-1])
11418505Sralph 				continue;
11518505Sralph 			*ap++ = bp;
11618505Sralph 			n = strlen(bp) + 1;
11718505Sralph 			bp += n;
11818505Sralph 			buflen -= n;
11918505Sralph 			continue;
12018505Sralph 		}
12118505Sralph 		if (type != T_A || n != 4) {
12218505Sralph 			if (_res.options & RES_DEBUG)
12318505Sralph 				printf("unexpected answer type %d, size %d\n",
12418505Sralph 					type, n);
12518505Sralph 			continue;
12618505Sralph 		}
12718505Sralph 		if (!iquery) {
12818505Sralph 			host.h_name = bp;
12918505Sralph 			bp += strlen(bp) + 1;
13018505Sralph 		}
13118505Sralph 		*ap = NULL;
13218505Sralph 		host.h_aliases = host_aliases;
13318505Sralph 		host.h_addrtype = class == C_IN ? AF_INET : AF_UNSPEC;
13418505Sralph 		if (bp + n >= &hostbuf[sizeof(hostbuf)]) {
13518505Sralph 			if (_res.options & RES_DEBUG)
13618505Sralph 				printf("size (%d) too big\n", n);
13718505Sralph 			return (NULL);
13818505Sralph 		}
13918505Sralph 		bcopy(cp, host.h_addr = bp, host.h_length = n);
14018505Sralph 		return (&host);
14118505Sralph 	}
14218505Sralph 	return (NULL);
14315662Sralph }
14415662Sralph 
14515662Sralph struct hostent *
14618505Sralph gethostbyname(name)
14718505Sralph 	char *name;
14815662Sralph {
14918505Sralph 	int n;
150*24509Sbloom #ifdef BOMBPROOFING
151*24509Sbloom 	register struct hostent *hp;
152*24509Sbloom #endif BOMBPROOFING
15315662Sralph 
15418531Sralph 	n = res_mkquery(QUERY, name, C_ANY, T_A, NULL, 0, NULL,
15518531Sralph 		hostbuf, sizeof(hostbuf));
15618505Sralph 	if (n < 0) {
15718505Sralph 		if (_res.options & RES_DEBUG)
15818531Sralph 			printf("res_mkquery failed\n");
15918505Sralph 		return (NULL);
160*24509Sbloom #ifndef BOMBPROOFING
16117761Sserge 	}
162*24509Sbloom 	return(getanswer(hostbuf, n, 0));
163*24509Sbloom #else
164*24509Sbloom 	} else
165*24509Sbloom 		hp = getanswer(hostbuf, n, 0);
166*24509Sbloom 	if (n < 0 || (hp == NULL && _host_bombed))
167*24509Sbloom 		return (_oldgethostbyname(name));
168*24509Sbloom 	else
169*24509Sbloom 		return (hp);
170*24509Sbloom #endif BOMBPROOFING
17115662Sralph }
17215662Sralph 
17315662Sralph struct hostent *
17418505Sralph gethostbyaddr(addr, len, type)
17515662Sralph 	char *addr;
17618505Sralph 	int len, type;
17715662Sralph {
17818505Sralph 	int n;
179*24509Sbloom #ifdef BOMBPROOFING
180*24509Sbloom 	register struct hostent *hp;
181*24509Sbloom #endif BOMBPROOFING
18215662Sralph 
18318505Sralph 	if (type != AF_INET)
18418505Sralph 		return (NULL);
18518531Sralph 	n = res_mkquery(IQUERY, NULL, C_IN, T_A, addr, len, NULL,
18618531Sralph 		hostbuf, sizeof(hostbuf));
18718505Sralph 	if (n < 0) {
18818505Sralph 		if (_res.options & RES_DEBUG)
18918531Sralph 			printf("res_mkquery failed\n");
19018505Sralph 		return (NULL);
191*24509Sbloom #ifndef BOMBPROOFING
19217761Sserge 	}
19318505Sralph 	return (getanswer(hostbuf, n, 1));
194*24509Sbloom #else
195*24509Sbloom 	} else
196*24509Sbloom 		hp = getanswer(hostbuf, n, 1);
197*24509Sbloom 	if (n < 0 || (hp == NULL && _host_bombed))
198*24509Sbloom 		return (_oldgethostbyaddr(addr));
199*24509Sbloom 	else
200*24509Sbloom 		return (hp);
201*24509Sbloom #endif BOMBPROOFING
20215662Sralph }
203*24509Sbloom 
204*24509Sbloom #ifdef BOMBPROOFING
205*24509Sbloom static
206*24509Sbloom struct hostent *
207*24509Sbloom _oldgethostbyname(name)
208*24509Sbloom 	register char *name;
209*24509Sbloom {
210*24509Sbloom 	register struct hostent *hp;
211*24509Sbloom 	register char **cp;
212*24509Sbloom         datum key;
213*24509Sbloom 
214*24509Sbloom 	if ((_host_db == (DBM *)NULL)
215*24509Sbloom 	  && ((_host_db = dbm_open(_host_file, O_RDONLY)) == (DBM *)NULL)) {
216*24509Sbloom 		sethostent(_host_stayopen);
217*24509Sbloom 		while (hp = gethostent()) {
218*24509Sbloom 			if (strcmp(hp->h_name, nam) == 0)
219*24509Sbloom 				break;
220*24509Sbloom 			for (cp = hp->h_aliases; cp != 0 && *cp != 0; cp++)
221*24509Sbloom 				if (strcmp(*cp, nam) == 0)
222*24509Sbloom 					goto found;
223*24509Sbloom 		}
224*24509Sbloom 	found:
225*24509Sbloom 		if (!_host_stayopen)
226*24509Sbloom 			endhostent();
227*24509Sbloom 		return (hp);
228*24509Sbloom 	}
229*24509Sbloom         key.dptr = nam;
230*24509Sbloom         key.dsize = strlen(nam);
231*24509Sbloom 	hp = fetchhost(key);
232*24509Sbloom 	if (!_host_stayopen) {
233*24509Sbloom 		dbm_close(_host_db);
234*24509Sbloom 		_host_db = (DBM *)NULL;
235*24509Sbloom 	}
236*24509Sbloom         return (hp);
237*24509Sbloom }
238*24509Sbloom 
239*24509Sbloom 
240*24509Sbloom static
241*24509Sbloom struct hostent *
242*24509Sbloom _oldgethostbyaddr(addr, len, type)
243*24509Sbloom 	char *addr;
244*24509Sbloom 	register int len, type;
245*24509Sbloom {
246*24509Sbloom 
247*24509Sbloom 	register struct hostent *hp;
248*24509Sbloom         datum key;
249*24509Sbloom 
250*24509Sbloom 	if ((_host_db == (DBM *)NULL)
251*24509Sbloom 	  && ((_host_db = dbm_open(_host_file, O_RDONLY)) == (DBM *)NULL)) {
252*24509Sbloom 		sethostent(_host_stayopen);
253*24509Sbloom 		while (hp = gethostent()) {
254*24509Sbloom 			if (hp->h_addrtype == type && hp->h_length == length
255*24509Sbloom 			    && bcmp(hp->h_addr, addr, length) == 0)
256*24509Sbloom 				break;
257*24509Sbloom 		}
258*24509Sbloom 		if (!_host_stayopen)
259*24509Sbloom 			endhostent();
260*24509Sbloom 		return (hp);
261*24509Sbloom 	}
262*24509Sbloom         key.dptr = addr;
263*24509Sbloom         key.dsize = length;
264*24509Sbloom 	hp = fetchhost(key);
265*24509Sbloom 	if (!_host_stayopen) {
266*24509Sbloom 		dbm_close(_host_db);
267*24509Sbloom 		_host_db = (DBM *)NULL;
268*24509Sbloom 	}
269*24509Sbloom         return (hp);
270*24509Sbloom }
271*24509Sbloom #endif BOMBPROOFING
272*24509Sbloom 
273