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
,
127 static enum nss_status
gaih_getanswer_noaaaa (const querybuf
*answer1
,
130 struct gaih_addrtuple
**pat
,
131 char *buffer
, size_t buflen
,
132 int *errnop
, int *h_errnop
,
136 static enum nss_status
gethostbyname3_context (struct resolv_context
*ctx
,
137 const char *name
, int af
,
138 struct hostent
*result
,
139 char *buffer
, size_t buflen
,
140 int *errnop
, int *h_errnop
,
144 /* Return the expected RDATA length for an address record type (A or
147 rrtype_to_rdata_length (int type
)
162 _nss_dns_gethostbyname3_r (const char *name
, int af
, struct hostent
*result
,
163 char *buffer
, size_t buflen
, int *errnop
,
164 int *h_errnop
, int32_t *ttlp
, char **canonp
)
166 struct resolv_context
*ctx
= __resolv_context_get ();
170 *h_errnop
= NETDB_INTERNAL
;
171 return NSS_STATUS_UNAVAIL
;
173 enum nss_status status
= gethostbyname3_context
174 (ctx
, name
, af
, result
, buffer
, buflen
, errnop
, h_errnop
, ttlp
, canonp
);
175 __resolv_context_put (ctx
);
178 libc_hidden_def (_nss_dns_gethostbyname3_r
)
180 static enum nss_status
181 gethostbyname3_context (struct resolv_context
*ctx
,
182 const char *name
, int af
, struct hostent
*result
,
183 char *buffer
, size_t buflen
, int *errnop
,
184 int *h_errnop
, int32_t *ttlp
, char **canonp
)
191 querybuf
*orig_host_buffer
;
192 char tmp
[NS_MAXDNAME
];
197 enum nss_status status
;
210 *errnop
= EAFNOSUPPORT
;
211 return NSS_STATUS_UNAVAIL
;
214 result
->h_addrtype
= af
;
215 result
->h_length
= size
;
218 * if there aren't any dots, it could be a user-level alias.
219 * this is also done in res_query() since we are not the only
220 * function that looks up host names.
222 if (strchr (name
, '.') == NULL
223 && (cp
= __res_context_hostalias (ctx
, name
, tmp
, sizeof (tmp
))) != NULL
)
226 host_buffer
.buf
= orig_host_buffer
= (querybuf
*) alloca (1024);
228 n
= __res_context_search (ctx
, name
, C_IN
, type
, host_buffer
.buf
->buf
,
229 1024, &host_buffer
.ptr
, NULL
, NULL
, NULL
, NULL
);
235 status
= NSS_STATUS_TRYAGAIN
;
238 /* System has run out of file descriptors. */
241 h_errno
= NETDB_INTERNAL
;
245 status
= NSS_STATUS_UNAVAIL
;
248 status
= NSS_STATUS_NOTFOUND
;
252 if (h_errno
== TRY_AGAIN
)
255 __set_errno (olderr
);
257 /* If we are looking for an IPv6 address and mapping is enabled
258 by having the RES_USE_INET6 bit in _res.options set, we try
260 if (af
== AF_INET6
&& res_use_inet6 ())
261 n
= __res_context_search (ctx
, name
, C_IN
, T_A
, host_buffer
.buf
->buf
,
262 host_buffer
.buf
!= orig_host_buffer
263 ? MAXPACKET
: 1024, &host_buffer
.ptr
,
264 NULL
, NULL
, NULL
, NULL
);
268 if (host_buffer
.buf
!= orig_host_buffer
)
269 free (host_buffer
.buf
);
275 result
->h_addrtype
= AF_INET
;
276 result
->h_length
= INADDRSZ
;
280 (ctx
, host_buffer
.buf
, n
, name
, type
, result
, buffer
, buflen
,
281 errnop
, h_errnop
, map
, ttlp
, canonp
);
282 if (host_buffer
.buf
!= orig_host_buffer
)
283 free (host_buffer
.buf
);
287 /* Verify that the name looks like a host name. There is no point in
288 sending a query which will not produce a usable name in the
290 static enum nss_status
291 check_name (const char *name
, int *h_errnop
)
293 if (__libc_res_hnok (name
))
294 return NSS_STATUS_SUCCESS
;
295 *h_errnop
= HOST_NOT_FOUND
;
296 return NSS_STATUS_NOTFOUND
;
300 _nss_dns_gethostbyname2_r (const char *name
, int af
, struct hostent
*result
,
301 char *buffer
, size_t buflen
, int *errnop
,
304 enum nss_status status
= check_name (name
, h_errnop
);
305 if (status
!= NSS_STATUS_SUCCESS
)
307 return _nss_dns_gethostbyname3_r (name
, af
, result
, buffer
, buflen
, errnop
,
308 h_errnop
, NULL
, NULL
);
310 libc_hidden_def (_nss_dns_gethostbyname2_r
)
313 _nss_dns_gethostbyname_r (const char *name
, struct hostent
*result
,
314 char *buffer
, size_t buflen
, int *errnop
,
317 enum nss_status status
= check_name (name
, h_errnop
);
318 if (status
!= NSS_STATUS_SUCCESS
)
320 struct resolv_context
*ctx
= __resolv_context_get ();
324 *h_errnop
= NETDB_INTERNAL
;
325 return NSS_STATUS_UNAVAIL
;
327 status
= NSS_STATUS_NOTFOUND
;
328 if (res_use_inet6 ())
329 status
= gethostbyname3_context (ctx
, name
, AF_INET6
, result
, buffer
,
330 buflen
, errnop
, h_errnop
, NULL
, NULL
);
331 if (status
== NSS_STATUS_NOTFOUND
)
332 status
= gethostbyname3_context (ctx
, name
, AF_INET
, result
, buffer
,
333 buflen
, errnop
, h_errnop
, NULL
, NULL
);
334 __resolv_context_put (ctx
);
337 libc_hidden_def (_nss_dns_gethostbyname_r
)
340 _nss_dns_gethostbyname4_r (const char *name
, struct gaih_addrtuple
**pat
,
341 char *buffer
, size_t buflen
, int *errnop
,
342 int *herrnop
, int32_t *ttlp
)
344 enum nss_status status
= check_name (name
, herrnop
);
345 if (status
!= NSS_STATUS_SUCCESS
)
347 struct resolv_context
*ctx
= __resolv_context_get ();
351 *herrnop
= NETDB_INTERNAL
;
352 return NSS_STATUS_UNAVAIL
;
356 * if there aren't any dots, it could be a user-level alias.
357 * this is also done in res_query() since we are not the only
358 * function that looks up host names.
360 if (strchr (name
, '.') == NULL
)
362 char *tmp
= alloca (NS_MAXDNAME
);
363 const char *cp
= __res_context_hostalias (ctx
, name
, tmp
, NS_MAXDNAME
);
373 querybuf
*orig_host_buffer
;
374 host_buffer
.buf
= orig_host_buffer
= (querybuf
*) alloca (2048);
375 u_char
*ans2p
= NULL
;
378 int ans2p_malloced
= 0;
384 if ((ctx
->resp
->options
& RES_NOAAAA
) == 0)
386 n
= __res_context_search (ctx
, name
, C_IN
, T_QUERY_A_AND_AAAA
,
387 host_buffer
.buf
->buf
, 2048, &host_buffer
.ptr
,
388 &ans2p
, &nans2p
, &resplen2
, &ans2p_malloced
);
390 status
= gaih_getanswer (host_buffer
.buf
, n
, (const querybuf
*) ans2p
,
391 resplen2
, name
, pat
, buffer
, buflen
,
392 errnop
, herrnop
, ttlp
);
396 n
= __res_context_search (ctx
, name
, C_IN
, T_A
,
397 host_buffer
.buf
->buf
, 2048, NULL
,
398 NULL
, NULL
, NULL
, NULL
);
400 status
= gaih_getanswer_noaaaa (host_buffer
.buf
, n
,
401 name
, pat
, buffer
, buflen
,
402 errnop
, herrnop
, ttlp
);
409 status
= NSS_STATUS_TRYAGAIN
;
412 /* System has run out of file descriptors. */
415 h_errno
= NETDB_INTERNAL
;
419 status
= NSS_STATUS_UNAVAIL
;
422 status
= NSS_STATUS_NOTFOUND
;
427 if (h_errno
== TRY_AGAIN
)
430 __set_errno (olderr
);
433 /* Check whether ans2p was separately allocated. */
437 if (host_buffer
.buf
!= orig_host_buffer
)
438 free (host_buffer
.buf
);
440 __resolv_context_put (ctx
);
443 libc_hidden_def (_nss_dns_gethostbyname4_r
)
446 _nss_dns_gethostbyaddr2_r (const void *addr
, socklen_t len
, int af
,
447 struct hostent
*result
, char *buffer
, size_t buflen
,
448 int *errnop
, int *h_errnop
, int32_t *ttlp
)
450 static const u_char mapped
[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
451 static const u_char tunnelled
[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
452 static const u_char v6local
[] = { 0,0, 0,1 };
453 const u_char
*uaddr
= (const u_char
*)addr
;
456 char *aliases
[MAX_NR_ALIASES
];
457 unsigned char host_addr
[16]; /* IPv4 or IPv6 */
458 char *h_addr_ptrs
[MAX_NR_ADDRS
+ 1];
460 } *host_data
= (struct host_data
*) buffer
;
466 querybuf
*orig_host_buffer
;
467 char qbuf
[MAXDNAME
+1], *qp
= NULL
;
472 uintptr_t pad
= -(uintptr_t) buffer
% __alignof__ (struct host_data
);
474 buflen
= buflen
> pad
? buflen
- pad
: 0;
476 if (__glibc_unlikely (buflen
< sizeof (struct host_data
)))
479 *h_errnop
= NETDB_INTERNAL
;
480 return NSS_STATUS_TRYAGAIN
;
483 host_data
= (struct host_data
*) buffer
;
485 struct resolv_context
*ctx
= __resolv_context_get ();
489 *h_errnop
= NETDB_INTERNAL
;
490 return NSS_STATUS_UNAVAIL
;
493 if (af
== AF_INET6
&& len
== IN6ADDRSZ
494 && (memcmp (uaddr
, mapped
, sizeof mapped
) == 0
495 || (memcmp (uaddr
, tunnelled
, sizeof tunnelled
) == 0
496 && memcmp (&uaddr
[sizeof tunnelled
], v6local
, sizeof v6local
))))
499 addr
+= sizeof mapped
;
500 uaddr
+= sizeof mapped
;
514 *errnop
= EAFNOSUPPORT
;
515 *h_errnop
= NETDB_INTERNAL
;
516 __resolv_context_put (ctx
);
517 return NSS_STATUS_UNAVAIL
;
521 *errnop
= EAFNOSUPPORT
;
522 *h_errnop
= NETDB_INTERNAL
;
523 __resolv_context_put (ctx
);
524 return NSS_STATUS_UNAVAIL
;
527 host_buffer
.buf
= orig_host_buffer
= (querybuf
*) alloca (1024);
532 sprintf (qbuf
, "%u.%u.%u.%u.in-addr.arpa", (uaddr
[3] & 0xff),
533 (uaddr
[2] & 0xff), (uaddr
[1] & 0xff), (uaddr
[0] & 0xff));
537 for (n
= IN6ADDRSZ
- 1; n
>= 0; n
--)
539 static const char nibblechar
[16] = "0123456789abcdef";
540 *qp
++ = nibblechar
[uaddr
[n
] & 0xf];
542 *qp
++ = nibblechar
[(uaddr
[n
] >> 4) & 0xf];
545 strcpy(qp
, "ip6.arpa");
552 n
= __res_context_query (ctx
, qbuf
, C_IN
, T_PTR
, host_buffer
.buf
->buf
,
553 1024, &host_buffer
.ptr
, NULL
, NULL
, NULL
, NULL
);
557 __set_errno (olderr
);
558 if (host_buffer
.buf
!= orig_host_buffer
)
559 free (host_buffer
.buf
);
560 __resolv_context_put (ctx
);
561 return errno
== ECONNREFUSED
? NSS_STATUS_UNAVAIL
: NSS_STATUS_NOTFOUND
;
565 (ctx
, host_buffer
.buf
, n
, qbuf
, T_PTR
, result
, buffer
, buflen
,
566 errnop
, h_errnop
, 0 /* XXX */, ttlp
, NULL
);
567 if (host_buffer
.buf
!= orig_host_buffer
)
568 free (host_buffer
.buf
);
569 if (status
!= NSS_STATUS_SUCCESS
)
571 __resolv_context_put (ctx
);
575 result
->h_addrtype
= af
;
576 result
->h_length
= len
;
577 memcpy (host_data
->host_addr
, addr
, len
);
578 host_data
->h_addr_ptrs
[0] = (char *) host_data
->host_addr
;
579 host_data
->h_addr_ptrs
[1] = NULL
;
580 *h_errnop
= NETDB_SUCCESS
;
581 __resolv_context_put (ctx
);
582 return NSS_STATUS_SUCCESS
;
584 libc_hidden_def (_nss_dns_gethostbyaddr2_r
)
588 _nss_dns_gethostbyaddr_r (const void *addr
, socklen_t len
, int af
,
589 struct hostent
*result
, char *buffer
, size_t buflen
,
590 int *errnop
, int *h_errnop
)
592 return _nss_dns_gethostbyaddr2_r (addr
, len
, af
, result
, buffer
, buflen
,
593 errnop
, h_errnop
, NULL
);
595 libc_hidden_def (_nss_dns_gethostbyaddr_r
)
598 addrsort (struct resolv_context
*ctx
, char **ap
, int num
)
602 short aval
[MAX_NR_ADDRS
];
604 size_t nsort
= __resolv_context_sort_count (ctx
);
607 if (num
> MAX_NR_ADDRS
)
609 for (i
= 0; i
< num
; i
++, p
++)
611 for (j
= 0 ; (unsigned)j
< nsort
; j
++)
613 struct resolv_sortlist_entry e
614 = __resolv_context_sort_entry (ctx
, j
);
615 if (e
.addr
.s_addr
== (((struct in_addr
*)(*p
))->s_addr
& e
.mask
))
619 if (needsort
== 0 && i
> 0 && j
< aval
[i
-1])
625 while (needsort
++ < num
)
626 for (j
= needsort
- 2; j
>= 0; j
--)
627 if (aval
[j
] > aval
[j
+1])
643 static enum nss_status
644 getanswer_r (struct resolv_context
*ctx
,
645 const querybuf
*answer
, int anslen
, const char *qname
, int qtype
,
646 struct hostent
*result
, char *buffer
, size_t buflen
,
647 int *errnop
, int *h_errnop
, int map
, int32_t *ttlp
, char **canonp
)
651 char *aliases
[MAX_NR_ALIASES
];
652 unsigned char host_addr
[16]; /* IPv4 or IPv6 */
653 char *h_addr_ptrs
[0];
657 const u_char
*end_of_message
, *cp
;
658 int n
, ancount
, qdcount
;
659 int haveanswer
, had_error
;
660 char *bp
, **ap
, **hap
;
663 int (*name_ok
) (const char *);
664 u_char packtmp
[NS_MAXCDNAME
];
666 uintptr_t pad
= -(uintptr_t) buffer
% __alignof__ (struct host_data
);
668 buflen
= buflen
> pad
? buflen
- pad
: 0;
669 if (__glibc_unlikely (buflen
< sizeof (struct host_data
)))
671 /* The buffer is too small. */
674 *h_errnop
= NETDB_INTERNAL
;
675 return NSS_STATUS_TRYAGAIN
;
677 host_data
= (struct host_data
*) buffer
;
678 linebuflen
= buflen
- sizeof (struct host_data
);
679 if (buflen
- sizeof (struct host_data
) != linebuflen
)
680 linebuflen
= INT_MAX
;
683 result
->h_name
= NULL
;
684 end_of_message
= answer
->buf
+ anslen
;
689 name_ok
= __libc_res_hnok
;
692 name_ok
= __libc_res_dnok
;
696 return NSS_STATUS_UNAVAIL
; /* XXX should be abort(); */
700 * find first satisfactory answer
703 ancount
= ntohs (hp
->ancount
);
704 qdcount
= ntohs (hp
->qdcount
);
705 cp
= answer
->buf
+ HFIXEDSZ
;
706 if (__glibc_unlikely (qdcount
!= 1))
708 *h_errnop
= NO_RECOVERY
;
709 return NSS_STATUS_UNAVAIL
;
711 if (sizeof (struct host_data
) + (ancount
+ 1) * sizeof (char *) >= buflen
)
713 bp
= (char *) &host_data
->h_addr_ptrs
[ancount
+ 1];
714 linebuflen
-= (ancount
+ 1) * sizeof (char *);
716 n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
717 packtmp
, sizeof packtmp
);
718 if (n
!= -1 && __ns_name_ntop (packtmp
, bp
, linebuflen
) == -1)
720 if (__glibc_unlikely (errno
== EMSGSIZE
))
726 if (__glibc_unlikely (n
< 0))
729 *h_errnop
= NO_RECOVERY
;
730 return NSS_STATUS_UNAVAIL
;
732 if (__glibc_unlikely (name_ok (bp
) == 0))
736 *h_errnop
= NO_RECOVERY
;
737 return NSS_STATUS_UNAVAIL
;
741 if (qtype
== T_A
|| qtype
== T_AAAA
)
743 /* res_send() has already verified that the query name is the
744 * same as the one we sent; this just gets the expanded name
745 * (i.e., with the succeeding search-domain tacked on).
747 n
= strlen (bp
) + 1; /* for the \0 */
748 if (n
>= MAXHOSTNAMELEN
)
750 *h_errnop
= NO_RECOVERY
;
752 return NSS_STATUS_TRYAGAIN
;
759 /* The qname can be abbreviated, but h_name is now absolute. */
760 qname
= result
->h_name
;
763 ap
= host_data
->aliases
;
765 result
->h_aliases
= host_data
->aliases
;
766 hap
= host_data
->h_addr_ptrs
;
768 result
->h_addr_list
= host_data
->h_addr_ptrs
;
772 while (ancount
-- > 0 && cp
< end_of_message
&& had_error
== 0)
776 n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
777 packtmp
, sizeof packtmp
);
778 if (n
!= -1 && __ns_name_ntop (packtmp
, bp
, linebuflen
) == -1)
780 if (__glibc_unlikely (errno
== EMSGSIZE
))
786 if (__glibc_unlikely (n
< 0 || (*name_ok
) (bp
) == 0))
793 if (__glibc_unlikely (cp
+ 10 > end_of_message
))
800 NS_GET16 (class, cp
);
803 NS_GET16 (n
, cp
); /* RDATA length. */
805 if (end_of_message
- cp
< n
)
807 /* RDATA extends beyond the end of the packet. */
812 if (__glibc_unlikely (class != C_IN
))
814 /* XXX - debug? syslog? */
816 continue; /* XXX - had_error++ ? */
819 if ((qtype
== T_A
|| qtype
== T_AAAA
) && type
== T_CNAME
)
821 /* A CNAME could also have a TTL entry. */
822 if (ttlp
!= NULL
&& ttl
< *ttlp
)
825 if (ap
>= &host_data
->aliases
[MAX_NR_ALIASES
- 1])
827 n
= __libc_dn_expand (answer
->buf
, end_of_message
, cp
,
829 if (__glibc_unlikely (n
< 0 || (*name_ok
) (tbuf
) == 0))
837 n
= strlen (bp
) + 1; /* For the \0. */
838 if (__glibc_unlikely (n
>= MAXHOSTNAMELEN
))
845 /* Get canonical name. */
846 n
= strlen (tbuf
) + 1; /* For the \0. */
847 if (__glibc_unlikely (n
> linebuflen
))
849 if (__glibc_unlikely (n
>= MAXHOSTNAMELEN
))
855 bp
= __mempcpy (bp
, tbuf
, n
); /* Cannot overflow. */
860 if (qtype
== T_PTR
&& type
== T_CNAME
)
862 /* A CNAME could also have a TTL entry. */
863 if (ttlp
!= NULL
&& ttl
< *ttlp
)
866 n
= __libc_dn_expand (answer
->buf
, end_of_message
, cp
,
868 if (__glibc_unlikely (n
< 0 || __libc_res_dnok (tbuf
) == 0))
874 /* Get canonical name. */
875 n
= strlen (tbuf
) + 1; /* For the \0. */
876 if (__glibc_unlikely (n
> linebuflen
))
878 if (__glibc_unlikely (n
>= MAXHOSTNAMELEN
))
884 bp
= __mempcpy (bp
, tbuf
, n
); /* Cannot overflow. */
889 if (type
== T_A
&& qtype
== T_AAAA
&& map
)
891 else if (__glibc_unlikely (type
!= qtype
))
894 continue; /* XXX - had_error++ ? */
900 if (__glibc_unlikely (__strcasecmp (tname
, bp
) != 0))
903 continue; /* XXX - had_error++ ? */
906 n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
907 packtmp
, sizeof packtmp
);
908 if (n
!= -1 && __ns_name_ntop (packtmp
, bp
, linebuflen
) == -1)
910 if (__glibc_unlikely (errno
== EMSGSIZE
))
916 if (__glibc_unlikely (n
< 0 || __libc_res_hnok (bp
) == 0))
921 if (ttlp
!= NULL
&& ttl
< *ttlp
)
923 /* bind would put multiple PTR records as aliases, but we don't do
926 *h_errnop
= NETDB_SUCCESS
;
927 return NSS_STATUS_SUCCESS
;
930 if (__glibc_unlikely (__strcasecmp (result
->h_name
, bp
) != 0))
933 continue; /* XXX - had_error++ ? */
936 /* Stop parsing at a record whose length is incorrect. */
937 if (n
!= rrtype_to_rdata_length (type
))
943 /* Skip records of the wrong type. */
944 if (n
!= result
->h_length
)
953 /* We compose a single hostent out of the entire chain of
954 entries, so the TTL of the hostent is essentially the lowest
956 if (ttlp
!= NULL
&& ttl
< *ttlp
)
961 nn
= strlen (bp
) + 1; /* for the \0 */
966 /* Provide sufficient alignment for both address
969 _Static_assert ((align
% __alignof__ (struct in_addr
)) == 0,
970 "struct in_addr alignment");
971 _Static_assert ((align
% __alignof__ (struct in6_addr
)) == 0,
972 "struct in6_addr alignment");
974 char *new_bp
= PTR_ALIGN_UP (bp
, align
);
975 linebuflen
-= new_bp
- bp
;
979 if (__glibc_unlikely (n
> linebuflen
))
981 bp
= __mempcpy (*hap
++ = bp
, cp
, n
);
997 * Note: we sort even if host can take only one address
998 * in its return structures - should give it the "best"
999 * address in that case, not some random one
1001 if (haveanswer
> 1 && qtype
== T_A
1002 && __resolv_context_sort_count (ctx
) > 0)
1003 addrsort (ctx
, host_data
->h_addr_ptrs
, haveanswer
);
1005 if (result
->h_name
== NULL
)
1007 n
= strlen (qname
) + 1; /* For the \0. */
1010 if (n
>= MAXHOSTNAMELEN
)
1012 result
->h_name
= bp
;
1013 bp
= __mempcpy (bp
, qname
, n
); /* Cannot overflow. */
1018 if (map_v4v6_hostent (result
, &bp
, &linebuflen
))
1020 *h_errnop
= NETDB_SUCCESS
;
1021 return NSS_STATUS_SUCCESS
;
1024 *h_errnop
= NO_RECOVERY
;
1026 /* Special case here: if the resolver sent a result but it only
1027 contains a CNAME while we are looking for a T_A or T_AAAA record,
1028 we fail with NOTFOUND instead of TRYAGAIN. */
1029 return ((qtype
== T_A
|| qtype
== T_AAAA
) && ap
!= host_data
->aliases
1030 ? NSS_STATUS_NOTFOUND
: NSS_STATUS_TRYAGAIN
);
1034 static enum nss_status
1035 gaih_getanswer_slice (const querybuf
*answer
, int anslen
, const char *qname
,
1036 struct gaih_addrtuple
***patp
,
1037 char **bufferp
, size_t *buflenp
,
1038 int *errnop
, int *h_errnop
, int32_t *ttlp
, int *firstp
)
1040 char *buffer
= *bufferp
;
1041 size_t buflen
= *buflenp
;
1043 struct gaih_addrtuple
**pat
= *patp
;
1044 const HEADER
*hp
= &answer
->hdr
;
1045 int ancount
= ntohs (hp
->ancount
);
1046 int qdcount
= ntohs (hp
->qdcount
);
1047 const u_char
*cp
= answer
->buf
+ HFIXEDSZ
;
1048 const u_char
*end_of_message
= answer
->buf
+ anslen
;
1049 if (__glibc_unlikely (qdcount
!= 1))
1051 *h_errnop
= NO_RECOVERY
;
1052 return NSS_STATUS_UNAVAIL
;
1055 u_char packtmp
[NS_MAXCDNAME
];
1056 int n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
1057 packtmp
, sizeof packtmp
);
1058 /* We unpack the name to check it for validity. But we do not need
1060 if (n
!= -1 && __ns_name_ntop (packtmp
, buffer
, buflen
) == -1)
1062 if (__glibc_unlikely (errno
== EMSGSIZE
))
1066 *h_errnop
= NETDB_INTERNAL
;
1067 return NSS_STATUS_TRYAGAIN
;
1073 if (__glibc_unlikely (n
< 0))
1076 *h_errnop
= NO_RECOVERY
;
1077 return NSS_STATUS_UNAVAIL
;
1079 if (__glibc_unlikely (__libc_res_hnok (buffer
) == 0))
1083 *h_errnop
= NO_RECOVERY
;
1084 return NSS_STATUS_UNAVAIL
;
1091 char *h_name
= NULL
;
1096 *h_errnop
= HOST_NOT_FOUND
;
1097 return NSS_STATUS_NOTFOUND
;
1100 while (ancount
-- > 0 && cp
< end_of_message
&& had_error
== 0)
1102 n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
1103 packtmp
, sizeof packtmp
);
1105 (h_namelen
= __ns_name_ntop (packtmp
, buffer
, buflen
)) == -1)
1107 if (__glibc_unlikely (errno
== EMSGSIZE
))
1112 if (__glibc_unlikely (n
< 0 || __libc_res_hnok (buffer
) == 0))
1117 if (*firstp
&& canon
== NULL
)
1120 buffer
+= h_namelen
;
1121 buflen
-= h_namelen
;
1126 if (__glibc_unlikely (cp
+ 10 > end_of_message
))
1133 NS_GET16 (type
, cp
);
1135 NS_GET16 (class, cp
);
1138 NS_GET16 (n
, cp
); /* RDATA length. */
1140 if (end_of_message
- cp
< n
)
1142 /* RDATA extends beyond the end of the packet. */
1153 if (type
== T_CNAME
)
1155 char tbuf
[MAXDNAME
];
1157 /* A CNAME could also have a TTL entry. */
1158 if (ttlp
!= NULL
&& ttl
< *ttlp
)
1161 n
= __libc_dn_expand (answer
->buf
, end_of_message
, cp
,
1163 if (__glibc_unlikely (n
< 0 || __libc_res_hnok (tbuf
) == 0))
1172 /* Reclaim buffer space. */
1173 if (h_name
+ h_namelen
== buffer
)
1176 buflen
+= h_namelen
;
1179 n
= strlen (tbuf
) + 1;
1180 if (__glibc_unlikely (n
> buflen
))
1182 if (__glibc_unlikely (n
>= MAXHOSTNAMELEN
))
1189 buffer
= __mempcpy (buffer
, tbuf
, n
);
1196 /* Stop parsing if we encounter a record with incorrect RDATA
1198 if (type
== T_A
|| type
== T_AAAA
)
1200 if (n
!= rrtype_to_rdata_length (type
))
1208 /* Skip unknown records. */
1213 assert (type
== T_A
|| type
== T_AAAA
);
1216 uintptr_t pad
= (-(uintptr_t) buffer
1217 % __alignof__ (struct gaih_addrtuple
));
1219 buflen
= buflen
> pad
? buflen
- pad
: 0;
1221 if (__glibc_unlikely (buflen
< sizeof (struct gaih_addrtuple
)))
1224 *pat
= (struct gaih_addrtuple
*) buffer
;
1225 buffer
+= sizeof (struct gaih_addrtuple
);
1226 buflen
-= sizeof (struct gaih_addrtuple
);
1229 (*pat
)->name
= NULL
;
1230 (*pat
)->next
= NULL
;
1234 /* We compose a single hostent out of the entire chain of
1235 entries, so the TTL of the hostent is essentially the lowest
1236 TTL in the chain. */
1237 if (ttlp
!= NULL
&& ttl
< *ttlp
)
1240 (*pat
)->name
= canon
?: h_name
;
1245 (*pat
)->family
= type
== T_A
? AF_INET
: AF_INET6
;
1246 memcpy ((*pat
)->addr
, cp
, n
);
1248 (*pat
)->scopeid
= 0;
1250 pat
= &((*pat
)->next
);
1261 *h_errnop
= NETDB_SUCCESS
;
1262 return NSS_STATUS_SUCCESS
;
1265 /* Special case here: if the resolver sent a result but it only
1266 contains a CNAME while we are looking for a T_A or T_AAAA record,
1267 we fail with NOTFOUND instead of TRYAGAIN. */
1270 *h_errnop
= HOST_NOT_FOUND
;
1271 return NSS_STATUS_NOTFOUND
;
1274 *h_errnop
= NETDB_INTERNAL
;
1275 return NSS_STATUS_TRYAGAIN
;
1279 static enum nss_status
1280 gaih_getanswer (const querybuf
*answer1
, int anslen1
, const querybuf
*answer2
,
1281 int anslen2
, const char *qname
,
1282 struct gaih_addrtuple
**pat
, char *buffer
, size_t buflen
,
1283 int *errnop
, int *h_errnop
, int32_t *ttlp
)
1287 enum nss_status status
= NSS_STATUS_NOTFOUND
;
1289 /* Combining the NSS status of two distinct queries requires some
1290 compromise and attention to symmetry (A or AAAA queries can be
1291 returned in any order). What follows is a breakdown of how this
1292 code is expected to work and why. We discuss only SUCCESS,
1293 TRYAGAIN, NOTFOUND and UNAVAIL, since they are the only returns
1294 that apply (though RETURN and MERGE exist). We make a distinction
1295 between TRYAGAIN (recoverable) and TRYAGAIN' (not-recoverable).
1296 A recoverable TRYAGAIN is almost always due to buffer size issues
1297 and returns ERANGE in errno and the caller is expected to retry
1298 with a larger buffer.
1300 Lastly, you may be tempted to make significant changes to the
1301 conditions in this code to bring about symmetry between responses.
1302 Please don't change anything without due consideration for
1303 expected application behaviour. Some of the synthesized responses
1304 aren't very well thought out and sometimes appear to imply that
1305 IPv4 responses are always answer 1, and IPv6 responses are always
1306 answer 2, but that's not true (see the implementation of send_dg
1307 and send_vc to see response can arrive in any order, particularly
1308 for UDP). However, we expect it holds roughly enough of the time
1309 that this code works, but certainly needs to be fixed to make this
1310 a more robust implementation.
1312 ----------------------------------------------
1313 | Answer 1 Status / | Synthesized | Reason |
1314 | Answer 2 Status | Status | |
1315 |--------------------------------------------|
1316 | SUCCESS/SUCCESS | SUCCESS | [1] |
1317 | SUCCESS/TRYAGAIN | TRYAGAIN | [5] |
1318 | SUCCESS/TRYAGAIN' | SUCCESS | [1] |
1319 | SUCCESS/NOTFOUND | SUCCESS | [1] |
1320 | SUCCESS/UNAVAIL | SUCCESS | [1] |
1321 | TRYAGAIN/SUCCESS | TRYAGAIN | [2] |
1322 | TRYAGAIN/TRYAGAIN | TRYAGAIN | [2] |
1323 | TRYAGAIN/TRYAGAIN' | TRYAGAIN | [2] |
1324 | TRYAGAIN/NOTFOUND | TRYAGAIN | [2] |
1325 | TRYAGAIN/UNAVAIL | TRYAGAIN | [2] |
1326 | TRYAGAIN'/SUCCESS | SUCCESS | [3] |
1327 | TRYAGAIN'/TRYAGAIN | TRYAGAIN | [3] |
1328 | TRYAGAIN'/TRYAGAIN' | TRYAGAIN' | [3] |
1329 | TRYAGAIN'/NOTFOUND | TRYAGAIN' | [3] |
1330 | TRYAGAIN'/UNAVAIL | UNAVAIL | [3] |
1331 | NOTFOUND/SUCCESS | SUCCESS | [3] |
1332 | NOTFOUND/TRYAGAIN | TRYAGAIN | [3] |
1333 | NOTFOUND/TRYAGAIN' | TRYAGAIN' | [3] |
1334 | NOTFOUND/NOTFOUND | NOTFOUND | [3] |
1335 | NOTFOUND/UNAVAIL | UNAVAIL | [3] |
1336 | UNAVAIL/SUCCESS | UNAVAIL | [4] |
1337 | UNAVAIL/TRYAGAIN | UNAVAIL | [4] |
1338 | UNAVAIL/TRYAGAIN' | UNAVAIL | [4] |
1339 | UNAVAIL/NOTFOUND | UNAVAIL | [4] |
1340 | UNAVAIL/UNAVAIL | UNAVAIL | [4] |
1341 ----------------------------------------------
1343 [1] If the first response is a success we return success.
1344 This ignores the state of the second answer and in fact
1345 incorrectly sets errno and h_errno to that of the second
1346 answer. However because the response is a success we ignore
1347 *errnop and *h_errnop (though that means you touched errno on
1348 success). We are being conservative here and returning the
1349 likely IPv4 response in the first answer as a success.
1351 [2] If the first response is a recoverable TRYAGAIN we return
1352 that instead of looking at the second response. The
1353 expectation here is that we have failed to get an IPv4 response
1354 and should retry both queries.
1356 [3] If the first response was not a SUCCESS and the second
1357 response is not NOTFOUND (had a SUCCESS, need to TRYAGAIN,
1358 or failed entirely e.g. TRYAGAIN' and UNAVAIL) then use the
1359 result from the second response, otherwise the first responses
1360 status is used. Again we have some odd side-effects when the
1361 second response is NOTFOUND because we overwrite *errnop and
1362 *h_errnop that means that a first answer of NOTFOUND might see
1363 its *errnop and *h_errnop values altered. Whether it matters
1364 in practice that a first response NOTFOUND has the wrong
1365 *errnop and *h_errnop is undecided.
1367 [4] If the first response is UNAVAIL we return that instead of
1368 looking at the second response. The expectation here is that
1369 it will have failed similarly e.g. configuration failure.
1371 [5] Testing this code is complicated by the fact that truncated
1372 second response buffers might be returned as SUCCESS if the
1373 first answer is a SUCCESS. To fix this we add symmetry to
1374 TRYAGAIN with the second response. If the second response
1375 is a recoverable error we now return TRYAGIN even if the first
1376 response was SUCCESS. */
1379 status
= gaih_getanswer_slice(answer1
, anslen1
, qname
,
1380 &pat
, &buffer
, &buflen
,
1381 errnop
, h_errnop
, ttlp
,
1384 if ((status
== NSS_STATUS_SUCCESS
|| status
== NSS_STATUS_NOTFOUND
1385 || (status
== NSS_STATUS_TRYAGAIN
1386 /* We want to look at the second answer in case of an
1387 NSS_STATUS_TRYAGAIN only if the error is non-recoverable, i.e.
1388 *h_errnop is NO_RECOVERY. If not, and if the failure was due to
1389 an insufficient buffer (ERANGE), then we need to drop the results
1390 and pass on the NSS_STATUS_TRYAGAIN to the caller so that it can
1391 repeat the query with a larger buffer. */
1392 && (*errnop
!= ERANGE
|| *h_errnop
== NO_RECOVERY
)))
1393 && answer2
!= NULL
&& anslen2
> 0)
1395 enum nss_status status2
= gaih_getanswer_slice(answer2
, anslen2
, qname
,
1396 &pat
, &buffer
, &buflen
,
1397 errnop
, h_errnop
, ttlp
,
1399 /* Use the second response status in some cases. */
1400 if (status
!= NSS_STATUS_SUCCESS
&& status2
!= NSS_STATUS_NOTFOUND
)
1402 /* Do not return a truncated second response (unless it was
1403 unavoidable e.g. unrecoverable TRYAGAIN). */
1404 if (status
== NSS_STATUS_SUCCESS
1405 && (status2
== NSS_STATUS_TRYAGAIN
1406 && *errnop
== ERANGE
&& *h_errnop
!= NO_RECOVERY
))
1407 status
= NSS_STATUS_TRYAGAIN
;
1413 /* Variant of gaih_getanswer without a second (AAAA) response. */
1414 static enum nss_status
1415 gaih_getanswer_noaaaa (const querybuf
*answer1
, int anslen1
, const char *qname
,
1416 struct gaih_addrtuple
**pat
,
1417 char *buffer
, size_t buflen
,
1418 int *errnop
, int *h_errnop
, int32_t *ttlp
)
1422 enum nss_status status
= NSS_STATUS_NOTFOUND
;
1424 status
= gaih_getanswer_slice (answer1
, anslen1
, qname
,
1425 &pat
, &buffer
, &buflen
,
1426 errnop
, h_errnop
, ttlp
,