1 /* Copyright (C) 1996-2016 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 <http://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
84 /* Get implementation for some internal functions. */
85 #include <resolv/mapv4v6addr.h>
86 #include <resolv/mapv4v6hostent.h>
91 # define MAXPACKET PACKETSZ
93 # define MAXPACKET 65536
95 /* As per RFC 1034 and 1035 a host name cannot exceed 255 octets in length. */
97 # undef MAXHOSTNAMELEN
99 #define MAXHOSTNAMELEN 256
101 /* We need this time later. */
102 typedef union querybuf
105 u_char buf
[MAXPACKET
];
108 /* These functions are defined in res_comp.c. */
109 #define NS_MAXCDNAME 255 /* maximum compressed domain name */
110 extern int __ns_name_ntop (const u_char
*, char *, size_t);
111 extern int __ns_name_unpack (const u_char
*, const u_char
*,
112 const u_char
*, u_char
*, size_t);
115 static enum nss_status
getanswer_r (const querybuf
*answer
, int anslen
,
116 const char *qname
, int qtype
,
117 struct hostent
*result
, char *buffer
,
118 size_t buflen
, int *errnop
, int *h_errnop
,
119 int map
, int32_t *ttlp
, char **canonp
);
121 static enum nss_status
gaih_getanswer (const querybuf
*answer1
, int anslen1
,
122 const querybuf
*answer2
, int anslen2
,
124 struct gaih_addrtuple
**pat
,
125 char *buffer
, size_t buflen
,
126 int *errnop
, int *h_errnop
,
129 extern enum nss_status
_nss_dns_gethostbyname3_r (const char *name
, int af
,
130 struct hostent
*result
,
131 char *buffer
, size_t buflen
,
132 int *errnop
, int *h_errnop
,
135 hidden_proto (_nss_dns_gethostbyname3_r
)
137 /* Return the expected RDATA length for an address record type (A or
140 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
)
163 querybuf
*orig_host_buffer
;
164 char tmp
[NS_MAXDNAME
];
169 enum nss_status status
;
171 if (__res_maybe_init (&_res
, 0) == -1)
172 return NSS_STATUS_UNAVAIL
;
185 *errnop
= EAFNOSUPPORT
;
186 return NSS_STATUS_UNAVAIL
;
189 result
->h_addrtype
= af
;
190 result
->h_length
= size
;
193 * if there aren't any dots, it could be a user-level alias.
194 * this is also done in res_query() since we are not the only
195 * function that looks up host names.
197 if (strchr (name
, '.') == NULL
198 && (cp
= res_hostalias (&_res
, name
, tmp
, sizeof (tmp
))) != NULL
)
201 host_buffer
.buf
= orig_host_buffer
= (querybuf
*) alloca (1024);
203 n
= __libc_res_nsearch (&_res
, name
, C_IN
, type
, host_buffer
.buf
->buf
,
204 1024, &host_buffer
.ptr
, NULL
, NULL
, NULL
, NULL
);
210 status
= NSS_STATUS_TRYAGAIN
;
213 /* System has run out of file descriptors. */
216 h_errno
= NETDB_INTERNAL
;
220 status
= NSS_STATUS_UNAVAIL
;
223 status
= NSS_STATUS_NOTFOUND
;
227 if (h_errno
== TRY_AGAIN
)
230 __set_errno (olderr
);
232 /* If we are looking for an IPv6 address and mapping is enabled
233 by having the RES_USE_INET6 bit in _res.options set, we try
235 if (af
== AF_INET6
&& (_res
.options
& RES_USE_INET6
))
236 n
= __libc_res_nsearch (&_res
, name
, C_IN
, T_A
, host_buffer
.buf
->buf
,
237 host_buffer
.buf
!= orig_host_buffer
238 ? MAXPACKET
: 1024, &host_buffer
.ptr
,
239 NULL
, NULL
, NULL
, NULL
);
243 if (host_buffer
.buf
!= orig_host_buffer
)
244 free (host_buffer
.buf
);
250 result
->h_addrtype
= AF_INET
;
251 result
->h_length
= INADDRSZ
;
254 status
= getanswer_r (host_buffer
.buf
, n
, name
, type
, result
, buffer
, buflen
,
255 errnop
, h_errnop
, map
, ttlp
, canonp
);
256 if (host_buffer
.buf
!= orig_host_buffer
)
257 free (host_buffer
.buf
);
260 hidden_def (_nss_dns_gethostbyname3_r
)
264 _nss_dns_gethostbyname2_r (const char *name
, int af
, struct hostent
*result
,
265 char *buffer
, size_t buflen
, int *errnop
,
268 return _nss_dns_gethostbyname3_r (name
, af
, result
, buffer
, buflen
, errnop
,
269 h_errnop
, NULL
, NULL
);
274 _nss_dns_gethostbyname_r (const char *name
, struct hostent
*result
,
275 char *buffer
, size_t buflen
, int *errnop
,
278 enum nss_status status
= NSS_STATUS_NOTFOUND
;
280 if (_res
.options
& RES_USE_INET6
)
281 status
= _nss_dns_gethostbyname3_r (name
, AF_INET6
, result
, buffer
,
282 buflen
, errnop
, h_errnop
, NULL
, NULL
);
283 if (status
== NSS_STATUS_NOTFOUND
)
284 status
= _nss_dns_gethostbyname3_r (name
, AF_INET
, result
, buffer
,
285 buflen
, errnop
, h_errnop
, NULL
, NULL
);
292 _nss_dns_gethostbyname4_r (const char *name
, struct gaih_addrtuple
**pat
,
293 char *buffer
, size_t buflen
, int *errnop
,
294 int *herrnop
, int32_t *ttlp
)
296 if (__res_maybe_init (&_res
, 0) == -1)
297 return NSS_STATUS_UNAVAIL
;
300 * if there aren't any dots, it could be a user-level alias.
301 * this is also done in res_query() since we are not the only
302 * function that looks up host names.
304 if (strchr (name
, '.') == NULL
)
306 char *tmp
= alloca (NS_MAXDNAME
);
307 const char *cp
= res_hostalias (&_res
, name
, tmp
, NS_MAXDNAME
);
317 querybuf
*orig_host_buffer
;
318 host_buffer
.buf
= orig_host_buffer
= (querybuf
*) alloca (2048);
319 u_char
*ans2p
= NULL
;
322 int ans2p_malloced
= 0;
325 enum nss_status status
;
326 int n
= __libc_res_nsearch (&_res
, name
, C_IN
, T_UNSPEC
,
327 host_buffer
.buf
->buf
, 2048, &host_buffer
.ptr
,
328 &ans2p
, &nans2p
, &resplen2
, &ans2p_malloced
);
331 status
= gaih_getanswer (host_buffer
.buf
, n
, (const querybuf
*) ans2p
,
332 resplen2
, name
, pat
, buffer
, buflen
,
333 errnop
, herrnop
, ttlp
);
340 status
= NSS_STATUS_TRYAGAIN
;
343 /* System has run out of file descriptors. */
346 h_errno
= NETDB_INTERNAL
;
350 status
= NSS_STATUS_UNAVAIL
;
353 status
= NSS_STATUS_NOTFOUND
;
358 if (h_errno
== TRY_AGAIN
)
361 __set_errno (olderr
);
364 /* Check whether ans2p was separately allocated. */
368 if (host_buffer
.buf
!= orig_host_buffer
)
369 free (host_buffer
.buf
);
375 extern enum nss_status
_nss_dns_gethostbyaddr2_r (const void *addr
,
376 socklen_t len
, int af
,
377 struct hostent
*result
,
378 char *buffer
, size_t buflen
,
379 int *errnop
, int *h_errnop
,
381 hidden_proto (_nss_dns_gethostbyaddr2_r
)
384 _nss_dns_gethostbyaddr2_r (const void *addr
, socklen_t len
, int af
,
385 struct hostent
*result
, char *buffer
, size_t buflen
,
386 int *errnop
, int *h_errnop
, int32_t *ttlp
)
388 static const u_char mapped
[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
389 static const u_char tunnelled
[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
390 static const u_char v6local
[] = { 0,0, 0,1 };
391 const u_char
*uaddr
= (const u_char
*)addr
;
394 char *aliases
[MAX_NR_ALIASES
];
395 unsigned char host_addr
[16]; /* IPv4 or IPv6 */
396 char *h_addr_ptrs
[MAX_NR_ADDRS
+ 1];
398 } *host_data
= (struct host_data
*) buffer
;
404 querybuf
*orig_host_buffer
;
405 char qbuf
[MAXDNAME
+1], *qp
= NULL
;
410 uintptr_t pad
= -(uintptr_t) buffer
% __alignof__ (struct host_data
);
412 buflen
= buflen
> pad
? buflen
- pad
: 0;
414 if (__glibc_unlikely (buflen
< sizeof (struct host_data
)))
417 *h_errnop
= NETDB_INTERNAL
;
418 return NSS_STATUS_TRYAGAIN
;
421 host_data
= (struct host_data
*) buffer
;
423 if (__res_maybe_init (&_res
, 0) == -1)
424 return NSS_STATUS_UNAVAIL
;
426 if (af
== AF_INET6
&& len
== IN6ADDRSZ
427 && (memcmp (uaddr
, mapped
, sizeof mapped
) == 0
428 || (memcmp (uaddr
, tunnelled
, sizeof tunnelled
) == 0
429 && memcmp (&uaddr
[sizeof tunnelled
], v6local
, sizeof v6local
))))
432 addr
+= sizeof mapped
;
433 uaddr
+= sizeof mapped
;
447 *errnop
= EAFNOSUPPORT
;
448 *h_errnop
= NETDB_INTERNAL
;
449 return NSS_STATUS_UNAVAIL
;
453 *errnop
= EAFNOSUPPORT
;
454 *h_errnop
= NETDB_INTERNAL
;
455 return NSS_STATUS_UNAVAIL
;
458 host_buffer
.buf
= orig_host_buffer
= (querybuf
*) alloca (1024);
463 sprintf (qbuf
, "%u.%u.%u.%u.in-addr.arpa", (uaddr
[3] & 0xff),
464 (uaddr
[2] & 0xff), (uaddr
[1] & 0xff), (uaddr
[0] & 0xff));
467 /* Only lookup with the byte string format if the user wants it. */
468 if (__glibc_unlikely (_res
.options
& RES_USEBSTRING
))
470 qp
= stpcpy (qbuf
, "\\[x");
471 for (n
= 0; n
< IN6ADDRSZ
; ++n
)
472 qp
+= sprintf (qp
, "%02hhx", uaddr
[n
]);
473 strcpy (qp
, "].ip6.arpa");
474 n
= __libc_res_nquery (&_res
, qbuf
, C_IN
, T_PTR
,
475 host_buffer
.buf
->buf
, 1024, &host_buffer
.ptr
,
476 NULL
, NULL
, NULL
, NULL
);
481 for (n
= IN6ADDRSZ
- 1; n
>= 0; n
--)
483 static const char nibblechar
[16] = "0123456789abcdef";
484 *qp
++ = nibblechar
[uaddr
[n
] & 0xf];
486 *qp
++ = nibblechar
[(uaddr
[n
] >> 4) & 0xf];
489 strcpy(qp
, "ip6.arpa");
496 n
= __libc_res_nquery (&_res
, qbuf
, C_IN
, T_PTR
, host_buffer
.buf
->buf
,
497 1024, &host_buffer
.ptr
, NULL
, NULL
, NULL
, NULL
);
498 if (n
< 0 && af
== AF_INET6
&& (_res
.options
& RES_NOIP6DOTINT
) == 0)
500 strcpy (qp
, "ip6.int");
501 n
= __libc_res_nquery (&_res
, qbuf
, C_IN
, T_PTR
, host_buffer
.buf
->buf
,
502 host_buffer
.buf
!= orig_host_buffer
503 ? MAXPACKET
: 1024, &host_buffer
.ptr
,
504 NULL
, NULL
, NULL
, NULL
);
509 __set_errno (olderr
);
510 if (host_buffer
.buf
!= orig_host_buffer
)
511 free (host_buffer
.buf
);
512 return errno
== ECONNREFUSED
? NSS_STATUS_UNAVAIL
: NSS_STATUS_NOTFOUND
;
516 status
= getanswer_r (host_buffer
.buf
, n
, qbuf
, T_PTR
, result
, buffer
, buflen
,
517 errnop
, h_errnop
, 0 /* XXX */, ttlp
, NULL
);
518 if (host_buffer
.buf
!= orig_host_buffer
)
519 free (host_buffer
.buf
);
520 if (status
!= NSS_STATUS_SUCCESS
)
523 result
->h_addrtype
= af
;
524 result
->h_length
= len
;
525 memcpy (host_data
->host_addr
, addr
, len
);
526 host_data
->h_addr_ptrs
[0] = (char *) host_data
->host_addr
;
527 host_data
->h_addr_ptrs
[1] = NULL
;
529 /* XXX I think this is wrong. Why should an IPv4 address be
530 converted to IPv6 if the user explicitly asked for IPv4? */
531 if (af
== AF_INET
&& (_res
.options
& RES_USE_INET6
))
533 map_v4v6_address ((char *) host_data
->host_addr
,
534 (char *) host_data
->host_addr
);
535 result
->h_addrtype
= AF_INET6
;
536 result
->h_length
= IN6ADDRSZ
;
539 *h_errnop
= NETDB_SUCCESS
;
540 return NSS_STATUS_SUCCESS
;
542 hidden_def (_nss_dns_gethostbyaddr2_r
)
546 _nss_dns_gethostbyaddr_r (const void *addr
, socklen_t len
, int af
,
547 struct hostent
*result
, char *buffer
, size_t buflen
,
548 int *errnop
, int *h_errnop
)
550 return _nss_dns_gethostbyaddr2_r (addr
, len
, af
, result
, buffer
, buflen
,
551 errnop
, h_errnop
, NULL
);
554 static void addrsort (char **ap
, int num
);
557 addrsort (char **ap
, int num
)
561 short aval
[MAX_NR_ADDRS
];
565 if (num
> MAX_NR_ADDRS
)
567 for (i
= 0; i
< num
; i
++, p
++)
569 for (j
= 0 ; (unsigned)j
< _res
.nsort
; j
++)
570 if (_res
.sort_list
[j
].addr
.s_addr
==
571 (((struct in_addr
*)(*p
))->s_addr
& _res
.sort_list
[j
].mask
))
574 if (needsort
== 0 && i
> 0 && j
< aval
[i
-1])
580 while (needsort
++ < num
)
581 for (j
= needsort
- 2; j
>= 0; j
--)
582 if (aval
[j
] > aval
[j
+1])
598 static enum nss_status
599 getanswer_r (const querybuf
*answer
, int anslen
, const char *qname
, int qtype
,
600 struct hostent
*result
, char *buffer
, size_t buflen
,
601 int *errnop
, int *h_errnop
, int map
, int32_t *ttlp
, char **canonp
)
605 char *aliases
[MAX_NR_ALIASES
];
606 unsigned char host_addr
[16]; /* IPv4 or IPv6 */
607 char *h_addr_ptrs
[0];
611 const u_char
*end_of_message
, *cp
;
612 int n
, ancount
, qdcount
;
613 int haveanswer
, had_error
;
614 char *bp
, **ap
, **hap
;
617 int (*name_ok
) (const char *);
618 u_char packtmp
[NS_MAXCDNAME
];
620 uintptr_t pad
= -(uintptr_t) buffer
% __alignof__ (struct host_data
);
622 buflen
= buflen
> pad
? buflen
- pad
: 0;
623 if (__glibc_unlikely (buflen
< sizeof (struct host_data
)))
625 /* The buffer is too small. */
628 *h_errnop
= NETDB_INTERNAL
;
629 return NSS_STATUS_TRYAGAIN
;
631 host_data
= (struct host_data
*) buffer
;
632 linebuflen
= buflen
- sizeof (struct host_data
);
633 if (buflen
- sizeof (struct host_data
) != linebuflen
)
634 linebuflen
= INT_MAX
;
637 result
->h_name
= NULL
;
638 end_of_message
= answer
->buf
+ anslen
;
650 return NSS_STATUS_UNAVAIL
; /* XXX should be abort(); */
654 * find first satisfactory answer
657 ancount
= ntohs (hp
->ancount
);
658 qdcount
= ntohs (hp
->qdcount
);
659 cp
= answer
->buf
+ HFIXEDSZ
;
660 if (__builtin_expect (qdcount
, 1) != 1)
662 *h_errnop
= NO_RECOVERY
;
663 return NSS_STATUS_UNAVAIL
;
665 if (sizeof (struct host_data
) + (ancount
+ 1) * sizeof (char *) >= buflen
)
667 bp
= (char *) &host_data
->h_addr_ptrs
[ancount
+ 1];
668 linebuflen
-= (ancount
+ 1) * sizeof (char *);
670 n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
671 packtmp
, sizeof packtmp
);
672 if (n
!= -1 && __ns_name_ntop (packtmp
, bp
, linebuflen
) == -1)
674 if (__builtin_expect (errno
, 0) == EMSGSIZE
)
680 if (n
> 0 && bp
[0] == '.')
683 if (__builtin_expect (n
< 0 || ((*name_ok
) (bp
) == 0 && (errno
= EBADMSG
)),
687 *h_errnop
= NO_RECOVERY
;
688 return NSS_STATUS_UNAVAIL
;
692 if (qtype
== T_A
|| qtype
== T_AAAA
)
694 /* res_send() has already verified that the query name is the
695 * same as the one we sent; this just gets the expanded name
696 * (i.e., with the succeeding search-domain tacked on).
698 n
= strlen (bp
) + 1; /* for the \0 */
699 if (n
>= MAXHOSTNAMELEN
)
701 *h_errnop
= NO_RECOVERY
;
703 return NSS_STATUS_TRYAGAIN
;
710 /* The qname can be abbreviated, but h_name is now absolute. */
711 qname
= result
->h_name
;
714 ap
= host_data
->aliases
;
716 result
->h_aliases
= host_data
->aliases
;
717 hap
= host_data
->h_addr_ptrs
;
719 result
->h_addr_list
= host_data
->h_addr_ptrs
;
723 while (ancount
-- > 0 && cp
< end_of_message
&& had_error
== 0)
727 n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
728 packtmp
, sizeof packtmp
);
729 if (n
!= -1 && __ns_name_ntop (packtmp
, bp
, linebuflen
) == -1)
731 if (__builtin_expect (errno
, 0) == EMSGSIZE
)
737 if (__glibc_unlikely (n
< 0 || (*name_ok
) (bp
) == 0))
744 if (__glibc_unlikely (cp
+ 10 > end_of_message
))
750 type
= __ns_get16 (cp
);
751 cp
+= INT16SZ
; /* type */
752 class = __ns_get16 (cp
);
753 cp
+= INT16SZ
; /* class */
754 int32_t ttl
= __ns_get32 (cp
);
755 cp
+= INT32SZ
; /* TTL */
757 cp
+= INT16SZ
; /* len */
759 if (end_of_message
- cp
< n
)
761 /* RDATA extends beyond the end of the packet. */
766 if (__glibc_unlikely (class != C_IN
))
768 /* XXX - debug? syslog? */
770 continue; /* XXX - had_error++ ? */
773 if ((qtype
== T_A
|| qtype
== T_AAAA
) && type
== T_CNAME
)
775 /* A CNAME could also have a TTL entry. */
776 if (ttlp
!= NULL
&& ttl
< *ttlp
)
779 if (ap
>= &host_data
->aliases
[MAX_NR_ALIASES
- 1])
781 n
= dn_expand (answer
->buf
, end_of_message
, cp
, tbuf
, sizeof tbuf
);
782 if (__glibc_unlikely (n
< 0 || (*name_ok
) (tbuf
) == 0))
790 n
= strlen (bp
) + 1; /* For the \0. */
791 if (__builtin_expect (n
, 0) >= MAXHOSTNAMELEN
)
798 /* Get canonical name. */
799 n
= strlen (tbuf
) + 1; /* For the \0. */
800 if (__glibc_unlikely (n
> linebuflen
))
802 if (__builtin_expect (n
, 0) >= MAXHOSTNAMELEN
)
808 bp
= __mempcpy (bp
, tbuf
, n
); /* Cannot overflow. */
813 if (qtype
== T_PTR
&& type
== T_CNAME
)
815 /* A CNAME could also have a TTL entry. */
816 if (ttlp
!= NULL
&& ttl
< *ttlp
)
819 n
= dn_expand (answer
->buf
, end_of_message
, cp
, tbuf
, sizeof tbuf
);
820 if (__glibc_unlikely (n
< 0 || res_dnok (tbuf
) == 0))
826 /* Get canonical name. */
827 n
= strlen (tbuf
) + 1; /* For the \0. */
828 if (__glibc_unlikely (n
> linebuflen
))
830 if (__builtin_expect (n
, 0) >= MAXHOSTNAMELEN
)
836 bp
= __mempcpy (bp
, tbuf
, n
); /* Cannot overflow. */
841 if (type
== T_A
&& qtype
== T_AAAA
&& map
)
843 else if (__glibc_unlikely (type
!= qtype
))
846 continue; /* XXX - had_error++ ? */
852 if (__glibc_unlikely (strcasecmp (tname
, bp
) != 0))
855 continue; /* XXX - had_error++ ? */
858 n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
859 packtmp
, sizeof packtmp
);
860 if (n
!= -1 && __ns_name_ntop (packtmp
, bp
, linebuflen
) == -1)
862 if (__builtin_expect (errno
, 0) == EMSGSIZE
)
868 if (__glibc_unlikely (n
< 0 || res_hnok (bp
) == 0))
873 if (ttlp
!= NULL
&& ttl
< *ttlp
)
875 /* bind would put multiple PTR records as aliases, but we don't do
880 n
= strlen (bp
) + 1; /* for the \0 */
881 if (__glibc_unlikely (n
>= MAXHOSTNAMELEN
))
888 if (map_v4v6_hostent (result
, &bp
, &linebuflen
))
891 *h_errnop
= NETDB_SUCCESS
;
892 return NSS_STATUS_SUCCESS
;
895 if (__builtin_expect (strcasecmp (result
->h_name
, bp
), 0) != 0)
898 continue; /* XXX - had_error++ ? */
901 /* Stop parsing at a record whose length is incorrect. */
902 if (n
!= rrtype_to_rdata_length (type
))
908 /* Skip records of the wrong type. */
909 if (n
!= result
->h_length
)
918 /* We compose a single hostent out of the entire chain of
919 entries, so the TTL of the hostent is essentially the lowest
921 if (ttlp
!= NULL
&& ttl
< *ttlp
)
926 nn
= strlen (bp
) + 1; /* for the \0 */
931 linebuflen
-= sizeof (align
) - ((u_long
) bp
% sizeof (align
));
932 bp
+= sizeof (align
) - ((u_long
) bp
% sizeof (align
));
934 if (__glibc_unlikely (n
> linebuflen
))
936 bp
= __mempcpy (*hap
++ = bp
, cp
, n
);
952 * Note: we sort even if host can take only one address
953 * in its return structures - should give it the "best"
954 * address in that case, not some random one
956 if (_res
.nsort
&& haveanswer
> 1 && qtype
== T_A
)
957 addrsort (host_data
->h_addr_ptrs
, haveanswer
);
959 if (result
->h_name
== NULL
)
961 n
= strlen (qname
) + 1; /* For the \0. */
964 if (n
>= MAXHOSTNAMELEN
)
967 bp
= __mempcpy (bp
, qname
, n
); /* Cannot overflow. */
972 if (map_v4v6_hostent (result
, &bp
, &linebuflen
))
974 *h_errnop
= NETDB_SUCCESS
;
975 return NSS_STATUS_SUCCESS
;
978 *h_errnop
= NO_RECOVERY
;
980 /* Special case here: if the resolver sent a result but it only
981 contains a CNAME while we are looking for a T_A or T_AAAA record,
982 we fail with NOTFOUND instead of TRYAGAIN. */
983 return ((qtype
== T_A
|| qtype
== T_AAAA
) && ap
!= host_data
->aliases
984 ? NSS_STATUS_NOTFOUND
: NSS_STATUS_TRYAGAIN
);
988 static enum nss_status
989 gaih_getanswer_slice (const querybuf
*answer
, int anslen
, const char *qname
,
990 struct gaih_addrtuple
***patp
,
991 char **bufferp
, size_t *buflenp
,
992 int *errnop
, int *h_errnop
, int32_t *ttlp
, int *firstp
)
994 char *buffer
= *bufferp
;
995 size_t buflen
= *buflenp
;
997 struct gaih_addrtuple
**pat
= *patp
;
998 const HEADER
*hp
= &answer
->hdr
;
999 int ancount
= ntohs (hp
->ancount
);
1000 int qdcount
= ntohs (hp
->qdcount
);
1001 const u_char
*cp
= answer
->buf
+ HFIXEDSZ
;
1002 const u_char
*end_of_message
= answer
->buf
+ anslen
;
1003 if (__glibc_unlikely (qdcount
!= 1))
1005 *h_errnop
= NO_RECOVERY
;
1006 return NSS_STATUS_UNAVAIL
;
1009 u_char packtmp
[NS_MAXCDNAME
];
1010 int n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
1011 packtmp
, sizeof packtmp
);
1012 /* We unpack the name to check it for validity. But we do not need
1014 if (n
!= -1 && __ns_name_ntop (packtmp
, buffer
, buflen
) == -1)
1016 if (__builtin_expect (errno
, 0) == EMSGSIZE
)
1020 *h_errnop
= NETDB_INTERNAL
;
1021 return NSS_STATUS_TRYAGAIN
;
1027 if (__builtin_expect (n
< 0 || (res_hnok (buffer
) == 0
1028 && (errno
= EBADMSG
)), 0))
1031 *h_errnop
= NO_RECOVERY
;
1032 return NSS_STATUS_UNAVAIL
;
1039 char *h_name
= NULL
;
1044 *h_errnop
= HOST_NOT_FOUND
;
1045 return NSS_STATUS_NOTFOUND
;
1048 while (ancount
-- > 0 && cp
< end_of_message
&& had_error
== 0)
1050 n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
1051 packtmp
, sizeof packtmp
);
1053 (h_namelen
= __ns_name_ntop (packtmp
, buffer
, buflen
)) == -1)
1055 if (__builtin_expect (errno
, 0) == EMSGSIZE
)
1060 if (__glibc_unlikely (n
< 0 || res_hnok (buffer
) == 0))
1065 if (*firstp
&& canon
== NULL
)
1068 buffer
+= h_namelen
;
1069 buflen
-= h_namelen
;
1074 if (__glibc_unlikely (cp
+ 10 > end_of_message
))
1080 int type
= __ns_get16 (cp
);
1081 cp
+= INT16SZ
; /* type */
1082 int class = __ns_get16 (cp
);
1083 cp
+= INT16SZ
; /* class */
1084 int32_t ttl
= __ns_get32 (cp
);
1085 cp
+= INT32SZ
; /* TTL */
1086 n
= __ns_get16 (cp
);
1087 cp
+= INT16SZ
; /* len */
1089 if (end_of_message
- cp
< n
)
1091 /* RDATA extends beyond the end of the packet. */
1102 if (type
== T_CNAME
)
1104 char tbuf
[MAXDNAME
];
1106 /* A CNAME could also have a TTL entry. */
1107 if (ttlp
!= NULL
&& ttl
< *ttlp
)
1110 n
= dn_expand (answer
->buf
, end_of_message
, cp
, tbuf
, sizeof tbuf
);
1111 if (__glibc_unlikely (n
< 0 || res_hnok (tbuf
) == 0))
1120 /* Reclaim buffer space. */
1121 if (h_name
+ h_namelen
== buffer
)
1124 buflen
+= h_namelen
;
1127 n
= strlen (tbuf
) + 1;
1128 if (__glibc_unlikely (n
> buflen
))
1130 if (__glibc_unlikely (n
>= MAXHOSTNAMELEN
))
1137 buffer
= __mempcpy (buffer
, tbuf
, n
);
1144 /* Stop parsing if we encounter a record with incorrect RDATA
1146 if (type
== T_A
|| type
== T_AAAA
)
1148 if (n
!= rrtype_to_rdata_length (type
))
1156 /* Skip unknown records. */
1161 assert (type
== T_A
|| type
== T_AAAA
);
1164 uintptr_t pad
= (-(uintptr_t) buffer
1165 % __alignof__ (struct gaih_addrtuple
));
1167 buflen
= buflen
> pad
? buflen
- pad
: 0;
1169 if (__builtin_expect (buflen
< sizeof (struct gaih_addrtuple
),
1173 *pat
= (struct gaih_addrtuple
*) buffer
;
1174 buffer
+= sizeof (struct gaih_addrtuple
);
1175 buflen
-= sizeof (struct gaih_addrtuple
);
1178 (*pat
)->name
= NULL
;
1179 (*pat
)->next
= NULL
;
1183 /* We compose a single hostent out of the entire chain of
1184 entries, so the TTL of the hostent is essentially the lowest
1185 TTL in the chain. */
1186 if (ttlp
!= NULL
&& ttl
< *ttlp
)
1189 (*pat
)->name
= canon
?: h_name
;
1194 (*pat
)->family
= type
== T_A
? AF_INET
: AF_INET6
;
1195 memcpy ((*pat
)->addr
, cp
, n
);
1197 (*pat
)->scopeid
= 0;
1199 pat
= &((*pat
)->next
);
1210 *h_errnop
= NETDB_SUCCESS
;
1211 return NSS_STATUS_SUCCESS
;
1214 /* Special case here: if the resolver sent a result but it only
1215 contains a CNAME while we are looking for a T_A or T_AAAA record,
1216 we fail with NOTFOUND instead of TRYAGAIN. */
1219 *h_errnop
= HOST_NOT_FOUND
;
1220 return NSS_STATUS_NOTFOUND
;
1223 *h_errnop
= NETDB_INTERNAL
;
1224 return NSS_STATUS_TRYAGAIN
;
1228 static enum nss_status
1229 gaih_getanswer (const querybuf
*answer1
, int anslen1
, const querybuf
*answer2
,
1230 int anslen2
, const char *qname
,
1231 struct gaih_addrtuple
**pat
, char *buffer
, size_t buflen
,
1232 int *errnop
, int *h_errnop
, int32_t *ttlp
)
1236 enum nss_status status
= NSS_STATUS_NOTFOUND
;
1238 /* Combining the NSS status of two distinct queries requires some
1239 compromise and attention to symmetry (A or AAAA queries can be
1240 returned in any order). What follows is a breakdown of how this
1241 code is expected to work and why. We discuss only SUCCESS,
1242 TRYAGAIN, NOTFOUND and UNAVAIL, since they are the only returns
1243 that apply (though RETURN and MERGE exist). We make a distinction
1244 between TRYAGAIN (recoverable) and TRYAGAIN' (not-recoverable).
1245 A recoverable TRYAGAIN is almost always due to buffer size issues
1246 and returns ERANGE in errno and the caller is expected to retry
1247 with a larger buffer.
1249 Lastly, you may be tempted to make significant changes to the
1250 conditions in this code to bring about symmetry between responses.
1251 Please don't change anything without due consideration for
1252 expected application behaviour. Some of the synthesized responses
1253 aren't very well thought out and sometimes appear to imply that
1254 IPv4 responses are always answer 1, and IPv6 responses are always
1255 answer 2, but that's not true (see the implementation of send_dg
1256 and send_vc to see response can arrive in any order, particularly
1257 for UDP). However, we expect it holds roughly enough of the time
1258 that this code works, but certainly needs to be fixed to make this
1259 a more robust implementation.
1261 ----------------------------------------------
1262 | Answer 1 Status / | Synthesized | Reason |
1263 | Answer 2 Status | Status | |
1264 |--------------------------------------------|
1265 | SUCCESS/SUCCESS | SUCCESS | [1] |
1266 | SUCCESS/TRYAGAIN | TRYAGAIN | [5] |
1267 | SUCCESS/TRYAGAIN' | SUCCESS | [1] |
1268 | SUCCESS/NOTFOUND | SUCCESS | [1] |
1269 | SUCCESS/UNAVAIL | SUCCESS | [1] |
1270 | TRYAGAIN/SUCCESS | TRYAGAIN | [2] |
1271 | TRYAGAIN/TRYAGAIN | TRYAGAIN | [2] |
1272 | TRYAGAIN/TRYAGAIN' | TRYAGAIN | [2] |
1273 | TRYAGAIN/NOTFOUND | TRYAGAIN | [2] |
1274 | TRYAGAIN/UNAVAIL | TRYAGAIN | [2] |
1275 | TRYAGAIN'/SUCCESS | SUCCESS | [3] |
1276 | TRYAGAIN'/TRYAGAIN | TRYAGAIN | [3] |
1277 | TRYAGAIN'/TRYAGAIN' | TRYAGAIN' | [3] |
1278 | TRYAGAIN'/NOTFOUND | TRYAGAIN' | [3] |
1279 | TRYAGAIN'/UNAVAIL | UNAVAIL | [3] |
1280 | NOTFOUND/SUCCESS | SUCCESS | [3] |
1281 | NOTFOUND/TRYAGAIN | TRYAGAIN | [3] |
1282 | NOTFOUND/TRYAGAIN' | TRYAGAIN' | [3] |
1283 | NOTFOUND/NOTFOUND | NOTFOUND | [3] |
1284 | NOTFOUND/UNAVAIL | UNAVAIL | [3] |
1285 | UNAVAIL/SUCCESS | UNAVAIL | [4] |
1286 | UNAVAIL/TRYAGAIN | UNAVAIL | [4] |
1287 | UNAVAIL/TRYAGAIN' | UNAVAIL | [4] |
1288 | UNAVAIL/NOTFOUND | UNAVAIL | [4] |
1289 | UNAVAIL/UNAVAIL | UNAVAIL | [4] |
1290 ----------------------------------------------
1292 [1] If the first response is a success we return success.
1293 This ignores the state of the second answer and in fact
1294 incorrectly sets errno and h_errno to that of the second
1295 answer. However because the response is a success we ignore
1296 *errnop and *h_errnop (though that means you touched errno on
1297 success). We are being conservative here and returning the
1298 likely IPv4 response in the first answer as a success.
1300 [2] If the first response is a recoverable TRYAGAIN we return
1301 that instead of looking at the second response. The
1302 expectation here is that we have failed to get an IPv4 response
1303 and should retry both queries.
1305 [3] If the first response was not a SUCCESS and the second
1306 response is not NOTFOUND (had a SUCCESS, need to TRYAGAIN,
1307 or failed entirely e.g. TRYAGAIN' and UNAVAIL) then use the
1308 result from the second response, otherwise the first responses
1309 status is used. Again we have some odd side-effects when the
1310 second response is NOTFOUND because we overwrite *errnop and
1311 *h_errnop that means that a first answer of NOTFOUND might see
1312 its *errnop and *h_errnop values altered. Whether it matters
1313 in practice that a first response NOTFOUND has the wrong
1314 *errnop and *h_errnop is undecided.
1316 [4] If the first response is UNAVAIL we return that instead of
1317 looking at the second response. The expectation here is that
1318 it will have failed similarly e.g. configuration failure.
1320 [5] Testing this code is complicated by the fact that truncated
1321 second response buffers might be returned as SUCCESS if the
1322 first answer is a SUCCESS. To fix this we add symmetry to
1323 TRYAGAIN with the second response. If the second response
1324 is a recoverable error we now return TRYAGIN even if the first
1325 response was SUCCESS. */
1328 status
= gaih_getanswer_slice(answer1
, anslen1
, qname
,
1329 &pat
, &buffer
, &buflen
,
1330 errnop
, h_errnop
, ttlp
,
1333 if ((status
== NSS_STATUS_SUCCESS
|| status
== NSS_STATUS_NOTFOUND
1334 || (status
== NSS_STATUS_TRYAGAIN
1335 /* We want to look at the second answer in case of an
1336 NSS_STATUS_TRYAGAIN only if the error is non-recoverable, i.e.
1337 *h_errnop is NO_RECOVERY. If not, and if the failure was due to
1338 an insufficient buffer (ERANGE), then we need to drop the results
1339 and pass on the NSS_STATUS_TRYAGAIN to the caller so that it can
1340 repeat the query with a larger buffer. */
1341 && (*errnop
!= ERANGE
|| *h_errnop
== NO_RECOVERY
)))
1342 && answer2
!= NULL
&& anslen2
> 0)
1344 enum nss_status status2
= gaih_getanswer_slice(answer2
, anslen2
, qname
,
1345 &pat
, &buffer
, &buflen
,
1346 errnop
, h_errnop
, ttlp
,
1348 /* Use the second response status in some cases. */
1349 if (status
!= NSS_STATUS_SUCCESS
&& status2
!= NSS_STATUS_NOTFOUND
)
1351 /* Do not return a truncated second response (unless it was
1352 unavoidable e.g. unrecoverable TRYAGAIN). */
1353 if (status
== NSS_STATUS_SUCCESS
1354 && (status2
== NSS_STATUS_TRYAGAIN
1355 && *errnop
== ERANGE
&& *h_errnop
!= NO_RECOVERY
))
1356 status
= NSS_STATUS_TRYAGAIN
;