2 * ++Copyright++ 1985, 1988, 1993
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
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
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
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 <shlib-compat.h>
58 #if SHLIB_COMPAT (libresolv, GLIBC_2_0, GLIBC_2_25)
60 # include <sys/types.h>
61 # include <sys/param.h>
62 # include <sys/socket.h>
63 # include <netinet/in.h>
64 # include <arpa/inet.h>
65 # include <arpa/nameser.h>
69 # include <resolv/resolv-internal.h>
70 # include <resolv/resolv_context.h>
76 # define MAXALIASES 35
79 static char *h_addr_ptrs
[MAXADDRS
+ 1];
81 static struct hostent host
;
82 static char *host_aliases
[MAXALIASES
];
83 static char hostbuf
[8*1024];
84 static u_char host_addr
[16]; /* IPv4 or IPv6 */
85 static FILE *hostf
= NULL
;
86 static int stayopen
= 0;
88 static struct hostent
*res_gethostbyname2_context (struct resolv_context
*,
89 const char *name
, int af
);
91 static void map_v4v6_address (const char *src
, char *dst
) __THROW
;
92 static void map_v4v6_hostent (struct hostent
*hp
, char **bp
, int *len
) __THROW
;
94 extern void addrsort (char **, int) __THROW
;
97 # define MAXPACKET PACKETSZ
99 # define MAXPACKET 65536
102 /* As per RFC 1034 and 1035 a host name cannot exceed 255 octets in length. */
103 # ifdef MAXHOSTNAMELEN
104 # undef MAXHOSTNAMELEN
106 # define MAXHOSTNAMELEN 256
110 u_char buf
[MAXPACKET
];
124 Dprintf (char *msg
, int num
)
126 if (_res
.options
& RES_DEBUG
) {
134 # define Dprintf(msg, num) /*nada*/
137 # define BOUNDED_INCR(x) \
141 __set_h_errno (NO_RECOVERY); \
146 # define BOUNDS_CHECK(ptr, count) \
148 if ((ptr) + (count) > eom) { \
149 __set_h_errno (NO_RECOVERY); \
155 static struct hostent
*
156 getanswer (const querybuf
*answer
, int anslen
, const char *qname
, int qtype
)
161 const u_char
*eom
, *erdata
;
162 char *bp
, **ap
, **hap
;
163 int type
, class, buflen
, ancount
, qdcount
;
164 int haveanswer
, had_error
;
168 int (*name_ok
) (const char *);
172 eom
= answer
->buf
+ anslen
;
182 return (NULL
); /* XXX should be abort(); */
185 * find first satisfactory answer
188 ancount
= ntohs(hp
->ancount
);
189 qdcount
= ntohs(hp
->qdcount
);
191 buflen
= sizeof hostbuf
;
193 BOUNDED_INCR(HFIXEDSZ
);
195 __set_h_errno (NO_RECOVERY
);
198 n
= dn_expand(answer
->buf
, eom
, cp
, bp
, buflen
);
199 if ((n
< 0) || !(*name_ok
)(bp
)) {
200 __set_h_errno (NO_RECOVERY
);
203 BOUNDED_INCR(n
+ QFIXEDSZ
);
204 if (qtype
== T_A
|| qtype
== T_AAAA
) {
205 /* res_send() has already verified that the query name is the
206 * same as the one we sent; this just gets the expanded name
207 * (i.e., with the succeeding search-domain tacked on).
209 n
= strlen(bp
) + 1; /* for the \0 */
210 if (n
>= MAXHOSTNAMELEN
) {
211 __set_h_errno (NO_RECOVERY
);
217 /* The qname can be abbreviated, but h_name is now absolute. */
222 host
.h_aliases
= host_aliases
;
225 host
.h_addr_list
= h_addr_ptrs
;
228 while (ancount
-- > 0 && cp
< eom
&& !had_error
) {
229 n
= dn_expand(answer
->buf
, eom
, cp
, bp
, buflen
);
230 if ((n
< 0) || !(*name_ok
)(bp
)) {
235 BOUNDS_CHECK(cp
, 3 * INT16SZ
+ INT32SZ
);
237 cp
+= INT16SZ
; /* type */
238 class = ns_get16(cp
);
239 cp
+= INT16SZ
+ INT32SZ
; /* class, TTL */
241 cp
+= INT16SZ
; /* len */
245 /* XXX - debug? syslog? */
247 continue; /* XXX - had_error++ ? */
249 if ((qtype
== T_A
|| qtype
== T_AAAA
) && type
== T_CNAME
) {
250 if (ap
>= &host_aliases
[MAXALIASES
-1])
252 n
= dn_expand(answer
->buf
, eom
, cp
, tbuf
, sizeof tbuf
);
253 if ((n
< 0) || !(*name_ok
)(tbuf
)) {
259 __set_h_errno (NO_RECOVERY
);
264 n
= strlen(bp
) + 1; /* for the \0 */
265 if (n
>= MAXHOSTNAMELEN
) {
271 /* Get canonical name. */
272 n
= strlen(tbuf
) + 1; /* for the \0 */
273 if (n
> buflen
|| n
>= MAXHOSTNAMELEN
) {
283 if (qtype
== T_PTR
&& type
== T_CNAME
) {
284 n
= dn_expand(answer
->buf
, eom
, cp
, tbuf
, sizeof tbuf
);
285 if (n
< 0 || !res_dnok(tbuf
)) {
291 __set_h_errno (NO_RECOVERY
);
294 /* Get canonical name. */
295 n
= strlen(tbuf
) + 1; /* for the \0 */
296 if (n
> buflen
|| n
>= MAXHOSTNAMELEN
) {
307 /* Log a low priority message if we get an unexpected
308 * record, but skip it if we are using DNSSEC since it
309 * uses many different types in responses that do not
313 continue; /* XXX - had_error++ ? */
317 if (strcasecmp(tname
, bp
) != 0) {
319 continue; /* XXX - had_error++ ? */
321 n
= dn_expand(answer
->buf
, eom
, cp
, bp
, buflen
);
322 if ((n
< 0) || !res_hnok(bp
)) {
328 __set_h_errno (NO_RECOVERY
);
333 else if (ap
< &host_aliases
[MAXALIASES
-1])
338 n
= strlen(bp
) + 1; /* for the \0 */
339 if (n
>= MAXHOSTNAMELEN
) {
349 if (strcasecmp(host
.h_name
, bp
) != 0) {
351 continue; /* XXX - had_error++ ? */
353 if (n
!= host
.h_length
) {
361 nn
= strlen(bp
) + 1; /* for the \0 */
366 /* XXX: when incrementing bp, we have to decrement
367 * buflen by the same amount --okir */
368 buflen
-= sizeof(align
) - ((u_long
)bp
% sizeof(align
));
370 bp
+= sizeof(align
) - ((u_long
)bp
% sizeof(align
));
372 if (bp
+ n
>= &hostbuf
[sizeof hostbuf
]) {
373 Dprintf("size (%d) too big\n", n
);
377 if (hap
>= &h_addr_ptrs
[MAXADDRS
-1]) {
379 Dprintf("Too many addresses (%d)\n",
385 memmove(*hap
++ = bp
, cp
, n
);
390 __set_h_errno (NO_RECOVERY
);
404 * Note: we sort even if host can take only one address
405 * in its return structures - should give it the "best"
406 * address in that case, not some random one
408 if (_res
.nsort
&& haveanswer
> 1 && qtype
== T_A
)
409 addrsort(h_addr_ptrs
, haveanswer
);
411 n
= strlen(qname
) + 1; /* for the \0 */
412 if (n
> buflen
|| n
>= MAXHOSTNAMELEN
)
419 if (res_use_inet6 ())
420 map_v4v6_hostent(&host
, &bp
, &buflen
);
421 __set_h_errno (NETDB_SUCCESS
);
425 __set_h_errno (NO_RECOVERY
);
429 extern struct hostent
*res_gethostbyname2(const char *name
, int af
);
430 libresolv_hidden_proto (res_gethostbyname2
)
433 res_gethostbyname (const char *name
)
435 struct resolv_context
*ctx
= __resolv_context_get ();
438 __set_h_errno (NETDB_INTERNAL
);
442 if (res_use_inet6 ())
444 struct hostent
*hp
= res_gethostbyname2_context (ctx
, name
, AF_INET6
);
447 __resolv_context_put (ctx
);
451 struct hostent
*hp
= res_gethostbyname2_context (ctx
, name
, AF_INET
);
452 __resolv_context_put (ctx
);
455 compat_symbol (libresolv
, res_gethostbyname
, res_gethostbyname
, GLIBC_2_0
);
457 static struct hostent
*
458 res_gethostbyname2_context (struct resolv_context
*ctx
,
459 const char *name
, int af
)
469 int n
, size
, type
, len
;
482 __set_h_errno (NETDB_INTERNAL
);
483 __set_errno (EAFNOSUPPORT
);
487 host
.h_addrtype
= af
;
488 host
.h_length
= size
;
491 * if there aren't any dots, it could be a user-level alias.
492 * this is also done in res_query() since we are not the only
493 * function that looks up host names.
496 if (strchr (name
, '.') != NULL
497 && (cp
= __res_context_hostalias (ctx
, name
, abuf
, sizeof (abuf
))))
501 * disallow names consisting only of digits/dots, unless
504 if (isdigit(name
[0]))
505 for (cp
= name
;; ++cp
) {
510 * All-numeric, no dot at the end.
511 * Fake up a hostent as if we'd actually
514 if (inet_pton(af
, name
, host_addr
) <= 0) {
515 __set_h_errno (HOST_NOT_FOUND
);
518 strncpy(hostbuf
, name
, MAXDNAME
);
519 hostbuf
[MAXDNAME
] = '\0';
520 bp
= hostbuf
+ MAXDNAME
;
521 len
= sizeof hostbuf
- MAXDNAME
;
522 host
.h_name
= hostbuf
;
523 host
.h_aliases
= host_aliases
;
524 host_aliases
[0] = NULL
;
525 h_addr_ptrs
[0] = (char *)host_addr
;
526 h_addr_ptrs
[1] = NULL
;
527 host
.h_addr_list
= h_addr_ptrs
;
528 if (res_use_inet6 ())
529 map_v4v6_hostent(&host
, &bp
, &len
);
530 __set_h_errno (NETDB_SUCCESS
);
533 if (!isdigit(*cp
) && *cp
!= '.')
536 if ((isxdigit(name
[0]) && strchr(name
, ':') != NULL
) ||
538 for (cp
= name
;; ++cp
) {
543 * All-IPv6-legal, no dot at the end.
544 * Fake up a hostent as if we'd actually
547 if (inet_pton(af
, name
, host_addr
) <= 0) {
548 __set_h_errno (HOST_NOT_FOUND
);
551 strncpy(hostbuf
, name
, MAXDNAME
);
552 hostbuf
[MAXDNAME
] = '\0';
553 bp
= hostbuf
+ MAXDNAME
;
554 len
= sizeof hostbuf
- MAXDNAME
;
555 host
.h_name
= hostbuf
;
556 host
.h_aliases
= host_aliases
;
557 host_aliases
[0] = NULL
;
558 h_addr_ptrs
[0] = (char *)host_addr
;
559 h_addr_ptrs
[1] = NULL
;
560 host
.h_addr_list
= h_addr_ptrs
;
561 __set_h_errno (NETDB_SUCCESS
);
564 if (!isxdigit(*cp
) && *cp
!= ':' && *cp
!= '.')
568 buf
.buf
= origbuf
= (querybuf
*) alloca (1024);
570 if ((n
= __res_context_search
571 (ctx
, name
, C_IN
, type
, buf
.buf
->buf
, 1024,
572 &buf
.ptr
, NULL
, NULL
, NULL
, NULL
)) < 0) {
573 if (buf
.buf
!= origbuf
)
575 Dprintf("res_nsearch failed (%d)\n", n
);
576 if (errno
== ECONNREFUSED
)
577 return (_gethtbyname2(name
, af
));
580 ret
= getanswer(buf
.buf
, n
, name
, type
);
581 if (buf
.buf
!= origbuf
)
587 res_gethostbyname2 (const char *name
, int af
)
589 struct resolv_context
*ctx
= __resolv_context_get ();
592 __set_h_errno (NETDB_INTERNAL
);
595 struct hostent
*hp
= res_gethostbyname2_context (ctx
, name
, AF_INET
);
596 __resolv_context_put (ctx
);
599 libresolv_hidden_def (res_gethostbyname2
)
600 compat_symbol (libresolv
, res_gethostbyname2
, res_gethostbyname2
, GLIBC_2_0
);
602 static struct hostent
*
603 res_gethostbyaddr_context (struct resolv_context
*ctx
,
604 const void *addr
, socklen_t len
, int af
)
606 const u_char
*uaddr
= (const u_char
*)addr
;
607 static const u_char mapped
[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
608 static const u_char tunnelled
[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
618 char qbuf
[MAXDNAME
+1], *qp
= NULL
;
620 if (af
== AF_INET6
&& len
== IN6ADDRSZ
&&
621 (!memcmp(uaddr
, mapped
, sizeof mapped
) ||
622 !memcmp(uaddr
, tunnelled
, sizeof tunnelled
))) {
624 addr
+= sizeof mapped
;
625 uaddr
+= sizeof mapped
;
637 __set_errno (EAFNOSUPPORT
);
638 __set_h_errno (NETDB_INTERNAL
);
642 __set_errno (EINVAL
);
643 __set_h_errno (NETDB_INTERNAL
);
648 (void) sprintf(qbuf
, "%u.%u.%u.%u.in-addr.arpa",
656 for (n
= IN6ADDRSZ
- 1; n
>= 0; n
--) {
657 qp
+= sprintf(qp
, "%x.%x.",
659 (uaddr
[n
] >> 4) & 0xf);
661 strcpy(qp
, "ip6.arpa");
667 buf
.buf
= orig_buf
= (querybuf
*) alloca (1024);
669 n
= __res_context_query (ctx
, qbuf
, C_IN
, T_PTR
, buf
.buf
->buf
, 1024,
670 &buf
.ptr
, NULL
, NULL
, NULL
, NULL
);
672 if (buf
.buf
!= orig_buf
)
674 Dprintf("res_nquery failed (%d)\n", n
);
675 if (errno
== ECONNREFUSED
)
676 return (_gethtbyaddr(addr
, len
, af
));
679 hp
= getanswer(buf
.buf
, n
, qbuf
, T_PTR
);
680 if (buf
.buf
!= orig_buf
)
683 return (NULL
); /* h_errno was set by getanswer() */
686 memmove(host_addr
, addr
, len
);
687 h_addr_ptrs
[0] = (char *)host_addr
;
688 h_addr_ptrs
[1] = NULL
;
689 if (af
== AF_INET
&& res_use_inet6 ()) {
690 map_v4v6_address((char*)host_addr
, (char*)host_addr
);
691 hp
->h_addrtype
= AF_INET6
;
692 hp
->h_length
= IN6ADDRSZ
;
694 __set_h_errno (NETDB_SUCCESS
);
699 res_gethostbyaddr (const void *addr
, socklen_t len
, int af
)
701 struct resolv_context
*ctx
= __resolv_context_get ();
704 __set_h_errno (NETDB_INTERNAL
);
707 struct hostent
*hp
= res_gethostbyaddr_context (ctx
, addr
, len
, af
);
708 __resolv_context_put (ctx
);
711 compat_symbol (libresolv
, res_gethostbyaddr
, res_gethostbyaddr
, GLIBC_2_0
);
717 hostf
= fopen(_PATH_HOSTS
, "rce" );
722 libresolv_hidden_def (_sethtent
)
723 compat_symbol (libresolv
, _sethtent
, _sethtent
, GLIBC_2_0
);
728 if (hostf
&& !stayopen
) {
729 (void) fclose(hostf
);
741 if (!hostf
&& !(hostf
= fopen(_PATH_HOSTS
, "rce" ))) {
742 __set_h_errno (NETDB_INTERNAL
);
746 if (!(p
= fgets(hostbuf
, sizeof hostbuf
, hostf
))) {
747 __set_h_errno (HOST_NOT_FOUND
);
752 if (!(cp
= strpbrk(p
, "#\n")))
755 if (!(cp
= strpbrk(p
, " \t")))
758 if (inet_pton(AF_INET6
, p
, host_addr
) > 0) {
761 } else if (inet_pton(AF_INET
, p
, host_addr
) > 0) {
762 if (res_use_inet6 ()) {
763 map_v4v6_address((char*)host_addr
, (char*)host_addr
);
773 h_addr_ptrs
[0] = (char *)host_addr
;
774 h_addr_ptrs
[1] = NULL
;
775 host
.h_addr_list
= h_addr_ptrs
;
777 host
.h_addrtype
= af
;
778 while (*cp
== ' ' || *cp
== '\t')
781 q
= host
.h_aliases
= host_aliases
;
782 if ((cp
= strpbrk(cp
, " \t")))
785 if (*cp
== ' ' || *cp
== '\t') {
789 if (q
< &host_aliases
[MAXALIASES
- 1])
791 if ((cp
= strpbrk(cp
, " \t")))
795 __set_h_errno (NETDB_SUCCESS
);
798 libresolv_hidden_def (_gethtent
)
799 compat_symbol (libresolv
, _gethtent
, _gethtent
, GLIBC_2_0
);
802 _gethtbyname (const char *name
)
806 if (res_use_inet6 ()) {
807 hp
= _gethtbyname2(name
, AF_INET6
);
811 return (_gethtbyname2(name
, AF_INET
));
813 compat_symbol (libresolv
, _gethtbyname
, _gethtbyname
, GLIBC_2_0
);
816 _gethtbyname2 (const char *name
, int af
)
822 while ((p
= _gethtent())) {
823 if (p
->h_addrtype
!= af
)
825 if (strcasecmp(p
->h_name
, name
) == 0)
827 for (cp
= p
->h_aliases
; *cp
!= 0; cp
++)
828 if (strcasecmp(*cp
, name
) == 0)
835 libresolv_hidden_def (_gethtbyname2
)
836 compat_symbol (libresolv
, _gethtbyname2
, _gethtbyname2
, GLIBC_2_0
);
839 _gethtbyaddr (const char *addr
, size_t len
, int af
)
844 while ((p
= _gethtent()))
845 if (p
->h_addrtype
== af
&& !memcmp(p
->h_addr
, addr
, len
))
850 libresolv_hidden_def (_gethtbyaddr
)
851 compat_symbol (libresolv
, _gethtbyaddr
, _gethtbyaddr
, GLIBC_2_0
);
854 map_v4v6_address (const char *src
, char *dst
)
856 u_char
*p
= (u_char
*)dst
;
860 /* Stash a temporary copy so our caller can update in place. */
861 memcpy(tmp
, src
, INADDRSZ
);
862 /* Mark this ipv6 addr as a mapped ipv4. */
863 for (i
= 0; i
< 10; i
++)
867 /* Retrieve the saved copy and we're done. */
868 memcpy((void*)p
, tmp
, INADDRSZ
);
872 map_v4v6_hostent (struct hostent
*hp
, char **bpp
, int *lenp
)
876 if (hp
->h_addrtype
!= AF_INET
|| hp
->h_length
!= INADDRSZ
)
878 hp
->h_addrtype
= AF_INET6
;
879 hp
->h_length
= IN6ADDRSZ
;
880 for (ap
= hp
->h_addr_list
; *ap
; ap
++) {
881 int i
= sizeof(align
) - ((u_long
)*bpp
% sizeof(align
));
883 if (*lenp
< (i
+ IN6ADDRSZ
)) {
884 /* Out of memory. Truncate address list here. XXX */
890 map_v4v6_address(*ap
, *bpp
);
898 addrsort (char **ap
, int num
)
902 short aval
[MAXADDRS
];
906 for (i
= 0; i
< num
; i
++, p
++) {
907 for (j
= 0 ; (unsigned)j
< _res
.nsort
; j
++)
908 if (_res
.sort_list
[j
].addr
.s_addr
==
909 (((struct in_addr
*)(*p
))->s_addr
& _res
.sort_list
[j
].mask
))
912 if (needsort
== 0 && i
> 0 && j
< aval
[i
-1])
918 while (needsort
< num
) {
919 for (j
= needsort
- 1; j
>= 0; j
--) {
920 if (aval
[j
] > aval
[j
+1]) {
938 #endif /* SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_25) */