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.
4
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.
9
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.
14
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/>. */
18
19/* Parts of this file are plain copies of the file `gethtnamadr.c' from
20 the bind package and it has the following copyright. */
21
22/*
23 * ++Copyright++ 1985, 1988, 1993
24 * -
25 * Copyright (c) 1985, 1988, 1993
26 * The Regents of the University of California. All rights reserved.
27 *
28 * Redistribution and use in source and binary forms, with or without
29 * modification, are permitted provided that the following conditions
30 * are met:
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.
39 *
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
50 * SUCH DAMAGE.
51 * -
52 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
53 *
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.
60 *
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
68 * SOFTWARE.
69 * -
70 * --Copyright--
71 */
72
73#include <assert.h>
74#include <ctype.h>
75#include <errno.h>
76#include <netdb.h>
77#include <stdio.h>
78#include <stdlib.h>
79#include <stddef.h>
80#include <string.h>
81
82#include "nsswitch.h"
83
84/* Get implementation for some internal functions. */
85#include <resolv/mapv4v6addr.h>
86#include <resolv/mapv4v6hostent.h>
87
88#define RESOLVSORT
89
90#if PACKETSZ > 65536
91# define MAXPACKET PACKETSZ
92#else
93# define MAXPACKET 65536
94#endif
95/* As per RFC 1034 and 1035 a host name cannot exceed 255 octets in length. */
96#ifdef MAXHOSTNAMELEN
97# undef MAXHOSTNAMELEN
98#endif
99#define MAXHOSTNAMELEN 256
100
101/* We need this time later. */
102typedef union querybuf
103{
104 HEADER hdr;
105 u_char buf[MAXPACKET];
106} querybuf;
107
108/* These functions are defined in res_comp.c. */
109#define NS_MAXCDNAME 255 /* maximum compressed domain name */
110extern int __ns_name_ntop (const u_char *, char *, size_t);
111extern int __ns_name_unpack (const u_char *, const u_char *,
112 const u_char *, u_char *, size_t);
113
114
115static 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);
120
121static enum nss_status gaih_getanswer (const querybuf *answer1, int anslen1,
122 const querybuf *answer2, int anslen2,
123 const char *qname,
124 struct gaih_addrtuple **pat,
125 char *buffer, size_t buflen,
126 int *errnop, int *h_errnop,
127 int32_t *ttlp);
128
129extern 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,
133 int32_t *ttlp,
134 char **canonp);
135hidden_proto (_nss_dns_gethostbyname3_r)
136
137/* Return the expected RDATA length for an address record type (A or
138 AAAA). */
139static int
140rrtype_to_rdata_length (int type)
141{
142 switch (type)
143 {
144 case T_A:
145 return INADDRSZ;
146 case T_AAAA:
147 return IN6ADDRSZ;
148 default:
149 return -1;
150 }
151}
152
153enum nss_status
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)
157{
158 union
159 {
160 querybuf *buf;
161 u_char *ptr;
162 } host_buffer;
163 querybuf *orig_host_buffer;
164 char tmp[NS_MAXDNAME];
165 int size, type, n;
166 const char *cp;
167 int map = 0;
168 int olderr = errno;
169 enum nss_status status;
170
171 if (__res_maybe_init (&_res, 0) == -1)
172 return NSS_STATUS_UNAVAIL;
173
174 switch (af) {
175 case AF_INET:
176 size = INADDRSZ;
177 type = T_A;
178 break;
179 case AF_INET6:
180 size = IN6ADDRSZ;
181 type = T_AAAA;
182 break;
183 default:
184 *h_errnop = NO_DATA;
185 *errnop = EAFNOSUPPORT;
186 return NSS_STATUS_UNAVAIL;
187 }
188
189 result->h_addrtype = af;
190 result->h_length = size;
191
192 /*
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.
196 */
197 if (strchr (name, '.') == NULL
198 && (cp = res_hostalias (&_res, name, tmp, sizeof (tmp))) != NULL)
199 name = cp;
200
201 host_buffer.buf = orig_host_buffer = (querybuf *) alloca (1024);
202
203 n = __libc_res_nsearch (&_res, name, C_IN, type, host_buffer.buf->buf,
204 1024, &host_buffer.ptr, NULL, NULL, NULL, NULL);
205 if (n < 0)
206 {
207 switch (errno)
208 {
209 case ESRCH:
210 status = NSS_STATUS_TRYAGAIN;
211 h_errno = TRY_AGAIN;
212 break;
213 /* System has run out of file descriptors. */
214 case EMFILE:
215 case ENFILE:
216 h_errno = NETDB_INTERNAL;
217 /* Fall through. */
218 case ECONNREFUSED:
219 case ETIMEDOUT:
220 status = NSS_STATUS_UNAVAIL;
221 break;
222 default:
223 status = NSS_STATUS_NOTFOUND;
224 break;
225 }
226 *h_errnop = h_errno;
227 if (h_errno == TRY_AGAIN)
228 *errnop = EAGAIN;
229 else
230 __set_errno (olderr);
231
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
234 another lookup. */
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);
240
241 if (n < 0)
242 {
243 if (host_buffer.buf != orig_host_buffer)
244 free (host_buffer.buf);
245 return status;
246 }
247
248 map = 1;
249
250 result->h_addrtype = AF_INET;
251 result->h_length = INADDRSZ;
252 }
253
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);
258 return status;
259}
260hidden_def (_nss_dns_gethostbyname3_r)
261
262
263enum nss_status
264_nss_dns_gethostbyname2_r (const char *name, int af, struct hostent *result,
265 char *buffer, size_t buflen, int *errnop,
266 int *h_errnop)
267{
268 return _nss_dns_gethostbyname3_r (name, af, result, buffer, buflen, errnop,
269 h_errnop, NULL, NULL);
270}
271
272
273enum nss_status
274_nss_dns_gethostbyname_r (const char *name, struct hostent *result,
275 char *buffer, size_t buflen, int *errnop,
276 int *h_errnop)
277{
278 enum nss_status status = NSS_STATUS_NOTFOUND;
279
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);
286
287 return status;
288}
289
290
291enum nss_status
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)
295{
296 if (__res_maybe_init (&_res, 0) == -1)
297 return NSS_STATUS_UNAVAIL;
298
299 /*
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.
303 */
304 if (strchr (name, '.') == NULL)
305 {
306 char *tmp = alloca (NS_MAXDNAME);
307 const char *cp = res_hostalias (&_res, name, tmp, NS_MAXDNAME);
308 if (cp != NULL)
309 name = cp;
310 }
311
312 union
313 {
314 querybuf *buf;
315 u_char *ptr;
316 } host_buffer;
317 querybuf *orig_host_buffer;
318 host_buffer.buf = orig_host_buffer = (querybuf *) alloca (2048);
319 u_char *ans2p = NULL;
320 int nans2p = 0;
321 int resplen2 = 0;
322 int ans2p_malloced = 0;
323
324 int olderr = errno;
325 enum nss_status status;
326 int n = __libc_res_nsearch (&_res, name, C_IN, T_QUERY_A_AND_AAAA,
327 host_buffer.buf->buf, 2048, &host_buffer.ptr,
328 &ans2p, &nans2p, &resplen2, &ans2p_malloced);
329 if (n >= 0)
330 {
331 status = gaih_getanswer (host_buffer.buf, n, (const querybuf *) ans2p,
332 resplen2, name, pat, buffer, buflen,
333 errnop, herrnop, ttlp);
334 }
335 else
336 {
337 switch (errno)
338 {
339 case ESRCH:
340 status = NSS_STATUS_TRYAGAIN;
341 h_errno = TRY_AGAIN;
342 break;
343 /* System has run out of file descriptors. */
344 case EMFILE:
345 case ENFILE:
346 h_errno = NETDB_INTERNAL;
347 /* Fall through. */
348 case ECONNREFUSED:
349 case ETIMEDOUT:
350 status = NSS_STATUS_UNAVAIL;
351 break;
352 default:
353 status = NSS_STATUS_NOTFOUND;
354 break;
355 }
356
357 *herrnop = h_errno;
358 if (h_errno == TRY_AGAIN)
359 *errnop = EAGAIN;
360 else
361 __set_errno (olderr);
362 }
363
364 /* Check whether ans2p was separately allocated. */
365 if (ans2p_malloced)
366 free (ans2p);
367
368 if (host_buffer.buf != orig_host_buffer)
369 free (host_buffer.buf);
370
371 return status;
372}
373
374
375extern 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,
380 int32_t *ttlp);
381hidden_proto (_nss_dns_gethostbyaddr2_r)
382
383enum nss_status
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)
387{
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;
392 struct host_data
393 {
394 char *aliases[MAX_NR_ALIASES];
395 unsigned char host_addr[16]; /* IPv4 or IPv6 */
396 char *h_addr_ptrs[MAX_NR_ADDRS + 1];
397 char linebuffer[0];
398 } *host_data = (struct host_data *) buffer;
399 union
400 {
401 querybuf *buf;
402 u_char *ptr;
403 } host_buffer;
404 querybuf *orig_host_buffer;
405 char qbuf[MAXDNAME+1], *qp = NULL;
406 size_t size;
407 int n, status;
408 int olderr = errno;
409
410 uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct host_data);
411 buffer += pad;
412 buflen = buflen > pad ? buflen - pad : 0;
413
414 if (__glibc_unlikely (buflen < sizeof (struct host_data)))
415 {
416 *errnop = ERANGE;
417 *h_errnop = NETDB_INTERNAL;
418 return NSS_STATUS_TRYAGAIN;
419 }
420
421 host_data = (struct host_data *) buffer;
422
423 if (__res_maybe_init (&_res, 0) == -1)
424 return NSS_STATUS_UNAVAIL;
425
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))))
430 {
431 /* Unmap. */
432 addr += sizeof mapped;
433 uaddr += sizeof mapped;
434 af = AF_INET;
435 len = INADDRSZ;
436 }
437
438 switch (af)
439 {
440 case AF_INET:
441 size = INADDRSZ;
442 break;
443 case AF_INET6:
444 size = IN6ADDRSZ;
445 break;
446 default:
447 *errnop = EAFNOSUPPORT;
448 *h_errnop = NETDB_INTERNAL;
449 return NSS_STATUS_UNAVAIL;
450 }
451 if (size > len)
452 {
453 *errnop = EAFNOSUPPORT;
454 *h_errnop = NETDB_INTERNAL;
455 return NSS_STATUS_UNAVAIL;
456 }
457
458 host_buffer.buf = orig_host_buffer = (querybuf *) alloca (1024);
459
460 switch (af)
461 {
462 case AF_INET:
463 sprintf (qbuf, "%u.%u.%u.%u.in-addr.arpa", (uaddr[3] & 0xff),
464 (uaddr[2] & 0xff), (uaddr[1] & 0xff), (uaddr[0] & 0xff));
465 break;
466 case AF_INET6:
467 /* Only lookup with the byte string format if the user wants it. */
468 if (__glibc_unlikely (_res.options & RES_USEBSTRING))
469 {
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);
477 if (n >= 0)
478 goto got_it_already;
479 }
480 qp = qbuf;
481 for (n = IN6ADDRSZ - 1; n >= 0; n--)
482 {
483 static const char nibblechar[16] = "0123456789abcdef";
484 *qp++ = nibblechar[uaddr[n] & 0xf];
485 *qp++ = '.';
486 *qp++ = nibblechar[(uaddr[n] >> 4) & 0xf];
487 *qp++ = '.';
488 }
489 strcpy(qp, "ip6.arpa");
490 break;
491 default:
492 /* Cannot happen. */
493 break;
494 }
495
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)
499 {
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);
505 }
506 if (n < 0)
507 {
508 *h_errnop = h_errno;
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;
513 }
514
515 got_it_already:
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)
521 return status;
522
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;
528#if 0
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))
532 {
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;
537 }
538#endif
539 *h_errnop = NETDB_SUCCESS;
540 return NSS_STATUS_SUCCESS;
541}
542hidden_def (_nss_dns_gethostbyaddr2_r)
543
544
545enum nss_status
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)
549{
550 return _nss_dns_gethostbyaddr2_r (addr, len, af, result, buffer, buflen,
551 errnop, h_errnop, NULL);
552}
553
554static void addrsort (char **ap, int num);
555
556static void
557addrsort (char **ap, int num)
558{
559 int i, j;
560 char **p;
561 short aval[MAX_NR_ADDRS];
562 int needsort = 0;
563
564 p = ap;
565 if (num > MAX_NR_ADDRS)
566 num = MAX_NR_ADDRS;
567 for (i = 0; i < num; i++, p++)
568 {
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))
572 break;
573 aval[i] = j;
574 if (needsort == 0 && i > 0 && j < aval[i-1])
575 needsort = i;
576 }
577 if (!needsort)
578 return;
579
580 while (needsort++ < num)
581 for (j = needsort - 2; j >= 0; j--)
582 if (aval[j] > aval[j+1])
583 {
584 char *hp;
585
586 i = aval[j];
587 aval[j] = aval[j+1];
588 aval[j+1] = i;
589
590 hp = ap[j];
591 ap[j] = ap[j+1];
592 ap[j+1] = hp;
593 }
594 else
595 break;
596}
597
598static enum nss_status
599getanswer_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)
602{
603 struct host_data
604 {
605 char *aliases[MAX_NR_ALIASES];
606 unsigned char host_addr[16]; /* IPv4 or IPv6 */
607 char *h_addr_ptrs[0];
608 } *host_data;
609 int linebuflen;
610 const HEADER *hp;
611 const u_char *end_of_message, *cp;
612 int n, ancount, qdcount;
613 int haveanswer, had_error;
614 char *bp, **ap, **hap;
615 char tbuf[MAXDNAME];
616 const char *tname;
617 int (*name_ok) (const char *);
618 u_char packtmp[NS_MAXCDNAME];
619 int have_to_map = 0;
620 uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct host_data);
621 buffer += pad;
622 buflen = buflen > pad ? buflen - pad : 0;
623 if (__glibc_unlikely (buflen < sizeof (struct host_data)))
624 {
625 /* The buffer is too small. */
626 too_small:
627 *errnop = ERANGE;
628 *h_errnop = NETDB_INTERNAL;
629 return NSS_STATUS_TRYAGAIN;
630 }
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;
635
636 tname = qname;
637 result->h_name = NULL;
638 end_of_message = answer->buf + anslen;
639 switch (qtype)
640 {
641 case T_A:
642 case T_AAAA:
643 name_ok = res_hnok;
644 break;
645 case T_PTR:
646 name_ok = res_dnok;
647 break;
648 default:
649 *errnop = ENOENT;
650 return NSS_STATUS_UNAVAIL; /* XXX should be abort(); */
651 }
652
653 /*
654 * find first satisfactory answer
655 */
656 hp = &answer->hdr;
657 ancount = ntohs (hp->ancount);
658 qdcount = ntohs (hp->qdcount);
659 cp = answer->buf + HFIXEDSZ;
660 if (__builtin_expect (qdcount, 1) != 1)
661 {
662 *h_errnop = NO_RECOVERY;
663 return NSS_STATUS_UNAVAIL;
664 }
665 if (sizeof (struct host_data) + (ancount + 1) * sizeof (char *) >= buflen)
666 goto too_small;
667 bp = (char *) &host_data->h_addr_ptrs[ancount + 1];
668 linebuflen -= (ancount + 1) * sizeof (char *);
669
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)
673 {
674 if (__builtin_expect (errno, 0) == EMSGSIZE)
675 goto too_small;
676
677 n = -1;
678 }
679
680 if (n > 0 && bp[0] == '.')
681 bp[0] = '\0';
682
683 if (__builtin_expect (n < 0 || ((*name_ok) (bp) == 0 && (errno = EBADMSG)),
684 0))
685 {
686 *errnop = errno;
687 *h_errnop = NO_RECOVERY;
688 return NSS_STATUS_UNAVAIL;
689 }
690 cp += n + QFIXEDSZ;
691
692 if (qtype == T_A || qtype == T_AAAA)
693 {
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).
697 */
698 n = strlen (bp) + 1; /* for the \0 */
699 if (n >= MAXHOSTNAMELEN)
700 {
701 *h_errnop = NO_RECOVERY;
702 *errnop = ENOENT;
703 return NSS_STATUS_TRYAGAIN;
704 }
705 result->h_name = bp;
706 bp += n;
707 linebuflen -= n;
708 if (linebuflen < 0)
709 goto too_small;
710 /* The qname can be abbreviated, but h_name is now absolute. */
711 qname = result->h_name;
712 }
713
714 ap = host_data->aliases;
715 *ap = NULL;
716 result->h_aliases = host_data->aliases;
717 hap = host_data->h_addr_ptrs;
718 *hap = NULL;
719 result->h_addr_list = host_data->h_addr_ptrs;
720 haveanswer = 0;
721 had_error = 0;
722
723 while (ancount-- > 0 && cp < end_of_message && had_error == 0)
724 {
725 int type, class;
726
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)
730 {
731 if (__builtin_expect (errno, 0) == EMSGSIZE)
732 goto too_small;
733
734 n = -1;
735 }
736
737 if (__glibc_unlikely (n < 0 || (*name_ok) (bp) == 0))
738 {
739 ++had_error;
740 continue;
741 }
742 cp += n; /* name */
743
744 if (__glibc_unlikely (cp + 10 > end_of_message))
745 {
746 ++had_error;
747 continue;
748 }
749
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 */
756 n = __ns_get16 (cp);
757 cp += INT16SZ; /* len */
758
759 if (end_of_message - cp < n)
760 {
761 /* RDATA extends beyond the end of the packet. */
762 ++had_error;
763 continue;
764 }
765
766 if (__glibc_unlikely (class != C_IN))
767 {
768 /* XXX - debug? syslog? */
769 cp += n;
770 continue; /* XXX - had_error++ ? */
771 }
772
773 if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME)
774 {
775 /* A CNAME could also have a TTL entry. */
776 if (ttlp != NULL && ttl < *ttlp)
777 *ttlp = ttl;
778
779 if (ap >= &host_data->aliases[MAX_NR_ALIASES - 1])
780 continue;
781 n = dn_expand (answer->buf, end_of_message, cp, tbuf, sizeof tbuf);
782 if (__glibc_unlikely (n < 0 || (*name_ok) (tbuf) == 0))
783 {
784 ++had_error;
785 continue;
786 }
787 cp += n;
788 /* Store alias. */
789 *ap++ = bp;
790 n = strlen (bp) + 1; /* For the \0. */
791 if (__builtin_expect (n, 0) >= MAXHOSTNAMELEN)
792 {
793 ++had_error;
794 continue;
795 }
796 bp += n;
797 linebuflen -= n;
798 /* Get canonical name. */
799 n = strlen (tbuf) + 1; /* For the \0. */
800 if (__glibc_unlikely (n > linebuflen))
801 goto too_small;
802 if (__builtin_expect (n, 0) >= MAXHOSTNAMELEN)
803 {
804 ++had_error;
805 continue;
806 }
807 result->h_name = bp;
808 bp = __mempcpy (bp, tbuf, n); /* Cannot overflow. */
809 linebuflen -= n;
810 continue;
811 }
812
813 if (qtype == T_PTR && type == T_CNAME)
814 {
815 /* A CNAME could also have a TTL entry. */
816 if (ttlp != NULL && ttl < *ttlp)
817 *ttlp = ttl;
818
819 n = dn_expand (answer->buf, end_of_message, cp, tbuf, sizeof tbuf);
820 if (__glibc_unlikely (n < 0 || res_dnok (tbuf) == 0))
821 {
822 ++had_error;
823 continue;
824 }
825 cp += n;
826 /* Get canonical name. */
827 n = strlen (tbuf) + 1; /* For the \0. */
828 if (__glibc_unlikely (n > linebuflen))
829 goto too_small;
830 if (__builtin_expect (n, 0) >= MAXHOSTNAMELEN)
831 {
832 ++had_error;
833 continue;
834 }
835 tname = bp;
836 bp = __mempcpy (bp, tbuf, n); /* Cannot overflow. */
837 linebuflen -= n;
838 continue;
839 }
840
841 if (type == T_A && qtype == T_AAAA && map)
842 have_to_map = 1;
843 else if (__glibc_unlikely (type != qtype))
844 {
845 cp += n;
846 continue; /* XXX - had_error++ ? */
847 }
848
849 switch (type)
850 {
851 case T_PTR:
852 if (__glibc_unlikely (strcasecmp (tname, bp) != 0))
853 {
854 cp += n;
855 continue; /* XXX - had_error++ ? */
856 }
857
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)
861 {
862 if (__builtin_expect (errno, 0) == EMSGSIZE)
863 goto too_small;
864
865 n = -1;
866 }
867
868 if (__glibc_unlikely (n < 0 || res_hnok (bp) == 0))
869 {
870 ++had_error;
871 break;
872 }
873 if (ttlp != NULL && ttl < *ttlp)
874 *ttlp = ttl;
875 /* bind would put multiple PTR records as aliases, but we don't do
876 that. */
877 result->h_name = bp;
878 if (have_to_map)
879 {
880 n = strlen (bp) + 1; /* for the \0 */
881 if (__glibc_unlikely (n >= MAXHOSTNAMELEN))
882 {
883 ++had_error;
884 break;
885 }
886 bp += n;
887 linebuflen -= n;
888 if (map_v4v6_hostent (result, &bp, &linebuflen))
889 goto too_small;
890 }
891 *h_errnop = NETDB_SUCCESS;
892 return NSS_STATUS_SUCCESS;
893 case T_A:
894 case T_AAAA:
895 if (__builtin_expect (strcasecmp (result->h_name, bp), 0) != 0)
896 {
897 cp += n;
898 continue; /* XXX - had_error++ ? */
899 }
900
901 /* Stop parsing at a record whose length is incorrect. */
902 if (n != rrtype_to_rdata_length (type))
903 {
904 ++had_error;
905 break;
906 }
907
908 /* Skip records of the wrong type. */
909 if (n != result->h_length)
910 {
911 cp += n;
912 continue;
913 }
914 if (!haveanswer)
915 {
916 int nn;
917
918 /* We compose a single hostent out of the entire chain of
919 entries, so the TTL of the hostent is essentially the lowest
920 TTL in the chain. */
921 if (ttlp != NULL && ttl < *ttlp)
922 *ttlp = ttl;
923 if (canonp != NULL)
924 *canonp = bp;
925 result->h_name = bp;
926 nn = strlen (bp) + 1; /* for the \0 */
927 bp += nn;
928 linebuflen -= nn;
929 }
930
931 linebuflen -= sizeof (align) - ((u_long) bp % sizeof (align));
932 bp += sizeof (align) - ((u_long) bp % sizeof (align));
933
934 if (__glibc_unlikely (n > linebuflen))
935 goto too_small;
936 bp = __mempcpy (*hap++ = bp, cp, n);
937 cp += n;
938 linebuflen -= n;
939 break;
940 default:
941 abort ();
942 }
943 if (had_error == 0)
944 ++haveanswer;
945 }
946
947 if (haveanswer > 0)
948 {
949 *ap = NULL;
950 *hap = NULL;
951 /*
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
955 */
956 if (_res.nsort && haveanswer > 1 && qtype == T_A)
957 addrsort (host_data->h_addr_ptrs, haveanswer);
958
959 if (result->h_name == NULL)
960 {
961 n = strlen (qname) + 1; /* For the \0. */
962 if (n > linebuflen)
963 goto too_small;
964 if (n >= MAXHOSTNAMELEN)
965 goto no_recovery;
966 result->h_name = bp;
967 bp = __mempcpy (bp, qname, n); /* Cannot overflow. */
968 linebuflen -= n;
969 }
970
971 if (have_to_map)
972 if (map_v4v6_hostent (result, &bp, &linebuflen))
973 goto too_small;
974 *h_errnop = NETDB_SUCCESS;
975 return NSS_STATUS_SUCCESS;
976 }
977 no_recovery:
978 *h_errnop = NO_RECOVERY;
979 *errnop = ENOENT;
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);
985}
986
987
988static enum nss_status
989gaih_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)
993{
994 char *buffer = *bufferp;
995 size_t buflen = *buflenp;
996
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))
1004 {
1005 *h_errnop = NO_RECOVERY;
1006 return NSS_STATUS_UNAVAIL;
1007 }
1008
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
1013 it later. */
1014 if (n != -1 && __ns_name_ntop (packtmp, buffer, buflen) == -1)
1015 {
1016 if (__builtin_expect (errno, 0) == EMSGSIZE)
1017 {
1018 too_small:
1019 *errnop = ERANGE;
1020 *h_errnop = NETDB_INTERNAL;
1021 return NSS_STATUS_TRYAGAIN;
1022 }
1023
1024 n = -1;
1025 }
1026
1027 if (__builtin_expect (n < 0 || (res_hnok (buffer) == 0
1028 && (errno = EBADMSG)), 0))
1029 {
1030 *errnop = errno;
1031 *h_errnop = NO_RECOVERY;
1032 return NSS_STATUS_UNAVAIL;
1033 }
1034 cp += n + QFIXEDSZ;
1035
1036 int haveanswer = 0;
1037 int had_error = 0;
1038 char *canon = NULL;
1039 char *h_name = NULL;
1040 int h_namelen = 0;
1041
1042 if (ancount == 0)
1043 {
1044 *h_errnop = HOST_NOT_FOUND;
1045 return NSS_STATUS_NOTFOUND;
1046 }
1047
1048 while (ancount-- > 0 && cp < end_of_message && had_error == 0)
1049 {
1050 n = __ns_name_unpack (answer->buf, end_of_message, cp,
1051 packtmp, sizeof packtmp);
1052 if (n != -1 &&
1053 (h_namelen = __ns_name_ntop (packtmp, buffer, buflen)) == -1)
1054 {
1055 if (__builtin_expect (errno, 0) == EMSGSIZE)
1056 goto too_small;
1057
1058 n = -1;
1059 }
1060 if (__glibc_unlikely (n < 0 || res_hnok (buffer) == 0))
1061 {
1062 ++had_error;
1063 continue;
1064 }
1065 if (*firstp && canon == NULL)
1066 {
1067 h_name = buffer;
1068 buffer += h_namelen;
1069 buflen -= h_namelen;
1070 }
1071
1072 cp += n; /* name */
1073
1074 if (__glibc_unlikely (cp + 10 > end_of_message))
1075 {
1076 ++had_error;
1077 continue;
1078 }
1079
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 */
1088
1089 if (end_of_message - cp < n)
1090 {
1091 /* RDATA extends beyond the end of the packet. */
1092 ++had_error;
1093 continue;
1094 }
1095
1096 if (class != C_IN)
1097 {
1098 cp += n;
1099 continue;
1100 }
1101
1102 if (type == T_CNAME)
1103 {
1104 char tbuf[MAXDNAME];
1105
1106 /* A CNAME could also have a TTL entry. */
1107 if (ttlp != NULL && ttl < *ttlp)
1108 *ttlp = ttl;
1109
1110 n = dn_expand (answer->buf, end_of_message, cp, tbuf, sizeof tbuf);
1111 if (__glibc_unlikely (n < 0 || res_hnok (tbuf) == 0))
1112 {
1113 ++had_error;
1114 continue;
1115 }
1116 cp += n;
1117
1118 if (*firstp)
1119 {
1120 /* Reclaim buffer space. */
1121 if (h_name + h_namelen == buffer)
1122 {
1123 buffer = h_name;
1124 buflen += h_namelen;
1125 }
1126
1127 n = strlen (tbuf) + 1;
1128 if (__glibc_unlikely (n > buflen))
1129 goto too_small;
1130 if (__glibc_unlikely (n >= MAXHOSTNAMELEN))
1131 {
1132 ++had_error;
1133 continue;
1134 }
1135
1136 canon = buffer;
1137 buffer = __mempcpy (buffer, tbuf, n);
1138 buflen -= n;
1139 h_namelen = 0;
1140 }
1141 continue;
1142 }
1143
1144 /* Stop parsing if we encounter a record with incorrect RDATA
1145 length. */
1146 if (type == T_A || type == T_AAAA)
1147 {
1148 if (n != rrtype_to_rdata_length (type))
1149 {
1150 ++had_error;
1151 continue;
1152 }
1153 }
1154 else
1155 {
1156 /* Skip unknown records. */
1157 cp += n;
1158 continue;
1159 }
1160
1161 assert (type == T_A || type == T_AAAA);
1162 if (*pat == NULL)
1163 {
1164 uintptr_t pad = (-(uintptr_t) buffer
1165 % __alignof__ (struct gaih_addrtuple));
1166 buffer += pad;
1167 buflen = buflen > pad ? buflen - pad : 0;
1168
1169 if (__builtin_expect (buflen < sizeof (struct gaih_addrtuple),
1170 0))
1171 goto too_small;
1172
1173 *pat = (struct gaih_addrtuple *) buffer;
1174 buffer += sizeof (struct gaih_addrtuple);
1175 buflen -= sizeof (struct gaih_addrtuple);
1176 }
1177
1178 (*pat)->name = NULL;
1179 (*pat)->next = NULL;
1180
1181 if (*firstp)
1182 {
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)
1187 *ttlp = ttl;
1188
1189 (*pat)->name = canon ?: h_name;
1190
1191 *firstp = 0;
1192 }
1193
1194 (*pat)->family = type == T_A ? AF_INET : AF_INET6;
1195 memcpy ((*pat)->addr, cp, n);
1196 cp += n;
1197 (*pat)->scopeid = 0;
1198
1199 pat = &((*pat)->next);
1200
1201 haveanswer = 1;
1202 }
1203
1204 if (haveanswer)
1205 {
1206 *patp = pat;
1207 *bufferp = buffer;
1208 *buflenp = buflen;
1209
1210 *h_errnop = NETDB_SUCCESS;
1211 return NSS_STATUS_SUCCESS;
1212 }
1213
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. */
1217 if (canon != NULL)
1218 {
1219 *h_errnop = HOST_NOT_FOUND;
1220 return NSS_STATUS_NOTFOUND;
1221 }
1222
1223 *h_errnop = NETDB_INTERNAL;
1224 return NSS_STATUS_TRYAGAIN;
1225}
1226
1227
1228static enum nss_status
1229gaih_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)
1233{
1234 int first = 1;
1235
1236 enum nss_status status = NSS_STATUS_NOTFOUND;
1237
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.
1248
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.
1260
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 ----------------------------------------------
1291
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.
1299
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.
1304
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.
1315
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.
1319
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. */
1326
1327 if (anslen1 > 0)
1328 status = gaih_getanswer_slice(answer1, anslen1, qname,
1329 &pat, &buffer, &buflen,
1330 errnop, h_errnop, ttlp,
1331 &first);
1332
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)
1343 {
1344 enum nss_status status2 = gaih_getanswer_slice(answer2, anslen2, qname,
1345 &pat, &buffer, &buflen,
1346 errnop, h_errnop, ttlp,
1347 &first);
1348 /* Use the second response status in some cases. */
1349 if (status != NSS_STATUS_SUCCESS && status2 != NSS_STATUS_NOTFOUND)
1350 status = status2;
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;
1357 }
1358
1359 return status;
1360}
1361