1 /* Copyright (C) 1996-2022 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <https://www.gnu.org/licenses/>. */
18 /* Parts of this file are plain copies of the file `gethtnamadr.c' from
19 the bind package and it has the following copyright. */
22 * ++Copyright++ 1985, 1988, 1993
24 * Copyright (c) 1985, 1988, 1993
25 * The Regents of the University of California. All rights reserved.
27 * Redistribution and use in source and binary forms, with or without
28 * modification, are permitted provided that the following conditions
30 * 1. Redistributions of source code must retain the above copyright
31 * notice, this list of conditions and the following disclaimer.
32 * 2. Redistributions in binary form must reproduce the above copyright
33 * notice, this list of conditions and the following disclaimer in the
34 * documentation and/or other materials provided with the distribution.
35 * 4. Neither the name of the University nor the names of its contributors
36 * may be used to endorse or promote products derived from this software
37 * without specific prior written permission.
39 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
40 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
42 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
43 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
44 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
45 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
47 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
48 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
53 * Permission to use, copy, modify, and distribute this software for any
54 * purpose with or without fee is hereby granted, provided that the above
55 * copyright notice and this permission notice appear in all copies, and that
56 * the name of Digital Equipment Corporation not be used in advertising or
57 * publicity pertaining to distribution of the document or software without
58 * specific, written prior permission.
60 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
61 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
62 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
63 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
64 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
65 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
66 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
80 #include <libc-pointer-arith.h>
83 #include <arpa/nameser.h>
86 #include <resolv/resolv-internal.h>
87 #include <resolv/resolv_context.h>
89 /* Get implementations of some internal functions. */
90 #include <resolv/mapv4v6addr.h>
91 #include <resolv/mapv4v6hostent.h>
96 # define MAXPACKET PACKETSZ
98 # define MAXPACKET 65536
100 /* As per RFC 1034 and 1035 a host name cannot exceed 255 octets in length. */
101 #ifdef MAXHOSTNAMELEN
102 # undef MAXHOSTNAMELEN
104 #define MAXHOSTNAMELEN 256
106 /* We need this time later. */
107 typedef union querybuf
110 u_char buf
[MAXPACKET
];
113 static enum nss_status
getanswer_r (struct resolv_context
*ctx
,
114 const querybuf
*answer
, int anslen
,
115 const char *qname
, int qtype
,
116 struct hostent
*result
, char *buffer
,
117 size_t buflen
, int *errnop
, int *h_errnop
,
118 int map
, int32_t *ttlp
, char **canonp
);
120 static enum nss_status
gaih_getanswer (const querybuf
*answer1
, int anslen1
,
121 const querybuf
*answer2
, int anslen2
,
123 struct gaih_addrtuple
**pat
,
124 char *buffer
, size_t buflen
,
125 int *errnop
, int *h_errnop
,
128 static enum nss_status
gethostbyname3_context (struct resolv_context
*ctx
,
129 const char *name
, int af
,
130 struct hostent
*result
,
131 char *buffer
, size_t buflen
,
132 int *errnop
, int *h_errnop
,
136 /* Return the expected RDATA length for an address record type (A or
139 rrtype_to_rdata_length (int type
)
154 _nss_dns_gethostbyname3_r (const char *name
, int af
, struct hostent
*result
,
155 char *buffer
, size_t buflen
, int *errnop
,
156 int *h_errnop
, int32_t *ttlp
, char **canonp
)
158 struct resolv_context
*ctx
= __resolv_context_get ();
162 *h_errnop
= NETDB_INTERNAL
;
163 return NSS_STATUS_UNAVAIL
;
165 enum nss_status status
= gethostbyname3_context
166 (ctx
, name
, af
, result
, buffer
, buflen
, errnop
, h_errnop
, ttlp
, canonp
);
167 __resolv_context_put (ctx
);
170 libc_hidden_def (_nss_dns_gethostbyname3_r
)
172 static enum nss_status
173 gethostbyname3_context (struct resolv_context
*ctx
,
174 const char *name
, int af
, struct hostent
*result
,
175 char *buffer
, size_t buflen
, int *errnop
,
176 int *h_errnop
, int32_t *ttlp
, char **canonp
)
183 querybuf
*orig_host_buffer
;
184 char tmp
[NS_MAXDNAME
];
189 enum nss_status status
;
202 *errnop
= EAFNOSUPPORT
;
203 return NSS_STATUS_UNAVAIL
;
206 result
->h_addrtype
= af
;
207 result
->h_length
= size
;
210 * if there aren't any dots, it could be a user-level alias.
211 * this is also done in res_query() since we are not the only
212 * function that looks up host names.
214 if (strchr (name
, '.') == NULL
215 && (cp
= __res_context_hostalias (ctx
, name
, tmp
, sizeof (tmp
))) != NULL
)
218 host_buffer
.buf
= orig_host_buffer
= (querybuf
*) alloca (1024);
220 n
= __res_context_search (ctx
, name
, C_IN
, type
, host_buffer
.buf
->buf
,
221 1024, &host_buffer
.ptr
, NULL
, NULL
, NULL
, NULL
);
227 status
= NSS_STATUS_TRYAGAIN
;
230 /* System has run out of file descriptors. */
233 h_errno
= NETDB_INTERNAL
;
237 status
= NSS_STATUS_UNAVAIL
;
240 status
= NSS_STATUS_NOTFOUND
;
244 if (h_errno
== TRY_AGAIN
)
247 __set_errno (olderr
);
249 /* If we are looking for an IPv6 address and mapping is enabled
250 by having the RES_USE_INET6 bit in _res.options set, we try
252 if (af
== AF_INET6
&& res_use_inet6 ())
253 n
= __res_context_search (ctx
, name
, C_IN
, T_A
, host_buffer
.buf
->buf
,
254 host_buffer
.buf
!= orig_host_buffer
255 ? MAXPACKET
: 1024, &host_buffer
.ptr
,
256 NULL
, NULL
, NULL
, NULL
);
260 if (host_buffer
.buf
!= orig_host_buffer
)
261 free (host_buffer
.buf
);
267 result
->h_addrtype
= AF_INET
;
268 result
->h_length
= INADDRSZ
;
272 (ctx
, host_buffer
.buf
, n
, name
, type
, result
, buffer
, buflen
,
273 errnop
, h_errnop
, map
, ttlp
, canonp
);
274 if (host_buffer
.buf
!= orig_host_buffer
)
275 free (host_buffer
.buf
);
279 /* Verify that the name looks like a host name. There is no point in
280 sending a query which will not produce a usable name in the
282 static enum nss_status
283 check_name (const char *name
, int *h_errnop
)
285 if (__libc_res_hnok (name
))
286 return NSS_STATUS_SUCCESS
;
287 *h_errnop
= HOST_NOT_FOUND
;
288 return NSS_STATUS_NOTFOUND
;
292 _nss_dns_gethostbyname2_r (const char *name
, int af
, struct hostent
*result
,
293 char *buffer
, size_t buflen
, int *errnop
,
296 enum nss_status status
= check_name (name
, h_errnop
);
297 if (status
!= NSS_STATUS_SUCCESS
)
299 return _nss_dns_gethostbyname3_r (name
, af
, result
, buffer
, buflen
, errnop
,
300 h_errnop
, NULL
, NULL
);
302 libc_hidden_def (_nss_dns_gethostbyname2_r
)
305 _nss_dns_gethostbyname_r (const char *name
, struct hostent
*result
,
306 char *buffer
, size_t buflen
, int *errnop
,
309 enum nss_status status
= check_name (name
, h_errnop
);
310 if (status
!= NSS_STATUS_SUCCESS
)
312 struct resolv_context
*ctx
= __resolv_context_get ();
316 *h_errnop
= NETDB_INTERNAL
;
317 return NSS_STATUS_UNAVAIL
;
319 status
= NSS_STATUS_NOTFOUND
;
320 if (res_use_inet6 ())
321 status
= gethostbyname3_context (ctx
, name
, AF_INET6
, result
, buffer
,
322 buflen
, errnop
, h_errnop
, NULL
, NULL
);
323 if (status
== NSS_STATUS_NOTFOUND
)
324 status
= gethostbyname3_context (ctx
, name
, AF_INET
, result
, buffer
,
325 buflen
, errnop
, h_errnop
, NULL
, NULL
);
326 __resolv_context_put (ctx
);
329 libc_hidden_def (_nss_dns_gethostbyname_r
)
332 _nss_dns_gethostbyname4_r (const char *name
, struct gaih_addrtuple
**pat
,
333 char *buffer
, size_t buflen
, int *errnop
,
334 int *herrnop
, int32_t *ttlp
)
336 enum nss_status status
= check_name (name
, herrnop
);
337 if (status
!= NSS_STATUS_SUCCESS
)
339 struct resolv_context
*ctx
= __resolv_context_get ();
343 *herrnop
= NETDB_INTERNAL
;
344 return NSS_STATUS_UNAVAIL
;
348 * if there aren't any dots, it could be a user-level alias.
349 * this is also done in res_query() since we are not the only
350 * function that looks up host names.
352 if (strchr (name
, '.') == NULL
)
354 char *tmp
= alloca (NS_MAXDNAME
);
355 const char *cp
= __res_context_hostalias (ctx
, name
, tmp
, NS_MAXDNAME
);
365 querybuf
*orig_host_buffer
;
366 host_buffer
.buf
= orig_host_buffer
= (querybuf
*) alloca (2048);
367 u_char
*ans2p
= NULL
;
370 int ans2p_malloced
= 0;
373 int n
= __res_context_search (ctx
, name
, C_IN
, T_QUERY_A_AND_AAAA
,
374 host_buffer
.buf
->buf
, 2048, &host_buffer
.ptr
,
375 &ans2p
, &nans2p
, &resplen2
, &ans2p_malloced
);
378 status
= gaih_getanswer (host_buffer
.buf
, n
, (const querybuf
*) ans2p
,
379 resplen2
, name
, pat
, buffer
, buflen
,
380 errnop
, herrnop
, ttlp
);
387 status
= NSS_STATUS_TRYAGAIN
;
390 /* System has run out of file descriptors. */
393 h_errno
= NETDB_INTERNAL
;
397 status
= NSS_STATUS_UNAVAIL
;
400 status
= NSS_STATUS_NOTFOUND
;
405 if (h_errno
== TRY_AGAIN
)
408 __set_errno (olderr
);
411 /* Check whether ans2p was separately allocated. */
415 if (host_buffer
.buf
!= orig_host_buffer
)
416 free (host_buffer
.buf
);
418 __resolv_context_put (ctx
);
421 libc_hidden_def (_nss_dns_gethostbyname4_r
)
424 _nss_dns_gethostbyaddr2_r (const void *addr
, socklen_t len
, int af
,
425 struct hostent
*result
, char *buffer
, size_t buflen
,
426 int *errnop
, int *h_errnop
, int32_t *ttlp
)
428 static const u_char mapped
[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
429 static const u_char tunnelled
[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
430 static const u_char v6local
[] = { 0,0, 0,1 };
431 const u_char
*uaddr
= (const u_char
*)addr
;
434 char *aliases
[MAX_NR_ALIASES
];
435 unsigned char host_addr
[16]; /* IPv4 or IPv6 */
436 char *h_addr_ptrs
[MAX_NR_ADDRS
+ 1];
438 } *host_data
= (struct host_data
*) buffer
;
444 querybuf
*orig_host_buffer
;
445 char qbuf
[MAXDNAME
+1], *qp
= NULL
;
450 uintptr_t pad
= -(uintptr_t) buffer
% __alignof__ (struct host_data
);
452 buflen
= buflen
> pad
? buflen
- pad
: 0;
454 if (__glibc_unlikely (buflen
< sizeof (struct host_data
)))
457 *h_errnop
= NETDB_INTERNAL
;
458 return NSS_STATUS_TRYAGAIN
;
461 host_data
= (struct host_data
*) buffer
;
463 struct resolv_context
*ctx
= __resolv_context_get ();
467 *h_errnop
= NETDB_INTERNAL
;
468 return NSS_STATUS_UNAVAIL
;
471 if (af
== AF_INET6
&& len
== IN6ADDRSZ
472 && (memcmp (uaddr
, mapped
, sizeof mapped
) == 0
473 || (memcmp (uaddr
, tunnelled
, sizeof tunnelled
) == 0
474 && memcmp (&uaddr
[sizeof tunnelled
], v6local
, sizeof v6local
))))
477 addr
+= sizeof mapped
;
478 uaddr
+= sizeof mapped
;
492 *errnop
= EAFNOSUPPORT
;
493 *h_errnop
= NETDB_INTERNAL
;
494 __resolv_context_put (ctx
);
495 return NSS_STATUS_UNAVAIL
;
499 *errnop
= EAFNOSUPPORT
;
500 *h_errnop
= NETDB_INTERNAL
;
501 __resolv_context_put (ctx
);
502 return NSS_STATUS_UNAVAIL
;
505 host_buffer
.buf
= orig_host_buffer
= (querybuf
*) alloca (1024);
510 sprintf (qbuf
, "%u.%u.%u.%u.in-addr.arpa", (uaddr
[3] & 0xff),
511 (uaddr
[2] & 0xff), (uaddr
[1] & 0xff), (uaddr
[0] & 0xff));
515 for (n
= IN6ADDRSZ
- 1; n
>= 0; n
--)
517 static const char nibblechar
[16] = "0123456789abcdef";
518 *qp
++ = nibblechar
[uaddr
[n
] & 0xf];
520 *qp
++ = nibblechar
[(uaddr
[n
] >> 4) & 0xf];
523 strcpy(qp
, "ip6.arpa");
530 n
= __res_context_query (ctx
, qbuf
, C_IN
, T_PTR
, host_buffer
.buf
->buf
,
531 1024, &host_buffer
.ptr
, NULL
, NULL
, NULL
, NULL
);
535 __set_errno (olderr
);
536 if (host_buffer
.buf
!= orig_host_buffer
)
537 free (host_buffer
.buf
);
538 __resolv_context_put (ctx
);
539 return errno
== ECONNREFUSED
? NSS_STATUS_UNAVAIL
: NSS_STATUS_NOTFOUND
;
543 (ctx
, host_buffer
.buf
, n
, qbuf
, T_PTR
, result
, buffer
, buflen
,
544 errnop
, h_errnop
, 0 /* XXX */, ttlp
, NULL
);
545 if (host_buffer
.buf
!= orig_host_buffer
)
546 free (host_buffer
.buf
);
547 if (status
!= NSS_STATUS_SUCCESS
)
549 __resolv_context_put (ctx
);
553 result
->h_addrtype
= af
;
554 result
->h_length
= len
;
555 memcpy (host_data
->host_addr
, addr
, len
);
556 host_data
->h_addr_ptrs
[0] = (char *) host_data
->host_addr
;
557 host_data
->h_addr_ptrs
[1] = NULL
;
558 *h_errnop
= NETDB_SUCCESS
;
559 __resolv_context_put (ctx
);
560 return NSS_STATUS_SUCCESS
;
562 libc_hidden_def (_nss_dns_gethostbyaddr2_r
)
566 _nss_dns_gethostbyaddr_r (const void *addr
, socklen_t len
, int af
,
567 struct hostent
*result
, char *buffer
, size_t buflen
,
568 int *errnop
, int *h_errnop
)
570 return _nss_dns_gethostbyaddr2_r (addr
, len
, af
, result
, buffer
, buflen
,
571 errnop
, h_errnop
, NULL
);
573 libc_hidden_def (_nss_dns_gethostbyaddr_r
)
576 addrsort (struct resolv_context
*ctx
, char **ap
, int num
)
580 short aval
[MAX_NR_ADDRS
];
582 size_t nsort
= __resolv_context_sort_count (ctx
);
585 if (num
> MAX_NR_ADDRS
)
587 for (i
= 0; i
< num
; i
++, p
++)
589 for (j
= 0 ; (unsigned)j
< nsort
; j
++)
591 struct resolv_sortlist_entry e
592 = __resolv_context_sort_entry (ctx
, j
);
593 if (e
.addr
.s_addr
== (((struct in_addr
*)(*p
))->s_addr
& e
.mask
))
597 if (needsort
== 0 && i
> 0 && j
< aval
[i
-1])
603 while (needsort
++ < num
)
604 for (j
= needsort
- 2; j
>= 0; j
--)
605 if (aval
[j
] > aval
[j
+1])
621 static enum nss_status
622 getanswer_r (struct resolv_context
*ctx
,
623 const querybuf
*answer
, int anslen
, const char *qname
, int qtype
,
624 struct hostent
*result
, char *buffer
, size_t buflen
,
625 int *errnop
, int *h_errnop
, int map
, int32_t *ttlp
, char **canonp
)
629 char *aliases
[MAX_NR_ALIASES
];
630 unsigned char host_addr
[16]; /* IPv4 or IPv6 */
631 char *h_addr_ptrs
[0];
635 const u_char
*end_of_message
, *cp
;
636 int n
, ancount
, qdcount
;
637 int haveanswer
, had_error
;
638 char *bp
, **ap
, **hap
;
641 int (*name_ok
) (const char *);
642 u_char packtmp
[NS_MAXCDNAME
];
644 uintptr_t pad
= -(uintptr_t) buffer
% __alignof__ (struct host_data
);
646 buflen
= buflen
> pad
? buflen
- pad
: 0;
647 if (__glibc_unlikely (buflen
< sizeof (struct host_data
)))
649 /* The buffer is too small. */
652 *h_errnop
= NETDB_INTERNAL
;
653 return NSS_STATUS_TRYAGAIN
;
655 host_data
= (struct host_data
*) buffer
;
656 linebuflen
= buflen
- sizeof (struct host_data
);
657 if (buflen
- sizeof (struct host_data
) != linebuflen
)
658 linebuflen
= INT_MAX
;
661 result
->h_name
= NULL
;
662 end_of_message
= answer
->buf
+ anslen
;
667 name_ok
= __libc_res_hnok
;
670 name_ok
= __libc_res_dnok
;
674 return NSS_STATUS_UNAVAIL
; /* XXX should be abort(); */
678 * find first satisfactory answer
681 ancount
= ntohs (hp
->ancount
);
682 qdcount
= ntohs (hp
->qdcount
);
683 cp
= answer
->buf
+ HFIXEDSZ
;
684 if (__glibc_unlikely (qdcount
!= 1))
686 *h_errnop
= NO_RECOVERY
;
687 return NSS_STATUS_UNAVAIL
;
689 if (sizeof (struct host_data
) + (ancount
+ 1) * sizeof (char *) >= buflen
)
691 bp
= (char *) &host_data
->h_addr_ptrs
[ancount
+ 1];
692 linebuflen
-= (ancount
+ 1) * sizeof (char *);
694 n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
695 packtmp
, sizeof packtmp
);
696 if (n
!= -1 && __ns_name_ntop (packtmp
, bp
, linebuflen
) == -1)
698 if (__glibc_unlikely (errno
== EMSGSIZE
))
704 if (__glibc_unlikely (n
< 0))
707 *h_errnop
= NO_RECOVERY
;
708 return NSS_STATUS_UNAVAIL
;
710 if (__glibc_unlikely (name_ok (bp
) == 0))
714 *h_errnop
= NO_RECOVERY
;
715 return NSS_STATUS_UNAVAIL
;
719 if (qtype
== T_A
|| qtype
== T_AAAA
)
721 /* res_send() has already verified that the query name is the
722 * same as the one we sent; this just gets the expanded name
723 * (i.e., with the succeeding search-domain tacked on).
725 n
= strlen (bp
) + 1; /* for the \0 */
726 if (n
>= MAXHOSTNAMELEN
)
728 *h_errnop
= NO_RECOVERY
;
730 return NSS_STATUS_TRYAGAIN
;
737 /* The qname can be abbreviated, but h_name is now absolute. */
738 qname
= result
->h_name
;
741 ap
= host_data
->aliases
;
743 result
->h_aliases
= host_data
->aliases
;
744 hap
= host_data
->h_addr_ptrs
;
746 result
->h_addr_list
= host_data
->h_addr_ptrs
;
750 while (ancount
-- > 0 && cp
< end_of_message
&& had_error
== 0)
754 n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
755 packtmp
, sizeof packtmp
);
756 if (n
!= -1 && __ns_name_ntop (packtmp
, bp
, linebuflen
) == -1)
758 if (__glibc_unlikely (errno
== EMSGSIZE
))
764 if (__glibc_unlikely (n
< 0 || (*name_ok
) (bp
) == 0))
771 if (__glibc_unlikely (cp
+ 10 > end_of_message
))
778 NS_GET16 (class, cp
);
781 NS_GET16 (n
, cp
); /* RDATA length. */
783 if (end_of_message
- cp
< n
)
785 /* RDATA extends beyond the end of the packet. */
790 if (__glibc_unlikely (class != C_IN
))
792 /* XXX - debug? syslog? */
794 continue; /* XXX - had_error++ ? */
797 if ((qtype
== T_A
|| qtype
== T_AAAA
) && type
== T_CNAME
)
799 /* A CNAME could also have a TTL entry. */
800 if (ttlp
!= NULL
&& ttl
< *ttlp
)
803 if (ap
>= &host_data
->aliases
[MAX_NR_ALIASES
- 1])
805 n
= __libc_dn_expand (answer
->buf
, end_of_message
, cp
,
807 if (__glibc_unlikely (n
< 0 || (*name_ok
) (tbuf
) == 0))
815 n
= strlen (bp
) + 1; /* For the \0. */
816 if (__glibc_unlikely (n
>= MAXHOSTNAMELEN
))
823 /* Get canonical name. */
824 n
= strlen (tbuf
) + 1; /* For the \0. */
825 if (__glibc_unlikely (n
> linebuflen
))
827 if (__glibc_unlikely (n
>= MAXHOSTNAMELEN
))
833 bp
= __mempcpy (bp
, tbuf
, n
); /* Cannot overflow. */
838 if (qtype
== T_PTR
&& type
== T_CNAME
)
840 /* A CNAME could also have a TTL entry. */
841 if (ttlp
!= NULL
&& ttl
< *ttlp
)
844 n
= __libc_dn_expand (answer
->buf
, end_of_message
, cp
,
846 if (__glibc_unlikely (n
< 0 || __libc_res_dnok (tbuf
) == 0))
852 /* Get canonical name. */
853 n
= strlen (tbuf
) + 1; /* For the \0. */
854 if (__glibc_unlikely (n
> linebuflen
))
856 if (__glibc_unlikely (n
>= MAXHOSTNAMELEN
))
862 bp
= __mempcpy (bp
, tbuf
, n
); /* Cannot overflow. */
867 if (type
== T_A
&& qtype
== T_AAAA
&& map
)
869 else if (__glibc_unlikely (type
!= qtype
))
872 continue; /* XXX - had_error++ ? */
878 if (__glibc_unlikely (__strcasecmp (tname
, bp
) != 0))
881 continue; /* XXX - had_error++ ? */
884 n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
885 packtmp
, sizeof packtmp
);
886 if (n
!= -1 && __ns_name_ntop (packtmp
, bp
, linebuflen
) == -1)
888 if (__glibc_unlikely (errno
== EMSGSIZE
))
894 if (__glibc_unlikely (n
< 0 || __libc_res_hnok (bp
) == 0))
899 if (ttlp
!= NULL
&& ttl
< *ttlp
)
901 /* bind would put multiple PTR records as aliases, but we don't do
904 *h_errnop
= NETDB_SUCCESS
;
905 return NSS_STATUS_SUCCESS
;
908 if (__glibc_unlikely (__strcasecmp (result
->h_name
, bp
) != 0))
911 continue; /* XXX - had_error++ ? */
914 /* Stop parsing at a record whose length is incorrect. */
915 if (n
!= rrtype_to_rdata_length (type
))
921 /* Skip records of the wrong type. */
922 if (n
!= result
->h_length
)
931 /* We compose a single hostent out of the entire chain of
932 entries, so the TTL of the hostent is essentially the lowest
934 if (ttlp
!= NULL
&& ttl
< *ttlp
)
939 nn
= strlen (bp
) + 1; /* for the \0 */
944 /* Provide sufficient alignment for both address
947 _Static_assert ((align
% __alignof__ (struct in_addr
)) == 0,
948 "struct in_addr alignment");
949 _Static_assert ((align
% __alignof__ (struct in6_addr
)) == 0,
950 "struct in6_addr alignment");
952 char *new_bp
= PTR_ALIGN_UP (bp
, align
);
953 linebuflen
-= new_bp
- bp
;
957 if (__glibc_unlikely (n
> linebuflen
))
959 bp
= __mempcpy (*hap
++ = bp
, cp
, n
);
975 * Note: we sort even if host can take only one address
976 * in its return structures - should give it the "best"
977 * address in that case, not some random one
979 if (haveanswer
> 1 && qtype
== T_A
980 && __resolv_context_sort_count (ctx
) > 0)
981 addrsort (ctx
, host_data
->h_addr_ptrs
, haveanswer
);
983 if (result
->h_name
== NULL
)
985 n
= strlen (qname
) + 1; /* For the \0. */
988 if (n
>= MAXHOSTNAMELEN
)
991 bp
= __mempcpy (bp
, qname
, n
); /* Cannot overflow. */
996 if (map_v4v6_hostent (result
, &bp
, &linebuflen
))
998 *h_errnop
= NETDB_SUCCESS
;
999 return NSS_STATUS_SUCCESS
;
1002 *h_errnop
= NO_RECOVERY
;
1004 /* Special case here: if the resolver sent a result but it only
1005 contains a CNAME while we are looking for a T_A or T_AAAA record,
1006 we fail with NOTFOUND instead of TRYAGAIN. */
1007 return ((qtype
== T_A
|| qtype
== T_AAAA
) && ap
!= host_data
->aliases
1008 ? NSS_STATUS_NOTFOUND
: NSS_STATUS_TRYAGAIN
);
1012 static enum nss_status
1013 gaih_getanswer_slice (const querybuf
*answer
, int anslen
, const char *qname
,
1014 struct gaih_addrtuple
***patp
,
1015 char **bufferp
, size_t *buflenp
,
1016 int *errnop
, int *h_errnop
, int32_t *ttlp
, int *firstp
)
1018 char *buffer
= *bufferp
;
1019 size_t buflen
= *buflenp
;
1021 struct gaih_addrtuple
**pat
= *patp
;
1022 const HEADER
*hp
= &answer
->hdr
;
1023 int ancount
= ntohs (hp
->ancount
);
1024 int qdcount
= ntohs (hp
->qdcount
);
1025 const u_char
*cp
= answer
->buf
+ HFIXEDSZ
;
1026 const u_char
*end_of_message
= answer
->buf
+ anslen
;
1027 if (__glibc_unlikely (qdcount
!= 1))
1029 *h_errnop
= NO_RECOVERY
;
1030 return NSS_STATUS_UNAVAIL
;
1033 u_char packtmp
[NS_MAXCDNAME
];
1034 int n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
1035 packtmp
, sizeof packtmp
);
1036 /* We unpack the name to check it for validity. But we do not need
1038 if (n
!= -1 && __ns_name_ntop (packtmp
, buffer
, buflen
) == -1)
1040 if (__glibc_unlikely (errno
== EMSGSIZE
))
1044 *h_errnop
= NETDB_INTERNAL
;
1045 return NSS_STATUS_TRYAGAIN
;
1051 if (__glibc_unlikely (n
< 0))
1054 *h_errnop
= NO_RECOVERY
;
1055 return NSS_STATUS_UNAVAIL
;
1057 if (__glibc_unlikely (__libc_res_hnok (buffer
) == 0))
1061 *h_errnop
= NO_RECOVERY
;
1062 return NSS_STATUS_UNAVAIL
;
1069 char *h_name
= NULL
;
1074 *h_errnop
= HOST_NOT_FOUND
;
1075 return NSS_STATUS_NOTFOUND
;
1078 while (ancount
-- > 0 && cp
< end_of_message
&& had_error
== 0)
1080 n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
1081 packtmp
, sizeof packtmp
);
1083 (h_namelen
= __ns_name_ntop (packtmp
, buffer
, buflen
)) == -1)
1085 if (__glibc_unlikely (errno
== EMSGSIZE
))
1090 if (__glibc_unlikely (n
< 0 || __libc_res_hnok (buffer
) == 0))
1095 if (*firstp
&& canon
== NULL
)
1098 buffer
+= h_namelen
;
1099 buflen
-= h_namelen
;
1104 if (__glibc_unlikely (cp
+ 10 > end_of_message
))
1111 NS_GET16 (type
, cp
);
1113 NS_GET16 (class, cp
);
1116 NS_GET16 (n
, cp
); /* RDATA length. */
1118 if (end_of_message
- cp
< n
)
1120 /* RDATA extends beyond the end of the packet. */
1131 if (type
== T_CNAME
)
1133 char tbuf
[MAXDNAME
];
1135 /* A CNAME could also have a TTL entry. */
1136 if (ttlp
!= NULL
&& ttl
< *ttlp
)
1139 n
= __libc_dn_expand (answer
->buf
, end_of_message
, cp
,
1141 if (__glibc_unlikely (n
< 0 || __libc_res_hnok (tbuf
) == 0))
1150 /* Reclaim buffer space. */
1151 if (h_name
+ h_namelen
== buffer
)
1154 buflen
+= h_namelen
;
1157 n
= strlen (tbuf
) + 1;
1158 if (__glibc_unlikely (n
> buflen
))
1160 if (__glibc_unlikely (n
>= MAXHOSTNAMELEN
))
1167 buffer
= __mempcpy (buffer
, tbuf
, n
);
1174 /* Stop parsing if we encounter a record with incorrect RDATA
1176 if (type
== T_A
|| type
== T_AAAA
)
1178 if (n
!= rrtype_to_rdata_length (type
))
1186 /* Skip unknown records. */
1191 assert (type
== T_A
|| type
== T_AAAA
);
1194 uintptr_t pad
= (-(uintptr_t) buffer
1195 % __alignof__ (struct gaih_addrtuple
));
1197 buflen
= buflen
> pad
? buflen
- pad
: 0;
1199 if (__glibc_unlikely (buflen
< sizeof (struct gaih_addrtuple
)))
1202 *pat
= (struct gaih_addrtuple
*) buffer
;
1203 buffer
+= sizeof (struct gaih_addrtuple
);
1204 buflen
-= sizeof (struct gaih_addrtuple
);
1207 (*pat
)->name
= NULL
;
1208 (*pat
)->next
= NULL
;
1212 /* We compose a single hostent out of the entire chain of
1213 entries, so the TTL of the hostent is essentially the lowest
1214 TTL in the chain. */
1215 if (ttlp
!= NULL
&& ttl
< *ttlp
)
1218 (*pat
)->name
= canon
?: h_name
;
1223 (*pat
)->family
= type
== T_A
? AF_INET
: AF_INET6
;
1224 memcpy ((*pat
)->addr
, cp
, n
);
1226 (*pat
)->scopeid
= 0;
1228 pat
= &((*pat
)->next
);
1239 *h_errnop
= NETDB_SUCCESS
;
1240 return NSS_STATUS_SUCCESS
;
1243 /* Special case here: if the resolver sent a result but it only
1244 contains a CNAME while we are looking for a T_A or T_AAAA record,
1245 we fail with NOTFOUND instead of TRYAGAIN. */
1248 *h_errnop
= HOST_NOT_FOUND
;
1249 return NSS_STATUS_NOTFOUND
;
1252 *h_errnop
= NETDB_INTERNAL
;
1253 return NSS_STATUS_TRYAGAIN
;
1257 static enum nss_status
1258 gaih_getanswer (const querybuf
*answer1
, int anslen1
, const querybuf
*answer2
,
1259 int anslen2
, const char *qname
,
1260 struct gaih_addrtuple
**pat
, char *buffer
, size_t buflen
,
1261 int *errnop
, int *h_errnop
, int32_t *ttlp
)
1265 enum nss_status status
= NSS_STATUS_NOTFOUND
;
1267 /* Combining the NSS status of two distinct queries requires some
1268 compromise and attention to symmetry (A or AAAA queries can be
1269 returned in any order). What follows is a breakdown of how this
1270 code is expected to work and why. We discuss only SUCCESS,
1271 TRYAGAIN, NOTFOUND and UNAVAIL, since they are the only returns
1272 that apply (though RETURN and MERGE exist). We make a distinction
1273 between TRYAGAIN (recoverable) and TRYAGAIN' (not-recoverable).
1274 A recoverable TRYAGAIN is almost always due to buffer size issues
1275 and returns ERANGE in errno and the caller is expected to retry
1276 with a larger buffer.
1278 Lastly, you may be tempted to make significant changes to the
1279 conditions in this code to bring about symmetry between responses.
1280 Please don't change anything without due consideration for
1281 expected application behaviour. Some of the synthesized responses
1282 aren't very well thought out and sometimes appear to imply that
1283 IPv4 responses are always answer 1, and IPv6 responses are always
1284 answer 2, but that's not true (see the implementation of send_dg
1285 and send_vc to see response can arrive in any order, particularly
1286 for UDP). However, we expect it holds roughly enough of the time
1287 that this code works, but certainly needs to be fixed to make this
1288 a more robust implementation.
1290 ----------------------------------------------
1291 | Answer 1 Status / | Synthesized | Reason |
1292 | Answer 2 Status | Status | |
1293 |--------------------------------------------|
1294 | SUCCESS/SUCCESS | SUCCESS | [1] |
1295 | SUCCESS/TRYAGAIN | TRYAGAIN | [5] |
1296 | SUCCESS/TRYAGAIN' | SUCCESS | [1] |
1297 | SUCCESS/NOTFOUND | SUCCESS | [1] |
1298 | SUCCESS/UNAVAIL | SUCCESS | [1] |
1299 | TRYAGAIN/SUCCESS | TRYAGAIN | [2] |
1300 | TRYAGAIN/TRYAGAIN | TRYAGAIN | [2] |
1301 | TRYAGAIN/TRYAGAIN' | TRYAGAIN | [2] |
1302 | TRYAGAIN/NOTFOUND | TRYAGAIN | [2] |
1303 | TRYAGAIN/UNAVAIL | TRYAGAIN | [2] |
1304 | TRYAGAIN'/SUCCESS | SUCCESS | [3] |
1305 | TRYAGAIN'/TRYAGAIN | TRYAGAIN | [3] |
1306 | TRYAGAIN'/TRYAGAIN' | TRYAGAIN' | [3] |
1307 | TRYAGAIN'/NOTFOUND | TRYAGAIN' | [3] |
1308 | TRYAGAIN'/UNAVAIL | UNAVAIL | [3] |
1309 | NOTFOUND/SUCCESS | SUCCESS | [3] |
1310 | NOTFOUND/TRYAGAIN | TRYAGAIN | [3] |
1311 | NOTFOUND/TRYAGAIN' | TRYAGAIN' | [3] |
1312 | NOTFOUND/NOTFOUND | NOTFOUND | [3] |
1313 | NOTFOUND/UNAVAIL | UNAVAIL | [3] |
1314 | UNAVAIL/SUCCESS | UNAVAIL | [4] |
1315 | UNAVAIL/TRYAGAIN | UNAVAIL | [4] |
1316 | UNAVAIL/TRYAGAIN' | UNAVAIL | [4] |
1317 | UNAVAIL/NOTFOUND | UNAVAIL | [4] |
1318 | UNAVAIL/UNAVAIL | UNAVAIL | [4] |
1319 ----------------------------------------------
1321 [1] If the first response is a success we return success.
1322 This ignores the state of the second answer and in fact
1323 incorrectly sets errno and h_errno to that of the second
1324 answer. However because the response is a success we ignore
1325 *errnop and *h_errnop (though that means you touched errno on
1326 success). We are being conservative here and returning the
1327 likely IPv4 response in the first answer as a success.
1329 [2] If the first response is a recoverable TRYAGAIN we return
1330 that instead of looking at the second response. The
1331 expectation here is that we have failed to get an IPv4 response
1332 and should retry both queries.
1334 [3] If the first response was not a SUCCESS and the second
1335 response is not NOTFOUND (had a SUCCESS, need to TRYAGAIN,
1336 or failed entirely e.g. TRYAGAIN' and UNAVAIL) then use the
1337 result from the second response, otherwise the first responses
1338 status is used. Again we have some odd side-effects when the
1339 second response is NOTFOUND because we overwrite *errnop and
1340 *h_errnop that means that a first answer of NOTFOUND might see
1341 its *errnop and *h_errnop values altered. Whether it matters
1342 in practice that a first response NOTFOUND has the wrong
1343 *errnop and *h_errnop is undecided.
1345 [4] If the first response is UNAVAIL we return that instead of
1346 looking at the second response. The expectation here is that
1347 it will have failed similarly e.g. configuration failure.
1349 [5] Testing this code is complicated by the fact that truncated
1350 second response buffers might be returned as SUCCESS if the
1351 first answer is a SUCCESS. To fix this we add symmetry to
1352 TRYAGAIN with the second response. If the second response
1353 is a recoverable error we now return TRYAGIN even if the first
1354 response was SUCCESS. */
1357 status
= gaih_getanswer_slice(answer1
, anslen1
, qname
,
1358 &pat
, &buffer
, &buflen
,
1359 errnop
, h_errnop
, ttlp
,
1362 if ((status
== NSS_STATUS_SUCCESS
|| status
== NSS_STATUS_NOTFOUND
1363 || (status
== NSS_STATUS_TRYAGAIN
1364 /* We want to look at the second answer in case of an
1365 NSS_STATUS_TRYAGAIN only if the error is non-recoverable, i.e.
1366 *h_errnop is NO_RECOVERY. If not, and if the failure was due to
1367 an insufficient buffer (ERANGE), then we need to drop the results
1368 and pass on the NSS_STATUS_TRYAGAIN to the caller so that it can
1369 repeat the query with a larger buffer. */
1370 && (*errnop
!= ERANGE
|| *h_errnop
== NO_RECOVERY
)))
1371 && answer2
!= NULL
&& anslen2
> 0)
1373 enum nss_status status2
= gaih_getanswer_slice(answer2
, anslen2
, qname
,
1374 &pat
, &buffer
, &buflen
,
1375 errnop
, h_errnop
, ttlp
,
1377 /* Use the second response status in some cases. */
1378 if (status
!= NSS_STATUS_SUCCESS
&& status2
!= NSS_STATUS_NOTFOUND
)
1380 /* Do not return a truncated second response (unless it was
1381 unavoidable e.g. unrecoverable TRYAGAIN). */
1382 if (status
== NSS_STATUS_SUCCESS
1383 && (status2
== NSS_STATUS_TRYAGAIN
1384 && *errnop
== ERANGE
&& *h_errnop
!= NO_RECOVERY
))
1385 status
= NSS_STATUS_TRYAGAIN
;