1 /* Copyright (C) 1996-2015 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
81 #include <sys/syslog.h>
85 /* Get implementation for some internal functions. */
86 #include <resolv/mapv4v6addr.h>
87 #include <resolv/mapv4v6hostent.h>
92 # define MAXPACKET PACKETSZ
94 # define MAXPACKET 65536
96 /* As per RFC 1034 and 1035 a host name cannot exceed 255 octets in length. */
98 # undef MAXHOSTNAMELEN
100 #define MAXHOSTNAMELEN 256
102 static const char AskedForGot
[] = "\
103 gethostby*.getanswer: asked for \"%s\", got \"%s\"";
106 /* We need this time later. */
107 typedef union querybuf
110 u_char buf
[MAXPACKET
];
113 /* These functions are defined in res_comp.c. */
114 #define NS_MAXCDNAME 255 /* maximum compressed domain name */
115 extern int __ns_name_ntop (const u_char
*, char *, size_t);
116 extern int __ns_name_unpack (const u_char
*, const u_char
*,
117 const u_char
*, u_char
*, size_t);
120 static enum nss_status
getanswer_r (const querybuf
*answer
, int anslen
,
121 const char *qname
, int qtype
,
122 struct hostent
*result
, char *buffer
,
123 size_t buflen
, int *errnop
, int *h_errnop
,
124 int map
, int32_t *ttlp
, char **canonp
);
126 static enum nss_status
gaih_getanswer (const querybuf
*answer1
, int anslen1
,
127 const querybuf
*answer2
, int anslen2
,
129 struct gaih_addrtuple
**pat
,
130 char *buffer
, size_t buflen
,
131 int *errnop
, int *h_errnop
,
134 extern enum nss_status
_nss_dns_gethostbyname3_r (const char *name
, int af
,
135 struct hostent
*result
,
136 char *buffer
, size_t buflen
,
137 int *errnop
, int *h_errnop
,
140 hidden_proto (_nss_dns_gethostbyname3_r
)
143 _nss_dns_gethostbyname3_r (const char *name
, int af
, struct hostent
*result
,
144 char *buffer
, size_t buflen
, int *errnop
,
145 int *h_errnop
, int32_t *ttlp
, char **canonp
)
152 querybuf
*orig_host_buffer
;
153 char tmp
[NS_MAXDNAME
];
158 enum nss_status status
;
160 if (__res_maybe_init (&_res
, 0) == -1)
161 return NSS_STATUS_UNAVAIL
;
174 *errnop
= EAFNOSUPPORT
;
175 return NSS_STATUS_UNAVAIL
;
178 result
->h_addrtype
= af
;
179 result
->h_length
= size
;
182 * if there aren't any dots, it could be a user-level alias.
183 * this is also done in res_query() since we are not the only
184 * function that looks up host names.
186 if (strchr (name
, '.') == NULL
187 && (cp
= res_hostalias (&_res
, name
, tmp
, sizeof (tmp
))) != NULL
)
190 host_buffer
.buf
= orig_host_buffer
= (querybuf
*) alloca (1024);
192 n
= __libc_res_nsearch (&_res
, name
, C_IN
, type
, host_buffer
.buf
->buf
,
193 1024, &host_buffer
.ptr
, NULL
, NULL
, NULL
, NULL
);
199 status
= NSS_STATUS_TRYAGAIN
;
202 /* System has run out of file descriptors. */
205 h_errno
= NETDB_INTERNAL
;
209 status
= NSS_STATUS_UNAVAIL
;
212 status
= NSS_STATUS_NOTFOUND
;
216 if (h_errno
== TRY_AGAIN
)
219 __set_errno (olderr
);
221 /* If we are looking for an IPv6 address and mapping is enabled
222 by having the RES_USE_INET6 bit in _res.options set, we try
224 if (af
== AF_INET6
&& (_res
.options
& RES_USE_INET6
))
225 n
= __libc_res_nsearch (&_res
, name
, C_IN
, T_A
, host_buffer
.buf
->buf
,
226 host_buffer
.buf
!= orig_host_buffer
227 ? MAXPACKET
: 1024, &host_buffer
.ptr
,
228 NULL
, NULL
, NULL
, NULL
);
232 if (host_buffer
.buf
!= orig_host_buffer
)
233 free (host_buffer
.buf
);
239 result
->h_addrtype
= AF_INET
;
240 result
->h_length
= INADDRSZ
;
243 status
= getanswer_r (host_buffer
.buf
, n
, name
, type
, result
, buffer
, buflen
,
244 errnop
, h_errnop
, map
, ttlp
, canonp
);
245 if (host_buffer
.buf
!= orig_host_buffer
)
246 free (host_buffer
.buf
);
249 hidden_def (_nss_dns_gethostbyname3_r
)
253 _nss_dns_gethostbyname2_r (const char *name
, int af
, struct hostent
*result
,
254 char *buffer
, size_t buflen
, int *errnop
,
257 return _nss_dns_gethostbyname3_r (name
, af
, result
, buffer
, buflen
, errnop
,
258 h_errnop
, NULL
, NULL
);
263 _nss_dns_gethostbyname_r (const char *name
, struct hostent
*result
,
264 char *buffer
, size_t buflen
, int *errnop
,
267 enum nss_status status
= NSS_STATUS_NOTFOUND
;
269 if (_res
.options
& RES_USE_INET6
)
270 status
= _nss_dns_gethostbyname3_r (name
, AF_INET6
, result
, buffer
,
271 buflen
, errnop
, h_errnop
, NULL
, NULL
);
272 if (status
== NSS_STATUS_NOTFOUND
)
273 status
= _nss_dns_gethostbyname3_r (name
, AF_INET
, result
, buffer
,
274 buflen
, errnop
, h_errnop
, NULL
, NULL
);
281 _nss_dns_gethostbyname4_r (const char *name
, struct gaih_addrtuple
**pat
,
282 char *buffer
, size_t buflen
, int *errnop
,
283 int *herrnop
, int32_t *ttlp
)
285 if (__res_maybe_init (&_res
, 0) == -1)
286 return NSS_STATUS_UNAVAIL
;
289 * if there aren't any dots, it could be a user-level alias.
290 * this is also done in res_query() since we are not the only
291 * function that looks up host names.
293 if (strchr (name
, '.') == NULL
)
295 char *tmp
= alloca (NS_MAXDNAME
);
296 const char *cp
= res_hostalias (&_res
, name
, tmp
, NS_MAXDNAME
);
306 querybuf
*orig_host_buffer
;
307 host_buffer
.buf
= orig_host_buffer
= (querybuf
*) alloca (2048);
308 u_char
*ans2p
= NULL
;
311 int ans2p_malloced
= 0;
314 enum nss_status status
;
315 int n
= __libc_res_nsearch (&_res
, name
, C_IN
, T_UNSPEC
,
316 host_buffer
.buf
->buf
, 2048, &host_buffer
.ptr
,
317 &ans2p
, &nans2p
, &resplen2
, &ans2p_malloced
);
320 status
= gaih_getanswer (host_buffer
.buf
, n
, (const querybuf
*) ans2p
,
321 resplen2
, name
, pat
, buffer
, buflen
,
322 errnop
, herrnop
, ttlp
);
329 status
= NSS_STATUS_TRYAGAIN
;
332 /* System has run out of file descriptors. */
335 h_errno
= NETDB_INTERNAL
;
339 status
= NSS_STATUS_UNAVAIL
;
342 status
= NSS_STATUS_NOTFOUND
;
347 if (h_errno
== TRY_AGAIN
)
350 __set_errno (olderr
);
353 /* Check whether ans2p was separately allocated. */
357 if (host_buffer
.buf
!= orig_host_buffer
)
358 free (host_buffer
.buf
);
364 extern enum nss_status
_nss_dns_gethostbyaddr2_r (const void *addr
,
365 socklen_t len
, int af
,
366 struct hostent
*result
,
367 char *buffer
, size_t buflen
,
368 int *errnop
, int *h_errnop
,
370 hidden_proto (_nss_dns_gethostbyaddr2_r
)
373 _nss_dns_gethostbyaddr2_r (const void *addr
, socklen_t len
, int af
,
374 struct hostent
*result
, char *buffer
, size_t buflen
,
375 int *errnop
, int *h_errnop
, int32_t *ttlp
)
377 static const u_char mapped
[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
378 static const u_char tunnelled
[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
379 static const u_char v6local
[] = { 0,0, 0,1 };
380 const u_char
*uaddr
= (const u_char
*)addr
;
383 char *aliases
[MAX_NR_ALIASES
];
384 unsigned char host_addr
[16]; /* IPv4 or IPv6 */
385 char *h_addr_ptrs
[MAX_NR_ADDRS
+ 1];
387 } *host_data
= (struct host_data
*) buffer
;
393 querybuf
*orig_host_buffer
;
394 char qbuf
[MAXDNAME
+1], *qp
= NULL
;
399 uintptr_t pad
= -(uintptr_t) buffer
% __alignof__ (struct host_data
);
401 buflen
= buflen
> pad
? buflen
- pad
: 0;
403 if (__glibc_unlikely (buflen
< sizeof (struct host_data
)))
406 *h_errnop
= NETDB_INTERNAL
;
407 return NSS_STATUS_TRYAGAIN
;
410 host_data
= (struct host_data
*) buffer
;
412 if (__res_maybe_init (&_res
, 0) == -1)
413 return NSS_STATUS_UNAVAIL
;
415 if (af
== AF_INET6
&& len
== IN6ADDRSZ
416 && (memcmp (uaddr
, mapped
, sizeof mapped
) == 0
417 || (memcmp (uaddr
, tunnelled
, sizeof tunnelled
) == 0
418 && memcmp (&uaddr
[sizeof tunnelled
], v6local
, sizeof v6local
))))
421 addr
+= sizeof mapped
;
422 uaddr
+= sizeof mapped
;
436 *errnop
= EAFNOSUPPORT
;
437 *h_errnop
= NETDB_INTERNAL
;
438 return NSS_STATUS_UNAVAIL
;
442 *errnop
= EAFNOSUPPORT
;
443 *h_errnop
= NETDB_INTERNAL
;
444 return NSS_STATUS_UNAVAIL
;
447 host_buffer
.buf
= orig_host_buffer
= (querybuf
*) alloca (1024);
452 sprintf (qbuf
, "%u.%u.%u.%u.in-addr.arpa", (uaddr
[3] & 0xff),
453 (uaddr
[2] & 0xff), (uaddr
[1] & 0xff), (uaddr
[0] & 0xff));
456 /* Only lookup with the byte string format if the user wants it. */
457 if (__glibc_unlikely (_res
.options
& RES_USEBSTRING
))
459 qp
= stpcpy (qbuf
, "\\[x");
460 for (n
= 0; n
< IN6ADDRSZ
; ++n
)
461 qp
+= sprintf (qp
, "%02hhx", uaddr
[n
]);
462 strcpy (qp
, "].ip6.arpa");
463 n
= __libc_res_nquery (&_res
, qbuf
, C_IN
, T_PTR
,
464 host_buffer
.buf
->buf
, 1024, &host_buffer
.ptr
,
465 NULL
, NULL
, NULL
, NULL
);
470 for (n
= IN6ADDRSZ
- 1; n
>= 0; n
--)
472 static const char nibblechar
[16] = "0123456789abcdef";
473 *qp
++ = nibblechar
[uaddr
[n
] & 0xf];
475 *qp
++ = nibblechar
[(uaddr
[n
] >> 4) & 0xf];
478 strcpy(qp
, "ip6.arpa");
485 n
= __libc_res_nquery (&_res
, qbuf
, C_IN
, T_PTR
, host_buffer
.buf
->buf
,
486 1024, &host_buffer
.ptr
, NULL
, NULL
, NULL
, NULL
);
487 if (n
< 0 && af
== AF_INET6
&& (_res
.options
& RES_NOIP6DOTINT
) == 0)
489 strcpy (qp
, "ip6.int");
490 n
= __libc_res_nquery (&_res
, qbuf
, C_IN
, T_PTR
, host_buffer
.buf
->buf
,
491 host_buffer
.buf
!= orig_host_buffer
492 ? MAXPACKET
: 1024, &host_buffer
.ptr
,
493 NULL
, NULL
, NULL
, NULL
);
498 __set_errno (olderr
);
499 if (host_buffer
.buf
!= orig_host_buffer
)
500 free (host_buffer
.buf
);
501 return errno
== ECONNREFUSED
? NSS_STATUS_UNAVAIL
: NSS_STATUS_NOTFOUND
;
505 status
= getanswer_r (host_buffer
.buf
, n
, qbuf
, T_PTR
, result
, buffer
, buflen
,
506 errnop
, h_errnop
, 0 /* XXX */, ttlp
, NULL
);
507 if (host_buffer
.buf
!= orig_host_buffer
)
508 free (host_buffer
.buf
);
509 if (status
!= NSS_STATUS_SUCCESS
)
513 This is
not implemented because it is
not possible to use the current
514 source from bind in a multi
-threaded program
.
517 result
->h_addrtype
= af
;
518 result
->h_length
= len
;
519 memcpy (host_data
->host_addr
, addr
, len
);
520 host_data
->h_addr_ptrs
[0] = (char *) host_data
->host_addr
;
521 host_data
->h_addr_ptrs
[1] = NULL
;
523 /* XXX I think this is wrong. Why should an IPv4 address be
524 converted to IPv6 if the user explicitly asked for IPv4? */
525 if (af
== AF_INET
&& (_res
.options
& RES_USE_INET6
))
527 map_v4v6_address ((char *) host_data
->host_addr
,
528 (char *) host_data
->host_addr
);
529 result
->h_addrtype
= AF_INET6
;
530 result
->h_length
= IN6ADDRSZ
;
533 *h_errnop
= NETDB_SUCCESS
;
534 return NSS_STATUS_SUCCESS
;
536 hidden_def (_nss_dns_gethostbyaddr2_r
)
540 _nss_dns_gethostbyaddr_r (const void *addr
, socklen_t len
, int af
,
541 struct hostent
*result
, char *buffer
, size_t buflen
,
542 int *errnop
, int *h_errnop
)
544 return _nss_dns_gethostbyaddr2_r (addr
, len
, af
, result
, buffer
, buflen
,
545 errnop
, h_errnop
, NULL
);
549 static void addrsort (char **ap
, int num
);
552 addrsort (char **ap
, int num
)
556 short aval
[MAX_NR_ADDRS
];
560 if (num
> MAX_NR_ADDRS
)
562 for (i
= 0; i
< num
; i
++, p
++)
564 for (j
= 0 ; (unsigned)j
< _res
.nsort
; j
++)
565 if (_res
.sort_list
[j
].addr
.s_addr
==
566 (((struct in_addr
*)(*p
))->s_addr
& _res
.sort_list
[j
].mask
))
569 if (needsort
== 0 && i
> 0 && j
< aval
[i
-1])
575 while (needsort
++ < num
)
576 for (j
= needsort
- 2; j
>= 0; j
--)
577 if (aval
[j
] > aval
[j
+1])
594 static enum nss_status
595 getanswer_r (const querybuf
*answer
, int anslen
, const char *qname
, int qtype
,
596 struct hostent
*result
, char *buffer
, size_t buflen
,
597 int *errnop
, int *h_errnop
, int map
, int32_t *ttlp
, char **canonp
)
601 char *aliases
[MAX_NR_ALIASES
];
602 unsigned char host_addr
[16]; /* IPv4 or IPv6 */
603 char *h_addr_ptrs
[0];
607 const u_char
*end_of_message
, *cp
;
608 int n
, ancount
, qdcount
;
609 int haveanswer
, had_error
;
610 char *bp
, **ap
, **hap
;
613 int (*name_ok
) (const char *);
614 u_char packtmp
[NS_MAXCDNAME
];
616 uintptr_t pad
= -(uintptr_t) buffer
% __alignof__ (struct host_data
);
618 buflen
= buflen
> pad
? buflen
- pad
: 0;
619 if (__glibc_unlikely (buflen
< sizeof (struct host_data
)))
621 /* The buffer is too small. */
624 *h_errnop
= NETDB_INTERNAL
;
625 return NSS_STATUS_TRYAGAIN
;
627 host_data
= (struct host_data
*) buffer
;
628 linebuflen
= buflen
- sizeof (struct host_data
);
629 if (buflen
- sizeof (struct host_data
) != linebuflen
)
630 linebuflen
= INT_MAX
;
633 result
->h_name
= NULL
;
634 end_of_message
= answer
->buf
+ anslen
;
646 return NSS_STATUS_UNAVAIL
; /* XXX should be abort(); */
650 * find first satisfactory answer
653 ancount
= ntohs (hp
->ancount
);
654 qdcount
= ntohs (hp
->qdcount
);
655 cp
= answer
->buf
+ HFIXEDSZ
;
656 if (__builtin_expect (qdcount
, 1) != 1)
658 *h_errnop
= NO_RECOVERY
;
659 return NSS_STATUS_UNAVAIL
;
661 if (sizeof (struct host_data
) + (ancount
+ 1) * sizeof (char *) >= buflen
)
663 bp
= (char *) &host_data
->h_addr_ptrs
[ancount
+ 1];
664 linebuflen
-= (ancount
+ 1) * sizeof (char *);
666 n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
667 packtmp
, sizeof packtmp
);
668 if (n
!= -1 && __ns_name_ntop (packtmp
, bp
, linebuflen
) == -1)
670 if (__builtin_expect (errno
, 0) == EMSGSIZE
)
676 if (n
> 0 && bp
[0] == '.')
679 if (__builtin_expect (n
< 0 || ((*name_ok
) (bp
) == 0 && (errno
= EBADMSG
)),
683 *h_errnop
= NO_RECOVERY
;
684 return NSS_STATUS_UNAVAIL
;
688 if (qtype
== T_A
|| qtype
== T_AAAA
)
690 /* res_send() has already verified that the query name is the
691 * same as the one we sent; this just gets the expanded name
692 * (i.e., with the succeeding search-domain tacked on).
694 n
= strlen (bp
) + 1; /* for the \0 */
695 if (n
>= MAXHOSTNAMELEN
)
697 *h_errnop
= NO_RECOVERY
;
699 return NSS_STATUS_TRYAGAIN
;
706 /* The qname can be abbreviated, but h_name is now absolute. */
707 qname
= result
->h_name
;
710 ap
= host_data
->aliases
;
712 result
->h_aliases
= host_data
->aliases
;
713 hap
= host_data
->h_addr_ptrs
;
715 result
->h_addr_list
= host_data
->h_addr_ptrs
;
719 while (ancount
-- > 0 && cp
< end_of_message
&& had_error
== 0)
723 n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
724 packtmp
, sizeof packtmp
);
725 if (n
!= -1 && __ns_name_ntop (packtmp
, bp
, linebuflen
) == -1)
727 if (__builtin_expect (errno
, 0) == EMSGSIZE
)
733 if (__glibc_unlikely (n
< 0 || (*name_ok
) (bp
) == 0))
740 if (__glibc_unlikely (cp
+ 10 > end_of_message
))
746 type
= __ns_get16 (cp
);
747 cp
+= INT16SZ
; /* type */
748 class = __ns_get16 (cp
);
749 cp
+= INT16SZ
; /* class */
750 int32_t ttl
= __ns_get32 (cp
);
751 cp
+= INT32SZ
; /* TTL */
753 cp
+= INT16SZ
; /* len */
754 if (__glibc_unlikely (class != C_IN
))
756 /* XXX - debug? syslog? */
758 continue; /* XXX - had_error++ ? */
761 if ((qtype
== T_A
|| qtype
== T_AAAA
) && type
== T_CNAME
)
763 /* A CNAME could also have a TTL entry. */
764 if (ttlp
!= NULL
&& ttl
< *ttlp
)
767 if (ap
>= &host_data
->aliases
[MAX_NR_ALIASES
- 1])
769 n
= dn_expand (answer
->buf
, end_of_message
, cp
, tbuf
, sizeof tbuf
);
770 if (__glibc_unlikely (n
< 0 || (*name_ok
) (tbuf
) == 0))
778 n
= strlen (bp
) + 1; /* For the \0. */
779 if (__builtin_expect (n
, 0) >= MAXHOSTNAMELEN
)
786 /* Get canonical name. */
787 n
= strlen (tbuf
) + 1; /* For the \0. */
788 if (__glibc_unlikely (n
> linebuflen
))
790 if (__builtin_expect (n
, 0) >= MAXHOSTNAMELEN
)
796 bp
= __mempcpy (bp
, tbuf
, n
); /* Cannot overflow. */
801 if (qtype
== T_PTR
&& type
== T_CNAME
)
803 /* A CNAME could also have a TTL entry. */
804 if (ttlp
!= NULL
&& ttl
< *ttlp
)
807 n
= dn_expand (answer
->buf
, end_of_message
, cp
, tbuf
, sizeof tbuf
);
808 if (__glibc_unlikely (n
< 0 || res_dnok (tbuf
) == 0))
814 /* Get canonical name. */
815 n
= strlen (tbuf
) + 1; /* For the \0. */
816 if (__glibc_unlikely (n
> linebuflen
))
818 if (__builtin_expect (n
, 0) >= MAXHOSTNAMELEN
)
824 bp
= __mempcpy (bp
, tbuf
, n
); /* Cannot overflow. */
829 if (type
== T_A
&& qtype
== T_AAAA
&& map
)
831 else if (__glibc_unlikely (type
!= qtype
))
833 /* Log a low priority message if we get an unexpected record, but
834 skip it if we are using DNSSEC since it uses many different types
835 in responses that do not match QTYPE. */
836 if ((_res
.options
& RES_USE_DNSSEC
) == 0)
837 syslog (LOG_NOTICE
| LOG_AUTH
,
838 "gethostby*.getanswer: asked for \"%s %s %s\", "
840 qname
, p_class (C_IN
), p_type (qtype
), p_type (type
));
842 continue; /* XXX - had_error++ ? */
848 if (__glibc_unlikely (strcasecmp (tname
, bp
) != 0))
850 syslog (LOG_NOTICE
| LOG_AUTH
, AskedForGot
, qname
, bp
);
852 continue; /* XXX - had_error++ ? */
855 n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
856 packtmp
, sizeof packtmp
);
857 if (n
!= -1 && __ns_name_ntop (packtmp
, bp
, linebuflen
) == -1)
859 if (__builtin_expect (errno
, 0) == EMSGSIZE
)
865 if (__glibc_unlikely (n
< 0 || res_hnok (bp
) == 0))
870 if (ttlp
!= NULL
&& ttl
< *ttlp
)
872 /* bind would put multiple PTR records as aliases, but we don't do
877 n
= strlen (bp
) + 1; /* for the \0 */
878 if (__glibc_unlikely (n
>= MAXHOSTNAMELEN
))
885 if (map_v4v6_hostent (result
, &bp
, &linebuflen
))
888 *h_errnop
= NETDB_SUCCESS
;
889 return NSS_STATUS_SUCCESS
;
892 if (__builtin_expect (strcasecmp (result
->h_name
, bp
), 0) != 0)
894 syslog (LOG_NOTICE
| LOG_AUTH
, AskedForGot
, result
->h_name
, bp
);
896 continue; /* XXX - had_error++ ? */
898 if (n
!= result
->h_length
)
907 /* We compose a single hostent out of the entire chain of
908 entries, so the TTL of the hostent is essentially the lowest
910 if (ttlp
!= NULL
&& ttl
< *ttlp
)
915 nn
= strlen (bp
) + 1; /* for the \0 */
920 linebuflen
-= sizeof (align
) - ((u_long
) bp
% sizeof (align
));
921 bp
+= sizeof (align
) - ((u_long
) bp
% sizeof (align
));
923 if (__glibc_unlikely (n
> linebuflen
))
925 bp
= __mempcpy (*hap
++ = bp
, cp
, n
);
940 #if defined RESOLVSORT
942 * Note: we sort even if host can take only one address
943 * in its return structures - should give it the "best"
944 * address in that case, not some random one
946 if (_res
.nsort
&& haveanswer
> 1 && qtype
== T_A
)
947 addrsort (host_data
->h_addr_ptrs
, haveanswer
);
948 #endif /*RESOLVSORT*/
950 if (result
->h_name
== NULL
)
952 n
= strlen (qname
) + 1; /* For the \0. */
955 if (n
>= MAXHOSTNAMELEN
)
958 bp
= __mempcpy (bp
, qname
, n
); /* Cannot overflow. */
963 if (map_v4v6_hostent (result
, &bp
, &linebuflen
))
965 *h_errnop
= NETDB_SUCCESS
;
966 return NSS_STATUS_SUCCESS
;
969 *h_errnop
= NO_RECOVERY
;
971 /* Special case here: if the resolver sent a result but it only
972 contains a CNAME while we are looking for a T_A or T_AAAA record,
973 we fail with NOTFOUND instead of TRYAGAIN. */
974 return ((qtype
== T_A
|| qtype
== T_AAAA
) && ap
!= host_data
->aliases
975 ? NSS_STATUS_NOTFOUND
: NSS_STATUS_TRYAGAIN
);
979 static enum nss_status
980 gaih_getanswer_slice (const querybuf
*answer
, int anslen
, const char *qname
,
981 struct gaih_addrtuple
***patp
,
982 char **bufferp
, size_t *buflenp
,
983 int *errnop
, int *h_errnop
, int32_t *ttlp
, int *firstp
)
985 char *buffer
= *bufferp
;
986 size_t buflen
= *buflenp
;
988 struct gaih_addrtuple
**pat
= *patp
;
989 const HEADER
*hp
= &answer
->hdr
;
990 int ancount
= ntohs (hp
->ancount
);
991 int qdcount
= ntohs (hp
->qdcount
);
992 const u_char
*cp
= answer
->buf
+ HFIXEDSZ
;
993 const u_char
*end_of_message
= answer
->buf
+ anslen
;
994 if (__glibc_unlikely (qdcount
!= 1))
996 *h_errnop
= NO_RECOVERY
;
997 return NSS_STATUS_UNAVAIL
;
1000 u_char packtmp
[NS_MAXCDNAME
];
1001 int n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
1002 packtmp
, sizeof packtmp
);
1003 /* We unpack the name to check it for validity. But we do not need
1005 if (n
!= -1 && __ns_name_ntop (packtmp
, buffer
, buflen
) == -1)
1007 if (__builtin_expect (errno
, 0) == EMSGSIZE
)
1011 *h_errnop
= NETDB_INTERNAL
;
1012 return NSS_STATUS_TRYAGAIN
;
1018 if (__builtin_expect (n
< 0 || (res_hnok (buffer
) == 0
1019 && (errno
= EBADMSG
)), 0))
1022 *h_errnop
= NO_RECOVERY
;
1023 return NSS_STATUS_UNAVAIL
;
1030 char *h_name
= NULL
;
1034 return NSS_STATUS_NOTFOUND
;
1036 while (ancount
-- > 0 && cp
< end_of_message
&& had_error
== 0)
1038 n
= __ns_name_unpack (answer
->buf
, end_of_message
, cp
,
1039 packtmp
, sizeof packtmp
);
1041 (h_namelen
= __ns_name_ntop (packtmp
, buffer
, buflen
)) == -1)
1043 if (__builtin_expect (errno
, 0) == EMSGSIZE
)
1048 if (__glibc_unlikely (n
< 0 || res_hnok (buffer
) == 0))
1053 if (*firstp
&& canon
== NULL
)
1056 buffer
+= h_namelen
;
1057 buflen
-= h_namelen
;
1062 if (__glibc_unlikely (cp
+ 10 > end_of_message
))
1068 int type
= __ns_get16 (cp
);
1069 cp
+= INT16SZ
; /* type */
1070 int class = __ns_get16 (cp
);
1071 cp
+= INT16SZ
; /* class */
1072 int32_t ttl
= __ns_get32 (cp
);
1073 cp
+= INT32SZ
; /* TTL */
1074 n
= __ns_get16 (cp
);
1075 cp
+= INT16SZ
; /* len */
1083 if (type
== T_CNAME
)
1085 char tbuf
[MAXDNAME
];
1087 /* A CNAME could also have a TTL entry. */
1088 if (ttlp
!= NULL
&& ttl
< *ttlp
)
1091 n
= dn_expand (answer
->buf
, end_of_message
, cp
, tbuf
, sizeof tbuf
);
1092 if (__glibc_unlikely (n
< 0 || res_hnok (tbuf
) == 0))
1101 /* Reclaim buffer space. */
1102 if (h_name
+ h_namelen
== buffer
)
1105 buflen
+= h_namelen
;
1108 n
= strlen (tbuf
) + 1;
1109 if (__glibc_unlikely (n
> buflen
))
1111 if (__glibc_unlikely (n
>= MAXHOSTNAMELEN
))
1118 buffer
= __mempcpy (buffer
, tbuf
, n
);
1125 // We should not see any types other than those explicitly listed
1126 // below. Some types sent by server seem missing, though. Just
1127 // collect the data for now.
1128 if (__glibc_unlikely (type
!= T_A
&& type
!= T_AAAA
))
1130 if (__builtin_expect (type
== T_SIG
, 0)
1131 || __builtin_expect (type
== T_KEY
, 0)
1132 || __builtin_expect (type
== T_NXT
, 0)
1133 || __builtin_expect (type
== T_PTR
, 0)
1134 || __builtin_expect (type
== T_DNAME
, 0))
1137 /* We don't support DNSSEC yet. For now, ignore the record
1138 and send a low priority message to syslog.
1140 We also don't expect T_PTR or T_DNAME messages. */
1141 syslog (LOG_DEBUG
| LOG_AUTH
,
1142 "getaddrinfo*.gaih_getanswer: got type \"%s\"",
1147 if (type
!= T_A
&& type
!= T_AAAA
)
1152 uintptr_t pad
= (-(uintptr_t) buffer
1153 % __alignof__ (struct gaih_addrtuple
));
1155 buflen
= buflen
> pad
? buflen
- pad
: 0;
1157 if (__builtin_expect (buflen
< sizeof (struct gaih_addrtuple
),
1161 *pat
= (struct gaih_addrtuple
*) buffer
;
1162 buffer
+= sizeof (struct gaih_addrtuple
);
1163 buflen
-= sizeof (struct gaih_addrtuple
);
1166 (*pat
)->name
= NULL
;
1167 (*pat
)->next
= NULL
;
1171 /* We compose a single hostent out of the entire chain of
1172 entries, so the TTL of the hostent is essentially the lowest
1173 TTL in the chain. */
1174 if (ttlp
!= NULL
&& ttl
< *ttlp
)
1177 (*pat
)->name
= canon
?: h_name
;
1182 (*pat
)->family
= type
== T_A
? AF_INET
: AF_INET6
;
1183 if (__builtin_expect ((type
== T_A
&& n
!= INADDRSZ
)
1184 || (type
== T_AAAA
&& n
!= IN6ADDRSZ
), 0))
1189 memcpy ((*pat
)->addr
, cp
, n
);
1191 (*pat
)->scopeid
= 0;
1193 pat
= &((*pat
)->next
);
1204 *h_errnop
= NETDB_SUCCESS
;
1205 return NSS_STATUS_SUCCESS
;
1208 /* Special case here: if the resolver sent a result but it only
1209 contains a CNAME while we are looking for a T_A or T_AAAA record,
1210 we fail with NOTFOUND instead of TRYAGAIN. */
1211 return canon
== NULL
? NSS_STATUS_TRYAGAIN
: NSS_STATUS_NOTFOUND
;
1215 static enum nss_status
1216 gaih_getanswer (const querybuf
*answer1
, int anslen1
, const querybuf
*answer2
,
1217 int anslen2
, const char *qname
,
1218 struct gaih_addrtuple
**pat
, char *buffer
, size_t buflen
,
1219 int *errnop
, int *h_errnop
, int32_t *ttlp
)
1223 enum nss_status status
= NSS_STATUS_NOTFOUND
;
1226 status
= gaih_getanswer_slice(answer1
, anslen1
, qname
,
1227 &pat
, &buffer
, &buflen
,
1228 errnop
, h_errnop
, ttlp
,
1230 if ((status
== NSS_STATUS_SUCCESS
|| status
== NSS_STATUS_NOTFOUND
1231 || (status
== NSS_STATUS_TRYAGAIN
1232 /* We want to look at the second answer in case of an
1233 NSS_STATUS_TRYAGAIN only if the error is non-recoverable, i.e.
1234 *h_errnop is NO_RECOVERY. If not, and if the failure was due to
1235 an insufficient buffer (ERANGE), then we need to drop the results
1236 and pass on the NSS_STATUS_TRYAGAIN to the caller so that it can
1237 repeat the query with a larger buffer. */
1238 && (*errnop
!= ERANGE
|| *h_errnop
== NO_RECOVERY
)))
1239 && answer2
!= NULL
&& anslen2
> 0)
1241 enum nss_status status2
= gaih_getanswer_slice(answer2
, anslen2
, qname
,
1242 &pat
, &buffer
, &buflen
,
1243 errnop
, h_errnop
, ttlp
,
1245 if (status
!= NSS_STATUS_SUCCESS
&& status2
!= NSS_STATUS_NOTFOUND
)