1 /* Copyright (C) 1996-2020 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>
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>
93 NSS_DECLARE_MODULE_FUNCTIONS (dns
)
98 # define MAXPACKET PACKETSZ
100 # define MAXPACKET 65536
102 /* As per RFC 1034 and 1035 a host name cannot exceed 255 octets in length. */
103 #ifdef MAXHOSTNAMELEN
104 # undef MAXHOSTNAMELEN
106 #define MAXHOSTNAMELEN 256
108 /* We need this time later. */
109 typedef union querybuf
112 u_char buf
[MAXPACKET
];
115 static enum nss_status
getanswer_r (struct resolv_context
*ctx
,
116 const querybuf
*answer
, int anslen
,
117 const char *qname
, int qtype
,
118 struct hostent
*result
, char *buffer
,
119 size_t buflen
, int *errnop
, int *h_errnop
,
120 int map
, int32_t *ttlp
, char **canonp
);
122 static enum nss_status
gaih_getanswer (const querybuf
*answer1
, int anslen1
,
123 const querybuf
*answer2
, int anslen2
,
125 struct gaih_addrtuple
**pat
,
126 char *buffer
, size_t buflen
,
127 int *errnop
, int *h_errnop
,
130 static enum nss_status
gethostbyname3_context (struct resolv_context
*ctx
,
131 const char *name
, int af
,
132 struct hostent
*result
,
133 char *buffer
, size_t buflen
,
134 int *errnop
, int *h_errnop
,
138 /* Return the expected RDATA length for an address record type (A or
141 rrtype_to_rdata_length (int type
)
156 _nss_dns_gethostbyname3_r (const char *name
, int af
, struct hostent
*result
,
157 char *buffer
, size_t buflen
, int *errnop
,
158 int *h_errnop
, int32_t *ttlp
, char **canonp
)
160 struct resolv_context
*ctx
= __resolv_context_get ();
164 *h_errnop
= NETDB_INTERNAL
;
165 return NSS_STATUS_UNAVAIL
;
167 enum nss_status status
= gethostbyname3_context
168 (ctx
, name
, af
, result
, buffer
, buflen
, errnop
, h_errnop
, ttlp
, canonp
);
169 __resolv_context_put (ctx
);
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
)
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
);
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
);
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
);
424 extern enum nss_status
_nss_dns_gethostbyaddr2_r (const void *addr
,
425 socklen_t len
, int af
,
426 struct hostent
*result
,
427 char *buffer
, size_t buflen
,
428 int *errnop
, int *h_errnop
,
430 hidden_proto (_nss_dns_gethostbyaddr2_r
)
433 _nss_dns_gethostbyaddr2_r (const void *addr
, socklen_t len
, int af
,
434 struct hostent
*result
, char *buffer
, size_t buflen
,
435 int *errnop
, int *h_errnop
, int32_t *ttlp
)
437 static const u_char mapped
[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
438 static const u_char tunnelled
[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
439 static const u_char v6local
[] = { 0,0, 0,1 };
440 const u_char
*uaddr
= (const u_char
*)addr
;
443 char *aliases
[MAX_NR_ALIASES
];
444 unsigned char host_addr
[16]; /* IPv4 or IPv6 */
445 char *h_addr_ptrs
[MAX_NR_ADDRS
+ 1];
447 } *host_data
= (struct host_data
*) buffer
;
453 querybuf
*orig_host_buffer
;
454 char qbuf
[MAXDNAME
+1], *qp
= NULL
;
459 uintptr_t pad
= -(uintptr_t) buffer
% __alignof__ (struct host_data
);
461 buflen
= buflen
> pad
? buflen
- pad
: 0;
463 if (__glibc_unlikely (buflen
< sizeof (struct host_data
)))
466 *h_errnop
= NETDB_INTERNAL
;
467 return NSS_STATUS_TRYAGAIN
;
470 host_data
= (struct host_data
*) buffer
;
472 struct resolv_context
*ctx
= __resolv_context_get ();
476 *h_errnop
= NETDB_INTERNAL
;
477 return NSS_STATUS_UNAVAIL
;
480 if (af
== AF_INET6
&& len
== IN6ADDRSZ
481 && (memcmp (uaddr
, mapped
, sizeof mapped
) == 0
482 || (memcmp (uaddr
, tunnelled
, sizeof tunnelled
) == 0
483 && memcmp (&uaddr
[sizeof tunnelled
], v6local
, sizeof v6local
))))
486 addr
+= sizeof mapped
;
487 uaddr
+= sizeof mapped
;
501 *errnop
= EAFNOSUPPORT
;
502 *h_errnop
= NETDB_INTERNAL
;
503 __resolv_context_put (ctx
);
504 return NSS_STATUS_UNAVAIL
;
508 *errnop
= EAFNOSUPPORT
;
509 *h_errnop
= NETDB_INTERNAL
;
510 __resolv_context_put (ctx
);
511 return NSS_STATUS_UNAVAIL
;
514 host_buffer
.buf
= orig_host_buffer
= (querybuf
*) alloca (1024);
519 sprintf (qbuf
, "%u.%u.%u.%u.in-addr.arpa", (uaddr
[3] & 0xff),
520 (uaddr
[2] & 0xff), (uaddr
[1] & 0xff), (uaddr
[0] & 0xff));
524 for (n
= IN6ADDRSZ
- 1; n
>= 0; n
--)
526 static const char nibblechar
[16] = "0123456789abcdef";
527 *qp
++ = nibblechar
[uaddr
[n
] & 0xf];
529 *qp
++ = nibblechar
[(uaddr
[n
] >> 4) & 0xf];
532 strcpy(qp
, "ip6.arpa");
539 n
= __res_context_query (ctx
, qbuf
, C_IN
, T_PTR
, host_buffer
.buf
->buf
,
540 1024, &host_buffer
.ptr
, NULL
, NULL
, NULL
, NULL
);
544 __set_errno (olderr
);
545 if (host_buffer
.buf
!= orig_host_buffer
)
546 free (host_buffer
.buf
);
547 __resolv_context_put (ctx
);
548 return errno
== ECONNREFUSED
? NSS_STATUS_UNAVAIL
: NSS_STATUS_NOTFOUND
;
552 (ctx
, host_buffer
.buf
, n
, qbuf
, T_PTR
, result
, buffer
, buflen
,
553 errnop
, h_errnop
, 0 /* XXX */, ttlp
, NULL
);
554 if (host_buffer
.buf
!= orig_host_buffer
)
555 free (host_buffer
.buf
);
556 if (status
!= NSS_STATUS_SUCCESS
)
558 __resolv_context_put (ctx
);
562 result
->h_addrtype
= af
;
563 result
->h_length
= len
;
564 memcpy (host_data
->host_addr
, addr
, len
);
565 host_data
->h_addr_ptrs
[0] = (char *) host_data
->host_addr
;
566 host_data
->h_addr_ptrs
[1] = NULL
;
567 *h_errnop
= NETDB_SUCCESS
;
568 __resolv_context_put (ctx
);
569 return NSS_STATUS_SUCCESS
;
571 hidden_def (_nss_dns_gethostbyaddr2_r
)
575 _nss_dns_gethostbyaddr_r (const void *addr
, socklen_t len
, int af
,
576 struct hostent
*result
, char *buffer
, size_t buflen
,
577 int *errnop
, int *h_errnop
)
579 return _nss_dns_gethostbyaddr2_r (addr
, len
, af
, result
, buffer
, buflen
,
580 errnop
, h_errnop
, NULL
);
584 addrsort (struct resolv_context
*ctx
, char **ap
, int num
)
588 short aval
[MAX_NR_ADDRS
];
590 size_t nsort
= __resolv_context_sort_count (ctx
);
593 if (num
> MAX_NR_ADDRS
)
595 for (i
= 0; i
< num
; i
++, p
++)
597 for (j
= 0 ; (unsigned)j
< nsort
; j
++)
599 struct resolv_sortlist_entry e
600 = __resolv_context_sort_entry (ctx
, j
);
601 if (e
.addr
.s_addr
== (((struct in_addr
*)(*p
))->s_addr
& e
.mask
))
605 if (needsort
== 0 && i
> 0 && j
< aval
[i
-1])
611 while (needsort
++ < num
)
612 for (j
= needsort
- 2; j
>= 0; j
--)
613 if (aval
[j
] > aval
[j
+1])
629 static enum nss_status
630 getanswer_r (struct resolv_context
*ctx
,
631 const querybuf
*answer
, int anslen
, const char *qname
, int qtype
,
632 struct hostent
*result
, char *buffer
, size_t buflen
,
633 int *errnop
, int *h_errnop
, int map
, int32_t *ttlp
, char **canonp
)
637 char *aliases
[MAX_NR_ALIASES
];
638 unsigned char host_addr
[16]; /* IPv4 or IPv6 */
639 char *h_addr_ptrs
[0];
643 const u_char
*end_of_message
, *cp
;
644 int n
, ancount
, qdcount
;
645 int haveanswer
, had_error
;
646 char *bp
, **ap
, **hap
;
649 int (*name_ok
) (const char *);
650 u_char packtmp
[NS_MAXCDNAME
];
652 uintptr_t pad
= -(uintptr_t) buffer
% __alignof__ (struct host_data
);
654 buflen
= buflen
> pad
? buflen
- pad
: 0;
655 if (__glibc_unlikely (buflen
< sizeof (struct host_data
)))
657 /* The buffer is too small. */
660 *h_errnop
= NETDB_INTERNAL
;
661 return NSS_STATUS_TRYAGAIN
;
663 host_data
= (struct host_data
*) buffer
;
664 linebuflen
= buflen
- sizeof (struct host_data
);
665 if (buflen
- sizeof (struct host_data
) != linebuflen
)
666 linebuflen
= INT_MAX
;
669 result
->h_name
= NULL
;
670 end_of_message
= answer
->buf
+ anslen
;
682 return NSS_STATUS_UNAVAIL
; /* XXX should be abort(); */
686 * find first satisfactory answer
689 ancount
= ntohs (hp
->ancount
);
690 qdcount
= ntohs (hp
->qdcount
);
691 cp
= answer
->buf
+ HFIXEDSZ
;
692 if (__glibc_unlikely (qdcount
!= 1))
694 *h_errnop
= NO_RECOVERY
;
695 return NSS_STATUS_UNAVAIL
;
697 if (sizeof (struct host_data
) + (ancount
+ 1) * sizeof (char *) >= buflen
)
699 bp
= (char *) &host_data
->h_addr_ptrs
[ancount
+ 1];
700 linebuflen
-= (ancount
+ 1) * sizeof (char *);
702 n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
703 packtmp
, sizeof packtmp
);
704 if (n
!= -1 && __ns_name_ntop (packtmp
, bp
, linebuflen
) == -1)
706 if (__glibc_unlikely (errno
== EMSGSIZE
))
712 if (__glibc_unlikely (n
< 0))
715 *h_errnop
= NO_RECOVERY
;
716 return NSS_STATUS_UNAVAIL
;
718 if (__glibc_unlikely (name_ok (bp
) == 0))
722 *h_errnop
= NO_RECOVERY
;
723 return NSS_STATUS_UNAVAIL
;
727 if (qtype
== T_A
|| qtype
== T_AAAA
)
729 /* res_send() has already verified that the query name is the
730 * same as the one we sent; this just gets the expanded name
731 * (i.e., with the succeeding search-domain tacked on).
733 n
= strlen (bp
) + 1; /* for the \0 */
734 if (n
>= MAXHOSTNAMELEN
)
736 *h_errnop
= NO_RECOVERY
;
738 return NSS_STATUS_TRYAGAIN
;
745 /* The qname can be abbreviated, but h_name is now absolute. */
746 qname
= result
->h_name
;
749 ap
= host_data
->aliases
;
751 result
->h_aliases
= host_data
->aliases
;
752 hap
= host_data
->h_addr_ptrs
;
754 result
->h_addr_list
= host_data
->h_addr_ptrs
;
758 while (ancount
-- > 0 && cp
< end_of_message
&& had_error
== 0)
762 n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
763 packtmp
, sizeof packtmp
);
764 if (n
!= -1 && __ns_name_ntop (packtmp
, bp
, linebuflen
) == -1)
766 if (__glibc_unlikely (errno
== EMSGSIZE
))
772 if (__glibc_unlikely (n
< 0 || (*name_ok
) (bp
) == 0))
779 if (__glibc_unlikely (cp
+ 10 > end_of_message
))
785 type
= __ns_get16 (cp
);
786 cp
+= INT16SZ
; /* type */
787 class = __ns_get16 (cp
);
788 cp
+= INT16SZ
; /* class */
789 int32_t ttl
= __ns_get32 (cp
);
790 cp
+= INT32SZ
; /* TTL */
792 cp
+= INT16SZ
; /* len */
794 if (end_of_message
- cp
< n
)
796 /* RDATA extends beyond the end of the packet. */
801 if (__glibc_unlikely (class != C_IN
))
803 /* XXX - debug? syslog? */
805 continue; /* XXX - had_error++ ? */
808 if ((qtype
== T_A
|| qtype
== T_AAAA
) && type
== T_CNAME
)
810 /* A CNAME could also have a TTL entry. */
811 if (ttlp
!= NULL
&& ttl
< *ttlp
)
814 if (ap
>= &host_data
->aliases
[MAX_NR_ALIASES
- 1])
816 n
= dn_expand (answer
->buf
, end_of_message
, cp
, tbuf
, sizeof tbuf
);
817 if (__glibc_unlikely (n
< 0 || (*name_ok
) (tbuf
) == 0))
825 n
= strlen (bp
) + 1; /* For the \0. */
826 if (__glibc_unlikely (n
>= MAXHOSTNAMELEN
))
833 /* Get canonical name. */
834 n
= strlen (tbuf
) + 1; /* For the \0. */
835 if (__glibc_unlikely (n
> linebuflen
))
837 if (__glibc_unlikely (n
>= MAXHOSTNAMELEN
))
843 bp
= __mempcpy (bp
, tbuf
, n
); /* Cannot overflow. */
848 if (qtype
== T_PTR
&& type
== T_CNAME
)
850 /* A CNAME could also have a TTL entry. */
851 if (ttlp
!= NULL
&& ttl
< *ttlp
)
854 n
= dn_expand (answer
->buf
, end_of_message
, cp
, tbuf
, sizeof tbuf
);
855 if (__glibc_unlikely (n
< 0 || res_dnok (tbuf
) == 0))
861 /* Get canonical name. */
862 n
= strlen (tbuf
) + 1; /* For the \0. */
863 if (__glibc_unlikely (n
> linebuflen
))
865 if (__glibc_unlikely (n
>= MAXHOSTNAMELEN
))
871 bp
= __mempcpy (bp
, tbuf
, n
); /* Cannot overflow. */
876 if (type
== T_A
&& qtype
== T_AAAA
&& map
)
878 else if (__glibc_unlikely (type
!= qtype
))
881 continue; /* XXX - had_error++ ? */
887 if (__glibc_unlikely (strcasecmp (tname
, bp
) != 0))
890 continue; /* XXX - had_error++ ? */
893 n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
894 packtmp
, sizeof packtmp
);
895 if (n
!= -1 && __ns_name_ntop (packtmp
, bp
, linebuflen
) == -1)
897 if (__glibc_unlikely (errno
== EMSGSIZE
))
903 if (__glibc_unlikely (n
< 0 || res_hnok (bp
) == 0))
908 if (ttlp
!= NULL
&& ttl
< *ttlp
)
910 /* bind would put multiple PTR records as aliases, but we don't do
913 *h_errnop
= NETDB_SUCCESS
;
914 return NSS_STATUS_SUCCESS
;
917 if (__glibc_unlikely (strcasecmp (result
->h_name
, bp
) != 0))
920 continue; /* XXX - had_error++ ? */
923 /* Stop parsing at a record whose length is incorrect. */
924 if (n
!= rrtype_to_rdata_length (type
))
930 /* Skip records of the wrong type. */
931 if (n
!= result
->h_length
)
940 /* We compose a single hostent out of the entire chain of
941 entries, so the TTL of the hostent is essentially the lowest
943 if (ttlp
!= NULL
&& ttl
< *ttlp
)
948 nn
= strlen (bp
) + 1; /* for the \0 */
953 /* Provide sufficient alignment for both address
956 _Static_assert ((align
% __alignof__ (struct in_addr
)) == 0,
957 "struct in_addr alignment");
958 _Static_assert ((align
% __alignof__ (struct in6_addr
)) == 0,
959 "struct in6_addr alignment");
961 char *new_bp
= PTR_ALIGN_UP (bp
, align
);
962 linebuflen
-= new_bp
- bp
;
966 if (__glibc_unlikely (n
> linebuflen
))
968 bp
= __mempcpy (*hap
++ = bp
, cp
, n
);
984 * Note: we sort even if host can take only one address
985 * in its return structures - should give it the "best"
986 * address in that case, not some random one
988 if (haveanswer
> 1 && qtype
== T_A
989 && __resolv_context_sort_count (ctx
) > 0)
990 addrsort (ctx
, host_data
->h_addr_ptrs
, haveanswer
);
992 if (result
->h_name
== NULL
)
994 n
= strlen (qname
) + 1; /* For the \0. */
997 if (n
>= MAXHOSTNAMELEN
)
1000 bp
= __mempcpy (bp
, qname
, n
); /* Cannot overflow. */
1005 if (map_v4v6_hostent (result
, &bp
, &linebuflen
))
1007 *h_errnop
= NETDB_SUCCESS
;
1008 return NSS_STATUS_SUCCESS
;
1011 *h_errnop
= NO_RECOVERY
;
1013 /* Special case here: if the resolver sent a result but it only
1014 contains a CNAME while we are looking for a T_A or T_AAAA record,
1015 we fail with NOTFOUND instead of TRYAGAIN. */
1016 return ((qtype
== T_A
|| qtype
== T_AAAA
) && ap
!= host_data
->aliases
1017 ? NSS_STATUS_NOTFOUND
: NSS_STATUS_TRYAGAIN
);
1021 static enum nss_status
1022 gaih_getanswer_slice (const querybuf
*answer
, int anslen
, const char *qname
,
1023 struct gaih_addrtuple
***patp
,
1024 char **bufferp
, size_t *buflenp
,
1025 int *errnop
, int *h_errnop
, int32_t *ttlp
, int *firstp
)
1027 char *buffer
= *bufferp
;
1028 size_t buflen
= *buflenp
;
1030 struct gaih_addrtuple
**pat
= *patp
;
1031 const HEADER
*hp
= &answer
->hdr
;
1032 int ancount
= ntohs (hp
->ancount
);
1033 int qdcount
= ntohs (hp
->qdcount
);
1034 const u_char
*cp
= answer
->buf
+ HFIXEDSZ
;
1035 const u_char
*end_of_message
= answer
->buf
+ anslen
;
1036 if (__glibc_unlikely (qdcount
!= 1))
1038 *h_errnop
= NO_RECOVERY
;
1039 return NSS_STATUS_UNAVAIL
;
1042 u_char packtmp
[NS_MAXCDNAME
];
1043 int n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
1044 packtmp
, sizeof packtmp
);
1045 /* We unpack the name to check it for validity. But we do not need
1047 if (n
!= -1 && __ns_name_ntop (packtmp
, buffer
, buflen
) == -1)
1049 if (__glibc_unlikely (errno
== EMSGSIZE
))
1053 *h_errnop
= NETDB_INTERNAL
;
1054 return NSS_STATUS_TRYAGAIN
;
1060 if (__glibc_unlikely (n
< 0))
1063 *h_errnop
= NO_RECOVERY
;
1064 return NSS_STATUS_UNAVAIL
;
1066 if (__glibc_unlikely (res_hnok (buffer
) == 0))
1070 *h_errnop
= NO_RECOVERY
;
1071 return NSS_STATUS_UNAVAIL
;
1078 char *h_name
= NULL
;
1083 *h_errnop
= HOST_NOT_FOUND
;
1084 return NSS_STATUS_NOTFOUND
;
1087 while (ancount
-- > 0 && cp
< end_of_message
&& had_error
== 0)
1089 n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
1090 packtmp
, sizeof packtmp
);
1092 (h_namelen
= __ns_name_ntop (packtmp
, buffer
, buflen
)) == -1)
1094 if (__glibc_unlikely (errno
== EMSGSIZE
))
1099 if (__glibc_unlikely (n
< 0 || res_hnok (buffer
) == 0))
1104 if (*firstp
&& canon
== NULL
)
1107 buffer
+= h_namelen
;
1108 buflen
-= h_namelen
;
1113 if (__glibc_unlikely (cp
+ 10 > end_of_message
))
1119 int type
= __ns_get16 (cp
);
1120 cp
+= INT16SZ
; /* type */
1121 int class = __ns_get16 (cp
);
1122 cp
+= INT16SZ
; /* class */
1123 int32_t ttl
= __ns_get32 (cp
);
1124 cp
+= INT32SZ
; /* TTL */
1125 n
= __ns_get16 (cp
);
1126 cp
+= INT16SZ
; /* len */
1128 if (end_of_message
- cp
< n
)
1130 /* RDATA extends beyond the end of the packet. */
1141 if (type
== T_CNAME
)
1143 char tbuf
[MAXDNAME
];
1145 /* A CNAME could also have a TTL entry. */
1146 if (ttlp
!= NULL
&& ttl
< *ttlp
)
1149 n
= dn_expand (answer
->buf
, end_of_message
, cp
, tbuf
, sizeof tbuf
);
1150 if (__glibc_unlikely (n
< 0 || res_hnok (tbuf
) == 0))
1159 /* Reclaim buffer space. */
1160 if (h_name
+ h_namelen
== buffer
)
1163 buflen
+= h_namelen
;
1166 n
= strlen (tbuf
) + 1;
1167 if (__glibc_unlikely (n
> buflen
))
1169 if (__glibc_unlikely (n
>= MAXHOSTNAMELEN
))
1176 buffer
= __mempcpy (buffer
, tbuf
, n
);
1183 /* Stop parsing if we encounter a record with incorrect RDATA
1185 if (type
== T_A
|| type
== T_AAAA
)
1187 if (n
!= rrtype_to_rdata_length (type
))
1195 /* Skip unknown records. */
1200 assert (type
== T_A
|| type
== T_AAAA
);
1203 uintptr_t pad
= (-(uintptr_t) buffer
1204 % __alignof__ (struct gaih_addrtuple
));
1206 buflen
= buflen
> pad
? buflen
- pad
: 0;
1208 if (__glibc_unlikely (buflen
< sizeof (struct gaih_addrtuple
)))
1211 *pat
= (struct gaih_addrtuple
*) buffer
;
1212 buffer
+= sizeof (struct gaih_addrtuple
);
1213 buflen
-= sizeof (struct gaih_addrtuple
);
1216 (*pat
)->name
= NULL
;
1217 (*pat
)->next
= NULL
;
1221 /* We compose a single hostent out of the entire chain of
1222 entries, so the TTL of the hostent is essentially the lowest
1223 TTL in the chain. */
1224 if (ttlp
!= NULL
&& ttl
< *ttlp
)
1227 (*pat
)->name
= canon
?: h_name
;
1232 (*pat
)->family
= type
== T_A
? AF_INET
: AF_INET6
;
1233 memcpy ((*pat
)->addr
, cp
, n
);
1235 (*pat
)->scopeid
= 0;
1237 pat
= &((*pat
)->next
);
1248 *h_errnop
= NETDB_SUCCESS
;
1249 return NSS_STATUS_SUCCESS
;
1252 /* Special case here: if the resolver sent a result but it only
1253 contains a CNAME while we are looking for a T_A or T_AAAA record,
1254 we fail with NOTFOUND instead of TRYAGAIN. */
1257 *h_errnop
= HOST_NOT_FOUND
;
1258 return NSS_STATUS_NOTFOUND
;
1261 *h_errnop
= NETDB_INTERNAL
;
1262 return NSS_STATUS_TRYAGAIN
;
1266 static enum nss_status
1267 gaih_getanswer (const querybuf
*answer1
, int anslen1
, const querybuf
*answer2
,
1268 int anslen2
, const char *qname
,
1269 struct gaih_addrtuple
**pat
, char *buffer
, size_t buflen
,
1270 int *errnop
, int *h_errnop
, int32_t *ttlp
)
1274 enum nss_status status
= NSS_STATUS_NOTFOUND
;
1276 /* Combining the NSS status of two distinct queries requires some
1277 compromise and attention to symmetry (A or AAAA queries can be
1278 returned in any order). What follows is a breakdown of how this
1279 code is expected to work and why. We discuss only SUCCESS,
1280 TRYAGAIN, NOTFOUND and UNAVAIL, since they are the only returns
1281 that apply (though RETURN and MERGE exist). We make a distinction
1282 between TRYAGAIN (recoverable) and TRYAGAIN' (not-recoverable).
1283 A recoverable TRYAGAIN is almost always due to buffer size issues
1284 and returns ERANGE in errno and the caller is expected to retry
1285 with a larger buffer.
1287 Lastly, you may be tempted to make significant changes to the
1288 conditions in this code to bring about symmetry between responses.
1289 Please don't change anything without due consideration for
1290 expected application behaviour. Some of the synthesized responses
1291 aren't very well thought out and sometimes appear to imply that
1292 IPv4 responses are always answer 1, and IPv6 responses are always
1293 answer 2, but that's not true (see the implementation of send_dg
1294 and send_vc to see response can arrive in any order, particularly
1295 for UDP). However, we expect it holds roughly enough of the time
1296 that this code works, but certainly needs to be fixed to make this
1297 a more robust implementation.
1299 ----------------------------------------------
1300 | Answer 1 Status / | Synthesized | Reason |
1301 | Answer 2 Status | Status | |
1302 |--------------------------------------------|
1303 | SUCCESS/SUCCESS | SUCCESS | [1] |
1304 | SUCCESS/TRYAGAIN | TRYAGAIN | [5] |
1305 | SUCCESS/TRYAGAIN' | SUCCESS | [1] |
1306 | SUCCESS/NOTFOUND | SUCCESS | [1] |
1307 | SUCCESS/UNAVAIL | SUCCESS | [1] |
1308 | TRYAGAIN/SUCCESS | TRYAGAIN | [2] |
1309 | TRYAGAIN/TRYAGAIN | TRYAGAIN | [2] |
1310 | TRYAGAIN/TRYAGAIN' | TRYAGAIN | [2] |
1311 | TRYAGAIN/NOTFOUND | TRYAGAIN | [2] |
1312 | TRYAGAIN/UNAVAIL | TRYAGAIN | [2] |
1313 | TRYAGAIN'/SUCCESS | SUCCESS | [3] |
1314 | TRYAGAIN'/TRYAGAIN | TRYAGAIN | [3] |
1315 | TRYAGAIN'/TRYAGAIN' | TRYAGAIN' | [3] |
1316 | TRYAGAIN'/NOTFOUND | TRYAGAIN' | [3] |
1317 | TRYAGAIN'/UNAVAIL | UNAVAIL | [3] |
1318 | NOTFOUND/SUCCESS | SUCCESS | [3] |
1319 | NOTFOUND/TRYAGAIN | TRYAGAIN | [3] |
1320 | NOTFOUND/TRYAGAIN' | TRYAGAIN' | [3] |
1321 | NOTFOUND/NOTFOUND | NOTFOUND | [3] |
1322 | NOTFOUND/UNAVAIL | UNAVAIL | [3] |
1323 | UNAVAIL/SUCCESS | UNAVAIL | [4] |
1324 | UNAVAIL/TRYAGAIN | UNAVAIL | [4] |
1325 | UNAVAIL/TRYAGAIN' | UNAVAIL | [4] |
1326 | UNAVAIL/NOTFOUND | UNAVAIL | [4] |
1327 | UNAVAIL/UNAVAIL | UNAVAIL | [4] |
1328 ----------------------------------------------
1330 [1] If the first response is a success we return success.
1331 This ignores the state of the second answer and in fact
1332 incorrectly sets errno and h_errno to that of the second
1333 answer. However because the response is a success we ignore
1334 *errnop and *h_errnop (though that means you touched errno on
1335 success). We are being conservative here and returning the
1336 likely IPv4 response in the first answer as a success.
1338 [2] If the first response is a recoverable TRYAGAIN we return
1339 that instead of looking at the second response. The
1340 expectation here is that we have failed to get an IPv4 response
1341 and should retry both queries.
1343 [3] If the first response was not a SUCCESS and the second
1344 response is not NOTFOUND (had a SUCCESS, need to TRYAGAIN,
1345 or failed entirely e.g. TRYAGAIN' and UNAVAIL) then use the
1346 result from the second response, otherwise the first responses
1347 status is used. Again we have some odd side-effects when the
1348 second response is NOTFOUND because we overwrite *errnop and
1349 *h_errnop that means that a first answer of NOTFOUND might see
1350 its *errnop and *h_errnop values altered. Whether it matters
1351 in practice that a first response NOTFOUND has the wrong
1352 *errnop and *h_errnop is undecided.
1354 [4] If the first response is UNAVAIL we return that instead of
1355 looking at the second response. The expectation here is that
1356 it will have failed similarly e.g. configuration failure.
1358 [5] Testing this code is complicated by the fact that truncated
1359 second response buffers might be returned as SUCCESS if the
1360 first answer is a SUCCESS. To fix this we add symmetry to
1361 TRYAGAIN with the second response. If the second response
1362 is a recoverable error we now return TRYAGIN even if the first
1363 response was SUCCESS. */
1366 status
= gaih_getanswer_slice(answer1
, anslen1
, qname
,
1367 &pat
, &buffer
, &buflen
,
1368 errnop
, h_errnop
, ttlp
,
1371 if ((status
== NSS_STATUS_SUCCESS
|| status
== NSS_STATUS_NOTFOUND
1372 || (status
== NSS_STATUS_TRYAGAIN
1373 /* We want to look at the second answer in case of an
1374 NSS_STATUS_TRYAGAIN only if the error is non-recoverable, i.e.
1375 *h_errnop is NO_RECOVERY. If not, and if the failure was due to
1376 an insufficient buffer (ERANGE), then we need to drop the results
1377 and pass on the NSS_STATUS_TRYAGAIN to the caller so that it can
1378 repeat the query with a larger buffer. */
1379 && (*errnop
!= ERANGE
|| *h_errnop
== NO_RECOVERY
)))
1380 && answer2
!= NULL
&& anslen2
> 0)
1382 enum nss_status status2
= gaih_getanswer_slice(answer2
, anslen2
, qname
,
1383 &pat
, &buffer
, &buflen
,
1384 errnop
, h_errnop
, ttlp
,
1386 /* Use the second response status in some cases. */
1387 if (status
!= NSS_STATUS_SUCCESS
&& status2
!= NSS_STATUS_NOTFOUND
)
1389 /* Do not return a truncated second response (unless it was
1390 unavoidable e.g. unrecoverable TRYAGAIN). */
1391 if (status
== NSS_STATUS_SUCCESS
1392 && (status2
== NSS_STATUS_TRYAGAIN
1393 && *errnop
== ERANGE
&& *h_errnop
!= NO_RECOVERY
))
1394 status
= NSS_STATUS_TRYAGAIN
;