xref: /csrg-svn/lib/libc/net/gethostnamadr.c (revision 24509)
1 /*
2  * Copyright (c) 1985 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  */
6 
7 #ifndef lint
8 static char sccsid[] = "@(#)gethostnamadr.c	5.3 (Berkeley) 09/03/85";
9 #endif not lint
10 
11 #include <sys/types.h>
12 #include <sys/socket.h>
13 #include <netinet/in.h>
14 #include <netdb.h>
15 #include <stdio.h>
16 #include <arpa/nameser.h>
17 #include <arpa/resolv.h>
18 
19 #define	MAXALIASES	35
20 
21 #define XX 2
22 static char h_addr_buf[sizeof(struct in_addr) * XX];
23 static char *h_addr_ptr[XX] = {
24 	&h_addr_buf[0],
25 	&h_addr_buf[sizeof(struct in_addr)]
26 };
27 static struct hostent host = {
28 	NULL,		/* official name of host */
29 	NULL,		/* alias list */
30 	0,		/* host address type */
31 	0,		/* length of address */
32 	h_addr_ptr	/* list of addresses from name server */
33 };
34 static char *host_aliases[MAXALIASES];
35 static char hostbuf[BUFSIZ+1];
36 
37 #ifdef BOMBPROOFING
38 #include <ndbm.h>
39 DBM *_host_db = NULL;
40 int	_host_stayopen = 0;
41 int	_host_bombed;
42 struct hostent *_oldgethostbyname(), *_oldgethostbyaddr();
43 #endif BOMBPROOFING
44 
45 static struct hostent *
46 getanswer(msg, msglen, iquery)
47 	char *msg;
48 	int msglen, iquery;
49 {
50 	register HEADER *hp;
51 	register char *cp;
52 	register int n;
53 	char answer[PACKETSZ];
54 	char *eom, *bp, **ap;
55 	int type, class, ancount, buflen;
56 
57 #ifdef BOMBPROOFING
58 	_host_bombed = 0;
59 #endif BOMBPROOFING
60 	n = res_send(msg, msglen, answer, sizeof(answer));
61 	if (n < 0) {
62 		if (_res.options & RES_DEBUG)
63 			printf("res_send failed\n");
64 #ifdef BOMBPROOFING
65 		_host_bombed++;
66 #endif BOMBPROOFING
67 		return (NULL);
68 	}
69 	eom = answer + n;
70 	/*
71 	 * find first satisfactory answer
72 	 */
73 	hp = (HEADER *) answer;
74 	ancount = ntohs(hp->ancount);
75 	if (hp->rcode != NOERROR || ancount == 0) {
76 		if (_res.options & RES_DEBUG)
77 			printf("rcode = %d, ancount=%d\n", hp->rcode, ancount);
78 #ifdef BOMBPROOFING
79 		if (!(hp->rcode == NOERROR && ancount == 0))
80 			_host_bombed++;
81 #endif BOMBPROOFING
82 		return (NULL);
83 	}
84 	bp = hostbuf;
85 	buflen = sizeof(hostbuf);
86 	ap = host_aliases;
87 	cp = answer + sizeof(HEADER);
88 	if (hp->qdcount) {
89 		if (iquery) {
90 			if ((n = dn_expand(answer, cp, bp, buflen)) < 0)
91 				return (NULL);
92 			cp += n + QFIXEDSZ;
93 			host.h_name = bp;
94 			n = strlen(bp) + 1;
95 			bp += n;
96 			buflen -= n;
97 		} else
98 			cp += dn_skip(cp) + QFIXEDSZ;
99 	} else if (iquery)
100 		return (NULL);
101 	while (--ancount >= 0 && cp < eom) {
102 		if ((n = dn_expand(answer, cp, bp, buflen)) < 0)
103 			return (NULL);
104 		cp += n;
105 		type = getshort(cp);
106  		cp += sizeof(u_short);
107 		class = getshort(cp);
108  		cp += sizeof(u_short) + sizeof(u_long);
109 		n = getshort(cp);
110 		cp += sizeof(u_short);
111 		if (type == T_CNAME) {
112 			cp += n;
113 			if (ap >= &host_aliases[MAXALIASES-1])
114 				continue;
115 			*ap++ = bp;
116 			n = strlen(bp) + 1;
117 			bp += n;
118 			buflen -= n;
119 			continue;
120 		}
121 		if (type != T_A || n != 4) {
122 			if (_res.options & RES_DEBUG)
123 				printf("unexpected answer type %d, size %d\n",
124 					type, n);
125 			continue;
126 		}
127 		if (!iquery) {
128 			host.h_name = bp;
129 			bp += strlen(bp) + 1;
130 		}
131 		*ap = NULL;
132 		host.h_aliases = host_aliases;
133 		host.h_addrtype = class == C_IN ? AF_INET : AF_UNSPEC;
134 		if (bp + n >= &hostbuf[sizeof(hostbuf)]) {
135 			if (_res.options & RES_DEBUG)
136 				printf("size (%d) too big\n", n);
137 			return (NULL);
138 		}
139 		bcopy(cp, host.h_addr = bp, host.h_length = n);
140 		return (&host);
141 	}
142 	return (NULL);
143 }
144 
145 struct hostent *
146 gethostbyname(name)
147 	char *name;
148 {
149 	int n;
150 #ifdef BOMBPROOFING
151 	register struct hostent *hp;
152 #endif BOMBPROOFING
153 
154 	n = res_mkquery(QUERY, name, C_ANY, T_A, NULL, 0, NULL,
155 		hostbuf, sizeof(hostbuf));
156 	if (n < 0) {
157 		if (_res.options & RES_DEBUG)
158 			printf("res_mkquery failed\n");
159 		return (NULL);
160 #ifndef BOMBPROOFING
161 	}
162 	return(getanswer(hostbuf, n, 0));
163 #else
164 	} else
165 		hp = getanswer(hostbuf, n, 0);
166 	if (n < 0 || (hp == NULL && _host_bombed))
167 		return (_oldgethostbyname(name));
168 	else
169 		return (hp);
170 #endif BOMBPROOFING
171 }
172 
173 struct hostent *
174 gethostbyaddr(addr, len, type)
175 	char *addr;
176 	int len, type;
177 {
178 	int n;
179 #ifdef BOMBPROOFING
180 	register struct hostent *hp;
181 #endif BOMBPROOFING
182 
183 	if (type != AF_INET)
184 		return (NULL);
185 	n = res_mkquery(IQUERY, NULL, C_IN, T_A, addr, len, NULL,
186 		hostbuf, sizeof(hostbuf));
187 	if (n < 0) {
188 		if (_res.options & RES_DEBUG)
189 			printf("res_mkquery failed\n");
190 		return (NULL);
191 #ifndef BOMBPROOFING
192 	}
193 	return (getanswer(hostbuf, n, 1));
194 #else
195 	} else
196 		hp = getanswer(hostbuf, n, 1);
197 	if (n < 0 || (hp == NULL && _host_bombed))
198 		return (_oldgethostbyaddr(addr));
199 	else
200 		return (hp);
201 #endif BOMBPROOFING
202 }
203 
204 #ifdef BOMBPROOFING
205 static
206 struct hostent *
207 _oldgethostbyname(name)
208 	register char *name;
209 {
210 	register struct hostent *hp;
211 	register char **cp;
212         datum key;
213 
214 	if ((_host_db == (DBM *)NULL)
215 	  && ((_host_db = dbm_open(_host_file, O_RDONLY)) == (DBM *)NULL)) {
216 		sethostent(_host_stayopen);
217 		while (hp = gethostent()) {
218 			if (strcmp(hp->h_name, nam) == 0)
219 				break;
220 			for (cp = hp->h_aliases; cp != 0 && *cp != 0; cp++)
221 				if (strcmp(*cp, nam) == 0)
222 					goto found;
223 		}
224 	found:
225 		if (!_host_stayopen)
226 			endhostent();
227 		return (hp);
228 	}
229         key.dptr = nam;
230         key.dsize = strlen(nam);
231 	hp = fetchhost(key);
232 	if (!_host_stayopen) {
233 		dbm_close(_host_db);
234 		_host_db = (DBM *)NULL;
235 	}
236         return (hp);
237 }
238 
239 
240 static
241 struct hostent *
242 _oldgethostbyaddr(addr, len, type)
243 	char *addr;
244 	register int len, type;
245 {
246 
247 	register struct hostent *hp;
248         datum key;
249 
250 	if ((_host_db == (DBM *)NULL)
251 	  && ((_host_db = dbm_open(_host_file, O_RDONLY)) == (DBM *)NULL)) {
252 		sethostent(_host_stayopen);
253 		while (hp = gethostent()) {
254 			if (hp->h_addrtype == type && hp->h_length == length
255 			    && bcmp(hp->h_addr, addr, length) == 0)
256 				break;
257 		}
258 		if (!_host_stayopen)
259 			endhostent();
260 		return (hp);
261 	}
262         key.dptr = addr;
263         key.dsize = length;
264 	hp = fetchhost(key);
265 	if (!_host_stayopen) {
266 		dbm_close(_host_db);
267 		_host_db = (DBM *)NULL;
268 	}
269         return (hp);
270 }
271 #endif BOMBPROOFING
272 
273