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