Do not call __nan in scalb functions.
[glibc.git] / resolv / gethnamaddr.c
blob9ad2c3010a87f915ff0676753b21826ea9161fb6
1 /*
2 * ++Copyright++ 1985, 1988, 1993
3 * -
4 * Copyright (c) 1985, 1988, 1993
5 * The Regents of the University of California. All rights reserved.
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 * 4. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 * -
31 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
33 * Permission to use, copy, modify, and distribute this software for any
34 * purpose with or without fee is hereby granted, provided that the above
35 * copyright notice and this permission notice appear in all copies, and that
36 * the name of Digital Equipment Corporation not be used in advertising or
37 * publicity pertaining to distribution of the document or software without
38 * specific, written prior permission.
40 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
41 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
42 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
43 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
44 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
45 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
46 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
47 * SOFTWARE.
48 * -
49 * --Copyright--
52 /* XXX This file is not used by any of the resolver functions implemented by
53 glibc (i.e. get*info and gethostby*). It cannot be removed however because
54 it exports symbols in the libresolv ABI. The file is not maintained any
55 more, nor are these functions. */
57 #include <sys/types.h>
58 #include <sys/param.h>
59 #include <sys/socket.h>
60 #include <netinet/in.h>
61 #include <arpa/inet.h>
62 #include <arpa/nameser.h>
64 #include <stdio.h>
65 #include <netdb.h>
66 #include <resolv.h>
67 #include <ctype.h>
68 #include <errno.h>
69 #include <stdlib.h>
70 #include <string.h>
72 #define MAXALIASES 35
73 #define MAXADDRS 35
75 static char *h_addr_ptrs[MAXADDRS + 1];
77 static struct hostent host;
78 static char *host_aliases[MAXALIASES];
79 static char hostbuf[8*1024];
80 static u_char host_addr[16]; /* IPv4 or IPv6 */
81 static FILE *hostf = NULL;
82 static int stayopen = 0;
84 static void map_v4v6_address (const char *src, char *dst) __THROW;
85 static void map_v4v6_hostent (struct hostent *hp, char **bp, int *len) __THROW;
87 extern void addrsort (char **, int) __THROW;
89 #if PACKETSZ > 65536
90 #define MAXPACKET PACKETSZ
91 #else
92 #define MAXPACKET 65536
93 #endif
95 /* As per RFC 1034 and 1035 a host name cannot exceed 255 octets in length. */
96 #ifdef MAXHOSTNAMELEN
97 # undef MAXHOSTNAMELEN
98 #endif
99 #define MAXHOSTNAMELEN 256
101 typedef union {
102 HEADER hdr;
103 u_char buf[MAXPACKET];
104 } querybuf;
106 typedef union {
107 int32_t al;
108 char ac;
109 } align;
111 #ifndef h_errno
112 extern int h_errno;
113 #endif
115 #ifdef DEBUG
116 static void
117 Dprintf (char *msg, int num)
119 if (_res.options & RES_DEBUG) {
120 int save = errno;
122 printf(msg, num);
123 __set_errno (save);
126 #else
127 # define Dprintf(msg, num) /*nada*/
128 #endif
130 #define BOUNDED_INCR(x) \
131 do { \
132 cp += x; \
133 if (cp > eom) { \
134 __set_h_errno (NO_RECOVERY); \
135 return (NULL); \
137 } while (0)
139 #define BOUNDS_CHECK(ptr, count) \
140 do { \
141 if ((ptr) + (count) > eom) { \
142 __set_h_errno (NO_RECOVERY); \
143 return (NULL); \
145 } while (0)
148 static struct hostent *
149 getanswer (const querybuf *answer, int anslen, const char *qname, int qtype)
151 const HEADER *hp;
152 const u_char *cp;
153 int n;
154 const u_char *eom, *erdata;
155 char *bp, **ap, **hap;
156 int type, class, buflen, ancount, qdcount;
157 int haveanswer, had_error;
158 int toobig = 0;
159 char tbuf[MAXDNAME];
160 const char *tname;
161 int (*name_ok) (const char *);
163 tname = qname;
164 host.h_name = NULL;
165 eom = answer->buf + anslen;
166 switch (qtype) {
167 case T_A:
168 case T_AAAA:
169 name_ok = res_hnok;
170 break;
171 case T_PTR:
172 name_ok = res_dnok;
173 break;
174 default:
175 return (NULL); /* XXX should be abort(); */
178 * find first satisfactory answer
180 hp = &answer->hdr;
181 ancount = ntohs(hp->ancount);
182 qdcount = ntohs(hp->qdcount);
183 bp = hostbuf;
184 buflen = sizeof hostbuf;
185 cp = answer->buf;
186 BOUNDED_INCR(HFIXEDSZ);
187 if (qdcount != 1) {
188 __set_h_errno (NO_RECOVERY);
189 return (NULL);
191 n = dn_expand(answer->buf, eom, cp, bp, buflen);
192 if ((n < 0) || !(*name_ok)(bp)) {
193 __set_h_errno (NO_RECOVERY);
194 return (NULL);
196 BOUNDED_INCR(n + QFIXEDSZ);
197 if (qtype == T_A || qtype == T_AAAA) {
198 /* res_send() has already verified that the query name is the
199 * same as the one we sent; this just gets the expanded name
200 * (i.e., with the succeeding search-domain tacked on).
202 n = strlen(bp) + 1; /* for the \0 */
203 if (n >= MAXHOSTNAMELEN) {
204 __set_h_errno (NO_RECOVERY);
205 return (NULL);
207 host.h_name = bp;
208 bp += n;
209 buflen -= n;
210 /* The qname can be abbreviated, but h_name is now absolute. */
211 qname = host.h_name;
213 ap = host_aliases;
214 *ap = NULL;
215 host.h_aliases = host_aliases;
216 hap = h_addr_ptrs;
217 *hap = NULL;
218 host.h_addr_list = h_addr_ptrs;
219 haveanswer = 0;
220 had_error = 0;
221 while (ancount-- > 0 && cp < eom && !had_error) {
222 n = dn_expand(answer->buf, eom, cp, bp, buflen);
223 if ((n < 0) || !(*name_ok)(bp)) {
224 had_error++;
225 continue;
227 cp += n; /* name */
228 BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);
229 type = ns_get16(cp);
230 cp += INT16SZ; /* type */
231 class = ns_get16(cp);
232 cp += INT16SZ + INT32SZ; /* class, TTL */
233 n = ns_get16(cp);
234 cp += INT16SZ; /* len */
235 BOUNDS_CHECK(cp, n);
236 erdata = cp + n;
237 if (class != C_IN) {
238 /* XXX - debug? syslog? */
239 cp += n;
240 continue; /* XXX - had_error++ ? */
242 if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
243 if (ap >= &host_aliases[MAXALIASES-1])
244 continue;
245 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
246 if ((n < 0) || !(*name_ok)(tbuf)) {
247 had_error++;
248 continue;
250 cp += n;
251 if (cp != erdata) {
252 __set_h_errno (NO_RECOVERY);
253 return (NULL);
255 /* Store alias. */
256 *ap++ = bp;
257 n = strlen(bp) + 1; /* for the \0 */
258 if (n >= MAXHOSTNAMELEN) {
259 had_error++;
260 continue;
262 bp += n;
263 buflen -= n;
264 /* Get canonical name. */
265 n = strlen(tbuf) + 1; /* for the \0 */
266 if (n > buflen || n >= MAXHOSTNAMELEN) {
267 had_error++;
268 continue;
270 strcpy(bp, tbuf);
271 host.h_name = bp;
272 bp += n;
273 buflen -= n;
274 continue;
276 if (qtype == T_PTR && type == T_CNAME) {
277 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
278 if (n < 0 || !res_dnok(tbuf)) {
279 had_error++;
280 continue;
282 cp += n;
283 if (cp != erdata) {
284 __set_h_errno (NO_RECOVERY);
285 return (NULL);
287 /* Get canonical name. */
288 n = strlen(tbuf) + 1; /* for the \0 */
289 if (n > buflen || n >= MAXHOSTNAMELEN) {
290 had_error++;
291 continue;
293 strcpy(bp, tbuf);
294 tname = bp;
295 bp += n;
296 buflen -= n;
297 continue;
299 if (type != qtype) {
300 /* Log a low priority message if we get an unexpected
301 * record, but skip it if we are using DNSSEC since it
302 * uses many different types in responses that do not
303 * match QTYPE.
305 cp += n;
306 continue; /* XXX - had_error++ ? */
308 switch (type) {
309 case T_PTR:
310 if (strcasecmp(tname, bp) != 0) {
311 cp += n;
312 continue; /* XXX - had_error++ ? */
314 n = dn_expand(answer->buf, eom, cp, bp, buflen);
315 if ((n < 0) || !res_hnok(bp)) {
316 had_error++;
317 break;
319 cp += n;
320 if (cp != erdata) {
321 __set_h_errno (NO_RECOVERY);
322 return (NULL);
324 if (!haveanswer)
325 host.h_name = bp;
326 else if (ap < &host_aliases[MAXALIASES-1])
327 *ap++ = bp;
328 else
329 n = -1;
330 if (n != -1) {
331 n = strlen(bp) + 1; /* for the \0 */
332 if (n >= MAXHOSTNAMELEN) {
333 had_error++;
334 break;
336 bp += n;
337 buflen -= n;
339 break;
340 case T_A:
341 case T_AAAA:
342 if (strcasecmp(host.h_name, bp) != 0) {
343 cp += n;
344 continue; /* XXX - had_error++ ? */
346 if (n != host.h_length) {
347 cp += n;
348 continue;
350 if (!haveanswer) {
351 int nn;
353 host.h_name = bp;
354 nn = strlen(bp) + 1; /* for the \0 */
355 bp += nn;
356 buflen -= nn;
359 /* XXX: when incrementing bp, we have to decrement
360 * buflen by the same amount --okir */
361 buflen -= sizeof(align) - ((u_long)bp % sizeof(align));
363 bp += sizeof(align) - ((u_long)bp % sizeof(align));
365 if (bp + n >= &hostbuf[sizeof hostbuf]) {
366 Dprintf("size (%d) too big\n", n);
367 had_error++;
368 continue;
370 if (hap >= &h_addr_ptrs[MAXADDRS-1]) {
371 if (!toobig++) {
372 Dprintf("Too many addresses (%d)\n",
373 MAXADDRS);
375 cp += n;
376 continue;
378 memmove(*hap++ = bp, cp, n);
379 bp += n;
380 buflen -= n;
381 cp += n;
382 if (cp != erdata) {
383 __set_h_errno (NO_RECOVERY);
384 return (NULL);
386 break;
387 default:
388 abort();
390 if (!had_error)
391 haveanswer++;
393 if (haveanswer) {
394 *ap = NULL;
395 *hap = NULL;
397 * Note: we sort even if host can take only one address
398 * in its return structures - should give it the "best"
399 * address in that case, not some random one
401 if (_res.nsort && haveanswer > 1 && qtype == T_A)
402 addrsort(h_addr_ptrs, haveanswer);
403 if (!host.h_name) {
404 n = strlen(qname) + 1; /* for the \0 */
405 if (n > buflen || n >= MAXHOSTNAMELEN)
406 goto no_recovery;
407 strcpy(bp, qname);
408 host.h_name = bp;
409 bp += n;
410 buflen -= n;
412 if (_res.options & RES_USE_INET6)
413 map_v4v6_hostent(&host, &bp, &buflen);
414 __set_h_errno (NETDB_SUCCESS);
415 return (&host);
417 no_recovery:
418 __set_h_errno (NO_RECOVERY);
419 return (NULL);
422 extern struct hostent *gethostbyname2(const char *name, int af);
423 libresolv_hidden_proto (gethostbyname2)
425 struct hostent *
426 gethostbyname (const char *name)
428 struct hostent *hp;
430 if (__res_maybe_init (&_res, 0) == -1) {
431 __set_h_errno (NETDB_INTERNAL);
432 return (NULL);
434 if (_res.options & RES_USE_INET6) {
435 hp = gethostbyname2(name, AF_INET6);
436 if (hp)
437 return (hp);
439 return (gethostbyname2(name, AF_INET));
442 struct hostent *
443 gethostbyname2 (const char *name, int af)
445 union
447 querybuf *buf;
448 u_char *ptr;
449 } buf;
450 querybuf *origbuf;
451 const char *cp;
452 char *bp;
453 int n, size, type, len;
454 struct hostent *ret;
456 if (__res_maybe_init (&_res, 0) == -1) {
457 __set_h_errno (NETDB_INTERNAL);
458 return (NULL);
461 switch (af) {
462 case AF_INET:
463 size = INADDRSZ;
464 type = T_A;
465 break;
466 case AF_INET6:
467 size = IN6ADDRSZ;
468 type = T_AAAA;
469 break;
470 default:
471 __set_h_errno (NETDB_INTERNAL);
472 __set_errno (EAFNOSUPPORT);
473 return (NULL);
476 host.h_addrtype = af;
477 host.h_length = size;
480 * if there aren't any dots, it could be a user-level alias.
481 * this is also done in res_query() since we are not the only
482 * function that looks up host names.
484 if (!strchr(name, '.') && (cp = __hostalias(name)))
485 name = cp;
488 * disallow names consisting only of digits/dots, unless
489 * they end in a dot.
491 if (isdigit(name[0]))
492 for (cp = name;; ++cp) {
493 if (!*cp) {
494 if (*--cp == '.')
495 break;
497 * All-numeric, no dot at the end.
498 * Fake up a hostent as if we'd actually
499 * done a lookup.
501 if (inet_pton(af, name, host_addr) <= 0) {
502 __set_h_errno (HOST_NOT_FOUND);
503 return (NULL);
505 strncpy(hostbuf, name, MAXDNAME);
506 hostbuf[MAXDNAME] = '\0';
507 bp = hostbuf + MAXDNAME;
508 len = sizeof hostbuf - MAXDNAME;
509 host.h_name = hostbuf;
510 host.h_aliases = host_aliases;
511 host_aliases[0] = NULL;
512 h_addr_ptrs[0] = (char *)host_addr;
513 h_addr_ptrs[1] = NULL;
514 host.h_addr_list = h_addr_ptrs;
515 if (_res.options & RES_USE_INET6)
516 map_v4v6_hostent(&host, &bp, &len);
517 __set_h_errno (NETDB_SUCCESS);
518 return (&host);
520 if (!isdigit(*cp) && *cp != '.')
521 break;
523 if ((isxdigit(name[0]) && strchr(name, ':') != NULL) ||
524 name[0] == ':')
525 for (cp = name;; ++cp) {
526 if (!*cp) {
527 if (*--cp == '.')
528 break;
530 * All-IPv6-legal, no dot at the end.
531 * Fake up a hostent as if we'd actually
532 * done a lookup.
534 if (inet_pton(af, name, host_addr) <= 0) {
535 __set_h_errno (HOST_NOT_FOUND);
536 return (NULL);
538 strncpy(hostbuf, name, MAXDNAME);
539 hostbuf[MAXDNAME] = '\0';
540 bp = hostbuf + MAXDNAME;
541 len = sizeof hostbuf - MAXDNAME;
542 host.h_name = hostbuf;
543 host.h_aliases = host_aliases;
544 host_aliases[0] = NULL;
545 h_addr_ptrs[0] = (char *)host_addr;
546 h_addr_ptrs[1] = NULL;
547 host.h_addr_list = h_addr_ptrs;
548 __set_h_errno (NETDB_SUCCESS);
549 return (&host);
551 if (!isxdigit(*cp) && *cp != ':' && *cp != '.')
552 break;
555 buf.buf = origbuf = (querybuf *) alloca (1024);
557 if ((n = __libc_res_nsearch(&_res, name, C_IN, type, buf.buf->buf, 1024,
558 &buf.ptr, NULL, NULL, NULL, NULL)) < 0) {
559 if (buf.buf != origbuf)
560 free (buf.buf);
561 Dprintf("res_nsearch failed (%d)\n", n);
562 if (errno == ECONNREFUSED)
563 return (_gethtbyname2(name, af));
564 return (NULL);
566 ret = getanswer(buf.buf, n, name, type);
567 if (buf.buf != origbuf)
568 free (buf.buf);
569 return ret;
571 libresolv_hidden_def (gethostbyname2)
573 struct hostent *
574 gethostbyaddr (const void *addr, socklen_t len, int af)
576 const u_char *uaddr = (const u_char *)addr;
577 static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
578 static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
579 int n;
580 socklen_t size;
581 union
583 querybuf *buf;
584 u_char *ptr;
585 } buf;
586 querybuf *orig_buf;
587 struct hostent *hp;
588 char qbuf[MAXDNAME+1], *qp = NULL;
590 if (__res_maybe_init (&_res, 0) == -1) {
591 __set_h_errno (NETDB_INTERNAL);
592 return (NULL);
594 if (af == AF_INET6 && len == IN6ADDRSZ &&
595 (!memcmp(uaddr, mapped, sizeof mapped) ||
596 !memcmp(uaddr, tunnelled, sizeof tunnelled))) {
597 /* Unmap. */
598 addr += sizeof mapped;
599 uaddr += sizeof mapped;
600 af = AF_INET;
601 len = INADDRSZ;
603 switch (af) {
604 case AF_INET:
605 size = INADDRSZ;
606 break;
607 case AF_INET6:
608 size = IN6ADDRSZ;
609 break;
610 default:
611 __set_errno (EAFNOSUPPORT);
612 __set_h_errno (NETDB_INTERNAL);
613 return (NULL);
615 if (size != len) {
616 __set_errno (EINVAL);
617 __set_h_errno (NETDB_INTERNAL);
618 return (NULL);
620 switch (af) {
621 case AF_INET:
622 (void) sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
623 (uaddr[3] & 0xff),
624 (uaddr[2] & 0xff),
625 (uaddr[1] & 0xff),
626 (uaddr[0] & 0xff));
627 break;
628 case AF_INET6:
629 qp = qbuf;
630 for (n = IN6ADDRSZ - 1; n >= 0; n--) {
631 qp += sprintf(qp, "%x.%x.",
632 uaddr[n] & 0xf,
633 (uaddr[n] >> 4) & 0xf);
635 strcpy(qp, "ip6.arpa");
636 break;
637 default:
638 abort();
641 buf.buf = orig_buf = (querybuf *) alloca (1024);
643 n = __libc_res_nquery(&_res, qbuf, C_IN, T_PTR, buf.buf->buf, 1024,
644 &buf.ptr, NULL, NULL, NULL, NULL);
645 if (n < 0 && af == AF_INET6 && (_res.options & RES_NOIP6DOTINT) == 0) {
646 strcpy(qp, "ip6.int");
647 n = __libc_res_nquery(&_res, qbuf, C_IN, T_PTR, buf.buf->buf,
648 buf.buf != orig_buf ? MAXPACKET : 1024,
649 &buf.ptr, NULL, NULL, NULL, NULL);
651 if (n < 0) {
652 if (buf.buf != orig_buf)
653 free (buf.buf);
654 Dprintf("res_nquery failed (%d)\n", n);
655 if (errno == ECONNREFUSED)
656 return (_gethtbyaddr(addr, len, af));
657 return (NULL);
659 hp = getanswer(buf.buf, n, qbuf, T_PTR);
660 if (buf.buf != orig_buf)
661 free (buf.buf);
662 if (!hp)
663 return (NULL); /* h_errno was set by getanswer() */
664 hp->h_addrtype = af;
665 hp->h_length = len;
666 memmove(host_addr, addr, len);
667 h_addr_ptrs[0] = (char *)host_addr;
668 h_addr_ptrs[1] = NULL;
669 if (af == AF_INET && (_res.options & RES_USE_INET6)) {
670 map_v4v6_address((char*)host_addr, (char*)host_addr);
671 hp->h_addrtype = AF_INET6;
672 hp->h_length = IN6ADDRSZ;
674 __set_h_errno (NETDB_SUCCESS);
675 return (hp);
678 void
679 _sethtent (int f)
681 if (!hostf)
682 hostf = fopen(_PATH_HOSTS, "rce" );
683 else
684 rewind(hostf);
685 stayopen = f;
687 libresolv_hidden_def (_sethtent)
689 void
690 _endhtent (void)
692 if (hostf && !stayopen) {
693 (void) fclose(hostf);
694 hostf = NULL;
698 struct hostent *
699 _gethtent (void)
701 char *p;
702 char *cp, **q;
703 int af, len;
705 if (!hostf && !(hostf = fopen(_PATH_HOSTS, "rce" ))) {
706 __set_h_errno (NETDB_INTERNAL);
707 return (NULL);
709 again:
710 if (!(p = fgets(hostbuf, sizeof hostbuf, hostf))) {
711 __set_h_errno (HOST_NOT_FOUND);
712 return (NULL);
714 if (*p == '#')
715 goto again;
716 if (!(cp = strpbrk(p, "#\n")))
717 goto again;
718 *cp = '\0';
719 if (!(cp = strpbrk(p, " \t")))
720 goto again;
721 *cp++ = '\0';
722 if (inet_pton(AF_INET6, p, host_addr) > 0) {
723 af = AF_INET6;
724 len = IN6ADDRSZ;
725 } else if (inet_pton(AF_INET, p, host_addr) > 0) {
726 if (_res.options & RES_USE_INET6) {
727 map_v4v6_address((char*)host_addr, (char*)host_addr);
728 af = AF_INET6;
729 len = IN6ADDRSZ;
730 } else {
731 af = AF_INET;
732 len = INADDRSZ;
734 } else {
735 goto again;
737 h_addr_ptrs[0] = (char *)host_addr;
738 h_addr_ptrs[1] = NULL;
739 host.h_addr_list = h_addr_ptrs;
740 host.h_length = len;
741 host.h_addrtype = af;
742 while (*cp == ' ' || *cp == '\t')
743 cp++;
744 host.h_name = cp;
745 q = host.h_aliases = host_aliases;
746 if ((cp = strpbrk(cp, " \t")))
747 *cp++ = '\0';
748 while (cp && *cp) {
749 if (*cp == ' ' || *cp == '\t') {
750 cp++;
751 continue;
753 if (q < &host_aliases[MAXALIASES - 1])
754 *q++ = cp;
755 if ((cp = strpbrk(cp, " \t")))
756 *cp++ = '\0';
758 *q = NULL;
759 __set_h_errno (NETDB_SUCCESS);
760 return (&host);
762 libresolv_hidden_def (_gethtent)
764 struct hostent *
765 _gethtbyname (const char *name)
767 struct hostent *hp;
769 if (_res.options & RES_USE_INET6) {
770 hp = _gethtbyname2(name, AF_INET6);
771 if (hp)
772 return (hp);
774 return (_gethtbyname2(name, AF_INET));
777 struct hostent *
778 _gethtbyname2 (const char *name, int af)
780 struct hostent *p;
781 char **cp;
783 _sethtent(0);
784 while ((p = _gethtent())) {
785 if (p->h_addrtype != af)
786 continue;
787 if (strcasecmp(p->h_name, name) == 0)
788 break;
789 for (cp = p->h_aliases; *cp != 0; cp++)
790 if (strcasecmp(*cp, name) == 0)
791 goto found;
793 found:
794 _endhtent();
795 return (p);
797 libresolv_hidden_def (_gethtbyname2)
799 struct hostent *
800 _gethtbyaddr (const char *addr, size_t len, int af)
802 struct hostent *p;
804 _sethtent(0);
805 while ((p = _gethtent()))
806 if (p->h_addrtype == af && !memcmp(p->h_addr, addr, len))
807 break;
808 _endhtent();
809 return (p);
811 libresolv_hidden_def (_gethtbyaddr)
813 static void
814 map_v4v6_address (const char *src, char *dst)
816 u_char *p = (u_char *)dst;
817 char tmp[INADDRSZ];
818 int i;
820 /* Stash a temporary copy so our caller can update in place. */
821 memcpy(tmp, src, INADDRSZ);
822 /* Mark this ipv6 addr as a mapped ipv4. */
823 for (i = 0; i < 10; i++)
824 *p++ = 0x00;
825 *p++ = 0xff;
826 *p++ = 0xff;
827 /* Retrieve the saved copy and we're done. */
828 memcpy((void*)p, tmp, INADDRSZ);
831 static void
832 map_v4v6_hostent (struct hostent *hp, char **bpp, int *lenp)
834 char **ap;
836 if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ)
837 return;
838 hp->h_addrtype = AF_INET6;
839 hp->h_length = IN6ADDRSZ;
840 for (ap = hp->h_addr_list; *ap; ap++) {
841 int i = sizeof(align) - ((u_long)*bpp % sizeof(align));
843 if (*lenp < (i + IN6ADDRSZ)) {
844 /* Out of memory. Truncate address list here. XXX */
845 *ap = NULL;
846 return;
848 *bpp += i;
849 *lenp -= i;
850 map_v4v6_address(*ap, *bpp);
851 *ap = *bpp;
852 *bpp += IN6ADDRSZ;
853 *lenp -= IN6ADDRSZ;
857 extern void
858 addrsort (char **ap, int num)
860 int i, j;
861 char **p;
862 short aval[MAXADDRS];
863 int needsort = 0;
865 p = ap;
866 for (i = 0; i < num; i++, p++) {
867 for (j = 0 ; (unsigned)j < _res.nsort; j++)
868 if (_res.sort_list[j].addr.s_addr ==
869 (((struct in_addr *)(*p))->s_addr & _res.sort_list[j].mask))
870 break;
871 aval[i] = j;
872 if (needsort == 0 && i > 0 && j < aval[i-1])
873 needsort = i;
875 if (!needsort)
876 return;
878 while (needsort < num) {
879 for (j = needsort - 1; j >= 0; j--) {
880 if (aval[j] > aval[j+1]) {
881 char *hp;
883 i = aval[j];
884 aval[j] = aval[j+1];
885 aval[j+1] = i;
887 hp = ap[j];
888 ap[j] = ap[j+1];
889 ap[j+1] = hp;
891 } else
892 break;
894 needsort++;