1 /* Copyright (C) 1996-2018 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Extended from original form by Ulrich Drepper <drepper@cygnus.com>, 1996.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
19 /* Parts of this file are plain copies of the file `gethtnamadr.c' from
20 the bind package and it has the following copyright. */
23 * ++Copyright++ 1985, 1988, 1993
25 * Copyright (c) 1985, 1988, 1993
26 * The Regents of the University of California. All rights reserved.
28 * Redistribution and use in source and binary forms, with or without
29 * modification, are permitted provided that the following conditions
31 * 1. Redistributions of source code must retain the above copyright
32 * notice, this list of conditions and the following disclaimer.
33 * 2. Redistributions in binary form must reproduce the above copyright
34 * notice, this list of conditions and the following disclaimer in the
35 * documentation and/or other materials provided with the distribution.
36 * 4. Neither the name of the University nor the names of its contributors
37 * may be used to endorse or promote products derived from this software
38 * without specific prior written permission.
40 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
41 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
44 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
54 * Permission to use, copy, modify, and distribute this software for any
55 * purpose with or without fee is hereby granted, provided that the above
56 * copyright notice and this permission notice appear in all copies, and that
57 * the name of Digital Equipment Corporation not be used in advertising or
58 * publicity pertaining to distribution of the document or software without
59 * specific, written prior permission.
61 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
62 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
63 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
64 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
65 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
66 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
67 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
83 #include <arpa/nameser.h>
85 #include <resolv/resolv-internal.h>
86 #include <resolv/resolv_context.h>
88 /* Get implementations of some internal functions. */
89 #include <resolv/mapv4v6addr.h>
90 #include <resolv/mapv4v6hostent.h>
95 # define MAXPACKET PACKETSZ
97 # define MAXPACKET 65536
99 /* As per RFC 1034 and 1035 a host name cannot exceed 255 octets in length. */
100 #ifdef MAXHOSTNAMELEN
101 # undef MAXHOSTNAMELEN
103 #define MAXHOSTNAMELEN 256
105 /* We need this time later. */
106 typedef union querybuf
109 u_char buf
[MAXPACKET
];
112 static enum nss_status
getanswer_r (struct resolv_context
*ctx
,
113 const querybuf
*answer
, int anslen
,
114 const char *qname
, int qtype
,
115 struct hostent
*result
, char *buffer
,
116 size_t buflen
, int *errnop
, int *h_errnop
,
117 int map
, int32_t *ttlp
, char **canonp
);
119 static enum nss_status
gaih_getanswer (const querybuf
*answer1
, int anslen1
,
120 const querybuf
*answer2
, int anslen2
,
122 struct gaih_addrtuple
**pat
,
123 char *buffer
, size_t buflen
,
124 int *errnop
, int *h_errnop
,
127 static enum nss_status
gethostbyname3_context (struct resolv_context
*ctx
,
128 const char *name
, int af
,
129 struct hostent
*result
,
130 char *buffer
, size_t buflen
,
131 int *errnop
, int *h_errnop
,
135 /* Return the expected RDATA length for an address record type (A or
138 rrtype_to_rdata_length (int type
)
153 _nss_dns_gethostbyname3_r (const char *name
, int af
, struct hostent
*result
,
154 char *buffer
, size_t buflen
, int *errnop
,
155 int *h_errnop
, int32_t *ttlp
, char **canonp
)
157 struct resolv_context
*ctx
= __resolv_context_get ();
161 *h_errnop
= NETDB_INTERNAL
;
162 return NSS_STATUS_UNAVAIL
;
164 enum nss_status status
= gethostbyname3_context
165 (ctx
, name
, af
, result
, buffer
, buflen
, errnop
, h_errnop
, ttlp
, canonp
);
166 __resolv_context_put (ctx
);
170 static enum nss_status
171 gethostbyname3_context (struct resolv_context
*ctx
,
172 const char *name
, int af
, struct hostent
*result
,
173 char *buffer
, size_t buflen
, int *errnop
,
174 int *h_errnop
, int32_t *ttlp
, char **canonp
)
181 querybuf
*orig_host_buffer
;
182 char tmp
[NS_MAXDNAME
];
187 enum nss_status status
;
200 *errnop
= EAFNOSUPPORT
;
201 return NSS_STATUS_UNAVAIL
;
204 result
->h_addrtype
= af
;
205 result
->h_length
= size
;
208 * if there aren't any dots, it could be a user-level alias.
209 * this is also done in res_query() since we are not the only
210 * function that looks up host names.
212 if (strchr (name
, '.') == NULL
213 && (cp
= __res_context_hostalias (ctx
, name
, tmp
, sizeof (tmp
))) != NULL
)
216 host_buffer
.buf
= orig_host_buffer
= (querybuf
*) alloca (1024);
218 n
= __res_context_search (ctx
, name
, C_IN
, type
, host_buffer
.buf
->buf
,
219 1024, &host_buffer
.ptr
, NULL
, NULL
, NULL
, NULL
);
225 status
= NSS_STATUS_TRYAGAIN
;
228 /* System has run out of file descriptors. */
231 h_errno
= NETDB_INTERNAL
;
235 status
= NSS_STATUS_UNAVAIL
;
238 status
= NSS_STATUS_NOTFOUND
;
242 if (h_errno
== TRY_AGAIN
)
245 __set_errno (olderr
);
247 /* If we are looking for an IPv6 address and mapping is enabled
248 by having the RES_USE_INET6 bit in _res.options set, we try
250 if (af
== AF_INET6
&& res_use_inet6 ())
251 n
= __res_context_search (ctx
, name
, C_IN
, T_A
, host_buffer
.buf
->buf
,
252 host_buffer
.buf
!= orig_host_buffer
253 ? MAXPACKET
: 1024, &host_buffer
.ptr
,
254 NULL
, NULL
, NULL
, NULL
);
258 if (host_buffer
.buf
!= orig_host_buffer
)
259 free (host_buffer
.buf
);
265 result
->h_addrtype
= AF_INET
;
266 result
->h_length
= INADDRSZ
;
270 (ctx
, host_buffer
.buf
, n
, name
, type
, result
, buffer
, buflen
,
271 errnop
, h_errnop
, map
, ttlp
, canonp
);
272 if (host_buffer
.buf
!= orig_host_buffer
)
273 free (host_buffer
.buf
);
278 _nss_dns_gethostbyname2_r (const char *name
, int af
, struct hostent
*result
,
279 char *buffer
, size_t buflen
, int *errnop
,
282 return _nss_dns_gethostbyname3_r (name
, af
, result
, buffer
, buflen
, errnop
,
283 h_errnop
, NULL
, NULL
);
288 _nss_dns_gethostbyname_r (const char *name
, struct hostent
*result
,
289 char *buffer
, size_t buflen
, int *errnop
,
292 struct resolv_context
*ctx
= __resolv_context_get ();
296 *h_errnop
= NETDB_INTERNAL
;
297 return NSS_STATUS_UNAVAIL
;
299 enum nss_status status
= NSS_STATUS_NOTFOUND
;
300 if (res_use_inet6 ())
301 status
= gethostbyname3_context (ctx
, name
, AF_INET6
, result
, buffer
,
302 buflen
, errnop
, h_errnop
, NULL
, NULL
);
303 if (status
== NSS_STATUS_NOTFOUND
)
304 status
= gethostbyname3_context (ctx
, name
, AF_INET
, result
, buffer
,
305 buflen
, errnop
, h_errnop
, NULL
, NULL
);
306 __resolv_context_put (ctx
);
312 _nss_dns_gethostbyname4_r (const char *name
, struct gaih_addrtuple
**pat
,
313 char *buffer
, size_t buflen
, int *errnop
,
314 int *herrnop
, int32_t *ttlp
)
316 struct resolv_context
*ctx
= __resolv_context_get ();
320 *herrnop
= NETDB_INTERNAL
;
321 return NSS_STATUS_UNAVAIL
;
325 * if there aren't any dots, it could be a user-level alias.
326 * this is also done in res_query() since we are not the only
327 * function that looks up host names.
329 if (strchr (name
, '.') == NULL
)
331 char *tmp
= alloca (NS_MAXDNAME
);
332 const char *cp
= __res_context_hostalias (ctx
, name
, tmp
, NS_MAXDNAME
);
342 querybuf
*orig_host_buffer
;
343 host_buffer
.buf
= orig_host_buffer
= (querybuf
*) alloca (2048);
344 u_char
*ans2p
= NULL
;
347 int ans2p_malloced
= 0;
350 enum nss_status status
;
351 int n
= __res_context_search (ctx
, name
, C_IN
, T_QUERY_A_AND_AAAA
,
352 host_buffer
.buf
->buf
, 2048, &host_buffer
.ptr
,
353 &ans2p
, &nans2p
, &resplen2
, &ans2p_malloced
);
356 status
= gaih_getanswer (host_buffer
.buf
, n
, (const querybuf
*) ans2p
,
357 resplen2
, name
, pat
, buffer
, buflen
,
358 errnop
, herrnop
, ttlp
);
365 status
= NSS_STATUS_TRYAGAIN
;
368 /* System has run out of file descriptors. */
371 h_errno
= NETDB_INTERNAL
;
375 status
= NSS_STATUS_UNAVAIL
;
378 status
= NSS_STATUS_NOTFOUND
;
383 if (h_errno
== TRY_AGAIN
)
386 __set_errno (olderr
);
389 /* Check whether ans2p was separately allocated. */
393 if (host_buffer
.buf
!= orig_host_buffer
)
394 free (host_buffer
.buf
);
396 __resolv_context_put (ctx
);
401 extern enum nss_status
_nss_dns_gethostbyaddr2_r (const void *addr
,
402 socklen_t len
, int af
,
403 struct hostent
*result
,
404 char *buffer
, size_t buflen
,
405 int *errnop
, int *h_errnop
,
407 hidden_proto (_nss_dns_gethostbyaddr2_r
)
410 _nss_dns_gethostbyaddr2_r (const void *addr
, socklen_t len
, int af
,
411 struct hostent
*result
, char *buffer
, size_t buflen
,
412 int *errnop
, int *h_errnop
, int32_t *ttlp
)
414 static const u_char mapped
[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
415 static const u_char tunnelled
[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
416 static const u_char v6local
[] = { 0,0, 0,1 };
417 const u_char
*uaddr
= (const u_char
*)addr
;
420 char *aliases
[MAX_NR_ALIASES
];
421 unsigned char host_addr
[16]; /* IPv4 or IPv6 */
422 char *h_addr_ptrs
[MAX_NR_ADDRS
+ 1];
424 } *host_data
= (struct host_data
*) buffer
;
430 querybuf
*orig_host_buffer
;
431 char qbuf
[MAXDNAME
+1], *qp
= NULL
;
436 uintptr_t pad
= -(uintptr_t) buffer
% __alignof__ (struct host_data
);
438 buflen
= buflen
> pad
? buflen
- pad
: 0;
440 if (__glibc_unlikely (buflen
< sizeof (struct host_data
)))
443 *h_errnop
= NETDB_INTERNAL
;
444 return NSS_STATUS_TRYAGAIN
;
447 host_data
= (struct host_data
*) buffer
;
449 struct resolv_context
*ctx
= __resolv_context_get ();
453 *h_errnop
= NETDB_INTERNAL
;
454 return NSS_STATUS_UNAVAIL
;
457 if (af
== AF_INET6
&& len
== IN6ADDRSZ
458 && (memcmp (uaddr
, mapped
, sizeof mapped
) == 0
459 || (memcmp (uaddr
, tunnelled
, sizeof tunnelled
) == 0
460 && memcmp (&uaddr
[sizeof tunnelled
], v6local
, sizeof v6local
))))
463 addr
+= sizeof mapped
;
464 uaddr
+= sizeof mapped
;
478 *errnop
= EAFNOSUPPORT
;
479 *h_errnop
= NETDB_INTERNAL
;
480 __resolv_context_put (ctx
);
481 return NSS_STATUS_UNAVAIL
;
485 *errnop
= EAFNOSUPPORT
;
486 *h_errnop
= NETDB_INTERNAL
;
487 __resolv_context_put (ctx
);
488 return NSS_STATUS_UNAVAIL
;
491 host_buffer
.buf
= orig_host_buffer
= (querybuf
*) alloca (1024);
496 sprintf (qbuf
, "%u.%u.%u.%u.in-addr.arpa", (uaddr
[3] & 0xff),
497 (uaddr
[2] & 0xff), (uaddr
[1] & 0xff), (uaddr
[0] & 0xff));
501 for (n
= IN6ADDRSZ
- 1; n
>= 0; n
--)
503 static const char nibblechar
[16] = "0123456789abcdef";
504 *qp
++ = nibblechar
[uaddr
[n
] & 0xf];
506 *qp
++ = nibblechar
[(uaddr
[n
] >> 4) & 0xf];
509 strcpy(qp
, "ip6.arpa");
516 n
= __res_context_query (ctx
, qbuf
, C_IN
, T_PTR
, host_buffer
.buf
->buf
,
517 1024, &host_buffer
.ptr
, NULL
, NULL
, NULL
, NULL
);
521 __set_errno (olderr
);
522 if (host_buffer
.buf
!= orig_host_buffer
)
523 free (host_buffer
.buf
);
524 __resolv_context_put (ctx
);
525 return errno
== ECONNREFUSED
? NSS_STATUS_UNAVAIL
: NSS_STATUS_NOTFOUND
;
529 (ctx
, host_buffer
.buf
, n
, qbuf
, T_PTR
, result
, buffer
, buflen
,
530 errnop
, h_errnop
, 0 /* XXX */, ttlp
, NULL
);
531 if (host_buffer
.buf
!= orig_host_buffer
)
532 free (host_buffer
.buf
);
533 if (status
!= NSS_STATUS_SUCCESS
)
535 __resolv_context_put (ctx
);
539 result
->h_addrtype
= af
;
540 result
->h_length
= len
;
541 memcpy (host_data
->host_addr
, addr
, len
);
542 host_data
->h_addr_ptrs
[0] = (char *) host_data
->host_addr
;
543 host_data
->h_addr_ptrs
[1] = NULL
;
544 *h_errnop
= NETDB_SUCCESS
;
545 __resolv_context_put (ctx
);
546 return NSS_STATUS_SUCCESS
;
548 hidden_def (_nss_dns_gethostbyaddr2_r
)
552 _nss_dns_gethostbyaddr_r (const void *addr
, socklen_t len
, int af
,
553 struct hostent
*result
, char *buffer
, size_t buflen
,
554 int *errnop
, int *h_errnop
)
556 return _nss_dns_gethostbyaddr2_r (addr
, len
, af
, result
, buffer
, buflen
,
557 errnop
, h_errnop
, NULL
);
561 addrsort (struct resolv_context
*ctx
, char **ap
, int num
)
565 short aval
[MAX_NR_ADDRS
];
567 size_t nsort
= __resolv_context_sort_count (ctx
);
570 if (num
> MAX_NR_ADDRS
)
572 for (i
= 0; i
< num
; i
++, p
++)
574 for (j
= 0 ; (unsigned)j
< nsort
; j
++)
576 struct resolv_sortlist_entry e
577 = __resolv_context_sort_entry (ctx
, j
);
578 if (e
.addr
.s_addr
== (((struct in_addr
*)(*p
))->s_addr
& e
.mask
))
582 if (needsort
== 0 && i
> 0 && j
< aval
[i
-1])
588 while (needsort
++ < num
)
589 for (j
= needsort
- 2; j
>= 0; j
--)
590 if (aval
[j
] > aval
[j
+1])
606 static enum nss_status
607 getanswer_r (struct resolv_context
*ctx
,
608 const querybuf
*answer
, int anslen
, const char *qname
, int qtype
,
609 struct hostent
*result
, char *buffer
, size_t buflen
,
610 int *errnop
, int *h_errnop
, int map
, int32_t *ttlp
, char **canonp
)
614 char *aliases
[MAX_NR_ALIASES
];
615 unsigned char host_addr
[16]; /* IPv4 or IPv6 */
616 char *h_addr_ptrs
[0];
620 const u_char
*end_of_message
, *cp
;
621 int n
, ancount
, qdcount
;
622 int haveanswer
, had_error
;
623 char *bp
, **ap
, **hap
;
626 int (*name_ok
) (const char *);
627 u_char packtmp
[NS_MAXCDNAME
];
629 uintptr_t pad
= -(uintptr_t) buffer
% __alignof__ (struct host_data
);
631 buflen
= buflen
> pad
? buflen
- pad
: 0;
632 if (__glibc_unlikely (buflen
< sizeof (struct host_data
)))
634 /* The buffer is too small. */
637 *h_errnop
= NETDB_INTERNAL
;
638 return NSS_STATUS_TRYAGAIN
;
640 host_data
= (struct host_data
*) buffer
;
641 linebuflen
= buflen
- sizeof (struct host_data
);
642 if (buflen
- sizeof (struct host_data
) != linebuflen
)
643 linebuflen
= INT_MAX
;
646 result
->h_name
= NULL
;
647 end_of_message
= answer
->buf
+ anslen
;
659 return NSS_STATUS_UNAVAIL
; /* XXX should be abort(); */
663 * find first satisfactory answer
666 ancount
= ntohs (hp
->ancount
);
667 qdcount
= ntohs (hp
->qdcount
);
668 cp
= answer
->buf
+ HFIXEDSZ
;
669 if (__glibc_unlikely (qdcount
!= 1))
671 *h_errnop
= NO_RECOVERY
;
672 return NSS_STATUS_UNAVAIL
;
674 if (sizeof (struct host_data
) + (ancount
+ 1) * sizeof (char *) >= buflen
)
676 bp
= (char *) &host_data
->h_addr_ptrs
[ancount
+ 1];
677 linebuflen
-= (ancount
+ 1) * sizeof (char *);
679 n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
680 packtmp
, sizeof packtmp
);
681 if (n
!= -1 && __ns_name_ntop (packtmp
, bp
, linebuflen
) == -1)
683 if (__glibc_unlikely (errno
== EMSGSIZE
))
689 if (n
> 0 && bp
[0] == '.')
692 if (__glibc_unlikely (n
< 0))
695 *h_errnop
= NO_RECOVERY
;
696 return NSS_STATUS_UNAVAIL
;
698 if (__glibc_unlikely (name_ok (bp
) == 0))
702 *h_errnop
= NO_RECOVERY
;
703 return NSS_STATUS_UNAVAIL
;
707 if (qtype
== T_A
|| qtype
== T_AAAA
)
709 /* res_send() has already verified that the query name is the
710 * same as the one we sent; this just gets the expanded name
711 * (i.e., with the succeeding search-domain tacked on).
713 n
= strlen (bp
) + 1; /* for the \0 */
714 if (n
>= MAXHOSTNAMELEN
)
716 *h_errnop
= NO_RECOVERY
;
718 return NSS_STATUS_TRYAGAIN
;
725 /* The qname can be abbreviated, but h_name is now absolute. */
726 qname
= result
->h_name
;
729 ap
= host_data
->aliases
;
731 result
->h_aliases
= host_data
->aliases
;
732 hap
= host_data
->h_addr_ptrs
;
734 result
->h_addr_list
= host_data
->h_addr_ptrs
;
738 while (ancount
-- > 0 && cp
< end_of_message
&& had_error
== 0)
742 n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
743 packtmp
, sizeof packtmp
);
744 if (n
!= -1 && __ns_name_ntop (packtmp
, bp
, linebuflen
) == -1)
746 if (__glibc_unlikely (errno
== EMSGSIZE
))
752 if (__glibc_unlikely (n
< 0 || (*name_ok
) (bp
) == 0))
759 if (__glibc_unlikely (cp
+ 10 > end_of_message
))
765 type
= __ns_get16 (cp
);
766 cp
+= INT16SZ
; /* type */
767 class = __ns_get16 (cp
);
768 cp
+= INT16SZ
; /* class */
769 int32_t ttl
= __ns_get32 (cp
);
770 cp
+= INT32SZ
; /* TTL */
772 cp
+= INT16SZ
; /* len */
774 if (end_of_message
- cp
< n
)
776 /* RDATA extends beyond the end of the packet. */
781 if (__glibc_unlikely (class != C_IN
))
783 /* XXX - debug? syslog? */
785 continue; /* XXX - had_error++ ? */
788 if ((qtype
== T_A
|| qtype
== T_AAAA
) && type
== T_CNAME
)
790 /* A CNAME could also have a TTL entry. */
791 if (ttlp
!= NULL
&& ttl
< *ttlp
)
794 if (ap
>= &host_data
->aliases
[MAX_NR_ALIASES
- 1])
796 n
= dn_expand (answer
->buf
, end_of_message
, cp
, tbuf
, sizeof tbuf
);
797 if (__glibc_unlikely (n
< 0 || (*name_ok
) (tbuf
) == 0))
805 n
= strlen (bp
) + 1; /* For the \0. */
806 if (__glibc_unlikely (n
>= MAXHOSTNAMELEN
))
813 /* Get canonical name. */
814 n
= strlen (tbuf
) + 1; /* For the \0. */
815 if (__glibc_unlikely (n
> linebuflen
))
817 if (__glibc_unlikely (n
>= MAXHOSTNAMELEN
))
823 bp
= __mempcpy (bp
, tbuf
, n
); /* Cannot overflow. */
828 if (qtype
== T_PTR
&& type
== T_CNAME
)
830 /* A CNAME could also have a TTL entry. */
831 if (ttlp
!= NULL
&& ttl
< *ttlp
)
834 n
= dn_expand (answer
->buf
, end_of_message
, cp
, tbuf
, sizeof tbuf
);
835 if (__glibc_unlikely (n
< 0 || res_dnok (tbuf
) == 0))
841 /* Get canonical name. */
842 n
= strlen (tbuf
) + 1; /* For the \0. */
843 if (__glibc_unlikely (n
> linebuflen
))
845 if (__glibc_unlikely (n
>= MAXHOSTNAMELEN
))
851 bp
= __mempcpy (bp
, tbuf
, n
); /* Cannot overflow. */
856 if (type
== T_A
&& qtype
== T_AAAA
&& map
)
858 else if (__glibc_unlikely (type
!= qtype
))
861 continue; /* XXX - had_error++ ? */
867 if (__glibc_unlikely (strcasecmp (tname
, bp
) != 0))
870 continue; /* XXX - had_error++ ? */
873 n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
874 packtmp
, sizeof packtmp
);
875 if (n
!= -1 && __ns_name_ntop (packtmp
, bp
, linebuflen
) == -1)
877 if (__glibc_unlikely (errno
== EMSGSIZE
))
883 if (__glibc_unlikely (n
< 0 || res_hnok (bp
) == 0))
888 if (ttlp
!= NULL
&& ttl
< *ttlp
)
890 /* bind would put multiple PTR records as aliases, but we don't do
893 *h_errnop
= NETDB_SUCCESS
;
894 return NSS_STATUS_SUCCESS
;
897 if (__glibc_unlikely (strcasecmp (result
->h_name
, bp
) != 0))
900 continue; /* XXX - had_error++ ? */
903 /* Stop parsing at a record whose length is incorrect. */
904 if (n
!= rrtype_to_rdata_length (type
))
910 /* Skip records of the wrong type. */
911 if (n
!= result
->h_length
)
920 /* We compose a single hostent out of the entire chain of
921 entries, so the TTL of the hostent is essentially the lowest
923 if (ttlp
!= NULL
&& ttl
< *ttlp
)
928 nn
= strlen (bp
) + 1; /* for the \0 */
933 linebuflen
-= sizeof (align
) - ((u_long
) bp
% sizeof (align
));
934 bp
+= sizeof (align
) - ((u_long
) bp
% sizeof (align
));
936 if (__glibc_unlikely (n
> linebuflen
))
938 bp
= __mempcpy (*hap
++ = bp
, cp
, n
);
954 * Note: we sort even if host can take only one address
955 * in its return structures - should give it the "best"
956 * address in that case, not some random one
958 if (haveanswer
> 1 && qtype
== T_A
959 && __resolv_context_sort_count (ctx
) > 0)
960 addrsort (ctx
, host_data
->h_addr_ptrs
, haveanswer
);
962 if (result
->h_name
== NULL
)
964 n
= strlen (qname
) + 1; /* For the \0. */
967 if (n
>= MAXHOSTNAMELEN
)
970 bp
= __mempcpy (bp
, qname
, n
); /* Cannot overflow. */
975 if (map_v4v6_hostent (result
, &bp
, &linebuflen
))
977 *h_errnop
= NETDB_SUCCESS
;
978 return NSS_STATUS_SUCCESS
;
981 *h_errnop
= NO_RECOVERY
;
983 /* Special case here: if the resolver sent a result but it only
984 contains a CNAME while we are looking for a T_A or T_AAAA record,
985 we fail with NOTFOUND instead of TRYAGAIN. */
986 return ((qtype
== T_A
|| qtype
== T_AAAA
) && ap
!= host_data
->aliases
987 ? NSS_STATUS_NOTFOUND
: NSS_STATUS_TRYAGAIN
);
991 static enum nss_status
992 gaih_getanswer_slice (const querybuf
*answer
, int anslen
, const char *qname
,
993 struct gaih_addrtuple
***patp
,
994 char **bufferp
, size_t *buflenp
,
995 int *errnop
, int *h_errnop
, int32_t *ttlp
, int *firstp
)
997 char *buffer
= *bufferp
;
998 size_t buflen
= *buflenp
;
1000 struct gaih_addrtuple
**pat
= *patp
;
1001 const HEADER
*hp
= &answer
->hdr
;
1002 int ancount
= ntohs (hp
->ancount
);
1003 int qdcount
= ntohs (hp
->qdcount
);
1004 const u_char
*cp
= answer
->buf
+ HFIXEDSZ
;
1005 const u_char
*end_of_message
= answer
->buf
+ anslen
;
1006 if (__glibc_unlikely (qdcount
!= 1))
1008 *h_errnop
= NO_RECOVERY
;
1009 return NSS_STATUS_UNAVAIL
;
1012 u_char packtmp
[NS_MAXCDNAME
];
1013 int n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
1014 packtmp
, sizeof packtmp
);
1015 /* We unpack the name to check it for validity. But we do not need
1017 if (n
!= -1 && __ns_name_ntop (packtmp
, buffer
, buflen
) == -1)
1019 if (__glibc_unlikely (errno
== EMSGSIZE
))
1023 *h_errnop
= NETDB_INTERNAL
;
1024 return NSS_STATUS_TRYAGAIN
;
1030 if (__glibc_unlikely (n
< 0))
1033 *h_errnop
= NO_RECOVERY
;
1034 return NSS_STATUS_UNAVAIL
;
1036 if (__glibc_unlikely (res_hnok (buffer
) == 0))
1040 *h_errnop
= NO_RECOVERY
;
1041 return NSS_STATUS_UNAVAIL
;
1048 char *h_name
= NULL
;
1053 *h_errnop
= HOST_NOT_FOUND
;
1054 return NSS_STATUS_NOTFOUND
;
1057 while (ancount
-- > 0 && cp
< end_of_message
&& had_error
== 0)
1059 n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
1060 packtmp
, sizeof packtmp
);
1062 (h_namelen
= __ns_name_ntop (packtmp
, buffer
, buflen
)) == -1)
1064 if (__glibc_unlikely (errno
== EMSGSIZE
))
1069 if (__glibc_unlikely (n
< 0 || res_hnok (buffer
) == 0))
1074 if (*firstp
&& canon
== NULL
)
1077 buffer
+= h_namelen
;
1078 buflen
-= h_namelen
;
1083 if (__glibc_unlikely (cp
+ 10 > end_of_message
))
1089 int type
= __ns_get16 (cp
);
1090 cp
+= INT16SZ
; /* type */
1091 int class = __ns_get16 (cp
);
1092 cp
+= INT16SZ
; /* class */
1093 int32_t ttl
= __ns_get32 (cp
);
1094 cp
+= INT32SZ
; /* TTL */
1095 n
= __ns_get16 (cp
);
1096 cp
+= INT16SZ
; /* len */
1098 if (end_of_message
- cp
< n
)
1100 /* RDATA extends beyond the end of the packet. */
1111 if (type
== T_CNAME
)
1113 char tbuf
[MAXDNAME
];
1115 /* A CNAME could also have a TTL entry. */
1116 if (ttlp
!= NULL
&& ttl
< *ttlp
)
1119 n
= dn_expand (answer
->buf
, end_of_message
, cp
, tbuf
, sizeof tbuf
);
1120 if (__glibc_unlikely (n
< 0 || res_hnok (tbuf
) == 0))
1129 /* Reclaim buffer space. */
1130 if (h_name
+ h_namelen
== buffer
)
1133 buflen
+= h_namelen
;
1136 n
= strlen (tbuf
) + 1;
1137 if (__glibc_unlikely (n
> buflen
))
1139 if (__glibc_unlikely (n
>= MAXHOSTNAMELEN
))
1146 buffer
= __mempcpy (buffer
, tbuf
, n
);
1153 /* Stop parsing if we encounter a record with incorrect RDATA
1155 if (type
== T_A
|| type
== T_AAAA
)
1157 if (n
!= rrtype_to_rdata_length (type
))
1165 /* Skip unknown records. */
1170 assert (type
== T_A
|| type
== T_AAAA
);
1173 uintptr_t pad
= (-(uintptr_t) buffer
1174 % __alignof__ (struct gaih_addrtuple
));
1176 buflen
= buflen
> pad
? buflen
- pad
: 0;
1178 if (__glibc_unlikely (buflen
< sizeof (struct gaih_addrtuple
)))
1181 *pat
= (struct gaih_addrtuple
*) buffer
;
1182 buffer
+= sizeof (struct gaih_addrtuple
);
1183 buflen
-= sizeof (struct gaih_addrtuple
);
1186 (*pat
)->name
= NULL
;
1187 (*pat
)->next
= NULL
;
1191 /* We compose a single hostent out of the entire chain of
1192 entries, so the TTL of the hostent is essentially the lowest
1193 TTL in the chain. */
1194 if (ttlp
!= NULL
&& ttl
< *ttlp
)
1197 (*pat
)->name
= canon
?: h_name
;
1202 (*pat
)->family
= type
== T_A
? AF_INET
: AF_INET6
;
1203 memcpy ((*pat
)->addr
, cp
, n
);
1205 (*pat
)->scopeid
= 0;
1207 pat
= &((*pat
)->next
);
1218 *h_errnop
= NETDB_SUCCESS
;
1219 return NSS_STATUS_SUCCESS
;
1222 /* Special case here: if the resolver sent a result but it only
1223 contains a CNAME while we are looking for a T_A or T_AAAA record,
1224 we fail with NOTFOUND instead of TRYAGAIN. */
1227 *h_errnop
= HOST_NOT_FOUND
;
1228 return NSS_STATUS_NOTFOUND
;
1231 *h_errnop
= NETDB_INTERNAL
;
1232 return NSS_STATUS_TRYAGAIN
;
1236 static enum nss_status
1237 gaih_getanswer (const querybuf
*answer1
, int anslen1
, const querybuf
*answer2
,
1238 int anslen2
, const char *qname
,
1239 struct gaih_addrtuple
**pat
, char *buffer
, size_t buflen
,
1240 int *errnop
, int *h_errnop
, int32_t *ttlp
)
1244 enum nss_status status
= NSS_STATUS_NOTFOUND
;
1246 /* Combining the NSS status of two distinct queries requires some
1247 compromise and attention to symmetry (A or AAAA queries can be
1248 returned in any order). What follows is a breakdown of how this
1249 code is expected to work and why. We discuss only SUCCESS,
1250 TRYAGAIN, NOTFOUND and UNAVAIL, since they are the only returns
1251 that apply (though RETURN and MERGE exist). We make a distinction
1252 between TRYAGAIN (recoverable) and TRYAGAIN' (not-recoverable).
1253 A recoverable TRYAGAIN is almost always due to buffer size issues
1254 and returns ERANGE in errno and the caller is expected to retry
1255 with a larger buffer.
1257 Lastly, you may be tempted to make significant changes to the
1258 conditions in this code to bring about symmetry between responses.
1259 Please don't change anything without due consideration for
1260 expected application behaviour. Some of the synthesized responses
1261 aren't very well thought out and sometimes appear to imply that
1262 IPv4 responses are always answer 1, and IPv6 responses are always
1263 answer 2, but that's not true (see the implementation of send_dg
1264 and send_vc to see response can arrive in any order, particularly
1265 for UDP). However, we expect it holds roughly enough of the time
1266 that this code works, but certainly needs to be fixed to make this
1267 a more robust implementation.
1269 ----------------------------------------------
1270 | Answer 1 Status / | Synthesized | Reason |
1271 | Answer 2 Status | Status | |
1272 |--------------------------------------------|
1273 | SUCCESS/SUCCESS | SUCCESS | [1] |
1274 | SUCCESS/TRYAGAIN | TRYAGAIN | [5] |
1275 | SUCCESS/TRYAGAIN' | SUCCESS | [1] |
1276 | SUCCESS/NOTFOUND | SUCCESS | [1] |
1277 | SUCCESS/UNAVAIL | SUCCESS | [1] |
1278 | TRYAGAIN/SUCCESS | TRYAGAIN | [2] |
1279 | TRYAGAIN/TRYAGAIN | TRYAGAIN | [2] |
1280 | TRYAGAIN/TRYAGAIN' | TRYAGAIN | [2] |
1281 | TRYAGAIN/NOTFOUND | TRYAGAIN | [2] |
1282 | TRYAGAIN/UNAVAIL | TRYAGAIN | [2] |
1283 | TRYAGAIN'/SUCCESS | SUCCESS | [3] |
1284 | TRYAGAIN'/TRYAGAIN | TRYAGAIN | [3] |
1285 | TRYAGAIN'/TRYAGAIN' | TRYAGAIN' | [3] |
1286 | TRYAGAIN'/NOTFOUND | TRYAGAIN' | [3] |
1287 | TRYAGAIN'/UNAVAIL | UNAVAIL | [3] |
1288 | NOTFOUND/SUCCESS | SUCCESS | [3] |
1289 | NOTFOUND/TRYAGAIN | TRYAGAIN | [3] |
1290 | NOTFOUND/TRYAGAIN' | TRYAGAIN' | [3] |
1291 | NOTFOUND/NOTFOUND | NOTFOUND | [3] |
1292 | NOTFOUND/UNAVAIL | UNAVAIL | [3] |
1293 | UNAVAIL/SUCCESS | UNAVAIL | [4] |
1294 | UNAVAIL/TRYAGAIN | UNAVAIL | [4] |
1295 | UNAVAIL/TRYAGAIN' | UNAVAIL | [4] |
1296 | UNAVAIL/NOTFOUND | UNAVAIL | [4] |
1297 | UNAVAIL/UNAVAIL | UNAVAIL | [4] |
1298 ----------------------------------------------
1300 [1] If the first response is a success we return success.
1301 This ignores the state of the second answer and in fact
1302 incorrectly sets errno and h_errno to that of the second
1303 answer. However because the response is a success we ignore
1304 *errnop and *h_errnop (though that means you touched errno on
1305 success). We are being conservative here and returning the
1306 likely IPv4 response in the first answer as a success.
1308 [2] If the first response is a recoverable TRYAGAIN we return
1309 that instead of looking at the second response. The
1310 expectation here is that we have failed to get an IPv4 response
1311 and should retry both queries.
1313 [3] If the first response was not a SUCCESS and the second
1314 response is not NOTFOUND (had a SUCCESS, need to TRYAGAIN,
1315 or failed entirely e.g. TRYAGAIN' and UNAVAIL) then use the
1316 result from the second response, otherwise the first responses
1317 status is used. Again we have some odd side-effects when the
1318 second response is NOTFOUND because we overwrite *errnop and
1319 *h_errnop that means that a first answer of NOTFOUND might see
1320 its *errnop and *h_errnop values altered. Whether it matters
1321 in practice that a first response NOTFOUND has the wrong
1322 *errnop and *h_errnop is undecided.
1324 [4] If the first response is UNAVAIL we return that instead of
1325 looking at the second response. The expectation here is that
1326 it will have failed similarly e.g. configuration failure.
1328 [5] Testing this code is complicated by the fact that truncated
1329 second response buffers might be returned as SUCCESS if the
1330 first answer is a SUCCESS. To fix this we add symmetry to
1331 TRYAGAIN with the second response. If the second response
1332 is a recoverable error we now return TRYAGIN even if the first
1333 response was SUCCESS. */
1336 status
= gaih_getanswer_slice(answer1
, anslen1
, qname
,
1337 &pat
, &buffer
, &buflen
,
1338 errnop
, h_errnop
, ttlp
,
1341 if ((status
== NSS_STATUS_SUCCESS
|| status
== NSS_STATUS_NOTFOUND
1342 || (status
== NSS_STATUS_TRYAGAIN
1343 /* We want to look at the second answer in case of an
1344 NSS_STATUS_TRYAGAIN only if the error is non-recoverable, i.e.
1345 *h_errnop is NO_RECOVERY. If not, and if the failure was due to
1346 an insufficient buffer (ERANGE), then we need to drop the results
1347 and pass on the NSS_STATUS_TRYAGAIN to the caller so that it can
1348 repeat the query with a larger buffer. */
1349 && (*errnop
!= ERANGE
|| *h_errnop
== NO_RECOVERY
)))
1350 && answer2
!= NULL
&& anslen2
> 0)
1352 enum nss_status status2
= gaih_getanswer_slice(answer2
, anslen2
, qname
,
1353 &pat
, &buffer
, &buflen
,
1354 errnop
, h_errnop
, ttlp
,
1356 /* Use the second response status in some cases. */
1357 if (status
!= NSS_STATUS_SUCCESS
&& status2
!= NSS_STATUS_NOTFOUND
)
1359 /* Do not return a truncated second response (unless it was
1360 unavoidable e.g. unrecoverable TRYAGAIN). */
1361 if (status
== NSS_STATUS_SUCCESS
1362 && (status2
== NSS_STATUS_TRYAGAIN
1363 && *errnop
== ERANGE
&& *h_errnop
!= NO_RECOVERY
))
1364 status
= NSS_STATUS_TRYAGAIN
;