1 /* Copyright (C) 1996-2021 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 <https://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
81 #include <libc-pointer-arith.h>
84 #include <arpa/nameser.h>
87 #include <resolv/resolv-internal.h>
88 #include <resolv/resolv_context.h>
90 /* Get implementations of some internal functions. */
91 #include <resolv/mapv4v6addr.h>
92 #include <resolv/mapv4v6hostent.h>
97 # define MAXPACKET PACKETSZ
99 # define MAXPACKET 65536
101 /* As per RFC 1034 and 1035 a host name cannot exceed 255 octets in length. */
102 #ifdef MAXHOSTNAMELEN
103 # undef MAXHOSTNAMELEN
105 #define MAXHOSTNAMELEN 256
107 /* We need this time later. */
108 typedef union querybuf
111 u_char buf
[MAXPACKET
];
114 static enum nss_status
getanswer_r (struct resolv_context
*ctx
,
115 const querybuf
*answer
, int anslen
,
116 const char *qname
, int qtype
,
117 struct hostent
*result
, char *buffer
,
118 size_t buflen
, int *errnop
, int *h_errnop
,
119 int map
, int32_t *ttlp
, char **canonp
);
121 static enum nss_status
gaih_getanswer (const querybuf
*answer1
, int anslen1
,
122 const querybuf
*answer2
, int anslen2
,
124 struct gaih_addrtuple
**pat
,
125 char *buffer
, size_t buflen
,
126 int *errnop
, int *h_errnop
,
129 static enum nss_status
gethostbyname3_context (struct resolv_context
*ctx
,
130 const char *name
, int af
,
131 struct hostent
*result
,
132 char *buffer
, size_t buflen
,
133 int *errnop
, int *h_errnop
,
137 /* Return the expected RDATA length for an address record type (A or
140 rrtype_to_rdata_length (int type
)
155 _nss_dns_gethostbyname3_r (const char *name
, int af
, struct hostent
*result
,
156 char *buffer
, size_t buflen
, int *errnop
,
157 int *h_errnop
, int32_t *ttlp
, char **canonp
)
159 struct resolv_context
*ctx
= __resolv_context_get ();
163 *h_errnop
= NETDB_INTERNAL
;
164 return NSS_STATUS_UNAVAIL
;
166 enum nss_status status
= gethostbyname3_context
167 (ctx
, name
, af
, result
, buffer
, buflen
, errnop
, h_errnop
, ttlp
, canonp
);
168 __resolv_context_put (ctx
);
171 libc_hidden_def (_nss_dns_gethostbyname3_r
)
173 static enum nss_status
174 gethostbyname3_context (struct resolv_context
*ctx
,
175 const char *name
, int af
, struct hostent
*result
,
176 char *buffer
, size_t buflen
, int *errnop
,
177 int *h_errnop
, int32_t *ttlp
, char **canonp
)
184 querybuf
*orig_host_buffer
;
185 char tmp
[NS_MAXDNAME
];
190 enum nss_status status
;
203 *errnop
= EAFNOSUPPORT
;
204 return NSS_STATUS_UNAVAIL
;
207 result
->h_addrtype
= af
;
208 result
->h_length
= size
;
211 * if there aren't any dots, it could be a user-level alias.
212 * this is also done in res_query() since we are not the only
213 * function that looks up host names.
215 if (strchr (name
, '.') == NULL
216 && (cp
= __res_context_hostalias (ctx
, name
, tmp
, sizeof (tmp
))) != NULL
)
219 host_buffer
.buf
= orig_host_buffer
= (querybuf
*) alloca (1024);
221 n
= __res_context_search (ctx
, name
, C_IN
, type
, host_buffer
.buf
->buf
,
222 1024, &host_buffer
.ptr
, NULL
, NULL
, NULL
, NULL
);
228 status
= NSS_STATUS_TRYAGAIN
;
231 /* System has run out of file descriptors. */
234 h_errno
= NETDB_INTERNAL
;
238 status
= NSS_STATUS_UNAVAIL
;
241 status
= NSS_STATUS_NOTFOUND
;
245 if (h_errno
== TRY_AGAIN
)
248 __set_errno (olderr
);
250 /* If we are looking for an IPv6 address and mapping is enabled
251 by having the RES_USE_INET6 bit in _res.options set, we try
253 if (af
== AF_INET6
&& res_use_inet6 ())
254 n
= __res_context_search (ctx
, name
, C_IN
, T_A
, host_buffer
.buf
->buf
,
255 host_buffer
.buf
!= orig_host_buffer
256 ? MAXPACKET
: 1024, &host_buffer
.ptr
,
257 NULL
, NULL
, NULL
, NULL
);
261 if (host_buffer
.buf
!= orig_host_buffer
)
262 free (host_buffer
.buf
);
268 result
->h_addrtype
= AF_INET
;
269 result
->h_length
= INADDRSZ
;
273 (ctx
, host_buffer
.buf
, n
, name
, type
, result
, buffer
, buflen
,
274 errnop
, h_errnop
, map
, ttlp
, canonp
);
275 if (host_buffer
.buf
!= orig_host_buffer
)
276 free (host_buffer
.buf
);
280 /* Verify that the name looks like a host name. There is no point in
281 sending a query which will not produce a usable name in the
283 static enum nss_status
284 check_name (const char *name
, int *h_errnop
)
286 if (__libc_res_hnok (name
))
287 return NSS_STATUS_SUCCESS
;
288 *h_errnop
= HOST_NOT_FOUND
;
289 return NSS_STATUS_NOTFOUND
;
293 _nss_dns_gethostbyname2_r (const char *name
, int af
, struct hostent
*result
,
294 char *buffer
, size_t buflen
, int *errnop
,
297 enum nss_status status
= check_name (name
, h_errnop
);
298 if (status
!= NSS_STATUS_SUCCESS
)
300 return _nss_dns_gethostbyname3_r (name
, af
, result
, buffer
, buflen
, errnop
,
301 h_errnop
, NULL
, NULL
);
303 libc_hidden_def (_nss_dns_gethostbyname2_r
)
306 _nss_dns_gethostbyname_r (const char *name
, struct hostent
*result
,
307 char *buffer
, size_t buflen
, int *errnop
,
310 enum nss_status status
= check_name (name
, h_errnop
);
311 if (status
!= NSS_STATUS_SUCCESS
)
313 struct resolv_context
*ctx
= __resolv_context_get ();
317 *h_errnop
= NETDB_INTERNAL
;
318 return NSS_STATUS_UNAVAIL
;
320 status
= NSS_STATUS_NOTFOUND
;
321 if (res_use_inet6 ())
322 status
= gethostbyname3_context (ctx
, name
, AF_INET6
, result
, buffer
,
323 buflen
, errnop
, h_errnop
, NULL
, NULL
);
324 if (status
== NSS_STATUS_NOTFOUND
)
325 status
= gethostbyname3_context (ctx
, name
, AF_INET
, result
, buffer
,
326 buflen
, errnop
, h_errnop
, NULL
, NULL
);
327 __resolv_context_put (ctx
);
330 libc_hidden_def (_nss_dns_gethostbyname_r
)
333 _nss_dns_gethostbyname4_r (const char *name
, struct gaih_addrtuple
**pat
,
334 char *buffer
, size_t buflen
, int *errnop
,
335 int *herrnop
, int32_t *ttlp
)
337 enum nss_status status
= check_name (name
, herrnop
);
338 if (status
!= NSS_STATUS_SUCCESS
)
340 struct resolv_context
*ctx
= __resolv_context_get ();
344 *herrnop
= NETDB_INTERNAL
;
345 return NSS_STATUS_UNAVAIL
;
349 * if there aren't any dots, it could be a user-level alias.
350 * this is also done in res_query() since we are not the only
351 * function that looks up host names.
353 if (strchr (name
, '.') == NULL
)
355 char *tmp
= alloca (NS_MAXDNAME
);
356 const char *cp
= __res_context_hostalias (ctx
, name
, tmp
, NS_MAXDNAME
);
366 querybuf
*orig_host_buffer
;
367 host_buffer
.buf
= orig_host_buffer
= (querybuf
*) alloca (2048);
368 u_char
*ans2p
= NULL
;
371 int ans2p_malloced
= 0;
374 int n
= __res_context_search (ctx
, name
, C_IN
, T_QUERY_A_AND_AAAA
,
375 host_buffer
.buf
->buf
, 2048, &host_buffer
.ptr
,
376 &ans2p
, &nans2p
, &resplen2
, &ans2p_malloced
);
379 status
= gaih_getanswer (host_buffer
.buf
, n
, (const querybuf
*) ans2p
,
380 resplen2
, name
, pat
, buffer
, buflen
,
381 errnop
, herrnop
, ttlp
);
388 status
= NSS_STATUS_TRYAGAIN
;
391 /* System has run out of file descriptors. */
394 h_errno
= NETDB_INTERNAL
;
398 status
= NSS_STATUS_UNAVAIL
;
401 status
= NSS_STATUS_NOTFOUND
;
406 if (h_errno
== TRY_AGAIN
)
409 __set_errno (olderr
);
412 /* Check whether ans2p was separately allocated. */
416 if (host_buffer
.buf
!= orig_host_buffer
)
417 free (host_buffer
.buf
);
419 __resolv_context_put (ctx
);
422 libc_hidden_def (_nss_dns_gethostbyname4_r
)
425 _nss_dns_gethostbyaddr2_r (const void *addr
, socklen_t len
, int af
,
426 struct hostent
*result
, char *buffer
, size_t buflen
,
427 int *errnop
, int *h_errnop
, int32_t *ttlp
)
429 static const u_char mapped
[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
430 static const u_char tunnelled
[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
431 static const u_char v6local
[] = { 0,0, 0,1 };
432 const u_char
*uaddr
= (const u_char
*)addr
;
435 char *aliases
[MAX_NR_ALIASES
];
436 unsigned char host_addr
[16]; /* IPv4 or IPv6 */
437 char *h_addr_ptrs
[MAX_NR_ADDRS
+ 1];
439 } *host_data
= (struct host_data
*) buffer
;
445 querybuf
*orig_host_buffer
;
446 char qbuf
[MAXDNAME
+1], *qp
= NULL
;
451 uintptr_t pad
= -(uintptr_t) buffer
% __alignof__ (struct host_data
);
453 buflen
= buflen
> pad
? buflen
- pad
: 0;
455 if (__glibc_unlikely (buflen
< sizeof (struct host_data
)))
458 *h_errnop
= NETDB_INTERNAL
;
459 return NSS_STATUS_TRYAGAIN
;
462 host_data
= (struct host_data
*) buffer
;
464 struct resolv_context
*ctx
= __resolv_context_get ();
468 *h_errnop
= NETDB_INTERNAL
;
469 return NSS_STATUS_UNAVAIL
;
472 if (af
== AF_INET6
&& len
== IN6ADDRSZ
473 && (memcmp (uaddr
, mapped
, sizeof mapped
) == 0
474 || (memcmp (uaddr
, tunnelled
, sizeof tunnelled
) == 0
475 && memcmp (&uaddr
[sizeof tunnelled
], v6local
, sizeof v6local
))))
478 addr
+= sizeof mapped
;
479 uaddr
+= sizeof mapped
;
493 *errnop
= EAFNOSUPPORT
;
494 *h_errnop
= NETDB_INTERNAL
;
495 __resolv_context_put (ctx
);
496 return NSS_STATUS_UNAVAIL
;
500 *errnop
= EAFNOSUPPORT
;
501 *h_errnop
= NETDB_INTERNAL
;
502 __resolv_context_put (ctx
);
503 return NSS_STATUS_UNAVAIL
;
506 host_buffer
.buf
= orig_host_buffer
= (querybuf
*) alloca (1024);
511 sprintf (qbuf
, "%u.%u.%u.%u.in-addr.arpa", (uaddr
[3] & 0xff),
512 (uaddr
[2] & 0xff), (uaddr
[1] & 0xff), (uaddr
[0] & 0xff));
516 for (n
= IN6ADDRSZ
- 1; n
>= 0; n
--)
518 static const char nibblechar
[16] = "0123456789abcdef";
519 *qp
++ = nibblechar
[uaddr
[n
] & 0xf];
521 *qp
++ = nibblechar
[(uaddr
[n
] >> 4) & 0xf];
524 strcpy(qp
, "ip6.arpa");
531 n
= __res_context_query (ctx
, qbuf
, C_IN
, T_PTR
, host_buffer
.buf
->buf
,
532 1024, &host_buffer
.ptr
, NULL
, NULL
, NULL
, NULL
);
536 __set_errno (olderr
);
537 if (host_buffer
.buf
!= orig_host_buffer
)
538 free (host_buffer
.buf
);
539 __resolv_context_put (ctx
);
540 return errno
== ECONNREFUSED
? NSS_STATUS_UNAVAIL
: NSS_STATUS_NOTFOUND
;
544 (ctx
, host_buffer
.buf
, n
, qbuf
, T_PTR
, result
, buffer
, buflen
,
545 errnop
, h_errnop
, 0 /* XXX */, ttlp
, NULL
);
546 if (host_buffer
.buf
!= orig_host_buffer
)
547 free (host_buffer
.buf
);
548 if (status
!= NSS_STATUS_SUCCESS
)
550 __resolv_context_put (ctx
);
554 result
->h_addrtype
= af
;
555 result
->h_length
= len
;
556 memcpy (host_data
->host_addr
, addr
, len
);
557 host_data
->h_addr_ptrs
[0] = (char *) host_data
->host_addr
;
558 host_data
->h_addr_ptrs
[1] = NULL
;
559 *h_errnop
= NETDB_SUCCESS
;
560 __resolv_context_put (ctx
);
561 return NSS_STATUS_SUCCESS
;
563 libc_hidden_def (_nss_dns_gethostbyaddr2_r
)
567 _nss_dns_gethostbyaddr_r (const void *addr
, socklen_t len
, int af
,
568 struct hostent
*result
, char *buffer
, size_t buflen
,
569 int *errnop
, int *h_errnop
)
571 return _nss_dns_gethostbyaddr2_r (addr
, len
, af
, result
, buffer
, buflen
,
572 errnop
, h_errnop
, NULL
);
574 libc_hidden_def (_nss_dns_gethostbyaddr_r
)
577 addrsort (struct resolv_context
*ctx
, char **ap
, int num
)
581 short aval
[MAX_NR_ADDRS
];
583 size_t nsort
= __resolv_context_sort_count (ctx
);
586 if (num
> MAX_NR_ADDRS
)
588 for (i
= 0; i
< num
; i
++, p
++)
590 for (j
= 0 ; (unsigned)j
< nsort
; j
++)
592 struct resolv_sortlist_entry e
593 = __resolv_context_sort_entry (ctx
, j
);
594 if (e
.addr
.s_addr
== (((struct in_addr
*)(*p
))->s_addr
& e
.mask
))
598 if (needsort
== 0 && i
> 0 && j
< aval
[i
-1])
604 while (needsort
++ < num
)
605 for (j
= needsort
- 2; j
>= 0; j
--)
606 if (aval
[j
] > aval
[j
+1])
622 static enum nss_status
623 getanswer_r (struct resolv_context
*ctx
,
624 const querybuf
*answer
, int anslen
, const char *qname
, int qtype
,
625 struct hostent
*result
, char *buffer
, size_t buflen
,
626 int *errnop
, int *h_errnop
, int map
, int32_t *ttlp
, char **canonp
)
630 char *aliases
[MAX_NR_ALIASES
];
631 unsigned char host_addr
[16]; /* IPv4 or IPv6 */
632 char *h_addr_ptrs
[0];
636 const u_char
*end_of_message
, *cp
;
637 int n
, ancount
, qdcount
;
638 int haveanswer
, had_error
;
639 char *bp
, **ap
, **hap
;
642 int (*name_ok
) (const char *);
643 u_char packtmp
[NS_MAXCDNAME
];
645 uintptr_t pad
= -(uintptr_t) buffer
% __alignof__ (struct host_data
);
647 buflen
= buflen
> pad
? buflen
- pad
: 0;
648 if (__glibc_unlikely (buflen
< sizeof (struct host_data
)))
650 /* The buffer is too small. */
653 *h_errnop
= NETDB_INTERNAL
;
654 return NSS_STATUS_TRYAGAIN
;
656 host_data
= (struct host_data
*) buffer
;
657 linebuflen
= buflen
- sizeof (struct host_data
);
658 if (buflen
- sizeof (struct host_data
) != linebuflen
)
659 linebuflen
= INT_MAX
;
662 result
->h_name
= NULL
;
663 end_of_message
= answer
->buf
+ anslen
;
668 name_ok
= __libc_res_hnok
;
671 name_ok
= __libc_res_dnok
;
675 return NSS_STATUS_UNAVAIL
; /* XXX should be abort(); */
679 * find first satisfactory answer
682 ancount
= ntohs (hp
->ancount
);
683 qdcount
= ntohs (hp
->qdcount
);
684 cp
= answer
->buf
+ HFIXEDSZ
;
685 if (__glibc_unlikely (qdcount
!= 1))
687 *h_errnop
= NO_RECOVERY
;
688 return NSS_STATUS_UNAVAIL
;
690 if (sizeof (struct host_data
) + (ancount
+ 1) * sizeof (char *) >= buflen
)
692 bp
= (char *) &host_data
->h_addr_ptrs
[ancount
+ 1];
693 linebuflen
-= (ancount
+ 1) * sizeof (char *);
695 n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
696 packtmp
, sizeof packtmp
);
697 if (n
!= -1 && __ns_name_ntop (packtmp
, bp
, linebuflen
) == -1)
699 if (__glibc_unlikely (errno
== EMSGSIZE
))
705 if (__glibc_unlikely (n
< 0))
708 *h_errnop
= NO_RECOVERY
;
709 return NSS_STATUS_UNAVAIL
;
711 if (__glibc_unlikely (name_ok (bp
) == 0))
715 *h_errnop
= NO_RECOVERY
;
716 return NSS_STATUS_UNAVAIL
;
720 if (qtype
== T_A
|| qtype
== T_AAAA
)
722 /* res_send() has already verified that the query name is the
723 * same as the one we sent; this just gets the expanded name
724 * (i.e., with the succeeding search-domain tacked on).
726 n
= strlen (bp
) + 1; /* for the \0 */
727 if (n
>= MAXHOSTNAMELEN
)
729 *h_errnop
= NO_RECOVERY
;
731 return NSS_STATUS_TRYAGAIN
;
738 /* The qname can be abbreviated, but h_name is now absolute. */
739 qname
= result
->h_name
;
742 ap
= host_data
->aliases
;
744 result
->h_aliases
= host_data
->aliases
;
745 hap
= host_data
->h_addr_ptrs
;
747 result
->h_addr_list
= host_data
->h_addr_ptrs
;
751 while (ancount
-- > 0 && cp
< end_of_message
&& had_error
== 0)
755 n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
756 packtmp
, sizeof packtmp
);
757 if (n
!= -1 && __ns_name_ntop (packtmp
, bp
, linebuflen
) == -1)
759 if (__glibc_unlikely (errno
== EMSGSIZE
))
765 if (__glibc_unlikely (n
< 0 || (*name_ok
) (bp
) == 0))
772 if (__glibc_unlikely (cp
+ 10 > end_of_message
))
779 NS_GET16 (class, cp
);
782 NS_GET16 (n
, cp
); /* RDATA length. */
784 if (end_of_message
- cp
< n
)
786 /* RDATA extends beyond the end of the packet. */
791 if (__glibc_unlikely (class != C_IN
))
793 /* XXX - debug? syslog? */
795 continue; /* XXX - had_error++ ? */
798 if ((qtype
== T_A
|| qtype
== T_AAAA
) && type
== T_CNAME
)
800 /* A CNAME could also have a TTL entry. */
801 if (ttlp
!= NULL
&& ttl
< *ttlp
)
804 if (ap
>= &host_data
->aliases
[MAX_NR_ALIASES
- 1])
806 n
= __libc_dn_expand (answer
->buf
, end_of_message
, cp
,
808 if (__glibc_unlikely (n
< 0 || (*name_ok
) (tbuf
) == 0))
816 n
= strlen (bp
) + 1; /* For the \0. */
817 if (__glibc_unlikely (n
>= MAXHOSTNAMELEN
))
824 /* Get canonical name. */
825 n
= strlen (tbuf
) + 1; /* For the \0. */
826 if (__glibc_unlikely (n
> linebuflen
))
828 if (__glibc_unlikely (n
>= MAXHOSTNAMELEN
))
834 bp
= __mempcpy (bp
, tbuf
, n
); /* Cannot overflow. */
839 if (qtype
== T_PTR
&& type
== T_CNAME
)
841 /* A CNAME could also have a TTL entry. */
842 if (ttlp
!= NULL
&& ttl
< *ttlp
)
845 n
= __libc_dn_expand (answer
->buf
, end_of_message
, cp
,
847 if (__glibc_unlikely (n
< 0 || __libc_res_dnok (tbuf
) == 0))
853 /* Get canonical name. */
854 n
= strlen (tbuf
) + 1; /* For the \0. */
855 if (__glibc_unlikely (n
> linebuflen
))
857 if (__glibc_unlikely (n
>= MAXHOSTNAMELEN
))
863 bp
= __mempcpy (bp
, tbuf
, n
); /* Cannot overflow. */
868 if (type
== T_A
&& qtype
== T_AAAA
&& map
)
870 else if (__glibc_unlikely (type
!= qtype
))
873 continue; /* XXX - had_error++ ? */
879 if (__glibc_unlikely (__strcasecmp (tname
, bp
) != 0))
882 continue; /* XXX - had_error++ ? */
885 n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
886 packtmp
, sizeof packtmp
);
887 if (n
!= -1 && __ns_name_ntop (packtmp
, bp
, linebuflen
) == -1)
889 if (__glibc_unlikely (errno
== EMSGSIZE
))
895 if (__glibc_unlikely (n
< 0 || __libc_res_hnok (bp
) == 0))
900 if (ttlp
!= NULL
&& ttl
< *ttlp
)
902 /* bind would put multiple PTR records as aliases, but we don't do
905 *h_errnop
= NETDB_SUCCESS
;
906 return NSS_STATUS_SUCCESS
;
909 if (__glibc_unlikely (__strcasecmp (result
->h_name
, bp
) != 0))
912 continue; /* XXX - had_error++ ? */
915 /* Stop parsing at a record whose length is incorrect. */
916 if (n
!= rrtype_to_rdata_length (type
))
922 /* Skip records of the wrong type. */
923 if (n
!= result
->h_length
)
932 /* We compose a single hostent out of the entire chain of
933 entries, so the TTL of the hostent is essentially the lowest
935 if (ttlp
!= NULL
&& ttl
< *ttlp
)
940 nn
= strlen (bp
) + 1; /* for the \0 */
945 /* Provide sufficient alignment for both address
948 _Static_assert ((align
% __alignof__ (struct in_addr
)) == 0,
949 "struct in_addr alignment");
950 _Static_assert ((align
% __alignof__ (struct in6_addr
)) == 0,
951 "struct in6_addr alignment");
953 char *new_bp
= PTR_ALIGN_UP (bp
, align
);
954 linebuflen
-= new_bp
- bp
;
958 if (__glibc_unlikely (n
> linebuflen
))
960 bp
= __mempcpy (*hap
++ = bp
, cp
, n
);
976 * Note: we sort even if host can take only one address
977 * in its return structures - should give it the "best"
978 * address in that case, not some random one
980 if (haveanswer
> 1 && qtype
== T_A
981 && __resolv_context_sort_count (ctx
) > 0)
982 addrsort (ctx
, host_data
->h_addr_ptrs
, haveanswer
);
984 if (result
->h_name
== NULL
)
986 n
= strlen (qname
) + 1; /* For the \0. */
989 if (n
>= MAXHOSTNAMELEN
)
992 bp
= __mempcpy (bp
, qname
, n
); /* Cannot overflow. */
997 if (map_v4v6_hostent (result
, &bp
, &linebuflen
))
999 *h_errnop
= NETDB_SUCCESS
;
1000 return NSS_STATUS_SUCCESS
;
1003 *h_errnop
= NO_RECOVERY
;
1005 /* Special case here: if the resolver sent a result but it only
1006 contains a CNAME while we are looking for a T_A or T_AAAA record,
1007 we fail with NOTFOUND instead of TRYAGAIN. */
1008 return ((qtype
== T_A
|| qtype
== T_AAAA
) && ap
!= host_data
->aliases
1009 ? NSS_STATUS_NOTFOUND
: NSS_STATUS_TRYAGAIN
);
1013 static enum nss_status
1014 gaih_getanswer_slice (const querybuf
*answer
, int anslen
, const char *qname
,
1015 struct gaih_addrtuple
***patp
,
1016 char **bufferp
, size_t *buflenp
,
1017 int *errnop
, int *h_errnop
, int32_t *ttlp
, int *firstp
)
1019 char *buffer
= *bufferp
;
1020 size_t buflen
= *buflenp
;
1022 struct gaih_addrtuple
**pat
= *patp
;
1023 const HEADER
*hp
= &answer
->hdr
;
1024 int ancount
= ntohs (hp
->ancount
);
1025 int qdcount
= ntohs (hp
->qdcount
);
1026 const u_char
*cp
= answer
->buf
+ HFIXEDSZ
;
1027 const u_char
*end_of_message
= answer
->buf
+ anslen
;
1028 if (__glibc_unlikely (qdcount
!= 1))
1030 *h_errnop
= NO_RECOVERY
;
1031 return NSS_STATUS_UNAVAIL
;
1034 u_char packtmp
[NS_MAXCDNAME
];
1035 int n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
1036 packtmp
, sizeof packtmp
);
1037 /* We unpack the name to check it for validity. But we do not need
1039 if (n
!= -1 && __ns_name_ntop (packtmp
, buffer
, buflen
) == -1)
1041 if (__glibc_unlikely (errno
== EMSGSIZE
))
1045 *h_errnop
= NETDB_INTERNAL
;
1046 return NSS_STATUS_TRYAGAIN
;
1052 if (__glibc_unlikely (n
< 0))
1055 *h_errnop
= NO_RECOVERY
;
1056 return NSS_STATUS_UNAVAIL
;
1058 if (__glibc_unlikely (__libc_res_hnok (buffer
) == 0))
1062 *h_errnop
= NO_RECOVERY
;
1063 return NSS_STATUS_UNAVAIL
;
1070 char *h_name
= NULL
;
1075 *h_errnop
= HOST_NOT_FOUND
;
1076 return NSS_STATUS_NOTFOUND
;
1079 while (ancount
-- > 0 && cp
< end_of_message
&& had_error
== 0)
1081 n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
1082 packtmp
, sizeof packtmp
);
1084 (h_namelen
= __ns_name_ntop (packtmp
, buffer
, buflen
)) == -1)
1086 if (__glibc_unlikely (errno
== EMSGSIZE
))
1091 if (__glibc_unlikely (n
< 0 || __libc_res_hnok (buffer
) == 0))
1096 if (*firstp
&& canon
== NULL
)
1099 buffer
+= h_namelen
;
1100 buflen
-= h_namelen
;
1105 if (__glibc_unlikely (cp
+ 10 > end_of_message
))
1112 NS_GET16 (type
, cp
);
1114 NS_GET16 (class, cp
);
1117 NS_GET16 (n
, cp
); /* RDATA length. */
1119 if (end_of_message
- cp
< n
)
1121 /* RDATA extends beyond the end of the packet. */
1132 if (type
== T_CNAME
)
1134 char tbuf
[MAXDNAME
];
1136 /* A CNAME could also have a TTL entry. */
1137 if (ttlp
!= NULL
&& ttl
< *ttlp
)
1140 n
= __libc_dn_expand (answer
->buf
, end_of_message
, cp
,
1142 if (__glibc_unlikely (n
< 0 || __libc_res_hnok (tbuf
) == 0))
1151 /* Reclaim buffer space. */
1152 if (h_name
+ h_namelen
== buffer
)
1155 buflen
+= h_namelen
;
1158 n
= strlen (tbuf
) + 1;
1159 if (__glibc_unlikely (n
> buflen
))
1161 if (__glibc_unlikely (n
>= MAXHOSTNAMELEN
))
1168 buffer
= __mempcpy (buffer
, tbuf
, n
);
1175 /* Stop parsing if we encounter a record with incorrect RDATA
1177 if (type
== T_A
|| type
== T_AAAA
)
1179 if (n
!= rrtype_to_rdata_length (type
))
1187 /* Skip unknown records. */
1192 assert (type
== T_A
|| type
== T_AAAA
);
1195 uintptr_t pad
= (-(uintptr_t) buffer
1196 % __alignof__ (struct gaih_addrtuple
));
1198 buflen
= buflen
> pad
? buflen
- pad
: 0;
1200 if (__glibc_unlikely (buflen
< sizeof (struct gaih_addrtuple
)))
1203 *pat
= (struct gaih_addrtuple
*) buffer
;
1204 buffer
+= sizeof (struct gaih_addrtuple
);
1205 buflen
-= sizeof (struct gaih_addrtuple
);
1208 (*pat
)->name
= NULL
;
1209 (*pat
)->next
= NULL
;
1213 /* We compose a single hostent out of the entire chain of
1214 entries, so the TTL of the hostent is essentially the lowest
1215 TTL in the chain. */
1216 if (ttlp
!= NULL
&& ttl
< *ttlp
)
1219 (*pat
)->name
= canon
?: h_name
;
1224 (*pat
)->family
= type
== T_A
? AF_INET
: AF_INET6
;
1225 memcpy ((*pat
)->addr
, cp
, n
);
1227 (*pat
)->scopeid
= 0;
1229 pat
= &((*pat
)->next
);
1240 *h_errnop
= NETDB_SUCCESS
;
1241 return NSS_STATUS_SUCCESS
;
1244 /* Special case here: if the resolver sent a result but it only
1245 contains a CNAME while we are looking for a T_A or T_AAAA record,
1246 we fail with NOTFOUND instead of TRYAGAIN. */
1249 *h_errnop
= HOST_NOT_FOUND
;
1250 return NSS_STATUS_NOTFOUND
;
1253 *h_errnop
= NETDB_INTERNAL
;
1254 return NSS_STATUS_TRYAGAIN
;
1258 static enum nss_status
1259 gaih_getanswer (const querybuf
*answer1
, int anslen1
, const querybuf
*answer2
,
1260 int anslen2
, const char *qname
,
1261 struct gaih_addrtuple
**pat
, char *buffer
, size_t buflen
,
1262 int *errnop
, int *h_errnop
, int32_t *ttlp
)
1266 enum nss_status status
= NSS_STATUS_NOTFOUND
;
1268 /* Combining the NSS status of two distinct queries requires some
1269 compromise and attention to symmetry (A or AAAA queries can be
1270 returned in any order). What follows is a breakdown of how this
1271 code is expected to work and why. We discuss only SUCCESS,
1272 TRYAGAIN, NOTFOUND and UNAVAIL, since they are the only returns
1273 that apply (though RETURN and MERGE exist). We make a distinction
1274 between TRYAGAIN (recoverable) and TRYAGAIN' (not-recoverable).
1275 A recoverable TRYAGAIN is almost always due to buffer size issues
1276 and returns ERANGE in errno and the caller is expected to retry
1277 with a larger buffer.
1279 Lastly, you may be tempted to make significant changes to the
1280 conditions in this code to bring about symmetry between responses.
1281 Please don't change anything without due consideration for
1282 expected application behaviour. Some of the synthesized responses
1283 aren't very well thought out and sometimes appear to imply that
1284 IPv4 responses are always answer 1, and IPv6 responses are always
1285 answer 2, but that's not true (see the implementation of send_dg
1286 and send_vc to see response can arrive in any order, particularly
1287 for UDP). However, we expect it holds roughly enough of the time
1288 that this code works, but certainly needs to be fixed to make this
1289 a more robust implementation.
1291 ----------------------------------------------
1292 | Answer 1 Status / | Synthesized | Reason |
1293 | Answer 2 Status | Status | |
1294 |--------------------------------------------|
1295 | SUCCESS/SUCCESS | SUCCESS | [1] |
1296 | SUCCESS/TRYAGAIN | TRYAGAIN | [5] |
1297 | SUCCESS/TRYAGAIN' | SUCCESS | [1] |
1298 | SUCCESS/NOTFOUND | SUCCESS | [1] |
1299 | SUCCESS/UNAVAIL | SUCCESS | [1] |
1300 | TRYAGAIN/SUCCESS | TRYAGAIN | [2] |
1301 | TRYAGAIN/TRYAGAIN | TRYAGAIN | [2] |
1302 | TRYAGAIN/TRYAGAIN' | TRYAGAIN | [2] |
1303 | TRYAGAIN/NOTFOUND | TRYAGAIN | [2] |
1304 | TRYAGAIN/UNAVAIL | TRYAGAIN | [2] |
1305 | TRYAGAIN'/SUCCESS | SUCCESS | [3] |
1306 | TRYAGAIN'/TRYAGAIN | TRYAGAIN | [3] |
1307 | TRYAGAIN'/TRYAGAIN' | TRYAGAIN' | [3] |
1308 | TRYAGAIN'/NOTFOUND | TRYAGAIN' | [3] |
1309 | TRYAGAIN'/UNAVAIL | UNAVAIL | [3] |
1310 | NOTFOUND/SUCCESS | SUCCESS | [3] |
1311 | NOTFOUND/TRYAGAIN | TRYAGAIN | [3] |
1312 | NOTFOUND/TRYAGAIN' | TRYAGAIN' | [3] |
1313 | NOTFOUND/NOTFOUND | NOTFOUND | [3] |
1314 | NOTFOUND/UNAVAIL | UNAVAIL | [3] |
1315 | UNAVAIL/SUCCESS | UNAVAIL | [4] |
1316 | UNAVAIL/TRYAGAIN | UNAVAIL | [4] |
1317 | UNAVAIL/TRYAGAIN' | UNAVAIL | [4] |
1318 | UNAVAIL/NOTFOUND | UNAVAIL | [4] |
1319 | UNAVAIL/UNAVAIL | UNAVAIL | [4] |
1320 ----------------------------------------------
1322 [1] If the first response is a success we return success.
1323 This ignores the state of the second answer and in fact
1324 incorrectly sets errno and h_errno to that of the second
1325 answer. However because the response is a success we ignore
1326 *errnop and *h_errnop (though that means you touched errno on
1327 success). We are being conservative here and returning the
1328 likely IPv4 response in the first answer as a success.
1330 [2] If the first response is a recoverable TRYAGAIN we return
1331 that instead of looking at the second response. The
1332 expectation here is that we have failed to get an IPv4 response
1333 and should retry both queries.
1335 [3] If the first response was not a SUCCESS and the second
1336 response is not NOTFOUND (had a SUCCESS, need to TRYAGAIN,
1337 or failed entirely e.g. TRYAGAIN' and UNAVAIL) then use the
1338 result from the second response, otherwise the first responses
1339 status is used. Again we have some odd side-effects when the
1340 second response is NOTFOUND because we overwrite *errnop and
1341 *h_errnop that means that a first answer of NOTFOUND might see
1342 its *errnop and *h_errnop values altered. Whether it matters
1343 in practice that a first response NOTFOUND has the wrong
1344 *errnop and *h_errnop is undecided.
1346 [4] If the first response is UNAVAIL we return that instead of
1347 looking at the second response. The expectation here is that
1348 it will have failed similarly e.g. configuration failure.
1350 [5] Testing this code is complicated by the fact that truncated
1351 second response buffers might be returned as SUCCESS if the
1352 first answer is a SUCCESS. To fix this we add symmetry to
1353 TRYAGAIN with the second response. If the second response
1354 is a recoverable error we now return TRYAGIN even if the first
1355 response was SUCCESS. */
1358 status
= gaih_getanswer_slice(answer1
, anslen1
, qname
,
1359 &pat
, &buffer
, &buflen
,
1360 errnop
, h_errnop
, ttlp
,
1363 if ((status
== NSS_STATUS_SUCCESS
|| status
== NSS_STATUS_NOTFOUND
1364 || (status
== NSS_STATUS_TRYAGAIN
1365 /* We want to look at the second answer in case of an
1366 NSS_STATUS_TRYAGAIN only if the error is non-recoverable, i.e.
1367 *h_errnop is NO_RECOVERY. If not, and if the failure was due to
1368 an insufficient buffer (ERANGE), then we need to drop the results
1369 and pass on the NSS_STATUS_TRYAGAIN to the caller so that it can
1370 repeat the query with a larger buffer. */
1371 && (*errnop
!= ERANGE
|| *h_errnop
== NO_RECOVERY
)))
1372 && answer2
!= NULL
&& anslen2
> 0)
1374 enum nss_status status2
= gaih_getanswer_slice(answer2
, anslen2
, qname
,
1375 &pat
, &buffer
, &buflen
,
1376 errnop
, h_errnop
, ttlp
,
1378 /* Use the second response status in some cases. */
1379 if (status
!= NSS_STATUS_SUCCESS
&& status2
!= NSS_STATUS_NOTFOUND
)
1381 /* Do not return a truncated second response (unless it was
1382 unavoidable e.g. unrecoverable TRYAGAIN). */
1383 if (status
== NSS_STATUS_SUCCESS
1384 && (status2
== NSS_STATUS_TRYAGAIN
1385 && *errnop
== ERANGE
&& *h_errnop
!= NO_RECOVERY
))
1386 status
= NSS_STATUS_TRYAGAIN
;