1 /* Copyright (C) 1996-2019 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>
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
);
171 static enum nss_status
172 gethostbyname3_context (struct resolv_context
*ctx
,
173 const char *name
, int af
, struct hostent
*result
,
174 char *buffer
, size_t buflen
, int *errnop
,
175 int *h_errnop
, int32_t *ttlp
, char **canonp
)
182 querybuf
*orig_host_buffer
;
183 char tmp
[NS_MAXDNAME
];
188 enum nss_status status
;
201 *errnop
= EAFNOSUPPORT
;
202 return NSS_STATUS_UNAVAIL
;
205 result
->h_addrtype
= af
;
206 result
->h_length
= size
;
209 * if there aren't any dots, it could be a user-level alias.
210 * this is also done in res_query() since we are not the only
211 * function that looks up host names.
213 if (strchr (name
, '.') == NULL
214 && (cp
= __res_context_hostalias (ctx
, name
, tmp
, sizeof (tmp
))) != NULL
)
217 host_buffer
.buf
= orig_host_buffer
= (querybuf
*) alloca (1024);
219 n
= __res_context_search (ctx
, name
, C_IN
, type
, host_buffer
.buf
->buf
,
220 1024, &host_buffer
.ptr
, NULL
, NULL
, NULL
, NULL
);
226 status
= NSS_STATUS_TRYAGAIN
;
229 /* System has run out of file descriptors. */
232 h_errno
= NETDB_INTERNAL
;
236 status
= NSS_STATUS_UNAVAIL
;
239 status
= NSS_STATUS_NOTFOUND
;
243 if (h_errno
== TRY_AGAIN
)
246 __set_errno (olderr
);
248 /* If we are looking for an IPv6 address and mapping is enabled
249 by having the RES_USE_INET6 bit in _res.options set, we try
251 if (af
== AF_INET6
&& res_use_inet6 ())
252 n
= __res_context_search (ctx
, name
, C_IN
, T_A
, host_buffer
.buf
->buf
,
253 host_buffer
.buf
!= orig_host_buffer
254 ? MAXPACKET
: 1024, &host_buffer
.ptr
,
255 NULL
, NULL
, NULL
, NULL
);
259 if (host_buffer
.buf
!= orig_host_buffer
)
260 free (host_buffer
.buf
);
266 result
->h_addrtype
= AF_INET
;
267 result
->h_length
= INADDRSZ
;
271 (ctx
, host_buffer
.buf
, n
, name
, type
, result
, buffer
, buflen
,
272 errnop
, h_errnop
, map
, ttlp
, canonp
);
273 if (host_buffer
.buf
!= orig_host_buffer
)
274 free (host_buffer
.buf
);
278 /* Verify that the name looks like a host name. There is no point in
279 sending a query which will not produce a usable name in the
281 static enum nss_status
282 check_name (const char *name
, int *h_errnop
)
285 return NSS_STATUS_SUCCESS
;
286 *h_errnop
= HOST_NOT_FOUND
;
287 return NSS_STATUS_NOTFOUND
;
291 _nss_dns_gethostbyname2_r (const char *name
, int af
, struct hostent
*result
,
292 char *buffer
, size_t buflen
, int *errnop
,
295 enum nss_status status
= check_name (name
, h_errnop
);
296 if (status
!= NSS_STATUS_SUCCESS
)
298 return _nss_dns_gethostbyname3_r (name
, af
, result
, buffer
, buflen
, errnop
,
299 h_errnop
, NULL
, NULL
);
304 _nss_dns_gethostbyname_r (const char *name
, struct hostent
*result
,
305 char *buffer
, size_t buflen
, int *errnop
,
308 enum nss_status status
= check_name (name
, h_errnop
);
309 if (status
!= NSS_STATUS_SUCCESS
)
311 struct resolv_context
*ctx
= __resolv_context_get ();
315 *h_errnop
= NETDB_INTERNAL
;
316 return NSS_STATUS_UNAVAIL
;
318 status
= NSS_STATUS_NOTFOUND
;
319 if (res_use_inet6 ())
320 status
= gethostbyname3_context (ctx
, name
, AF_INET6
, result
, buffer
,
321 buflen
, errnop
, h_errnop
, NULL
, NULL
);
322 if (status
== NSS_STATUS_NOTFOUND
)
323 status
= gethostbyname3_context (ctx
, name
, AF_INET
, result
, buffer
,
324 buflen
, errnop
, h_errnop
, NULL
, NULL
);
325 __resolv_context_put (ctx
);
331 _nss_dns_gethostbyname4_r (const char *name
, struct gaih_addrtuple
**pat
,
332 char *buffer
, size_t buflen
, int *errnop
,
333 int *herrnop
, int32_t *ttlp
)
335 enum nss_status status
= check_name (name
, herrnop
);
336 if (status
!= NSS_STATUS_SUCCESS
)
338 struct resolv_context
*ctx
= __resolv_context_get ();
342 *herrnop
= NETDB_INTERNAL
;
343 return NSS_STATUS_UNAVAIL
;
347 * if there aren't any dots, it could be a user-level alias.
348 * this is also done in res_query() since we are not the only
349 * function that looks up host names.
351 if (strchr (name
, '.') == NULL
)
353 char *tmp
= alloca (NS_MAXDNAME
);
354 const char *cp
= __res_context_hostalias (ctx
, name
, tmp
, NS_MAXDNAME
);
364 querybuf
*orig_host_buffer
;
365 host_buffer
.buf
= orig_host_buffer
= (querybuf
*) alloca (2048);
366 u_char
*ans2p
= NULL
;
369 int ans2p_malloced
= 0;
372 int n
= __res_context_search (ctx
, name
, C_IN
, T_QUERY_A_AND_AAAA
,
373 host_buffer
.buf
->buf
, 2048, &host_buffer
.ptr
,
374 &ans2p
, &nans2p
, &resplen2
, &ans2p_malloced
);
377 status
= gaih_getanswer (host_buffer
.buf
, n
, (const querybuf
*) ans2p
,
378 resplen2
, name
, pat
, buffer
, buflen
,
379 errnop
, herrnop
, ttlp
);
386 status
= NSS_STATUS_TRYAGAIN
;
389 /* System has run out of file descriptors. */
392 h_errno
= NETDB_INTERNAL
;
396 status
= NSS_STATUS_UNAVAIL
;
399 status
= NSS_STATUS_NOTFOUND
;
404 if (h_errno
== TRY_AGAIN
)
407 __set_errno (olderr
);
410 /* Check whether ans2p was separately allocated. */
414 if (host_buffer
.buf
!= orig_host_buffer
)
415 free (host_buffer
.buf
);
417 __resolv_context_put (ctx
);
422 extern enum nss_status
_nss_dns_gethostbyaddr2_r (const void *addr
,
423 socklen_t len
, int af
,
424 struct hostent
*result
,
425 char *buffer
, size_t buflen
,
426 int *errnop
, int *h_errnop
,
428 hidden_proto (_nss_dns_gethostbyaddr2_r
)
431 _nss_dns_gethostbyaddr2_r (const void *addr
, socklen_t len
, int af
,
432 struct hostent
*result
, char *buffer
, size_t buflen
,
433 int *errnop
, int *h_errnop
, int32_t *ttlp
)
435 static const u_char mapped
[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
436 static const u_char tunnelled
[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
437 static const u_char v6local
[] = { 0,0, 0,1 };
438 const u_char
*uaddr
= (const u_char
*)addr
;
441 char *aliases
[MAX_NR_ALIASES
];
442 unsigned char host_addr
[16]; /* IPv4 or IPv6 */
443 char *h_addr_ptrs
[MAX_NR_ADDRS
+ 1];
445 } *host_data
= (struct host_data
*) buffer
;
451 querybuf
*orig_host_buffer
;
452 char qbuf
[MAXDNAME
+1], *qp
= NULL
;
457 uintptr_t pad
= -(uintptr_t) buffer
% __alignof__ (struct host_data
);
459 buflen
= buflen
> pad
? buflen
- pad
: 0;
461 if (__glibc_unlikely (buflen
< sizeof (struct host_data
)))
464 *h_errnop
= NETDB_INTERNAL
;
465 return NSS_STATUS_TRYAGAIN
;
468 host_data
= (struct host_data
*) buffer
;
470 struct resolv_context
*ctx
= __resolv_context_get ();
474 *h_errnop
= NETDB_INTERNAL
;
475 return NSS_STATUS_UNAVAIL
;
478 if (af
== AF_INET6
&& len
== IN6ADDRSZ
479 && (memcmp (uaddr
, mapped
, sizeof mapped
) == 0
480 || (memcmp (uaddr
, tunnelled
, sizeof tunnelled
) == 0
481 && memcmp (&uaddr
[sizeof tunnelled
], v6local
, sizeof v6local
))))
484 addr
+= sizeof mapped
;
485 uaddr
+= sizeof mapped
;
499 *errnop
= EAFNOSUPPORT
;
500 *h_errnop
= NETDB_INTERNAL
;
501 __resolv_context_put (ctx
);
502 return NSS_STATUS_UNAVAIL
;
506 *errnop
= EAFNOSUPPORT
;
507 *h_errnop
= NETDB_INTERNAL
;
508 __resolv_context_put (ctx
);
509 return NSS_STATUS_UNAVAIL
;
512 host_buffer
.buf
= orig_host_buffer
= (querybuf
*) alloca (1024);
517 sprintf (qbuf
, "%u.%u.%u.%u.in-addr.arpa", (uaddr
[3] & 0xff),
518 (uaddr
[2] & 0xff), (uaddr
[1] & 0xff), (uaddr
[0] & 0xff));
522 for (n
= IN6ADDRSZ
- 1; n
>= 0; n
--)
524 static const char nibblechar
[16] = "0123456789abcdef";
525 *qp
++ = nibblechar
[uaddr
[n
] & 0xf];
527 *qp
++ = nibblechar
[(uaddr
[n
] >> 4) & 0xf];
530 strcpy(qp
, "ip6.arpa");
537 n
= __res_context_query (ctx
, qbuf
, C_IN
, T_PTR
, host_buffer
.buf
->buf
,
538 1024, &host_buffer
.ptr
, NULL
, NULL
, NULL
, NULL
);
542 __set_errno (olderr
);
543 if (host_buffer
.buf
!= orig_host_buffer
)
544 free (host_buffer
.buf
);
545 __resolv_context_put (ctx
);
546 return errno
== ECONNREFUSED
? NSS_STATUS_UNAVAIL
: NSS_STATUS_NOTFOUND
;
550 (ctx
, host_buffer
.buf
, n
, qbuf
, T_PTR
, result
, buffer
, buflen
,
551 errnop
, h_errnop
, 0 /* XXX */, ttlp
, NULL
);
552 if (host_buffer
.buf
!= orig_host_buffer
)
553 free (host_buffer
.buf
);
554 if (status
!= NSS_STATUS_SUCCESS
)
556 __resolv_context_put (ctx
);
560 result
->h_addrtype
= af
;
561 result
->h_length
= len
;
562 memcpy (host_data
->host_addr
, addr
, len
);
563 host_data
->h_addr_ptrs
[0] = (char *) host_data
->host_addr
;
564 host_data
->h_addr_ptrs
[1] = NULL
;
565 *h_errnop
= NETDB_SUCCESS
;
566 __resolv_context_put (ctx
);
567 return NSS_STATUS_SUCCESS
;
569 hidden_def (_nss_dns_gethostbyaddr2_r
)
573 _nss_dns_gethostbyaddr_r (const void *addr
, socklen_t len
, int af
,
574 struct hostent
*result
, char *buffer
, size_t buflen
,
575 int *errnop
, int *h_errnop
)
577 return _nss_dns_gethostbyaddr2_r (addr
, len
, af
, result
, buffer
, buflen
,
578 errnop
, h_errnop
, NULL
);
582 addrsort (struct resolv_context
*ctx
, char **ap
, int num
)
586 short aval
[MAX_NR_ADDRS
];
588 size_t nsort
= __resolv_context_sort_count (ctx
);
591 if (num
> MAX_NR_ADDRS
)
593 for (i
= 0; i
< num
; i
++, p
++)
595 for (j
= 0 ; (unsigned)j
< nsort
; j
++)
597 struct resolv_sortlist_entry e
598 = __resolv_context_sort_entry (ctx
, j
);
599 if (e
.addr
.s_addr
== (((struct in_addr
*)(*p
))->s_addr
& e
.mask
))
603 if (needsort
== 0 && i
> 0 && j
< aval
[i
-1])
609 while (needsort
++ < num
)
610 for (j
= needsort
- 2; j
>= 0; j
--)
611 if (aval
[j
] > aval
[j
+1])
627 static enum nss_status
628 getanswer_r (struct resolv_context
*ctx
,
629 const querybuf
*answer
, int anslen
, const char *qname
, int qtype
,
630 struct hostent
*result
, char *buffer
, size_t buflen
,
631 int *errnop
, int *h_errnop
, int map
, int32_t *ttlp
, char **canonp
)
635 char *aliases
[MAX_NR_ALIASES
];
636 unsigned char host_addr
[16]; /* IPv4 or IPv6 */
637 char *h_addr_ptrs
[0];
641 const u_char
*end_of_message
, *cp
;
642 int n
, ancount
, qdcount
;
643 int haveanswer
, had_error
;
644 char *bp
, **ap
, **hap
;
647 int (*name_ok
) (const char *);
648 u_char packtmp
[NS_MAXCDNAME
];
650 uintptr_t pad
= -(uintptr_t) buffer
% __alignof__ (struct host_data
);
652 buflen
= buflen
> pad
? buflen
- pad
: 0;
653 if (__glibc_unlikely (buflen
< sizeof (struct host_data
)))
655 /* The buffer is too small. */
658 *h_errnop
= NETDB_INTERNAL
;
659 return NSS_STATUS_TRYAGAIN
;
661 host_data
= (struct host_data
*) buffer
;
662 linebuflen
= buflen
- sizeof (struct host_data
);
663 if (buflen
- sizeof (struct host_data
) != linebuflen
)
664 linebuflen
= INT_MAX
;
667 result
->h_name
= NULL
;
668 end_of_message
= answer
->buf
+ anslen
;
680 return NSS_STATUS_UNAVAIL
; /* XXX should be abort(); */
684 * find first satisfactory answer
687 ancount
= ntohs (hp
->ancount
);
688 qdcount
= ntohs (hp
->qdcount
);
689 cp
= answer
->buf
+ HFIXEDSZ
;
690 if (__glibc_unlikely (qdcount
!= 1))
692 *h_errnop
= NO_RECOVERY
;
693 return NSS_STATUS_UNAVAIL
;
695 if (sizeof (struct host_data
) + (ancount
+ 1) * sizeof (char *) >= buflen
)
697 bp
= (char *) &host_data
->h_addr_ptrs
[ancount
+ 1];
698 linebuflen
-= (ancount
+ 1) * sizeof (char *);
700 n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
701 packtmp
, sizeof packtmp
);
702 if (n
!= -1 && __ns_name_ntop (packtmp
, bp
, linebuflen
) == -1)
704 if (__glibc_unlikely (errno
== EMSGSIZE
))
710 if (__glibc_unlikely (n
< 0))
713 *h_errnop
= NO_RECOVERY
;
714 return NSS_STATUS_UNAVAIL
;
716 if (__glibc_unlikely (name_ok (bp
) == 0))
720 *h_errnop
= NO_RECOVERY
;
721 return NSS_STATUS_UNAVAIL
;
725 if (qtype
== T_A
|| qtype
== T_AAAA
)
727 /* res_send() has already verified that the query name is the
728 * same as the one we sent; this just gets the expanded name
729 * (i.e., with the succeeding search-domain tacked on).
731 n
= strlen (bp
) + 1; /* for the \0 */
732 if (n
>= MAXHOSTNAMELEN
)
734 *h_errnop
= NO_RECOVERY
;
736 return NSS_STATUS_TRYAGAIN
;
743 /* The qname can be abbreviated, but h_name is now absolute. */
744 qname
= result
->h_name
;
747 ap
= host_data
->aliases
;
749 result
->h_aliases
= host_data
->aliases
;
750 hap
= host_data
->h_addr_ptrs
;
752 result
->h_addr_list
= host_data
->h_addr_ptrs
;
756 while (ancount
-- > 0 && cp
< end_of_message
&& had_error
== 0)
760 n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
761 packtmp
, sizeof packtmp
);
762 if (n
!= -1 && __ns_name_ntop (packtmp
, bp
, linebuflen
) == -1)
764 if (__glibc_unlikely (errno
== EMSGSIZE
))
770 if (__glibc_unlikely (n
< 0 || (*name_ok
) (bp
) == 0))
777 if (__glibc_unlikely (cp
+ 10 > end_of_message
))
783 type
= __ns_get16 (cp
);
784 cp
+= INT16SZ
; /* type */
785 class = __ns_get16 (cp
);
786 cp
+= INT16SZ
; /* class */
787 int32_t ttl
= __ns_get32 (cp
);
788 cp
+= INT32SZ
; /* TTL */
790 cp
+= INT16SZ
; /* len */
792 if (end_of_message
- cp
< n
)
794 /* RDATA extends beyond the end of the packet. */
799 if (__glibc_unlikely (class != C_IN
))
801 /* XXX - debug? syslog? */
803 continue; /* XXX - had_error++ ? */
806 if ((qtype
== T_A
|| qtype
== T_AAAA
) && type
== T_CNAME
)
808 /* A CNAME could also have a TTL entry. */
809 if (ttlp
!= NULL
&& ttl
< *ttlp
)
812 if (ap
>= &host_data
->aliases
[MAX_NR_ALIASES
- 1])
814 n
= dn_expand (answer
->buf
, end_of_message
, cp
, tbuf
, sizeof tbuf
);
815 if (__glibc_unlikely (n
< 0 || (*name_ok
) (tbuf
) == 0))
823 n
= strlen (bp
) + 1; /* For the \0. */
824 if (__glibc_unlikely (n
>= MAXHOSTNAMELEN
))
831 /* Get canonical name. */
832 n
= strlen (tbuf
) + 1; /* For the \0. */
833 if (__glibc_unlikely (n
> linebuflen
))
835 if (__glibc_unlikely (n
>= MAXHOSTNAMELEN
))
841 bp
= __mempcpy (bp
, tbuf
, n
); /* Cannot overflow. */
846 if (qtype
== T_PTR
&& type
== T_CNAME
)
848 /* A CNAME could also have a TTL entry. */
849 if (ttlp
!= NULL
&& ttl
< *ttlp
)
852 n
= dn_expand (answer
->buf
, end_of_message
, cp
, tbuf
, sizeof tbuf
);
853 if (__glibc_unlikely (n
< 0 || res_dnok (tbuf
) == 0))
859 /* Get canonical name. */
860 n
= strlen (tbuf
) + 1; /* For the \0. */
861 if (__glibc_unlikely (n
> linebuflen
))
863 if (__glibc_unlikely (n
>= MAXHOSTNAMELEN
))
869 bp
= __mempcpy (bp
, tbuf
, n
); /* Cannot overflow. */
874 if (type
== T_A
&& qtype
== T_AAAA
&& map
)
876 else if (__glibc_unlikely (type
!= qtype
))
879 continue; /* XXX - had_error++ ? */
885 if (__glibc_unlikely (strcasecmp (tname
, bp
) != 0))
888 continue; /* XXX - had_error++ ? */
891 n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
892 packtmp
, sizeof packtmp
);
893 if (n
!= -1 && __ns_name_ntop (packtmp
, bp
, linebuflen
) == -1)
895 if (__glibc_unlikely (errno
== EMSGSIZE
))
901 if (__glibc_unlikely (n
< 0 || res_hnok (bp
) == 0))
906 if (ttlp
!= NULL
&& ttl
< *ttlp
)
908 /* bind would put multiple PTR records as aliases, but we don't do
911 *h_errnop
= NETDB_SUCCESS
;
912 return NSS_STATUS_SUCCESS
;
915 if (__glibc_unlikely (strcasecmp (result
->h_name
, bp
) != 0))
918 continue; /* XXX - had_error++ ? */
921 /* Stop parsing at a record whose length is incorrect. */
922 if (n
!= rrtype_to_rdata_length (type
))
928 /* Skip records of the wrong type. */
929 if (n
!= result
->h_length
)
938 /* We compose a single hostent out of the entire chain of
939 entries, so the TTL of the hostent is essentially the lowest
941 if (ttlp
!= NULL
&& ttl
< *ttlp
)
946 nn
= strlen (bp
) + 1; /* for the \0 */
951 /* Provide sufficient alignment for both address
954 _Static_assert ((align
% __alignof__ (struct in_addr
)) == 0,
955 "struct in_addr alignment");
956 _Static_assert ((align
% __alignof__ (struct in6_addr
)) == 0,
957 "struct in6_addr alignment");
959 char *new_bp
= PTR_ALIGN_UP (bp
, align
);
960 linebuflen
-= new_bp
- bp
;
964 if (__glibc_unlikely (n
> linebuflen
))
966 bp
= __mempcpy (*hap
++ = bp
, cp
, n
);
982 * Note: we sort even if host can take only one address
983 * in its return structures - should give it the "best"
984 * address in that case, not some random one
986 if (haveanswer
> 1 && qtype
== T_A
987 && __resolv_context_sort_count (ctx
) > 0)
988 addrsort (ctx
, host_data
->h_addr_ptrs
, haveanswer
);
990 if (result
->h_name
== NULL
)
992 n
= strlen (qname
) + 1; /* For the \0. */
995 if (n
>= MAXHOSTNAMELEN
)
998 bp
= __mempcpy (bp
, qname
, n
); /* Cannot overflow. */
1003 if (map_v4v6_hostent (result
, &bp
, &linebuflen
))
1005 *h_errnop
= NETDB_SUCCESS
;
1006 return NSS_STATUS_SUCCESS
;
1009 *h_errnop
= NO_RECOVERY
;
1011 /* Special case here: if the resolver sent a result but it only
1012 contains a CNAME while we are looking for a T_A or T_AAAA record,
1013 we fail with NOTFOUND instead of TRYAGAIN. */
1014 return ((qtype
== T_A
|| qtype
== T_AAAA
) && ap
!= host_data
->aliases
1015 ? NSS_STATUS_NOTFOUND
: NSS_STATUS_TRYAGAIN
);
1019 static enum nss_status
1020 gaih_getanswer_slice (const querybuf
*answer
, int anslen
, const char *qname
,
1021 struct gaih_addrtuple
***patp
,
1022 char **bufferp
, size_t *buflenp
,
1023 int *errnop
, int *h_errnop
, int32_t *ttlp
, int *firstp
)
1025 char *buffer
= *bufferp
;
1026 size_t buflen
= *buflenp
;
1028 struct gaih_addrtuple
**pat
= *patp
;
1029 const HEADER
*hp
= &answer
->hdr
;
1030 int ancount
= ntohs (hp
->ancount
);
1031 int qdcount
= ntohs (hp
->qdcount
);
1032 const u_char
*cp
= answer
->buf
+ HFIXEDSZ
;
1033 const u_char
*end_of_message
= answer
->buf
+ anslen
;
1034 if (__glibc_unlikely (qdcount
!= 1))
1036 *h_errnop
= NO_RECOVERY
;
1037 return NSS_STATUS_UNAVAIL
;
1040 u_char packtmp
[NS_MAXCDNAME
];
1041 int n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
1042 packtmp
, sizeof packtmp
);
1043 /* We unpack the name to check it for validity. But we do not need
1045 if (n
!= -1 && __ns_name_ntop (packtmp
, buffer
, buflen
) == -1)
1047 if (__glibc_unlikely (errno
== EMSGSIZE
))
1051 *h_errnop
= NETDB_INTERNAL
;
1052 return NSS_STATUS_TRYAGAIN
;
1058 if (__glibc_unlikely (n
< 0))
1061 *h_errnop
= NO_RECOVERY
;
1062 return NSS_STATUS_UNAVAIL
;
1064 if (__glibc_unlikely (res_hnok (buffer
) == 0))
1068 *h_errnop
= NO_RECOVERY
;
1069 return NSS_STATUS_UNAVAIL
;
1076 char *h_name
= NULL
;
1081 *h_errnop
= HOST_NOT_FOUND
;
1082 return NSS_STATUS_NOTFOUND
;
1085 while (ancount
-- > 0 && cp
< end_of_message
&& had_error
== 0)
1087 n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
1088 packtmp
, sizeof packtmp
);
1090 (h_namelen
= __ns_name_ntop (packtmp
, buffer
, buflen
)) == -1)
1092 if (__glibc_unlikely (errno
== EMSGSIZE
))
1097 if (__glibc_unlikely (n
< 0 || res_hnok (buffer
) == 0))
1102 if (*firstp
&& canon
== NULL
)
1105 buffer
+= h_namelen
;
1106 buflen
-= h_namelen
;
1111 if (__glibc_unlikely (cp
+ 10 > end_of_message
))
1117 int type
= __ns_get16 (cp
);
1118 cp
+= INT16SZ
; /* type */
1119 int class = __ns_get16 (cp
);
1120 cp
+= INT16SZ
; /* class */
1121 int32_t ttl
= __ns_get32 (cp
);
1122 cp
+= INT32SZ
; /* TTL */
1123 n
= __ns_get16 (cp
);
1124 cp
+= INT16SZ
; /* len */
1126 if (end_of_message
- cp
< n
)
1128 /* RDATA extends beyond the end of the packet. */
1139 if (type
== T_CNAME
)
1141 char tbuf
[MAXDNAME
];
1143 /* A CNAME could also have a TTL entry. */
1144 if (ttlp
!= NULL
&& ttl
< *ttlp
)
1147 n
= dn_expand (answer
->buf
, end_of_message
, cp
, tbuf
, sizeof tbuf
);
1148 if (__glibc_unlikely (n
< 0 || res_hnok (tbuf
) == 0))
1157 /* Reclaim buffer space. */
1158 if (h_name
+ h_namelen
== buffer
)
1161 buflen
+= h_namelen
;
1164 n
= strlen (tbuf
) + 1;
1165 if (__glibc_unlikely (n
> buflen
))
1167 if (__glibc_unlikely (n
>= MAXHOSTNAMELEN
))
1174 buffer
= __mempcpy (buffer
, tbuf
, n
);
1181 /* Stop parsing if we encounter a record with incorrect RDATA
1183 if (type
== T_A
|| type
== T_AAAA
)
1185 if (n
!= rrtype_to_rdata_length (type
))
1193 /* Skip unknown records. */
1198 assert (type
== T_A
|| type
== T_AAAA
);
1201 uintptr_t pad
= (-(uintptr_t) buffer
1202 % __alignof__ (struct gaih_addrtuple
));
1204 buflen
= buflen
> pad
? buflen
- pad
: 0;
1206 if (__glibc_unlikely (buflen
< sizeof (struct gaih_addrtuple
)))
1209 *pat
= (struct gaih_addrtuple
*) buffer
;
1210 buffer
+= sizeof (struct gaih_addrtuple
);
1211 buflen
-= sizeof (struct gaih_addrtuple
);
1214 (*pat
)->name
= NULL
;
1215 (*pat
)->next
= NULL
;
1219 /* We compose a single hostent out of the entire chain of
1220 entries, so the TTL of the hostent is essentially the lowest
1221 TTL in the chain. */
1222 if (ttlp
!= NULL
&& ttl
< *ttlp
)
1225 (*pat
)->name
= canon
?: h_name
;
1230 (*pat
)->family
= type
== T_A
? AF_INET
: AF_INET6
;
1231 memcpy ((*pat
)->addr
, cp
, n
);
1233 (*pat
)->scopeid
= 0;
1235 pat
= &((*pat
)->next
);
1246 *h_errnop
= NETDB_SUCCESS
;
1247 return NSS_STATUS_SUCCESS
;
1250 /* Special case here: if the resolver sent a result but it only
1251 contains a CNAME while we are looking for a T_A or T_AAAA record,
1252 we fail with NOTFOUND instead of TRYAGAIN. */
1255 *h_errnop
= HOST_NOT_FOUND
;
1256 return NSS_STATUS_NOTFOUND
;
1259 *h_errnop
= NETDB_INTERNAL
;
1260 return NSS_STATUS_TRYAGAIN
;
1264 static enum nss_status
1265 gaih_getanswer (const querybuf
*answer1
, int anslen1
, const querybuf
*answer2
,
1266 int anslen2
, const char *qname
,
1267 struct gaih_addrtuple
**pat
, char *buffer
, size_t buflen
,
1268 int *errnop
, int *h_errnop
, int32_t *ttlp
)
1272 enum nss_status status
= NSS_STATUS_NOTFOUND
;
1274 /* Combining the NSS status of two distinct queries requires some
1275 compromise and attention to symmetry (A or AAAA queries can be
1276 returned in any order). What follows is a breakdown of how this
1277 code is expected to work and why. We discuss only SUCCESS,
1278 TRYAGAIN, NOTFOUND and UNAVAIL, since they are the only returns
1279 that apply (though RETURN and MERGE exist). We make a distinction
1280 between TRYAGAIN (recoverable) and TRYAGAIN' (not-recoverable).
1281 A recoverable TRYAGAIN is almost always due to buffer size issues
1282 and returns ERANGE in errno and the caller is expected to retry
1283 with a larger buffer.
1285 Lastly, you may be tempted to make significant changes to the
1286 conditions in this code to bring about symmetry between responses.
1287 Please don't change anything without due consideration for
1288 expected application behaviour. Some of the synthesized responses
1289 aren't very well thought out and sometimes appear to imply that
1290 IPv4 responses are always answer 1, and IPv6 responses are always
1291 answer 2, but that's not true (see the implementation of send_dg
1292 and send_vc to see response can arrive in any order, particularly
1293 for UDP). However, we expect it holds roughly enough of the time
1294 that this code works, but certainly needs to be fixed to make this
1295 a more robust implementation.
1297 ----------------------------------------------
1298 | Answer 1 Status / | Synthesized | Reason |
1299 | Answer 2 Status | Status | |
1300 |--------------------------------------------|
1301 | SUCCESS/SUCCESS | SUCCESS | [1] |
1302 | SUCCESS/TRYAGAIN | TRYAGAIN | [5] |
1303 | SUCCESS/TRYAGAIN' | SUCCESS | [1] |
1304 | SUCCESS/NOTFOUND | SUCCESS | [1] |
1305 | SUCCESS/UNAVAIL | SUCCESS | [1] |
1306 | TRYAGAIN/SUCCESS | TRYAGAIN | [2] |
1307 | TRYAGAIN/TRYAGAIN | TRYAGAIN | [2] |
1308 | TRYAGAIN/TRYAGAIN' | TRYAGAIN | [2] |
1309 | TRYAGAIN/NOTFOUND | TRYAGAIN | [2] |
1310 | TRYAGAIN/UNAVAIL | TRYAGAIN | [2] |
1311 | TRYAGAIN'/SUCCESS | SUCCESS | [3] |
1312 | TRYAGAIN'/TRYAGAIN | TRYAGAIN | [3] |
1313 | TRYAGAIN'/TRYAGAIN' | TRYAGAIN' | [3] |
1314 | TRYAGAIN'/NOTFOUND | TRYAGAIN' | [3] |
1315 | TRYAGAIN'/UNAVAIL | UNAVAIL | [3] |
1316 | NOTFOUND/SUCCESS | SUCCESS | [3] |
1317 | NOTFOUND/TRYAGAIN | TRYAGAIN | [3] |
1318 | NOTFOUND/TRYAGAIN' | TRYAGAIN' | [3] |
1319 | NOTFOUND/NOTFOUND | NOTFOUND | [3] |
1320 | NOTFOUND/UNAVAIL | UNAVAIL | [3] |
1321 | UNAVAIL/SUCCESS | UNAVAIL | [4] |
1322 | UNAVAIL/TRYAGAIN | UNAVAIL | [4] |
1323 | UNAVAIL/TRYAGAIN' | UNAVAIL | [4] |
1324 | UNAVAIL/NOTFOUND | UNAVAIL | [4] |
1325 | UNAVAIL/UNAVAIL | UNAVAIL | [4] |
1326 ----------------------------------------------
1328 [1] If the first response is a success we return success.
1329 This ignores the state of the second answer and in fact
1330 incorrectly sets errno and h_errno to that of the second
1331 answer. However because the response is a success we ignore
1332 *errnop and *h_errnop (though that means you touched errno on
1333 success). We are being conservative here and returning the
1334 likely IPv4 response in the first answer as a success.
1336 [2] If the first response is a recoverable TRYAGAIN we return
1337 that instead of looking at the second response. The
1338 expectation here is that we have failed to get an IPv4 response
1339 and should retry both queries.
1341 [3] If the first response was not a SUCCESS and the second
1342 response is not NOTFOUND (had a SUCCESS, need to TRYAGAIN,
1343 or failed entirely e.g. TRYAGAIN' and UNAVAIL) then use the
1344 result from the second response, otherwise the first responses
1345 status is used. Again we have some odd side-effects when the
1346 second response is NOTFOUND because we overwrite *errnop and
1347 *h_errnop that means that a first answer of NOTFOUND might see
1348 its *errnop and *h_errnop values altered. Whether it matters
1349 in practice that a first response NOTFOUND has the wrong
1350 *errnop and *h_errnop is undecided.
1352 [4] If the first response is UNAVAIL we return that instead of
1353 looking at the second response. The expectation here is that
1354 it will have failed similarly e.g. configuration failure.
1356 [5] Testing this code is complicated by the fact that truncated
1357 second response buffers might be returned as SUCCESS if the
1358 first answer is a SUCCESS. To fix this we add symmetry to
1359 TRYAGAIN with the second response. If the second response
1360 is a recoverable error we now return TRYAGIN even if the first
1361 response was SUCCESS. */
1364 status
= gaih_getanswer_slice(answer1
, anslen1
, qname
,
1365 &pat
, &buffer
, &buflen
,
1366 errnop
, h_errnop
, ttlp
,
1369 if ((status
== NSS_STATUS_SUCCESS
|| status
== NSS_STATUS_NOTFOUND
1370 || (status
== NSS_STATUS_TRYAGAIN
1371 /* We want to look at the second answer in case of an
1372 NSS_STATUS_TRYAGAIN only if the error is non-recoverable, i.e.
1373 *h_errnop is NO_RECOVERY. If not, and if the failure was due to
1374 an insufficient buffer (ERANGE), then we need to drop the results
1375 and pass on the NSS_STATUS_TRYAGAIN to the caller so that it can
1376 repeat the query with a larger buffer. */
1377 && (*errnop
!= ERANGE
|| *h_errnop
== NO_RECOVERY
)))
1378 && answer2
!= NULL
&& anslen2
> 0)
1380 enum nss_status status2
= gaih_getanswer_slice(answer2
, anslen2
, qname
,
1381 &pat
, &buffer
, &buflen
,
1382 errnop
, h_errnop
, ttlp
,
1384 /* Use the second response status in some cases. */
1385 if (status
!= NSS_STATUS_SUCCESS
&& status2
!= NSS_STATUS_NOTFOUND
)
1387 /* Do not return a truncated second response (unless it was
1388 unavoidable e.g. unrecoverable TRYAGAIN). */
1389 if (status
== NSS_STATUS_SUCCESS
1390 && (status2
== NSS_STATUS_TRYAGAIN
1391 && *errnop
== ERANGE
&& *h_errnop
!= NO_RECOVERY
))
1392 status
= NSS_STATUS_TRYAGAIN
;