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