1 | /*
|
---|
2 | * ++Copyright++ 1985, 1988, 1993
|
---|
3 | * -
|
---|
4 | * Copyright (c) 1985, 1988, 1993
|
---|
5 | * The Regents of the University of California. All rights reserved.
|
---|
6 | *
|
---|
7 | * Redistribution and use in source and binary forms, with or without
|
---|
8 | * modification, are permitted provided that the following conditions
|
---|
9 | * are met:
|
---|
10 | * 1. Redistributions of source code must retain the above copyright
|
---|
11 | * notice, this list of conditions and the following disclaimer.
|
---|
12 | * 2. Redistributions in binary form must reproduce the above copyright
|
---|
13 | * notice, this list of conditions and the following disclaimer in the
|
---|
14 | * documentation and/or other materials provided with the distribution.
|
---|
15 | * 3. All advertising materials mentioning features or use of this software
|
---|
16 | * must display the following acknowledgement:
|
---|
17 | * This product includes software developed by the University of
|
---|
18 | * California, Berkeley and its contributors.
|
---|
19 | * 4. Neither the name of the University nor the names of its contributors
|
---|
20 | * may be used to endorse or promote products derived from this software
|
---|
21 | * without specific prior written permission.
|
---|
22 | *
|
---|
23 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
---|
24 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
---|
25 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
---|
26 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
---|
27 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
---|
28 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
---|
29 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
---|
30 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
---|
31 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
---|
32 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
---|
33 | * SUCH DAMAGE.
|
---|
34 | * -
|
---|
35 | * Portions Copyright (c) 1993 by Digital Equipment Corporation.
|
---|
36 | *
|
---|
37 | * Permission to use, copy, modify, and distribute this software for any
|
---|
38 | * purpose with or without fee is hereby granted, provided that the above
|
---|
39 | * copyright notice and this permission notice appear in all copies, and that
|
---|
40 | * the name of Digital Equipment Corporation not be used in advertising or
|
---|
41 | * publicity pertaining to distribution of the document or software without
|
---|
42 | * specific, written prior permission.
|
---|
43 | *
|
---|
44 | * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
|
---|
45 | * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
|
---|
46 | * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
|
---|
47 | * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
---|
48 | * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
---|
49 | * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
---|
50 | * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
---|
51 | * SOFTWARE.
|
---|
52 | * -
|
---|
53 | * --Copyright--
|
---|
54 | */
|
---|
55 |
|
---|
56 | /*
|
---|
57 | * Portions copyright (c) 1999, 2000
|
---|
58 | * Intel Corporation.
|
---|
59 | * All rights reserved.
|
---|
60 | *
|
---|
61 | * Redistribution and use in source and binary forms, with or without
|
---|
62 | * modification, are permitted provided that the following conditions
|
---|
63 | * are met:
|
---|
64 | *
|
---|
65 | * 1. Redistributions of source code must retain the above copyright
|
---|
66 | * notice, this list of conditions and the following disclaimer.
|
---|
67 | *
|
---|
68 | * 2. Redistributions in binary form must reproduce the above copyright
|
---|
69 | * notice, this list of conditions and the following disclaimer in the
|
---|
70 | * documentation and/or other materials provided with the distribution.
|
---|
71 | *
|
---|
72 | * 3. All advertising materials mentioning features or use of this software
|
---|
73 | * must display the following acknowledgement:
|
---|
74 | *
|
---|
75 | * This product includes software developed by Intel Corporation and
|
---|
76 | * its contributors.
|
---|
77 | *
|
---|
78 | * 4. Neither the name of Intel Corporation or its contributors may be
|
---|
79 | * used to endorse or promote products derived from this software
|
---|
80 | * without specific prior written permission.
|
---|
81 | *
|
---|
82 | * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION AND CONTRIBUTORS ``AS IS''
|
---|
83 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
---|
84 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
---|
85 | * ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR CONTRIBUTORS BE
|
---|
86 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
---|
87 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
---|
88 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
---|
89 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
---|
90 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
---|
91 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
---|
92 | * THE POSSIBILITY OF SUCH DAMAGE.
|
---|
93 | *
|
---|
94 | */
|
---|
95 |
|
---|
96 | #if defined(LIBC_SCCS) && !defined(lint)
|
---|
97 | static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93";
|
---|
98 | static char fromrcsid[] = "From: Id: gethnamaddr.c,v 8.23 1998/04/07 04:59:46 vixie Exp $";
|
---|
99 | static char rcsid[] = "$Id: gethostbydns.c,v 1.1.1.1 2003/11/19 01:51:27 kyu3 Exp $";
|
---|
100 | #endif /* LIBC_SCCS and not lint */
|
---|
101 |
|
---|
102 | #include <sys/types.h>
|
---|
103 | #include <sys/param.h>
|
---|
104 | #include <sys/socket.h>
|
---|
105 | #include <netinet/in.h>
|
---|
106 | #include <arpa/inet.h>
|
---|
107 | #include <arpa/nameser.h>
|
---|
108 |
|
---|
109 | #include <stdio.h>
|
---|
110 | #include <unistd.h>
|
---|
111 | #include <string.h>
|
---|
112 | #include <netdb.h>
|
---|
113 | #include <resolv.h>
|
---|
114 | #include <ctype.h>
|
---|
115 | #include <errno.h>
|
---|
116 | #ifdef _ORG_FREEBSD_
|
---|
117 | #include <syslog.h>
|
---|
118 | #else
|
---|
119 | #include <stdlib.h>
|
---|
120 | u_int32_t _getlong(const u_char *src);
|
---|
121 | u_int16_t _getshort(const u_char *src);
|
---|
122 | #endif
|
---|
123 |
|
---|
124 | #include "res_config.h"
|
---|
125 | #include "Socklib_internals.h"
|
---|
126 |
|
---|
127 | #define SPRINTF(x) ((size_t)sprintf x)
|
---|
128 |
|
---|
129 | #define MAXALIASES 35
|
---|
130 | #define MAXADDRS 35
|
---|
131 |
|
---|
132 | static const char AskedForGot[] =
|
---|
133 | "gethostby*.gethostanswer: asked for \"%s\", got \"%s\"";
|
---|
134 |
|
---|
135 | static char *h_addr_ptrs[MAXADDRS + 1];
|
---|
136 |
|
---|
137 | static struct hostent host;
|
---|
138 | static char *host_aliases[MAXALIASES];
|
---|
139 | static char hostbuf[8*1024];
|
---|
140 | static u_char host_addr[16]; /* IPv4 or IPv6 */
|
---|
141 |
|
---|
142 | #ifdef RESOLVSORT
|
---|
143 | static void addrsort(char **, int);
|
---|
144 | #endif
|
---|
145 |
|
---|
146 | #if PACKETSZ > 1024
|
---|
147 | #define MAXPACKET PACKETSZ
|
---|
148 | #else
|
---|
149 | #define MAXPACKET 1024
|
---|
150 | #endif
|
---|
151 |
|
---|
152 | typedef union {
|
---|
153 | HEADER hdr;
|
---|
154 | u_char buf[MAXPACKET];
|
---|
155 | } querybuf;
|
---|
156 |
|
---|
157 | typedef union {
|
---|
158 | int32_t al;
|
---|
159 | char ac;
|
---|
160 | } align;
|
---|
161 |
|
---|
162 | extern int h_errno;
|
---|
163 | int _dns_ttl_;
|
---|
164 |
|
---|
165 | #ifdef DEBUG_RES
|
---|
166 | static void
|
---|
167 | dprintf(char *msg, int num)
|
---|
168 | {
|
---|
169 | if (_res.options & RES_DEBUG) {
|
---|
170 | int save = errno;
|
---|
171 |
|
---|
172 | printf(msg, num);
|
---|
173 | errno = save;
|
---|
174 | }
|
---|
175 | }
|
---|
176 | #else
|
---|
177 | # define dprintf(msg, num) /*nada*/
|
---|
178 | #endif
|
---|
179 |
|
---|
180 | #define BOUNDED_INCR(x) \
|
---|
181 | do { \
|
---|
182 | cp += x; \
|
---|
183 | if (cp > eom) { \
|
---|
184 | h_errno = NO_RECOVERY; \
|
---|
185 | return (NULL); \
|
---|
186 | } \
|
---|
187 | } while (0)
|
---|
188 |
|
---|
189 | #define BOUNDS_CHECK(ptr, count) \
|
---|
190 | do { \
|
---|
191 | if ((ptr) + (count) > eom) { \
|
---|
192 | h_errno = NO_RECOVERY; \
|
---|
193 | return (NULL); \
|
---|
194 | } \
|
---|
195 | } while (0)
|
---|
196 |
|
---|
197 | static struct hostent *
|
---|
198 | gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype)
|
---|
199 | {
|
---|
200 | register const HEADER *hp;
|
---|
201 | register const u_char *cp;
|
---|
202 | register int n;
|
---|
203 | const u_char *eom, *erdata;
|
---|
204 | char *bp, **ap, **hap;
|
---|
205 | int type, class, buflen, ancount, qdcount;
|
---|
206 | int haveanswer, had_error;
|
---|
207 | int toobig = 0;
|
---|
208 | char tbuf[MAXDNAME];
|
---|
209 | const char *tname;
|
---|
210 | int (*name_ok)(const char *);
|
---|
211 |
|
---|
212 | tname = qname;
|
---|
213 | host.h_name = NULL;
|
---|
214 | eom = answer->buf + anslen;
|
---|
215 | switch (qtype) {
|
---|
216 | case T_A:
|
---|
217 | case T_AAAA:
|
---|
218 | name_ok = res_hnok;
|
---|
219 | break;
|
---|
220 | case T_PTR:
|
---|
221 | name_ok = res_dnok;
|
---|
222 | break;
|
---|
223 | default:
|
---|
224 | h_errno = NO_RECOVERY;
|
---|
225 | return (NULL); /* XXX should be abort(); */
|
---|
226 | }
|
---|
227 | /*
|
---|
228 | * find first satisfactory answer
|
---|
229 | */
|
---|
230 | hp = &answer->hdr;
|
---|
231 | ancount = ntohs(hp->ancount);
|
---|
232 | qdcount = ntohs(hp->qdcount);
|
---|
233 | bp = hostbuf;
|
---|
234 | buflen = sizeof hostbuf;
|
---|
235 | cp = answer->buf;
|
---|
236 | BOUNDED_INCR(HFIXEDSZ);
|
---|
237 | if (qdcount != 1) {
|
---|
238 | h_errno = NO_RECOVERY;
|
---|
239 | return (NULL);
|
---|
240 | }
|
---|
241 | n = dn_expand(answer->buf, eom, cp, bp, buflen);
|
---|
242 | if ((n < 0) || !(*name_ok)(bp)) {
|
---|
243 | h_errno = NO_RECOVERY;
|
---|
244 | return (NULL);
|
---|
245 | }
|
---|
246 | BOUNDED_INCR(n + QFIXEDSZ);
|
---|
247 | if (qtype == T_A || qtype == T_AAAA) {
|
---|
248 | /* res_send() has already verified that the query name is the
|
---|
249 | * same as the one we sent; this just gets the expanded name
|
---|
250 | * (i.e., with the succeeding search-domain tacked on).
|
---|
251 | */
|
---|
252 | n = (int)strlen(bp) + 1; /* for the \0 */
|
---|
253 | if (n >= MAXHOSTNAMELEN) {
|
---|
254 | h_errno = NO_RECOVERY;
|
---|
255 | return (NULL);
|
---|
256 | }
|
---|
257 | host.h_name = bp;
|
---|
258 | bp += n;
|
---|
259 | buflen -= n;
|
---|
260 | /* The qname can be abbreviated, but h_name is now absolute. */
|
---|
261 | qname = host.h_name;
|
---|
262 | }
|
---|
263 | ap = host_aliases;
|
---|
264 | *ap = NULL;
|
---|
265 | host.h_aliases = host_aliases;
|
---|
266 | hap = h_addr_ptrs;
|
---|
267 | *hap = NULL;
|
---|
268 | host.h_addr_list = h_addr_ptrs;
|
---|
269 | haveanswer = 0;
|
---|
270 | had_error = 0;
|
---|
271 | _dns_ttl_ = -1;
|
---|
272 | while (ancount-- > 0 && cp < eom && !had_error) {
|
---|
273 | n = dn_expand(answer->buf, eom, cp, bp, buflen);
|
---|
274 | if ((n < 0) || !(*name_ok)(bp)) {
|
---|
275 | had_error++;
|
---|
276 | continue;
|
---|
277 | }
|
---|
278 | cp += n; /* name */
|
---|
279 | BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);
|
---|
280 | type = _getshort(cp);
|
---|
281 | cp += INT16SZ; /* type */
|
---|
282 | class = _getshort(cp);
|
---|
283 | cp += INT16SZ; /* class */
|
---|
284 | if (qtype == T_A && type == T_A)
|
---|
285 | _dns_ttl_ = _getlong(cp);
|
---|
286 | cp += INT32SZ; /* TTL */
|
---|
287 | n = _getshort(cp);
|
---|
288 | cp += INT16SZ; /* len */
|
---|
289 | BOUNDS_CHECK(cp, n);
|
---|
290 | erdata = cp + n;
|
---|
291 | if (class != C_IN) {
|
---|
292 | /* XXX - debug? syslog? */
|
---|
293 | cp += n;
|
---|
294 | continue; /* XXX - had_error++ ? */
|
---|
295 | }
|
---|
296 | if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
|
---|
297 | if (ap >= &host_aliases[MAXALIASES-1])
|
---|
298 | continue;
|
---|
299 | n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
|
---|
300 | if ((n < 0) || !(*name_ok)(tbuf)) {
|
---|
301 | had_error++;
|
---|
302 | continue;
|
---|
303 | }
|
---|
304 | cp += n;
|
---|
305 | if (cp != erdata) {
|
---|
306 | h_errno = NO_RECOVERY;
|
---|
307 | return (NULL);
|
---|
308 | }
|
---|
309 | /* Store alias. */
|
---|
310 | *ap++ = bp;
|
---|
311 | n = (int)strlen(bp) + 1; /* for the \0 */
|
---|
312 | if (n >= MAXHOSTNAMELEN) {
|
---|
313 | had_error++;
|
---|
314 | continue;
|
---|
315 | }
|
---|
316 | bp += n;
|
---|
317 | buflen -= n;
|
---|
318 | /* Get canonical name. */
|
---|
319 | n = (int)strlen(tbuf) + 1; /* for the \0 */
|
---|
320 | if (n > buflen || n >= MAXHOSTNAMELEN) {
|
---|
321 | had_error++;
|
---|
322 | continue;
|
---|
323 | }
|
---|
324 | strcpy(bp, tbuf);
|
---|
325 | host.h_name = bp;
|
---|
326 | bp += n;
|
---|
327 | buflen -= n;
|
---|
328 | continue;
|
---|
329 | }
|
---|
330 | if (qtype == T_PTR && type == T_CNAME) {
|
---|
331 | n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
|
---|
332 | if (n < 0 || !res_dnok(tbuf)) {
|
---|
333 | had_error++;
|
---|
334 | continue;
|
---|
335 | }
|
---|
336 | cp += n;
|
---|
337 | if (cp != erdata) {
|
---|
338 | h_errno = NO_RECOVERY;
|
---|
339 | return (NULL);
|
---|
340 | }
|
---|
341 | /* Get canonical name. */
|
---|
342 | n = (int)strlen(tbuf) + 1; /* for the \0 */
|
---|
343 | if (n > buflen || n >= MAXHOSTNAMELEN) {
|
---|
344 | had_error++;
|
---|
345 | continue;
|
---|
346 | }
|
---|
347 | strcpy(bp, tbuf);
|
---|
348 | tname = bp;
|
---|
349 | bp += n;
|
---|
350 | buflen -= n;
|
---|
351 | continue;
|
---|
352 | }
|
---|
353 | if (type != qtype) {
|
---|
354 | #ifdef _ORG_FREEBSD_
|
---|
355 | syslog(LOG_NOTICE|LOG_AUTH,
|
---|
356 | "gethostby*.gethostanswer: asked for \"%s %s %s\", got type \"%s\"",
|
---|
357 | qname, p_class(C_IN), p_type(qtype),
|
---|
358 | p_type(type));
|
---|
359 | #endif
|
---|
360 | cp += n;
|
---|
361 | continue; /* XXX - had_error++ ? */
|
---|
362 | }
|
---|
363 | switch (type) {
|
---|
364 | case T_PTR:
|
---|
365 | if (strcasecmp(tname, bp) != 0) {
|
---|
366 | #ifdef _ORG_FREEBSD_
|
---|
367 | syslog(LOG_NOTICE|LOG_AUTH,
|
---|
368 | AskedForGot, qname, bp);
|
---|
369 | #endif
|
---|
370 | cp += n;
|
---|
371 | continue; /* XXX - had_error++ ? */
|
---|
372 | }
|
---|
373 | n = dn_expand(answer->buf, eom, cp, bp, buflen);
|
---|
374 | if ((n < 0) || !res_hnok(bp)) {
|
---|
375 | had_error++;
|
---|
376 | break;
|
---|
377 | }
|
---|
378 | #if MULTI_PTRS_ARE_ALIASES
|
---|
379 | cp += n;
|
---|
380 | if (cp != erdata) {
|
---|
381 | h_errno = NO_RECOVERY;
|
---|
382 | return (NULL);
|
---|
383 | }
|
---|
384 | if (!haveanswer)
|
---|
385 | host.h_name = bp;
|
---|
386 | else if (ap < &host_aliases[MAXALIASES-1])
|
---|
387 | *ap++ = bp;
|
---|
388 | else
|
---|
389 | n = -1;
|
---|
390 | if (n != -1) {
|
---|
391 | n = (int)strlen(bp) + 1; /* for the \0 */
|
---|
392 | if (n >= MAXHOSTNAMELEN) {
|
---|
393 | had_error++;
|
---|
394 | break;
|
---|
395 | }
|
---|
396 | bp += n;
|
---|
397 | buflen -= n;
|
---|
398 | }
|
---|
399 | break;
|
---|
400 | #else
|
---|
401 | host.h_name = bp;
|
---|
402 | if (_res.options & RES_USE_INET6) {
|
---|
403 | n = strlen(bp) + 1; /* for the \0 */
|
---|
404 | if (n >= MAXHOSTNAMELEN) {
|
---|
405 | had_error++;
|
---|
406 | break;
|
---|
407 | }
|
---|
408 | bp += n;
|
---|
409 | buflen -= n;
|
---|
410 | _map_v4v6_hostent(&host, &bp, &buflen);
|
---|
411 | }
|
---|
412 | h_errno = NETDB_SUCCESS;
|
---|
413 | return (&host);
|
---|
414 | #endif
|
---|
415 | case T_A:
|
---|
416 | case T_AAAA:
|
---|
417 | if (strcasecmp(host.h_name, bp) != 0) {
|
---|
418 | #ifdef _ORG_FREEBSD_
|
---|
419 | syslog(LOG_NOTICE|LOG_AUTH,
|
---|
420 | AskedForGot, host.h_name, bp);
|
---|
421 | #endif
|
---|
422 | cp += n;
|
---|
423 | continue; /* XXX - had_error++ ? */
|
---|
424 | }
|
---|
425 | if (n != host.h_length) {
|
---|
426 | cp += n;
|
---|
427 | continue;
|
---|
428 | }
|
---|
429 | if (!haveanswer) {
|
---|
430 | register int nn;
|
---|
431 |
|
---|
432 | host.h_name = bp;
|
---|
433 | nn = (int)strlen(bp) + 1; /* for the \0 */
|
---|
434 | bp += nn;
|
---|
435 | buflen -= nn;
|
---|
436 | }
|
---|
437 |
|
---|
438 | bp += sizeof(align) - ((size_t)bp % sizeof(align));
|
---|
439 |
|
---|
440 | if (bp + n >= &hostbuf[sizeof hostbuf]) {
|
---|
441 | dprintf("size (%d) too big\n", n);
|
---|
442 | had_error++;
|
---|
443 | continue;
|
---|
444 | }
|
---|
445 | if (hap >= &h_addr_ptrs[MAXADDRS-1]) {
|
---|
446 | if (!toobig++)
|
---|
447 | dprintf("Too many addresses (%d)\n",
|
---|
448 | MAXADDRS);
|
---|
449 | cp += n;
|
---|
450 | continue;
|
---|
451 | }
|
---|
452 | *hap++ = bp;
|
---|
453 | bcopy(cp, bp, n);
|
---|
454 | bp += n;
|
---|
455 | buflen -= n;
|
---|
456 | cp += n;
|
---|
457 | if (cp != erdata) {
|
---|
458 | h_errno = NO_RECOVERY;
|
---|
459 | return (NULL);
|
---|
460 | }
|
---|
461 | break;
|
---|
462 | default:
|
---|
463 | dprintf("Impossible condition (type=%d)\n", type);
|
---|
464 | h_errno = NO_RECOVERY;
|
---|
465 | return (NULL);
|
---|
466 | /* BIND has abort() here, too risky on bad data */
|
---|
467 | }
|
---|
468 | if (!had_error)
|
---|
469 | haveanswer++;
|
---|
470 | }
|
---|
471 | if (haveanswer) {
|
---|
472 | *ap = NULL;
|
---|
473 | *hap = NULL;
|
---|
474 | # if defined(RESOLVSORT)
|
---|
475 | /*
|
---|
476 | * Note: we sort even if host can take only one address
|
---|
477 | * in its return structures - should give it the "best"
|
---|
478 | * address in that case, not some random one
|
---|
479 | */
|
---|
480 | if (_res.nsort && haveanswer > 1 && qtype == T_A)
|
---|
481 | addrsort(h_addr_ptrs, haveanswer);
|
---|
482 | # endif /*RESOLVSORT*/
|
---|
483 | if (!host.h_name) {
|
---|
484 | n = (int)strlen(qname) + 1; /* for the \0 */
|
---|
485 | if (n > buflen || n >= MAXHOSTNAMELEN)
|
---|
486 | goto no_recovery;
|
---|
487 | strcpy(bp, qname);
|
---|
488 | host.h_name = bp;
|
---|
489 | bp += n;
|
---|
490 | buflen -= n;
|
---|
491 | }
|
---|
492 | if (_res.options & RES_USE_INET6)
|
---|
493 | _map_v4v6_hostent(&host, &bp, &buflen);
|
---|
494 | h_errno = NETDB_SUCCESS;
|
---|
495 | return (&host);
|
---|
496 | }
|
---|
497 | no_recovery:
|
---|
498 | h_errno = NO_RECOVERY;
|
---|
499 | return (NULL);
|
---|
500 | }
|
---|
501 |
|
---|
502 | struct hostent *
|
---|
503 | __dns_getanswer(const char *answer, int anslen, const char *qname, int qtype)
|
---|
504 | {
|
---|
505 | switch(qtype) {
|
---|
506 | case T_AAAA:
|
---|
507 | host.h_addrtype = AF_INET6;
|
---|
508 | host.h_length = IN6ADDRSZ;
|
---|
509 | break;
|
---|
510 | case T_A:
|
---|
511 | default:
|
---|
512 | host.h_addrtype = AF_INET;
|
---|
513 | host.h_length = INADDRSZ;
|
---|
514 | break;
|
---|
515 | }
|
---|
516 |
|
---|
517 | return(gethostanswer((const querybuf *)answer, anslen, qname, qtype));
|
---|
518 | }
|
---|
519 |
|
---|
520 | struct hostent *
|
---|
521 | _gethostbydnsname(const char *name, int af)
|
---|
522 | {
|
---|
523 | querybuf buf;
|
---|
524 | register const char *cp;
|
---|
525 | char *bp;
|
---|
526 | int n, size, type, len;
|
---|
527 |
|
---|
528 | if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
|
---|
529 | h_errno = NETDB_INTERNAL;
|
---|
530 | return (NULL);
|
---|
531 | }
|
---|
532 |
|
---|
533 | switch (af) {
|
---|
534 | case AF_INET:
|
---|
535 | size = INADDRSZ;
|
---|
536 | type = T_A;
|
---|
537 | break;
|
---|
538 | case AF_INET6:
|
---|
539 | size = IN6ADDRSZ;
|
---|
540 | type = T_AAAA;
|
---|
541 | break;
|
---|
542 | default:
|
---|
543 | h_errno = NETDB_INTERNAL;
|
---|
544 | errno = EAFNOSUPPORT;
|
---|
545 | return (NULL);
|
---|
546 | }
|
---|
547 |
|
---|
548 | host.h_addrtype = af;
|
---|
549 | host.h_length = size;
|
---|
550 |
|
---|
551 | /*
|
---|
552 | * if there aren't any dots, it could be a user-level alias.
|
---|
553 | * this is also done in res_query() since we are not the only
|
---|
554 | * function that looks up host names.
|
---|
555 | */
|
---|
556 | if (!strchr(name, '.') && ( NULL != (cp = __hostalias(name))))
|
---|
557 | name = cp;
|
---|
558 |
|
---|
559 | /*
|
---|
560 | * disallow names consisting only of digits/dots, unless
|
---|
561 | * they end in a dot.
|
---|
562 | */
|
---|
563 | if (isdigit(name[0]))
|
---|
564 | for (cp = name;; ++cp) {
|
---|
565 | if (!*cp) {
|
---|
566 | if (*--cp == '.')
|
---|
567 | break;
|
---|
568 | /*
|
---|
569 | * All-numeric, no dot at the end.
|
---|
570 | * Fake up a hostent as if we'd actually
|
---|
571 | * done a lookup.
|
---|
572 | */
|
---|
573 | if (inet_pton(af, name, host_addr) <= 0) {
|
---|
574 | h_errno = HOST_NOT_FOUND;
|
---|
575 | return (NULL);
|
---|
576 | }
|
---|
577 | strncpy(hostbuf, name, MAXDNAME);
|
---|
578 | hostbuf[MAXDNAME] = '\0';
|
---|
579 | bp = hostbuf + MAXDNAME;
|
---|
580 | len = sizeof hostbuf - MAXDNAME;
|
---|
581 | host.h_name = hostbuf;
|
---|
582 | host.h_aliases = host_aliases;
|
---|
583 | host_aliases[0] = NULL;
|
---|
584 | h_addr_ptrs[0] = (char *)host_addr;
|
---|
585 | h_addr_ptrs[1] = NULL;
|
---|
586 | host.h_addr_list = h_addr_ptrs;
|
---|
587 | if (_res.options & RES_USE_INET6)
|
---|
588 | _map_v4v6_hostent(&host, &bp, &len);
|
---|
589 | h_errno = NETDB_SUCCESS;
|
---|
590 | return (&host);
|
---|
591 | }
|
---|
592 | if (!isdigit(*cp) && *cp != '.')
|
---|
593 | break;
|
---|
594 | }
|
---|
595 | if ((isxdigit(name[0]) && strchr(name, ':') != NULL) ||
|
---|
596 | name[0] == ':')
|
---|
597 | for (cp = name;; ++cp) {
|
---|
598 | if (!*cp) {
|
---|
599 | if (*--cp == '.')
|
---|
600 | break;
|
---|
601 | /*
|
---|
602 | * All-IPv6-legal, no dot at the end.
|
---|
603 | * Fake up a hostent as if we'd actually
|
---|
604 | * done a lookup.
|
---|
605 | */
|
---|
606 | if (inet_pton(af, name, host_addr) <= 0) {
|
---|
607 | h_errno = HOST_NOT_FOUND;
|
---|
608 | return (NULL);
|
---|
609 | }
|
---|
610 | strncpy(hostbuf, name, MAXDNAME);
|
---|
611 | hostbuf[MAXDNAME] = '\0';
|
---|
612 | bp = hostbuf + MAXDNAME;
|
---|
613 | len = sizeof hostbuf - MAXDNAME;
|
---|
614 | host.h_name = hostbuf;
|
---|
615 | host.h_aliases = host_aliases;
|
---|
616 | host_aliases[0] = NULL;
|
---|
617 | h_addr_ptrs[0] = (char *)host_addr;
|
---|
618 | h_addr_ptrs[1] = NULL;
|
---|
619 | host.h_addr_list = h_addr_ptrs;
|
---|
620 | h_errno = NETDB_SUCCESS;
|
---|
621 | return (&host);
|
---|
622 | }
|
---|
623 | if (!isxdigit(*cp) && *cp != ':' && *cp != '.')
|
---|
624 | break;
|
---|
625 | }
|
---|
626 |
|
---|
627 | if ((n = res_search(name, C_IN, type, buf.buf, sizeof(buf))) < 0) {
|
---|
628 | dprintf("res_search failed (%d)\n", n);
|
---|
629 | return (NULL);
|
---|
630 | }
|
---|
631 | return (gethostanswer(&buf, n, name, type));
|
---|
632 | }
|
---|
633 |
|
---|
634 | struct hostent *
|
---|
635 | _gethostbydnsaddr(const char *addr, int len, int af)
|
---|
636 | {
|
---|
637 | const u_char *uaddr = (const u_char *)addr;
|
---|
638 | static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
|
---|
639 | static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
|
---|
640 | int n, size;
|
---|
641 | querybuf buf;
|
---|
642 | register struct hostent *hp;
|
---|
643 | char qbuf[MAXDNAME+1], *qp;
|
---|
644 | #ifdef SUNSECURITY
|
---|
645 | register struct hostent *rhp;
|
---|
646 | char **haddr;
|
---|
647 | u_long old_options;
|
---|
648 | char hname2[MAXDNAME+1];
|
---|
649 | #endif /*SUNSECURITY*/
|
---|
650 |
|
---|
651 | if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
|
---|
652 | h_errno = NETDB_INTERNAL;
|
---|
653 | return (NULL);
|
---|
654 | }
|
---|
655 | if (af == AF_INET6 && len == IN6ADDRSZ &&
|
---|
656 | (!bcmp(uaddr, mapped, sizeof mapped) ||
|
---|
657 | !bcmp(uaddr, tunnelled, sizeof tunnelled))) {
|
---|
658 | /* Unmap. */
|
---|
659 | addr += sizeof mapped;
|
---|
660 | uaddr += sizeof mapped;
|
---|
661 | af = AF_INET;
|
---|
662 | len = INADDRSZ;
|
---|
663 | }
|
---|
664 | switch (af) {
|
---|
665 | case AF_INET:
|
---|
666 | size = INADDRSZ;
|
---|
667 | break;
|
---|
668 | case AF_INET6:
|
---|
669 | size = IN6ADDRSZ;
|
---|
670 | break;
|
---|
671 | default:
|
---|
672 | errno = EAFNOSUPPORT;
|
---|
673 | h_errno = NETDB_INTERNAL;
|
---|
674 | return (NULL);
|
---|
675 | }
|
---|
676 | if (size != len) {
|
---|
677 | errno = EINVAL;
|
---|
678 | h_errno = NETDB_INTERNAL;
|
---|
679 | return (NULL);
|
---|
680 | }
|
---|
681 | switch (af) {
|
---|
682 | case AF_INET:
|
---|
683 | (void) sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
|
---|
684 | (uaddr[3] & 0xff),
|
---|
685 | (uaddr[2] & 0xff),
|
---|
686 | (uaddr[1] & 0xff),
|
---|
687 | (uaddr[0] & 0xff));
|
---|
688 | break;
|
---|
689 | case AF_INET6:
|
---|
690 | qp = qbuf;
|
---|
691 | for (n = IN6ADDRSZ - 1; n >= 0; n--) {
|
---|
692 | qp += SPRINTF((qp, "%x.%x.",
|
---|
693 | uaddr[n] & 0xf,
|
---|
694 | (uaddr[n] >> 4) & 0xf));
|
---|
695 | }
|
---|
696 | strcpy(qp, "ip6.int");
|
---|
697 | break;
|
---|
698 | default:
|
---|
699 | abort();
|
---|
700 | }
|
---|
701 | n = res_query(qbuf, C_IN, T_PTR, (u_char *)buf.buf, sizeof buf.buf);
|
---|
702 | if (n < 0) {
|
---|
703 | dprintf("res_query failed (%d)\n", n);
|
---|
704 | return (NULL);
|
---|
705 | }
|
---|
706 | if ( NULL == (hp = gethostanswer(&buf, n, qbuf, T_PTR)))
|
---|
707 | return (NULL); /* h_errno was set by gethostanswer() */
|
---|
708 | #ifdef SUNSECURITY
|
---|
709 | if (af == AF_INET) {
|
---|
710 | /*
|
---|
711 | * turn off search as the name should be absolute,
|
---|
712 | * 'localhost' should be matched by defnames
|
---|
713 | */
|
---|
714 | strncpy(hname2, hp->h_name, MAXDNAME);
|
---|
715 | hname2[MAXDNAME] = '\0';
|
---|
716 | old_options = _res.options;
|
---|
717 | _res.options &= ~RES_DNSRCH;
|
---|
718 | _res.options |= RES_DEFNAMES;
|
---|
719 | if (!(rhp = gethostbyname(hname2))) {
|
---|
720 | #ifdef _ORG_FREEBSD_
|
---|
721 | syslog(LOG_NOTICE|LOG_AUTH,
|
---|
722 | "gethostbyaddr: No A record for %s (verifying [%s])",
|
---|
723 | hname2, inet_ntoa(*((struct in_addr *)addr)));
|
---|
724 | #endif
|
---|
725 | _res.options = old_options;
|
---|
726 | h_errno = HOST_NOT_FOUND;
|
---|
727 | return (NULL);
|
---|
728 | }
|
---|
729 | _res.options = old_options;
|
---|
730 | for (haddr = rhp->h_addr_list; *haddr; haddr++)
|
---|
731 | if (!memcmp(*haddr, addr, INADDRSZ))
|
---|
732 | break;
|
---|
733 | if (!*haddr) {
|
---|
734 | #ifdef _ORG_FREEBSD_
|
---|
735 | syslog(LOG_NOTICE|LOG_AUTH,
|
---|
736 | "gethostbyaddr: A record of %s != PTR record [%s]",
|
---|
737 | hname2, inet_ntoa(*((struct in_addr *)addr)));
|
---|
738 | #endif
|
---|
739 | h_errno = HOST_NOT_FOUND;
|
---|
740 | return (NULL);
|
---|
741 | }
|
---|
742 | }
|
---|
743 | #endif /*SUNSECURITY*/
|
---|
744 | hp->h_addrtype = af;
|
---|
745 | hp->h_length = len;
|
---|
746 | bcopy(addr, host_addr, len);
|
---|
747 | h_addr_ptrs[0] = (char *)host_addr;
|
---|
748 | h_addr_ptrs[1] = NULL;
|
---|
749 | if (af == AF_INET && (_res.options & RES_USE_INET6)) {
|
---|
750 | _map_v4v6_address((char*)host_addr, (char*)host_addr);
|
---|
751 | hp->h_addrtype = AF_INET6;
|
---|
752 | hp->h_length = IN6ADDRSZ;
|
---|
753 | }
|
---|
754 | h_errno = NETDB_SUCCESS;
|
---|
755 | return (hp);
|
---|
756 | }
|
---|
757 |
|
---|
758 | #ifdef RESOLVSORT
|
---|
759 | static void
|
---|
760 | addrsort(char **ap, int num)
|
---|
761 | {
|
---|
762 | short i, j;
|
---|
763 | char **p;
|
---|
764 | short aval[MAXADDRS];
|
---|
765 | short needsort = 0;
|
---|
766 |
|
---|
767 | p = ap;
|
---|
768 | for (i = 0; i < num; i++, p++) {
|
---|
769 | for (j = 0 ; (unsigned)j < _res.nsort; j++)
|
---|
770 | if (_res.sort_list[j].addr.s_addr ==
|
---|
771 | (((struct in_addr *)(*p))->s_addr & _res.sort_list[j].mask))
|
---|
772 | break;
|
---|
773 | aval[i] = j;
|
---|
774 | if (needsort == 0 && i > 0 && j < aval[i-1])
|
---|
775 | needsort = i;
|
---|
776 | }
|
---|
777 | if (!needsort)
|
---|
778 | return;
|
---|
779 |
|
---|
780 | while (needsort < num) {
|
---|
781 | for (j = needsort - 1; j >= 0; j--) {
|
---|
782 | if (aval[j] > aval[j+1]) {
|
---|
783 | char *hp;
|
---|
784 |
|
---|
785 | i = aval[j];
|
---|
786 | aval[j] = aval[j+1];
|
---|
787 | aval[j+1] = i;
|
---|
788 |
|
---|
789 | hp = ap[j];
|
---|
790 | ap[j] = ap[j+1];
|
---|
791 | ap[j+1] = hp;
|
---|
792 |
|
---|
793 | } else
|
---|
794 | break;
|
---|
795 | }
|
---|
796 | needsort++;
|
---|
797 | }
|
---|
798 | }
|
---|
799 | #endif
|
---|
800 | void
|
---|
801 | _sethostdnsent(int stayopen)
|
---|
802 | {
|
---|
803 | if ((_res.options & RES_INIT) == 0 && res_init() == -1)
|
---|
804 | return;
|
---|
805 | if (stayopen)
|
---|
806 | _res.options |= RES_STAYOPEN | RES_USEVC;
|
---|
807 | }
|
---|
808 |
|
---|
809 | void
|
---|
810 | _endhostdnsent()
|
---|
811 | {
|
---|
812 | _res.options &= ~(RES_STAYOPEN | RES_USEVC);
|
---|
813 | res_close();
|
---|
814 | }
|
---|