1 /* Copyright (C) 1996-2017 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
83 #include <arpa/nameser.h>
85 /* Get implementeation for some internal functions. */
86 #include <resolv/resolv-internal.h>
87 #include <resolv/resolv_context.h>
88 #include <resolv/mapv4v6addr.h>
89 #include <resolv/mapv4v6hostent.h>
94 # define MAXPACKET PACKETSZ
96 # define MAXPACKET 65536
98 /* As per RFC 1034 and 1035 a host name cannot exceed 255 octets in length. */
100 # undef MAXHOSTNAMELEN
102 #define MAXHOSTNAMELEN 256
104 /* We need this time later. */
105 typedef union querybuf
108 u_char buf
[MAXPACKET
];
111 static enum nss_status
getanswer_r (const querybuf
*answer
, int anslen
,
112 const char *qname
, int qtype
,
113 struct hostent
*result
, char *buffer
,
114 size_t buflen
, int *errnop
, int *h_errnop
,
115 int map
, int32_t *ttlp
, char **canonp
);
117 static enum nss_status
gaih_getanswer (const querybuf
*answer1
, int anslen1
,
118 const querybuf
*answer2
, int anslen2
,
120 struct gaih_addrtuple
**pat
,
121 char *buffer
, size_t buflen
,
122 int *errnop
, int *h_errnop
,
125 static enum nss_status
gethostbyname3_context (struct resolv_context
*ctx
,
126 const char *name
, int af
,
127 struct hostent
*result
,
128 char *buffer
, size_t buflen
,
129 int *errnop
, int *h_errnop
,
133 /* Return the expected RDATA length for an address record type (A or
136 rrtype_to_rdata_length (int type
)
151 _nss_dns_gethostbyname3_r (const char *name
, int af
, struct hostent
*result
,
152 char *buffer
, size_t buflen
, int *errnop
,
153 int *h_errnop
, int32_t *ttlp
, char **canonp
)
155 struct resolv_context
*ctx
= __resolv_context_get ();
159 *h_errnop
= NETDB_INTERNAL
;
160 return NSS_STATUS_UNAVAIL
;
162 enum nss_status status
= gethostbyname3_context
163 (ctx
, name
, af
, result
, buffer
, buflen
, errnop
, h_errnop
, ttlp
, canonp
);
164 __resolv_context_put (ctx
);
168 static enum nss_status
169 gethostbyname3_context (struct resolv_context
*ctx
,
170 const char *name
, int af
, struct hostent
*result
,
171 char *buffer
, size_t buflen
, int *errnop
,
172 int *h_errnop
, int32_t *ttlp
, char **canonp
)
179 querybuf
*orig_host_buffer
;
180 char tmp
[NS_MAXDNAME
];
185 enum nss_status status
;
198 *errnop
= EAFNOSUPPORT
;
199 return NSS_STATUS_UNAVAIL
;
202 result
->h_addrtype
= af
;
203 result
->h_length
= size
;
206 * if there aren't any dots, it could be a user-level alias.
207 * this is also done in res_query() since we are not the only
208 * function that looks up host names.
210 if (strchr (name
, '.') == NULL
211 && (cp
= __res_context_hostalias (ctx
, name
, tmp
, sizeof (tmp
))) != NULL
)
214 host_buffer
.buf
= orig_host_buffer
= (querybuf
*) alloca (1024);
216 n
= __res_context_search (ctx
, name
, C_IN
, type
, host_buffer
.buf
->buf
,
217 1024, &host_buffer
.ptr
, NULL
, NULL
, NULL
, NULL
);
223 status
= NSS_STATUS_TRYAGAIN
;
226 /* System has run out of file descriptors. */
229 h_errno
= NETDB_INTERNAL
;
233 status
= NSS_STATUS_UNAVAIL
;
236 status
= NSS_STATUS_NOTFOUND
;
240 if (h_errno
== TRY_AGAIN
)
243 __set_errno (olderr
);
245 /* If we are looking for an IPv6 address and mapping is enabled
246 by having the RES_USE_INET6 bit in _res.options set, we try
248 if (af
== AF_INET6
&& res_use_inet6 ())
249 n
= __res_context_search (ctx
, name
, C_IN
, T_A
, host_buffer
.buf
->buf
,
250 host_buffer
.buf
!= orig_host_buffer
251 ? MAXPACKET
: 1024, &host_buffer
.ptr
,
252 NULL
, NULL
, NULL
, NULL
);
256 if (host_buffer
.buf
!= orig_host_buffer
)
257 free (host_buffer
.buf
);
263 result
->h_addrtype
= AF_INET
;
264 result
->h_length
= INADDRSZ
;
267 status
= getanswer_r (host_buffer
.buf
, n
, name
, type
, result
, buffer
, buflen
,
268 errnop
, h_errnop
, map
, ttlp
, canonp
);
269 if (host_buffer
.buf
!= orig_host_buffer
)
270 free (host_buffer
.buf
);
275 _nss_dns_gethostbyname2_r (const char *name
, int af
, struct hostent
*result
,
276 char *buffer
, size_t buflen
, int *errnop
,
279 return _nss_dns_gethostbyname3_r (name
, af
, result
, buffer
, buflen
, errnop
,
280 h_errnop
, NULL
, NULL
);
285 _nss_dns_gethostbyname_r (const char *name
, struct hostent
*result
,
286 char *buffer
, size_t buflen
, int *errnop
,
289 struct resolv_context
*ctx
= __resolv_context_get ();
293 *h_errnop
= NETDB_INTERNAL
;
294 return NSS_STATUS_UNAVAIL
;
296 enum nss_status status
= NSS_STATUS_NOTFOUND
;
297 if (res_use_inet6 ())
298 status
= gethostbyname3_context (ctx
, name
, AF_INET6
, result
, buffer
,
299 buflen
, errnop
, h_errnop
, NULL
, NULL
);
300 if (status
== NSS_STATUS_NOTFOUND
)
301 status
= gethostbyname3_context (ctx
, name
, AF_INET
, result
, buffer
,
302 buflen
, errnop
, h_errnop
, NULL
, NULL
);
303 __resolv_context_put (ctx
);
309 _nss_dns_gethostbyname4_r (const char *name
, struct gaih_addrtuple
**pat
,
310 char *buffer
, size_t buflen
, int *errnop
,
311 int *herrnop
, int32_t *ttlp
)
313 struct resolv_context
*ctx
= __resolv_context_get ();
317 *herrnop
= NETDB_INTERNAL
;
318 return NSS_STATUS_UNAVAIL
;
322 * if there aren't any dots, it could be a user-level alias.
323 * this is also done in res_query() since we are not the only
324 * function that looks up host names.
326 if (strchr (name
, '.') == NULL
)
328 char *tmp
= alloca (NS_MAXDNAME
);
329 const char *cp
= __res_context_hostalias (ctx
, name
, tmp
, NS_MAXDNAME
);
339 querybuf
*orig_host_buffer
;
340 host_buffer
.buf
= orig_host_buffer
= (querybuf
*) alloca (2048);
341 u_char
*ans2p
= NULL
;
344 int ans2p_malloced
= 0;
347 enum nss_status status
;
348 int n
= __res_context_search (ctx
, name
, C_IN
, T_QUERY_A_AND_AAAA
,
349 host_buffer
.buf
->buf
, 2048, &host_buffer
.ptr
,
350 &ans2p
, &nans2p
, &resplen2
, &ans2p_malloced
);
353 status
= gaih_getanswer (host_buffer
.buf
, n
, (const querybuf
*) ans2p
,
354 resplen2
, name
, pat
, buffer
, buflen
,
355 errnop
, herrnop
, ttlp
);
362 status
= NSS_STATUS_TRYAGAIN
;
365 /* System has run out of file descriptors. */
368 h_errno
= NETDB_INTERNAL
;
372 status
= NSS_STATUS_UNAVAIL
;
375 status
= NSS_STATUS_NOTFOUND
;
380 if (h_errno
== TRY_AGAIN
)
383 __set_errno (olderr
);
386 /* Check whether ans2p was separately allocated. */
390 if (host_buffer
.buf
!= orig_host_buffer
)
391 free (host_buffer
.buf
);
393 __resolv_context_put (ctx
);
398 extern enum nss_status
_nss_dns_gethostbyaddr2_r (const void *addr
,
399 socklen_t len
, int af
,
400 struct hostent
*result
,
401 char *buffer
, size_t buflen
,
402 int *errnop
, int *h_errnop
,
404 hidden_proto (_nss_dns_gethostbyaddr2_r
)
407 _nss_dns_gethostbyaddr2_r (const void *addr
, socklen_t len
, int af
,
408 struct hostent
*result
, char *buffer
, size_t buflen
,
409 int *errnop
, int *h_errnop
, int32_t *ttlp
)
411 static const u_char mapped
[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
412 static const u_char tunnelled
[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
413 static const u_char v6local
[] = { 0,0, 0,1 };
414 const u_char
*uaddr
= (const u_char
*)addr
;
417 char *aliases
[MAX_NR_ALIASES
];
418 unsigned char host_addr
[16]; /* IPv4 or IPv6 */
419 char *h_addr_ptrs
[MAX_NR_ADDRS
+ 1];
421 } *host_data
= (struct host_data
*) buffer
;
427 querybuf
*orig_host_buffer
;
428 char qbuf
[MAXDNAME
+1], *qp
= NULL
;
433 uintptr_t pad
= -(uintptr_t) buffer
% __alignof__ (struct host_data
);
435 buflen
= buflen
> pad
? buflen
- pad
: 0;
437 if (__glibc_unlikely (buflen
< sizeof (struct host_data
)))
440 *h_errnop
= NETDB_INTERNAL
;
441 return NSS_STATUS_TRYAGAIN
;
444 host_data
= (struct host_data
*) buffer
;
446 struct resolv_context
*ctx
= __resolv_context_get ();
450 *h_errnop
= NETDB_INTERNAL
;
451 return NSS_STATUS_UNAVAIL
;
454 if (af
== AF_INET6
&& len
== IN6ADDRSZ
455 && (memcmp (uaddr
, mapped
, sizeof mapped
) == 0
456 || (memcmp (uaddr
, tunnelled
, sizeof tunnelled
) == 0
457 && memcmp (&uaddr
[sizeof tunnelled
], v6local
, sizeof v6local
))))
460 addr
+= sizeof mapped
;
461 uaddr
+= sizeof mapped
;
475 *errnop
= EAFNOSUPPORT
;
476 *h_errnop
= NETDB_INTERNAL
;
477 __resolv_context_put (ctx
);
478 return NSS_STATUS_UNAVAIL
;
482 *errnop
= EAFNOSUPPORT
;
483 *h_errnop
= NETDB_INTERNAL
;
484 __resolv_context_put (ctx
);
485 return NSS_STATUS_UNAVAIL
;
488 host_buffer
.buf
= orig_host_buffer
= (querybuf
*) alloca (1024);
493 sprintf (qbuf
, "%u.%u.%u.%u.in-addr.arpa", (uaddr
[3] & 0xff),
494 (uaddr
[2] & 0xff), (uaddr
[1] & 0xff), (uaddr
[0] & 0xff));
498 for (n
= IN6ADDRSZ
- 1; n
>= 0; n
--)
500 static const char nibblechar
[16] = "0123456789abcdef";
501 *qp
++ = nibblechar
[uaddr
[n
] & 0xf];
503 *qp
++ = nibblechar
[(uaddr
[n
] >> 4) & 0xf];
506 strcpy(qp
, "ip6.arpa");
513 n
= __res_context_query (ctx
, qbuf
, C_IN
, T_PTR
, host_buffer
.buf
->buf
,
514 1024, &host_buffer
.ptr
, NULL
, NULL
, NULL
, NULL
);
518 __set_errno (olderr
);
519 if (host_buffer
.buf
!= orig_host_buffer
)
520 free (host_buffer
.buf
);
521 __resolv_context_put (ctx
);
522 return errno
== ECONNREFUSED
? NSS_STATUS_UNAVAIL
: NSS_STATUS_NOTFOUND
;
525 status
= getanswer_r (host_buffer
.buf
, n
, qbuf
, T_PTR
, result
, buffer
, buflen
,
526 errnop
, h_errnop
, 0 /* XXX */, ttlp
, NULL
);
527 if (host_buffer
.buf
!= orig_host_buffer
)
528 free (host_buffer
.buf
);
529 if (status
!= NSS_STATUS_SUCCESS
)
531 __resolv_context_put (ctx
);
535 result
->h_addrtype
= af
;
536 result
->h_length
= len
;
537 memcpy (host_data
->host_addr
, addr
, len
);
538 host_data
->h_addr_ptrs
[0] = (char *) host_data
->host_addr
;
539 host_data
->h_addr_ptrs
[1] = NULL
;
540 *h_errnop
= NETDB_SUCCESS
;
541 __resolv_context_put (ctx
);
542 return NSS_STATUS_SUCCESS
;
544 hidden_def (_nss_dns_gethostbyaddr2_r
)
548 _nss_dns_gethostbyaddr_r (const void *addr
, socklen_t len
, int af
,
549 struct hostent
*result
, char *buffer
, size_t buflen
,
550 int *errnop
, int *h_errnop
)
552 return _nss_dns_gethostbyaddr2_r (addr
, len
, af
, result
, buffer
, buflen
,
553 errnop
, h_errnop
, NULL
);
556 static void addrsort (char **ap
, int num
);
559 addrsort (char **ap
, int num
)
563 short aval
[MAX_NR_ADDRS
];
567 if (num
> MAX_NR_ADDRS
)
569 for (i
= 0; i
< num
; i
++, p
++)
571 for (j
= 0 ; (unsigned)j
< _res
.nsort
; j
++)
572 if (_res
.sort_list
[j
].addr
.s_addr
==
573 (((struct in_addr
*)(*p
))->s_addr
& _res
.sort_list
[j
].mask
))
576 if (needsort
== 0 && i
> 0 && j
< aval
[i
-1])
582 while (needsort
++ < num
)
583 for (j
= needsort
- 2; j
>= 0; j
--)
584 if (aval
[j
] > aval
[j
+1])
600 static enum nss_status
601 getanswer_r (const querybuf
*answer
, int anslen
, const char *qname
, int qtype
,
602 struct hostent
*result
, char *buffer
, size_t buflen
,
603 int *errnop
, int *h_errnop
, int map
, int32_t *ttlp
, char **canonp
)
607 char *aliases
[MAX_NR_ALIASES
];
608 unsigned char host_addr
[16]; /* IPv4 or IPv6 */
609 char *h_addr_ptrs
[0];
613 const u_char
*end_of_message
, *cp
;
614 int n
, ancount
, qdcount
;
615 int haveanswer
, had_error
;
616 char *bp
, **ap
, **hap
;
619 int (*name_ok
) (const char *);
620 u_char packtmp
[NS_MAXCDNAME
];
622 uintptr_t pad
= -(uintptr_t) buffer
% __alignof__ (struct host_data
);
624 buflen
= buflen
> pad
? buflen
- pad
: 0;
625 if (__glibc_unlikely (buflen
< sizeof (struct host_data
)))
627 /* The buffer is too small. */
630 *h_errnop
= NETDB_INTERNAL
;
631 return NSS_STATUS_TRYAGAIN
;
633 host_data
= (struct host_data
*) buffer
;
634 linebuflen
= buflen
- sizeof (struct host_data
);
635 if (buflen
- sizeof (struct host_data
) != linebuflen
)
636 linebuflen
= INT_MAX
;
639 result
->h_name
= NULL
;
640 end_of_message
= answer
->buf
+ anslen
;
652 return NSS_STATUS_UNAVAIL
; /* XXX should be abort(); */
656 * find first satisfactory answer
659 ancount
= ntohs (hp
->ancount
);
660 qdcount
= ntohs (hp
->qdcount
);
661 cp
= answer
->buf
+ HFIXEDSZ
;
662 if (__glibc_unlikely (qdcount
!= 1))
664 *h_errnop
= NO_RECOVERY
;
665 return NSS_STATUS_UNAVAIL
;
667 if (sizeof (struct host_data
) + (ancount
+ 1) * sizeof (char *) >= buflen
)
669 bp
= (char *) &host_data
->h_addr_ptrs
[ancount
+ 1];
670 linebuflen
-= (ancount
+ 1) * sizeof (char *);
672 n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
673 packtmp
, sizeof packtmp
);
674 if (n
!= -1 && __ns_name_ntop (packtmp
, bp
, linebuflen
) == -1)
676 if (__glibc_unlikely (errno
== EMSGSIZE
))
682 if (n
> 0 && bp
[0] == '.')
685 if (__glibc_unlikely (n
< 0))
688 *h_errnop
= NO_RECOVERY
;
689 return NSS_STATUS_UNAVAIL
;
691 if (__glibc_unlikely (name_ok (bp
) == 0))
695 *h_errnop
= NO_RECOVERY
;
696 return NSS_STATUS_UNAVAIL
;
700 if (qtype
== T_A
|| qtype
== T_AAAA
)
702 /* res_send() has already verified that the query name is the
703 * same as the one we sent; this just gets the expanded name
704 * (i.e., with the succeeding search-domain tacked on).
706 n
= strlen (bp
) + 1; /* for the \0 */
707 if (n
>= MAXHOSTNAMELEN
)
709 *h_errnop
= NO_RECOVERY
;
711 return NSS_STATUS_TRYAGAIN
;
718 /* The qname can be abbreviated, but h_name is now absolute. */
719 qname
= result
->h_name
;
722 ap
= host_data
->aliases
;
724 result
->h_aliases
= host_data
->aliases
;
725 hap
= host_data
->h_addr_ptrs
;
727 result
->h_addr_list
= host_data
->h_addr_ptrs
;
731 while (ancount
-- > 0 && cp
< end_of_message
&& had_error
== 0)
735 n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
736 packtmp
, sizeof packtmp
);
737 if (n
!= -1 && __ns_name_ntop (packtmp
, bp
, linebuflen
) == -1)
739 if (__glibc_unlikely (errno
== EMSGSIZE
))
745 if (__glibc_unlikely (n
< 0 || (*name_ok
) (bp
) == 0))
752 if (__glibc_unlikely (cp
+ 10 > end_of_message
))
758 type
= __ns_get16 (cp
);
759 cp
+= INT16SZ
; /* type */
760 class = __ns_get16 (cp
);
761 cp
+= INT16SZ
; /* class */
762 int32_t ttl
= __ns_get32 (cp
);
763 cp
+= INT32SZ
; /* TTL */
765 cp
+= INT16SZ
; /* len */
767 if (end_of_message
- cp
< n
)
769 /* RDATA extends beyond the end of the packet. */
774 if (__glibc_unlikely (class != C_IN
))
776 /* XXX - debug? syslog? */
778 continue; /* XXX - had_error++ ? */
781 if ((qtype
== T_A
|| qtype
== T_AAAA
) && type
== T_CNAME
)
783 /* A CNAME could also have a TTL entry. */
784 if (ttlp
!= NULL
&& ttl
< *ttlp
)
787 if (ap
>= &host_data
->aliases
[MAX_NR_ALIASES
- 1])
789 n
= dn_expand (answer
->buf
, end_of_message
, cp
, tbuf
, sizeof tbuf
);
790 if (__glibc_unlikely (n
< 0 || (*name_ok
) (tbuf
) == 0))
798 n
= strlen (bp
) + 1; /* For the \0. */
799 if (__glibc_unlikely (n
>= MAXHOSTNAMELEN
))
806 /* Get canonical name. */
807 n
= strlen (tbuf
) + 1; /* For the \0. */
808 if (__glibc_unlikely (n
> linebuflen
))
810 if (__glibc_unlikely (n
>= MAXHOSTNAMELEN
))
816 bp
= __mempcpy (bp
, tbuf
, n
); /* Cannot overflow. */
821 if (qtype
== T_PTR
&& type
== T_CNAME
)
823 /* A CNAME could also have a TTL entry. */
824 if (ttlp
!= NULL
&& ttl
< *ttlp
)
827 n
= dn_expand (answer
->buf
, end_of_message
, cp
, tbuf
, sizeof tbuf
);
828 if (__glibc_unlikely (n
< 0 || res_dnok (tbuf
) == 0))
834 /* Get canonical name. */
835 n
= strlen (tbuf
) + 1; /* For the \0. */
836 if (__glibc_unlikely (n
> linebuflen
))
838 if (__glibc_unlikely (n
>= MAXHOSTNAMELEN
))
844 bp
= __mempcpy (bp
, tbuf
, n
); /* Cannot overflow. */
849 if (type
== T_A
&& qtype
== T_AAAA
&& map
)
851 else if (__glibc_unlikely (type
!= qtype
))
854 continue; /* XXX - had_error++ ? */
860 if (__glibc_unlikely (strcasecmp (tname
, bp
) != 0))
863 continue; /* XXX - had_error++ ? */
866 n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
867 packtmp
, sizeof packtmp
);
868 if (n
!= -1 && __ns_name_ntop (packtmp
, bp
, linebuflen
) == -1)
870 if (__glibc_unlikely (errno
== EMSGSIZE
))
876 if (__glibc_unlikely (n
< 0 || res_hnok (bp
) == 0))
881 if (ttlp
!= NULL
&& ttl
< *ttlp
)
883 /* bind would put multiple PTR records as aliases, but we don't do
888 n
= strlen (bp
) + 1; /* for the \0 */
889 if (__glibc_unlikely (n
>= MAXHOSTNAMELEN
))
896 if (map_v4v6_hostent (result
, &bp
, &linebuflen
))
899 *h_errnop
= NETDB_SUCCESS
;
900 return NSS_STATUS_SUCCESS
;
903 if (__glibc_unlikely (strcasecmp (result
->h_name
, bp
) != 0))
906 continue; /* XXX - had_error++ ? */
909 /* Stop parsing at a record whose length is incorrect. */
910 if (n
!= rrtype_to_rdata_length (type
))
916 /* Skip records of the wrong type. */
917 if (n
!= result
->h_length
)
926 /* We compose a single hostent out of the entire chain of
927 entries, so the TTL of the hostent is essentially the lowest
929 if (ttlp
!= NULL
&& ttl
< *ttlp
)
934 nn
= strlen (bp
) + 1; /* for the \0 */
939 linebuflen
-= sizeof (align
) - ((u_long
) bp
% sizeof (align
));
940 bp
+= sizeof (align
) - ((u_long
) bp
% sizeof (align
));
942 if (__glibc_unlikely (n
> linebuflen
))
944 bp
= __mempcpy (*hap
++ = bp
, cp
, n
);
960 * Note: we sort even if host can take only one address
961 * in its return structures - should give it the "best"
962 * address in that case, not some random one
964 if (_res
.nsort
&& haveanswer
> 1 && qtype
== T_A
)
965 addrsort (host_data
->h_addr_ptrs
, haveanswer
);
967 if (result
->h_name
== NULL
)
969 n
= strlen (qname
) + 1; /* For the \0. */
972 if (n
>= MAXHOSTNAMELEN
)
975 bp
= __mempcpy (bp
, qname
, n
); /* Cannot overflow. */
980 if (map_v4v6_hostent (result
, &bp
, &linebuflen
))
982 *h_errnop
= NETDB_SUCCESS
;
983 return NSS_STATUS_SUCCESS
;
986 *h_errnop
= NO_RECOVERY
;
988 /* Special case here: if the resolver sent a result but it only
989 contains a CNAME while we are looking for a T_A or T_AAAA record,
990 we fail with NOTFOUND instead of TRYAGAIN. */
991 return ((qtype
== T_A
|| qtype
== T_AAAA
) && ap
!= host_data
->aliases
992 ? NSS_STATUS_NOTFOUND
: NSS_STATUS_TRYAGAIN
);
996 static enum nss_status
997 gaih_getanswer_slice (const querybuf
*answer
, int anslen
, const char *qname
,
998 struct gaih_addrtuple
***patp
,
999 char **bufferp
, size_t *buflenp
,
1000 int *errnop
, int *h_errnop
, int32_t *ttlp
, int *firstp
)
1002 char *buffer
= *bufferp
;
1003 size_t buflen
= *buflenp
;
1005 struct gaih_addrtuple
**pat
= *patp
;
1006 const HEADER
*hp
= &answer
->hdr
;
1007 int ancount
= ntohs (hp
->ancount
);
1008 int qdcount
= ntohs (hp
->qdcount
);
1009 const u_char
*cp
= answer
->buf
+ HFIXEDSZ
;
1010 const u_char
*end_of_message
= answer
->buf
+ anslen
;
1011 if (__glibc_unlikely (qdcount
!= 1))
1013 *h_errnop
= NO_RECOVERY
;
1014 return NSS_STATUS_UNAVAIL
;
1017 u_char packtmp
[NS_MAXCDNAME
];
1018 int n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
1019 packtmp
, sizeof packtmp
);
1020 /* We unpack the name to check it for validity. But we do not need
1022 if (n
!= -1 && __ns_name_ntop (packtmp
, buffer
, buflen
) == -1)
1024 if (__glibc_unlikely (errno
== EMSGSIZE
))
1028 *h_errnop
= NETDB_INTERNAL
;
1029 return NSS_STATUS_TRYAGAIN
;
1035 if (__glibc_unlikely (n
< 0))
1038 *h_errnop
= NO_RECOVERY
;
1039 return NSS_STATUS_UNAVAIL
;
1041 if (__glibc_unlikely (res_hnok (buffer
) == 0))
1045 *h_errnop
= NO_RECOVERY
;
1046 return NSS_STATUS_UNAVAIL
;
1053 char *h_name
= NULL
;
1058 *h_errnop
= HOST_NOT_FOUND
;
1059 return NSS_STATUS_NOTFOUND
;
1062 while (ancount
-- > 0 && cp
< end_of_message
&& had_error
== 0)
1064 n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
1065 packtmp
, sizeof packtmp
);
1067 (h_namelen
= __ns_name_ntop (packtmp
, buffer
, buflen
)) == -1)
1069 if (__glibc_unlikely (errno
== EMSGSIZE
))
1074 if (__glibc_unlikely (n
< 0 || res_hnok (buffer
) == 0))
1079 if (*firstp
&& canon
== NULL
)
1082 buffer
+= h_namelen
;
1083 buflen
-= h_namelen
;
1088 if (__glibc_unlikely (cp
+ 10 > end_of_message
))
1094 int type
= __ns_get16 (cp
);
1095 cp
+= INT16SZ
; /* type */
1096 int class = __ns_get16 (cp
);
1097 cp
+= INT16SZ
; /* class */
1098 int32_t ttl
= __ns_get32 (cp
);
1099 cp
+= INT32SZ
; /* TTL */
1100 n
= __ns_get16 (cp
);
1101 cp
+= INT16SZ
; /* len */
1103 if (end_of_message
- cp
< n
)
1105 /* RDATA extends beyond the end of the packet. */
1116 if (type
== T_CNAME
)
1118 char tbuf
[MAXDNAME
];
1120 /* A CNAME could also have a TTL entry. */
1121 if (ttlp
!= NULL
&& ttl
< *ttlp
)
1124 n
= dn_expand (answer
->buf
, end_of_message
, cp
, tbuf
, sizeof tbuf
);
1125 if (__glibc_unlikely (n
< 0 || res_hnok (tbuf
) == 0))
1134 /* Reclaim buffer space. */
1135 if (h_name
+ h_namelen
== buffer
)
1138 buflen
+= h_namelen
;
1141 n
= strlen (tbuf
) + 1;
1142 if (__glibc_unlikely (n
> buflen
))
1144 if (__glibc_unlikely (n
>= MAXHOSTNAMELEN
))
1151 buffer
= __mempcpy (buffer
, tbuf
, n
);
1158 /* Stop parsing if we encounter a record with incorrect RDATA
1160 if (type
== T_A
|| type
== T_AAAA
)
1162 if (n
!= rrtype_to_rdata_length (type
))
1170 /* Skip unknown records. */
1175 assert (type
== T_A
|| type
== T_AAAA
);
1178 uintptr_t pad
= (-(uintptr_t) buffer
1179 % __alignof__ (struct gaih_addrtuple
));
1181 buflen
= buflen
> pad
? buflen
- pad
: 0;
1183 if (__glibc_unlikely (buflen
< sizeof (struct gaih_addrtuple
)))
1186 *pat
= (struct gaih_addrtuple
*) buffer
;
1187 buffer
+= sizeof (struct gaih_addrtuple
);
1188 buflen
-= sizeof (struct gaih_addrtuple
);
1191 (*pat
)->name
= NULL
;
1192 (*pat
)->next
= NULL
;
1196 /* We compose a single hostent out of the entire chain of
1197 entries, so the TTL of the hostent is essentially the lowest
1198 TTL in the chain. */
1199 if (ttlp
!= NULL
&& ttl
< *ttlp
)
1202 (*pat
)->name
= canon
?: h_name
;
1207 (*pat
)->family
= type
== T_A
? AF_INET
: AF_INET6
;
1208 memcpy ((*pat
)->addr
, cp
, n
);
1210 (*pat
)->scopeid
= 0;
1212 pat
= &((*pat
)->next
);
1223 *h_errnop
= NETDB_SUCCESS
;
1224 return NSS_STATUS_SUCCESS
;
1227 /* Special case here: if the resolver sent a result but it only
1228 contains a CNAME while we are looking for a T_A or T_AAAA record,
1229 we fail with NOTFOUND instead of TRYAGAIN. */
1232 *h_errnop
= HOST_NOT_FOUND
;
1233 return NSS_STATUS_NOTFOUND
;
1236 *h_errnop
= NETDB_INTERNAL
;
1237 return NSS_STATUS_TRYAGAIN
;
1241 static enum nss_status
1242 gaih_getanswer (const querybuf
*answer1
, int anslen1
, const querybuf
*answer2
,
1243 int anslen2
, const char *qname
,
1244 struct gaih_addrtuple
**pat
, char *buffer
, size_t buflen
,
1245 int *errnop
, int *h_errnop
, int32_t *ttlp
)
1249 enum nss_status status
= NSS_STATUS_NOTFOUND
;
1251 /* Combining the NSS status of two distinct queries requires some
1252 compromise and attention to symmetry (A or AAAA queries can be
1253 returned in any order). What follows is a breakdown of how this
1254 code is expected to work and why. We discuss only SUCCESS,
1255 TRYAGAIN, NOTFOUND and UNAVAIL, since they are the only returns
1256 that apply (though RETURN and MERGE exist). We make a distinction
1257 between TRYAGAIN (recoverable) and TRYAGAIN' (not-recoverable).
1258 A recoverable TRYAGAIN is almost always due to buffer size issues
1259 and returns ERANGE in errno and the caller is expected to retry
1260 with a larger buffer.
1262 Lastly, you may be tempted to make significant changes to the
1263 conditions in this code to bring about symmetry between responses.
1264 Please don't change anything without due consideration for
1265 expected application behaviour. Some of the synthesized responses
1266 aren't very well thought out and sometimes appear to imply that
1267 IPv4 responses are always answer 1, and IPv6 responses are always
1268 answer 2, but that's not true (see the implementation of send_dg
1269 and send_vc to see response can arrive in any order, particularly
1270 for UDP). However, we expect it holds roughly enough of the time
1271 that this code works, but certainly needs to be fixed to make this
1272 a more robust implementation.
1274 ----------------------------------------------
1275 | Answer 1 Status / | Synthesized | Reason |
1276 | Answer 2 Status | Status | |
1277 |--------------------------------------------|
1278 | SUCCESS/SUCCESS | SUCCESS | [1] |
1279 | SUCCESS/TRYAGAIN | TRYAGAIN | [5] |
1280 | SUCCESS/TRYAGAIN' | SUCCESS | [1] |
1281 | SUCCESS/NOTFOUND | SUCCESS | [1] |
1282 | SUCCESS/UNAVAIL | SUCCESS | [1] |
1283 | TRYAGAIN/SUCCESS | TRYAGAIN | [2] |
1284 | TRYAGAIN/TRYAGAIN | TRYAGAIN | [2] |
1285 | TRYAGAIN/TRYAGAIN' | TRYAGAIN | [2] |
1286 | TRYAGAIN/NOTFOUND | TRYAGAIN | [2] |
1287 | TRYAGAIN/UNAVAIL | TRYAGAIN | [2] |
1288 | TRYAGAIN'/SUCCESS | SUCCESS | [3] |
1289 | TRYAGAIN'/TRYAGAIN | TRYAGAIN | [3] |
1290 | TRYAGAIN'/TRYAGAIN' | TRYAGAIN' | [3] |
1291 | TRYAGAIN'/NOTFOUND | TRYAGAIN' | [3] |
1292 | TRYAGAIN'/UNAVAIL | UNAVAIL | [3] |
1293 | NOTFOUND/SUCCESS | SUCCESS | [3] |
1294 | NOTFOUND/TRYAGAIN | TRYAGAIN | [3] |
1295 | NOTFOUND/TRYAGAIN' | TRYAGAIN' | [3] |
1296 | NOTFOUND/NOTFOUND | NOTFOUND | [3] |
1297 | NOTFOUND/UNAVAIL | UNAVAIL | [3] |
1298 | UNAVAIL/SUCCESS | UNAVAIL | [4] |
1299 | UNAVAIL/TRYAGAIN | UNAVAIL | [4] |
1300 | UNAVAIL/TRYAGAIN' | UNAVAIL | [4] |
1301 | UNAVAIL/NOTFOUND | UNAVAIL | [4] |
1302 | UNAVAIL/UNAVAIL | UNAVAIL | [4] |
1303 ----------------------------------------------
1305 [1] If the first response is a success we return success.
1306 This ignores the state of the second answer and in fact
1307 incorrectly sets errno and h_errno to that of the second
1308 answer. However because the response is a success we ignore
1309 *errnop and *h_errnop (though that means you touched errno on
1310 success). We are being conservative here and returning the
1311 likely IPv4 response in the first answer as a success.
1313 [2] If the first response is a recoverable TRYAGAIN we return
1314 that instead of looking at the second response. The
1315 expectation here is that we have failed to get an IPv4 response
1316 and should retry both queries.
1318 [3] If the first response was not a SUCCESS and the second
1319 response is not NOTFOUND (had a SUCCESS, need to TRYAGAIN,
1320 or failed entirely e.g. TRYAGAIN' and UNAVAIL) then use the
1321 result from the second response, otherwise the first responses
1322 status is used. Again we have some odd side-effects when the
1323 second response is NOTFOUND because we overwrite *errnop and
1324 *h_errnop that means that a first answer of NOTFOUND might see
1325 its *errnop and *h_errnop values altered. Whether it matters
1326 in practice that a first response NOTFOUND has the wrong
1327 *errnop and *h_errnop is undecided.
1329 [4] If the first response is UNAVAIL we return that instead of
1330 looking at the second response. The expectation here is that
1331 it will have failed similarly e.g. configuration failure.
1333 [5] Testing this code is complicated by the fact that truncated
1334 second response buffers might be returned as SUCCESS if the
1335 first answer is a SUCCESS. To fix this we add symmetry to
1336 TRYAGAIN with the second response. If the second response
1337 is a recoverable error we now return TRYAGIN even if the first
1338 response was SUCCESS. */
1341 status
= gaih_getanswer_slice(answer1
, anslen1
, qname
,
1342 &pat
, &buffer
, &buflen
,
1343 errnop
, h_errnop
, ttlp
,
1346 if ((status
== NSS_STATUS_SUCCESS
|| status
== NSS_STATUS_NOTFOUND
1347 || (status
== NSS_STATUS_TRYAGAIN
1348 /* We want to look at the second answer in case of an
1349 NSS_STATUS_TRYAGAIN only if the error is non-recoverable, i.e.
1350 *h_errnop is NO_RECOVERY. If not, and if the failure was due to
1351 an insufficient buffer (ERANGE), then we need to drop the results
1352 and pass on the NSS_STATUS_TRYAGAIN to the caller so that it can
1353 repeat the query with a larger buffer. */
1354 && (*errnop
!= ERANGE
|| *h_errnop
== NO_RECOVERY
)))
1355 && answer2
!= NULL
&& anslen2
> 0)
1357 enum nss_status status2
= gaih_getanswer_slice(answer2
, anslen2
, qname
,
1358 &pat
, &buffer
, &buflen
,
1359 errnop
, h_errnop
, ttlp
,
1361 /* Use the second response status in some cases. */
1362 if (status
!= NSS_STATUS_SUCCESS
&& status2
!= NSS_STATUS_NOTFOUND
)
1364 /* Do not return a truncated second response (unless it was
1365 unavoidable e.g. unrecoverable TRYAGAIN). */
1366 if (status
== NSS_STATUS_SUCCESS
1367 && (status2
== NSS_STATUS_TRYAGAIN
1368 && *errnop
== ERANGE
&& *h_errnop
!= NO_RECOVERY
))
1369 status
= NSS_STATUS_TRYAGAIN
;