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.
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#include <arpa/nameser.h>
84
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>
90
91#define RESOLVSORT
92
93#if PACKETSZ > 65536
94# define MAXPACKET PACKETSZ
95#else
96# define MAXPACKET 65536
97#endif
98/* As per RFC 1034 and 1035 a host name cannot exceed 255 octets in length. */
99#ifdef MAXHOSTNAMELEN
100# undef MAXHOSTNAMELEN
101#endif
102#define MAXHOSTNAMELEN 256
103
104/* We need this time later. */
105typedef union querybuf
106{
107 HEADER hdr;
108 u_char buf[MAXPACKET];
109} querybuf;
110
111static enum nss_status getanswer_r (struct resolv_context *ctx,
112 const querybuf *answer, int anslen,
113 const char *qname, int qtype,
114 struct hostent *result, char *buffer,
115 size_t buflen, int *errnop, int *h_errnop,
116 int map, int32_t *ttlp, char **canonp);
117
118static enum nss_status gaih_getanswer (const querybuf *answer1, int anslen1,
119 const querybuf *answer2, int anslen2,
120 const char *qname,
121 struct gaih_addrtuple **pat,
122 char *buffer, size_t buflen,
123 int *errnop, int *h_errnop,
124 int32_t *ttlp);
125
126static enum nss_status gethostbyname3_context (struct resolv_context *ctx,
127 const char *name, int af,
128 struct hostent *result,
129 char *buffer, size_t buflen,
130 int *errnop, int *h_errnop,
131 int32_t *ttlp,
132 char **canonp);
133
134/* Return the expected RDATA length for an address record type (A or
135 AAAA). */
136static int
137rrtype_to_rdata_length (int type)
138{
139 switch (type)
140 {
141 case T_A:
142 return INADDRSZ;
143 case T_AAAA:
144 return IN6ADDRSZ;
145 default:
146 return -1;
147 }
148}
149
150
151enum nss_status
152_nss_dns_gethostbyname3_r (const char *name, int af, struct hostent *result,
153 char *buffer, size_t buflen, int *errnop,
154 int *h_errnop, int32_t *ttlp, char **canonp)
155{
156 struct resolv_context *ctx = __resolv_context_get ();
157 if (ctx == NULL)
158 {
159 *errnop = errno;
160 *h_errnop = NETDB_INTERNAL;
161 return NSS_STATUS_UNAVAIL;
162 }
163 enum nss_status status = gethostbyname3_context
164 (ctx, name, af, result, buffer, buflen, errnop, h_errnop, ttlp, canonp);
165 __resolv_context_put (ctx);
166 return status;
167}
168
169static enum nss_status
170gethostbyname3_context (struct resolv_context *ctx,
171 const char *name, int af, struct hostent *result,
172 char *buffer, size_t buflen, int *errnop,
173 int *h_errnop, int32_t *ttlp, char **canonp)
174{
175 union
176 {
177 querybuf *buf;
178 u_char *ptr;
179 } host_buffer;
180 querybuf *orig_host_buffer;
181 char tmp[NS_MAXDNAME];
182 int size, type, n;
183 const char *cp;
184 int map = 0;
185 int olderr = errno;
186 enum nss_status status;
187
188 switch (af) {
189 case AF_INET:
190 size = INADDRSZ;
191 type = T_A;
192 break;
193 case AF_INET6:
194 size = IN6ADDRSZ;
195 type = T_AAAA;
196 break;
197 default:
198 *h_errnop = NO_DATA;
199 *errnop = EAFNOSUPPORT;
200 return NSS_STATUS_UNAVAIL;
201 }
202
203 result->h_addrtype = af;
204 result->h_length = size;
205
206 /*
207 * if there aren't any dots, it could be a user-level alias.
208 * this is also done in res_query() since we are not the only
209 * function that looks up host names.
210 */
211 if (strchr (name, '.') == NULL
212 && (cp = __res_context_hostalias (ctx, name, tmp, sizeof (tmp))) != NULL)
213 name = cp;
214
215 host_buffer.buf = orig_host_buffer = (querybuf *) alloca (1024);
216
217 n = __res_context_search (ctx, name, C_IN, type, host_buffer.buf->buf,
218 1024, &host_buffer.ptr, NULL, NULL, NULL, NULL);
219 if (n < 0)
220 {
221 switch (errno)
222 {
223 case ESRCH:
224 status = NSS_STATUS_TRYAGAIN;
225 h_errno = TRY_AGAIN;
226 break;
227 /* System has run out of file descriptors. */
228 case EMFILE:
229 case ENFILE:
230 h_errno = NETDB_INTERNAL;
231 /* Fall through. */
232 case ECONNREFUSED:
233 case ETIMEDOUT:
234 status = NSS_STATUS_UNAVAIL;
235 break;
236 default:
237 status = NSS_STATUS_NOTFOUND;
238 break;
239 }
240 *h_errnop = h_errno;
241 if (h_errno == TRY_AGAIN)
242 *errnop = EAGAIN;
243 else
244 __set_errno (olderr);
245
246 /* If we are looking for an IPv6 address and mapping is enabled
247 by having the RES_USE_INET6 bit in _res.options set, we try
248 another lookup. */
249 if (af == AF_INET6 && res_use_inet6 ())
250 n = __res_context_search (ctx, name, C_IN, T_A, host_buffer.buf->buf,
251 host_buffer.buf != orig_host_buffer
252 ? MAXPACKET : 1024, &host_buffer.ptr,
253 NULL, NULL, NULL, NULL);
254
255 if (n < 0)
256 {
257 if (host_buffer.buf != orig_host_buffer)
258 free (host_buffer.buf);
259 return status;
260 }
261
262 map = 1;
263
264 result->h_addrtype = AF_INET;
265 result->h_length = INADDRSZ;
266 }
267
268 status = getanswer_r
269 (ctx, host_buffer.buf, n, name, type, result, buffer, buflen,
270 errnop, h_errnop, map, ttlp, canonp);
271 if (host_buffer.buf != orig_host_buffer)
272 free (host_buffer.buf);
273 return status;
274}
275
276enum nss_status
277_nss_dns_gethostbyname2_r (const char *name, int af, struct hostent *result,
278 char *buffer, size_t buflen, int *errnop,
279 int *h_errnop)
280{
281 return _nss_dns_gethostbyname3_r (name, af, result, buffer, buflen, errnop,
282 h_errnop, NULL, NULL);
283}
284
285
286enum nss_status
287_nss_dns_gethostbyname_r (const char *name, struct hostent *result,
288 char *buffer, size_t buflen, int *errnop,
289 int *h_errnop)
290{
291 struct resolv_context *ctx = __resolv_context_get ();
292 if (ctx == NULL)
293 {
294 *errnop = errno;
295 *h_errnop = NETDB_INTERNAL;
296 return NSS_STATUS_UNAVAIL;
297 }
298 enum nss_status status = NSS_STATUS_NOTFOUND;
299 if (res_use_inet6 ())
300 status = gethostbyname3_context (ctx, name, AF_INET6, result, buffer,
301 buflen, errnop, h_errnop, NULL, NULL);
302 if (status == NSS_STATUS_NOTFOUND)
303 status = gethostbyname3_context (ctx, name, AF_INET, result, buffer,
304 buflen, errnop, h_errnop, NULL, NULL);
305 __resolv_context_put (ctx);
306 return status;
307}
308
309
310enum nss_status
311_nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
312 char *buffer, size_t buflen, int *errnop,
313 int *herrnop, int32_t *ttlp)
314{
315 struct resolv_context *ctx = __resolv_context_get ();
316 if (ctx == NULL)
317 {
318 *errnop = errno;
319 *herrnop = NETDB_INTERNAL;
320 return NSS_STATUS_UNAVAIL;
321 }
322
323 /*
324 * if there aren't any dots, it could be a user-level alias.
325 * this is also done in res_query() since we are not the only
326 * function that looks up host names.
327 */
328 if (strchr (name, '.') == NULL)
329 {
330 char *tmp = alloca (NS_MAXDNAME);
331 const char *cp = __res_context_hostalias (ctx, name, tmp, NS_MAXDNAME);
332 if (cp != NULL)
333 name = cp;
334 }
335
336 union
337 {
338 querybuf *buf;
339 u_char *ptr;
340 } host_buffer;
341 querybuf *orig_host_buffer;
342 host_buffer.buf = orig_host_buffer = (querybuf *) alloca (2048);
343 u_char *ans2p = NULL;
344 int nans2p = 0;
345 int resplen2 = 0;
346 int ans2p_malloced = 0;
347
348 int olderr = errno;
349 enum nss_status status;
350 int n = __res_context_search (ctx, name, C_IN, T_QUERY_A_AND_AAAA,
351 host_buffer.buf->buf, 2048, &host_buffer.ptr,
352 &ans2p, &nans2p, &resplen2, &ans2p_malloced);
353 if (n >= 0)
354 {
355 status = gaih_getanswer (host_buffer.buf, n, (const querybuf *) ans2p,
356 resplen2, name, pat, buffer, buflen,
357 errnop, herrnop, ttlp);
358 }
359 else
360 {
361 switch (errno)
362 {
363 case ESRCH:
364 status = NSS_STATUS_TRYAGAIN;
365 h_errno = TRY_AGAIN;
366 break;
367 /* System has run out of file descriptors. */
368 case EMFILE:
369 case ENFILE:
370 h_errno = NETDB_INTERNAL;
371 /* Fall through. */
372 case ECONNREFUSED:
373 case ETIMEDOUT:
374 status = NSS_STATUS_UNAVAIL;
375 break;
376 default:
377 status = NSS_STATUS_NOTFOUND;
378 break;
379 }
380
381 *herrnop = h_errno;
382 if (h_errno == TRY_AGAIN)
383 *errnop = EAGAIN;
384 else
385 __set_errno (olderr);
386 }
387
388 /* Check whether ans2p was separately allocated. */
389 if (ans2p_malloced)
390 free (ans2p);
391
392 if (host_buffer.buf != orig_host_buffer)
393 free (host_buffer.buf);
394
395 __resolv_context_put (ctx);
396 return status;
397}
398
399
400extern enum nss_status _nss_dns_gethostbyaddr2_r (const void *addr,
401 socklen_t len, int af,
402 struct hostent *result,
403 char *buffer, size_t buflen,
404 int *errnop, int *h_errnop,
405 int32_t *ttlp);
406hidden_proto (_nss_dns_gethostbyaddr2_r)
407
408enum nss_status
409_nss_dns_gethostbyaddr2_r (const void *addr, socklen_t len, int af,
410 struct hostent *result, char *buffer, size_t buflen,
411 int *errnop, int *h_errnop, int32_t *ttlp)
412{
413 static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
414 static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
415 static const u_char v6local[] = { 0,0, 0,1 };
416 const u_char *uaddr = (const u_char *)addr;
417 struct host_data
418 {
419 char *aliases[MAX_NR_ALIASES];
420 unsigned char host_addr[16]; /* IPv4 or IPv6 */
421 char *h_addr_ptrs[MAX_NR_ADDRS + 1];
422 char linebuffer[0];
423 } *host_data = (struct host_data *) buffer;
424 union
425 {
426 querybuf *buf;
427 u_char *ptr;
428 } host_buffer;
429 querybuf *orig_host_buffer;
430 char qbuf[MAXDNAME+1], *qp = NULL;
431 size_t size;
432 int n, status;
433 int olderr = errno;
434
435 uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct host_data);
436 buffer += pad;
437 buflen = buflen > pad ? buflen - pad : 0;
438
439 if (__glibc_unlikely (buflen < sizeof (struct host_data)))
440 {
441 *errnop = ERANGE;
442 *h_errnop = NETDB_INTERNAL;
443 return NSS_STATUS_TRYAGAIN;
444 }
445
446 host_data = (struct host_data *) buffer;
447
448 struct resolv_context *ctx = __resolv_context_get ();
449 if (ctx == NULL)
450 {
451 *errnop = errno;
452 *h_errnop = NETDB_INTERNAL;
453 return NSS_STATUS_UNAVAIL;
454 }
455
456 if (af == AF_INET6 && len == IN6ADDRSZ
457 && (memcmp (uaddr, mapped, sizeof mapped) == 0
458 || (memcmp (uaddr, tunnelled, sizeof tunnelled) == 0
459 && memcmp (&uaddr[sizeof tunnelled], v6local, sizeof v6local))))
460 {
461 /* Unmap. */
462 addr += sizeof mapped;
463 uaddr += sizeof mapped;
464 af = AF_INET;
465 len = INADDRSZ;
466 }
467
468 switch (af)
469 {
470 case AF_INET:
471 size = INADDRSZ;
472 break;
473 case AF_INET6:
474 size = IN6ADDRSZ;
475 break;
476 default:
477 *errnop = EAFNOSUPPORT;
478 *h_errnop = NETDB_INTERNAL;
479 __resolv_context_put (ctx);
480 return NSS_STATUS_UNAVAIL;
481 }
482 if (size > len)
483 {
484 *errnop = EAFNOSUPPORT;
485 *h_errnop = NETDB_INTERNAL;
486 __resolv_context_put (ctx);
487 return NSS_STATUS_UNAVAIL;
488 }
489
490 host_buffer.buf = orig_host_buffer = (querybuf *) alloca (1024);
491
492 switch (af)
493 {
494 case AF_INET:
495 sprintf (qbuf, "%u.%u.%u.%u.in-addr.arpa", (uaddr[3] & 0xff),
496 (uaddr[2] & 0xff), (uaddr[1] & 0xff), (uaddr[0] & 0xff));
497 break;
498 case AF_INET6:
499 qp = qbuf;
500 for (n = IN6ADDRSZ - 1; n >= 0; n--)
501 {
502 static const char nibblechar[16] = "0123456789abcdef";
503 *qp++ = nibblechar[uaddr[n] & 0xf];
504 *qp++ = '.';
505 *qp++ = nibblechar[(uaddr[n] >> 4) & 0xf];
506 *qp++ = '.';
507 }
508 strcpy(qp, "ip6.arpa");
509 break;
510 default:
511 /* Cannot happen. */
512 break;
513 }
514
515 n = __res_context_query (ctx, qbuf, C_IN, T_PTR, host_buffer.buf->buf,
516 1024, &host_buffer.ptr, NULL, NULL, NULL, NULL);
517 if (n < 0)
518 {
519 *h_errnop = h_errno;
520 __set_errno (olderr);
521 if (host_buffer.buf != orig_host_buffer)
522 free (host_buffer.buf);
523 __resolv_context_put (ctx);
524 return errno == ECONNREFUSED ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND;
525 }
526
527 status = getanswer_r
528 (ctx, host_buffer.buf, n, qbuf, T_PTR, result, buffer, buflen,
529 errnop, h_errnop, 0 /* XXX */, ttlp, NULL);
530 if (host_buffer.buf != orig_host_buffer)
531 free (host_buffer.buf);
532 if (status != NSS_STATUS_SUCCESS)
533 {
534 __resolv_context_put (ctx);
535 return status;
536 }
537
538 result->h_addrtype = af;
539 result->h_length = len;
540 memcpy (host_data->host_addr, addr, len);
541 host_data->h_addr_ptrs[0] = (char *) host_data->host_addr;
542 host_data->h_addr_ptrs[1] = NULL;
543 *h_errnop = NETDB_SUCCESS;
544 __resolv_context_put (ctx);
545 return NSS_STATUS_SUCCESS;
546}
547hidden_def (_nss_dns_gethostbyaddr2_r)
548
549
550enum nss_status
551_nss_dns_gethostbyaddr_r (const void *addr, socklen_t len, int af,
552 struct hostent *result, char *buffer, size_t buflen,
553 int *errnop, int *h_errnop)
554{
555 return _nss_dns_gethostbyaddr2_r (addr, len, af, result, buffer, buflen,
556 errnop, h_errnop, NULL);
557}
558
559static void
560addrsort (struct resolv_context *ctx, char **ap, int num)
561{
562 int i, j;
563 char **p;
564 short aval[MAX_NR_ADDRS];
565 int needsort = 0;
566 size_t nsort = __resolv_context_sort_count (ctx);
567
568 p = ap;
569 if (num > MAX_NR_ADDRS)
570 num = MAX_NR_ADDRS;
571 for (i = 0; i < num; i++, p++)
572 {
573 for (j = 0 ; (unsigned)j < nsort; j++)
574 {
575 struct resolv_sortlist_entry e
576 = __resolv_context_sort_entry (ctx, j);
577 if (e.addr.s_addr == (((struct in_addr *)(*p))->s_addr & e.mask))
578 break;
579 }
580 aval[i] = j;
581 if (needsort == 0 && i > 0 && j < aval[i-1])
582 needsort = i;
583 }
584 if (!needsort)
585 return;
586
587 while (needsort++ < num)
588 for (j = needsort - 2; j >= 0; j--)
589 if (aval[j] > aval[j+1])
590 {
591 char *hp;
592
593 i = aval[j];
594 aval[j] = aval[j+1];
595 aval[j+1] = i;
596
597 hp = ap[j];
598 ap[j] = ap[j+1];
599 ap[j+1] = hp;
600 }
601 else
602 break;
603}
604
605static enum nss_status
606getanswer_r (struct resolv_context *ctx,
607 const querybuf *answer, int anslen, const char *qname, int qtype,
608 struct hostent *result, char *buffer, size_t buflen,
609 int *errnop, int *h_errnop, int map, int32_t *ttlp, char **canonp)
610{
611 struct host_data
612 {
613 char *aliases[MAX_NR_ALIASES];
614 unsigned char host_addr[16]; /* IPv4 or IPv6 */
615 char *h_addr_ptrs[0];
616 } *host_data;
617 int linebuflen;
618 const HEADER *hp;
619 const u_char *end_of_message, *cp;
620 int n, ancount, qdcount;
621 int haveanswer, had_error;
622 char *bp, **ap, **hap;
623 char tbuf[MAXDNAME];
624 const char *tname;
625 int (*name_ok) (const char *);
626 u_char packtmp[NS_MAXCDNAME];
627 int have_to_map = 0;
628 uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct host_data);
629 buffer += pad;
630 buflen = buflen > pad ? buflen - pad : 0;
631 if (__glibc_unlikely (buflen < sizeof (struct host_data)))
632 {
633 /* The buffer is too small. */
634 too_small:
635 *errnop = ERANGE;
636 *h_errnop = NETDB_INTERNAL;
637 return NSS_STATUS_TRYAGAIN;
638 }
639 host_data = (struct host_data *) buffer;
640 linebuflen = buflen - sizeof (struct host_data);
641 if (buflen - sizeof (struct host_data) != linebuflen)
642 linebuflen = INT_MAX;
643
644 tname = qname;
645 result->h_name = NULL;
646 end_of_message = answer->buf + anslen;
647 switch (qtype)
648 {
649 case T_A:
650 case T_AAAA:
651 name_ok = res_hnok;
652 break;
653 case T_PTR:
654 name_ok = res_dnok;
655 break;
656 default:
657 *errnop = ENOENT;
658 return NSS_STATUS_UNAVAIL; /* XXX should be abort(); */
659 }
660
661 /*
662 * find first satisfactory answer
663 */
664 hp = &answer->hdr;
665 ancount = ntohs (hp->ancount);
666 qdcount = ntohs (hp->qdcount);
667 cp = answer->buf + HFIXEDSZ;
668 if (__glibc_unlikely (qdcount != 1))
669 {
670 *h_errnop = NO_RECOVERY;
671 return NSS_STATUS_UNAVAIL;
672 }
673 if (sizeof (struct host_data) + (ancount + 1) * sizeof (char *) >= buflen)
674 goto too_small;
675 bp = (char *) &host_data->h_addr_ptrs[ancount + 1];
676 linebuflen -= (ancount + 1) * sizeof (char *);
677
678 n = __ns_name_unpack (answer->buf, end_of_message, cp,
679 packtmp, sizeof packtmp);
680 if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
681 {
682 if (__glibc_unlikely (errno == EMSGSIZE))
683 goto too_small;
684
685 n = -1;
686 }
687
688 if (n > 0 && bp[0] == '.')
689 bp[0] = '\0';
690
691 if (__glibc_unlikely (n < 0))
692 {
693 *errnop = errno;
694 *h_errnop = NO_RECOVERY;
695 return NSS_STATUS_UNAVAIL;
696 }
697 if (__glibc_unlikely (name_ok (bp) == 0))
698 {
699 errno = EBADMSG;
700 *errnop = EBADMSG;
701 *h_errnop = NO_RECOVERY;
702 return NSS_STATUS_UNAVAIL;
703 }
704 cp += n + QFIXEDSZ;
705
706 if (qtype == T_A || qtype == T_AAAA)
707 {
708 /* res_send() has already verified that the query name is the
709 * same as the one we sent; this just gets the expanded name
710 * (i.e., with the succeeding search-domain tacked on).
711 */
712 n = strlen (bp) + 1; /* for the \0 */
713 if (n >= MAXHOSTNAMELEN)
714 {
715 *h_errnop = NO_RECOVERY;
716 *errnop = ENOENT;
717 return NSS_STATUS_TRYAGAIN;
718 }
719 result->h_name = bp;
720 bp += n;
721 linebuflen -= n;
722 if (linebuflen < 0)
723 goto too_small;
724 /* The qname can be abbreviated, but h_name is now absolute. */
725 qname = result->h_name;
726 }
727
728 ap = host_data->aliases;
729 *ap = NULL;
730 result->h_aliases = host_data->aliases;
731 hap = host_data->h_addr_ptrs;
732 *hap = NULL;
733 result->h_addr_list = host_data->h_addr_ptrs;
734 haveanswer = 0;
735 had_error = 0;
736
737 while (ancount-- > 0 && cp < end_of_message && had_error == 0)
738 {
739 int type, class;
740
741 n = __ns_name_unpack (answer->buf, end_of_message, cp,
742 packtmp, sizeof packtmp);
743 if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
744 {
745 if (__glibc_unlikely (errno == EMSGSIZE))
746 goto too_small;
747
748 n = -1;
749 }
750
751 if (__glibc_unlikely (n < 0 || (*name_ok) (bp) == 0))
752 {
753 ++had_error;
754 continue;
755 }
756 cp += n; /* name */
757
758 if (__glibc_unlikely (cp + 10 > end_of_message))
759 {
760 ++had_error;
761 continue;
762 }
763
764 type = __ns_get16 (cp);
765 cp += INT16SZ; /* type */
766 class = __ns_get16 (cp);
767 cp += INT16SZ; /* class */
768 int32_t ttl = __ns_get32 (cp);
769 cp += INT32SZ; /* TTL */
770 n = __ns_get16 (cp);
771 cp += INT16SZ; /* len */
772
773 if (end_of_message - cp < n)
774 {
775 /* RDATA extends beyond the end of the packet. */
776 ++had_error;
777 continue;
778 }
779
780 if (__glibc_unlikely (class != C_IN))
781 {
782 /* XXX - debug? syslog? */
783 cp += n;
784 continue; /* XXX - had_error++ ? */
785 }
786
787 if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME)
788 {
789 /* A CNAME could also have a TTL entry. */
790 if (ttlp != NULL && ttl < *ttlp)
791 *ttlp = ttl;
792
793 if (ap >= &host_data->aliases[MAX_NR_ALIASES - 1])
794 continue;
795 n = dn_expand (answer->buf, end_of_message, cp, tbuf, sizeof tbuf);
796 if (__glibc_unlikely (n < 0 || (*name_ok) (tbuf) == 0))
797 {
798 ++had_error;
799 continue;
800 }
801 cp += n;
802 /* Store alias. */
803 *ap++ = bp;
804 n = strlen (bp) + 1; /* For the \0. */
805 if (__glibc_unlikely (n >= MAXHOSTNAMELEN))
806 {
807 ++had_error;
808 continue;
809 }
810 bp += n;
811 linebuflen -= n;
812 /* Get canonical name. */
813 n = strlen (tbuf) + 1; /* For the \0. */
814 if (__glibc_unlikely (n > linebuflen))
815 goto too_small;
816 if (__glibc_unlikely (n >= MAXHOSTNAMELEN))
817 {
818 ++had_error;
819 continue;
820 }
821 result->h_name = bp;
822 bp = __mempcpy (bp, tbuf, n); /* Cannot overflow. */
823 linebuflen -= n;
824 continue;
825 }
826
827 if (qtype == T_PTR && type == T_CNAME)
828 {
829 /* A CNAME could also have a TTL entry. */
830 if (ttlp != NULL && ttl < *ttlp)
831 *ttlp = ttl;
832
833 n = dn_expand (answer->buf, end_of_message, cp, tbuf, sizeof tbuf);
834 if (__glibc_unlikely (n < 0 || res_dnok (tbuf) == 0))
835 {
836 ++had_error;
837 continue;
838 }
839 cp += n;
840 /* Get canonical name. */
841 n = strlen (tbuf) + 1; /* For the \0. */
842 if (__glibc_unlikely (n > linebuflen))
843 goto too_small;
844 if (__glibc_unlikely (n >= MAXHOSTNAMELEN))
845 {
846 ++had_error;
847 continue;
848 }
849 tname = bp;
850 bp = __mempcpy (bp, tbuf, n); /* Cannot overflow. */
851 linebuflen -= n;
852 continue;
853 }
854
855 if (type == T_A && qtype == T_AAAA && map)
856 have_to_map = 1;
857 else if (__glibc_unlikely (type != qtype))
858 {
859 cp += n;
860 continue; /* XXX - had_error++ ? */
861 }
862
863 switch (type)
864 {
865 case T_PTR:
866 if (__glibc_unlikely (strcasecmp (tname, bp) != 0))
867 {
868 cp += n;
869 continue; /* XXX - had_error++ ? */
870 }
871
872 n = __ns_name_unpack (answer->buf, end_of_message, cp,
873 packtmp, sizeof packtmp);
874 if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
875 {
876 if (__glibc_unlikely (errno == EMSGSIZE))
877 goto too_small;
878
879 n = -1;
880 }
881
882 if (__glibc_unlikely (n < 0 || res_hnok (bp) == 0))
883 {
884 ++had_error;
885 break;
886 }
887 if (ttlp != NULL && ttl < *ttlp)
888 *ttlp = ttl;
889 /* bind would put multiple PTR records as aliases, but we don't do
890 that. */
891 result->h_name = bp;
892 if (have_to_map)
893 {
894 n = strlen (bp) + 1; /* for the \0 */
895 if (__glibc_unlikely (n >= MAXHOSTNAMELEN))
896 {
897 ++had_error;
898 break;
899 }
900 bp += n;
901 linebuflen -= n;
902 if (map_v4v6_hostent (result, &bp, &linebuflen))
903 goto too_small;
904 }
905 *h_errnop = NETDB_SUCCESS;
906 return NSS_STATUS_SUCCESS;
907 case T_A:
908 case T_AAAA:
909 if (__glibc_unlikely (strcasecmp (result->h_name, bp) != 0))
910 {
911 cp += n;
912 continue; /* XXX - had_error++ ? */
913 }
914
915 /* Stop parsing at a record whose length is incorrect. */
916 if (n != rrtype_to_rdata_length (type))
917 {
918 ++had_error;
919 break;
920 }
921
922 /* Skip records of the wrong type. */
923 if (n != result->h_length)
924 {
925 cp += n;
926 continue;
927 }
928 if (!haveanswer)
929 {
930 int nn;
931
932 /* We compose a single hostent out of the entire chain of
933 entries, so the TTL of the hostent is essentially the lowest
934 TTL in the chain. */
935 if (ttlp != NULL && ttl < *ttlp)
936 *ttlp = ttl;
937 if (canonp != NULL)
938 *canonp = bp;
939 result->h_name = bp;
940 nn = strlen (bp) + 1; /* for the \0 */
941 bp += nn;
942 linebuflen -= nn;
943 }
944
945 linebuflen -= sizeof (align) - ((u_long) bp % sizeof (align));
946 bp += sizeof (align) - ((u_long) bp % sizeof (align));
947
948 if (__glibc_unlikely (n > linebuflen))
949 goto too_small;
950 bp = __mempcpy (*hap++ = bp, cp, n);
951 cp += n;
952 linebuflen -= n;
953 break;
954 default:
955 abort ();
956 }
957 if (had_error == 0)
958 ++haveanswer;
959 }
960
961 if (haveanswer > 0)
962 {
963 *ap = NULL;
964 *hap = NULL;
965 /*
966 * Note: we sort even if host can take only one address
967 * in its return structures - should give it the "best"
968 * address in that case, not some random one
969 */
970 if (haveanswer > 1 && qtype == T_A
971 && __resolv_context_sort_count (ctx) > 0)
972 addrsort (ctx, host_data->h_addr_ptrs, haveanswer);
973
974 if (result->h_name == NULL)
975 {
976 n = strlen (qname) + 1; /* For the \0. */
977 if (n > linebuflen)
978 goto too_small;
979 if (n >= MAXHOSTNAMELEN)
980 goto no_recovery;
981 result->h_name = bp;
982 bp = __mempcpy (bp, qname, n); /* Cannot overflow. */
983 linebuflen -= n;
984 }
985
986 if (have_to_map)
987 if (map_v4v6_hostent (result, &bp, &linebuflen))
988 goto too_small;
989 *h_errnop = NETDB_SUCCESS;
990 return NSS_STATUS_SUCCESS;
991 }
992 no_recovery:
993 *h_errnop = NO_RECOVERY;
994 *errnop = ENOENT;
995 /* Special case here: if the resolver sent a result but it only
996 contains a CNAME while we are looking for a T_A or T_AAAA record,
997 we fail with NOTFOUND instead of TRYAGAIN. */
998 return ((qtype == T_A || qtype == T_AAAA) && ap != host_data->aliases
999 ? NSS_STATUS_NOTFOUND : NSS_STATUS_TRYAGAIN);
1000}
1001
1002
1003static enum nss_status
1004gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
1005 struct gaih_addrtuple ***patp,
1006 char **bufferp, size_t *buflenp,
1007 int *errnop, int *h_errnop, int32_t *ttlp, int *firstp)
1008{
1009 char *buffer = *bufferp;
1010 size_t buflen = *buflenp;
1011
1012 struct gaih_addrtuple **pat = *patp;
1013 const HEADER *hp = &answer->hdr;
1014 int ancount = ntohs (hp->ancount);
1015 int qdcount = ntohs (hp->qdcount);
1016 const u_char *cp = answer->buf + HFIXEDSZ;
1017 const u_char *end_of_message = answer->buf + anslen;
1018 if (__glibc_unlikely (qdcount != 1))
1019 {
1020 *h_errnop = NO_RECOVERY;
1021 return NSS_STATUS_UNAVAIL;
1022 }
1023
1024 u_char packtmp[NS_MAXCDNAME];
1025 int n = __ns_name_unpack (answer->buf, end_of_message, cp,
1026 packtmp, sizeof packtmp);
1027 /* We unpack the name to check it for validity. But we do not need
1028 it later. */
1029 if (n != -1 && __ns_name_ntop (packtmp, buffer, buflen) == -1)
1030 {
1031 if (__glibc_unlikely (errno == EMSGSIZE))
1032 {
1033 too_small:
1034 *errnop = ERANGE;
1035 *h_errnop = NETDB_INTERNAL;
1036 return NSS_STATUS_TRYAGAIN;
1037 }
1038
1039 n = -1;
1040 }
1041
1042 if (__glibc_unlikely (n < 0))
1043 {
1044 *errnop = errno;
1045 *h_errnop = NO_RECOVERY;
1046 return NSS_STATUS_UNAVAIL;
1047 }
1048 if (__glibc_unlikely (res_hnok (buffer) == 0))
1049 {
1050 errno = EBADMSG;
1051 *errnop = EBADMSG;
1052 *h_errnop = NO_RECOVERY;
1053 return NSS_STATUS_UNAVAIL;
1054 }
1055 cp += n + QFIXEDSZ;
1056
1057 int haveanswer = 0;
1058 int had_error = 0;
1059 char *canon = NULL;
1060 char *h_name = NULL;
1061 int h_namelen = 0;
1062
1063 if (ancount == 0)
1064 {
1065 *h_errnop = HOST_NOT_FOUND;
1066 return NSS_STATUS_NOTFOUND;
1067 }
1068
1069 while (ancount-- > 0 && cp < end_of_message && had_error == 0)
1070 {
1071 n = __ns_name_unpack (answer->buf, end_of_message, cp,
1072 packtmp, sizeof packtmp);
1073 if (n != -1 &&
1074 (h_namelen = __ns_name_ntop (packtmp, buffer, buflen)) == -1)
1075 {
1076 if (__glibc_unlikely (errno == EMSGSIZE))
1077 goto too_small;
1078
1079 n = -1;
1080 }
1081 if (__glibc_unlikely (n < 0 || res_hnok (buffer) == 0))
1082 {
1083 ++had_error;
1084 continue;
1085 }
1086 if (*firstp && canon == NULL)
1087 {
1088 h_name = buffer;
1089 buffer += h_namelen;
1090 buflen -= h_namelen;
1091 }
1092
1093 cp += n; /* name */
1094
1095 if (__glibc_unlikely (cp + 10 > end_of_message))
1096 {
1097 ++had_error;
1098 continue;
1099 }
1100
1101 int type = __ns_get16 (cp);
1102 cp += INT16SZ; /* type */
1103 int class = __ns_get16 (cp);
1104 cp += INT16SZ; /* class */
1105 int32_t ttl = __ns_get32 (cp);
1106 cp += INT32SZ; /* TTL */
1107 n = __ns_get16 (cp);
1108 cp += INT16SZ; /* len */
1109
1110 if (end_of_message - cp < n)
1111 {
1112 /* RDATA extends beyond the end of the packet. */
1113 ++had_error;
1114 continue;
1115 }
1116
1117 if (class != C_IN)
1118 {
1119 cp += n;
1120 continue;
1121 }
1122
1123 if (type == T_CNAME)
1124 {
1125 char tbuf[MAXDNAME];
1126
1127 /* A CNAME could also have a TTL entry. */
1128 if (ttlp != NULL && ttl < *ttlp)
1129 *ttlp = ttl;
1130
1131 n = dn_expand (answer->buf, end_of_message, cp, tbuf, sizeof tbuf);
1132 if (__glibc_unlikely (n < 0 || res_hnok (tbuf) == 0))
1133 {
1134 ++had_error;
1135 continue;
1136 }
1137 cp += n;
1138
1139 if (*firstp)
1140 {
1141 /* Reclaim buffer space. */
1142 if (h_name + h_namelen == buffer)
1143 {
1144 buffer = h_name;
1145 buflen += h_namelen;
1146 }
1147
1148 n = strlen (tbuf) + 1;
1149 if (__glibc_unlikely (n > buflen))
1150 goto too_small;
1151 if (__glibc_unlikely (n >= MAXHOSTNAMELEN))
1152 {
1153 ++had_error;
1154 continue;
1155 }
1156
1157 canon = buffer;
1158 buffer = __mempcpy (buffer, tbuf, n);
1159 buflen -= n;
1160 h_namelen = 0;
1161 }
1162 continue;
1163 }
1164
1165 /* Stop parsing if we encounter a record with incorrect RDATA
1166 length. */
1167 if (type == T_A || type == T_AAAA)
1168 {
1169 if (n != rrtype_to_rdata_length (type))
1170 {
1171 ++had_error;
1172 continue;
1173 }
1174 }
1175 else
1176 {
1177 /* Skip unknown records. */
1178 cp += n;
1179 continue;
1180 }
1181
1182 assert (type == T_A || type == T_AAAA);
1183 if (*pat == NULL)
1184 {
1185 uintptr_t pad = (-(uintptr_t) buffer
1186 % __alignof__ (struct gaih_addrtuple));
1187 buffer += pad;
1188 buflen = buflen > pad ? buflen - pad : 0;
1189
1190 if (__glibc_unlikely (buflen < sizeof (struct gaih_addrtuple)))
1191 goto too_small;
1192
1193 *pat = (struct gaih_addrtuple *) buffer;
1194 buffer += sizeof (struct gaih_addrtuple);
1195 buflen -= sizeof (struct gaih_addrtuple);
1196 }
1197
1198 (*pat)->name = NULL;
1199 (*pat)->next = NULL;
1200
1201 if (*firstp)
1202 {
1203 /* We compose a single hostent out of the entire chain of
1204 entries, so the TTL of the hostent is essentially the lowest
1205 TTL in the chain. */
1206 if (ttlp != NULL && ttl < *ttlp)
1207 *ttlp = ttl;
1208
1209 (*pat)->name = canon ?: h_name;
1210
1211 *firstp = 0;
1212 }
1213
1214 (*pat)->family = type == T_A ? AF_INET : AF_INET6;
1215 memcpy ((*pat)->addr, cp, n);
1216 cp += n;
1217 (*pat)->scopeid = 0;
1218
1219 pat = &((*pat)->next);
1220
1221 haveanswer = 1;
1222 }
1223
1224 if (haveanswer)
1225 {
1226 *patp = pat;
1227 *bufferp = buffer;
1228 *buflenp = buflen;
1229
1230 *h_errnop = NETDB_SUCCESS;
1231 return NSS_STATUS_SUCCESS;
1232 }
1233
1234 /* Special case here: if the resolver sent a result but it only
1235 contains a CNAME while we are looking for a T_A or T_AAAA record,
1236 we fail with NOTFOUND instead of TRYAGAIN. */
1237 if (canon != NULL)
1238 {
1239 *h_errnop = HOST_NOT_FOUND;
1240 return NSS_STATUS_NOTFOUND;
1241 }
1242
1243 *h_errnop = NETDB_INTERNAL;
1244 return NSS_STATUS_TRYAGAIN;
1245}
1246
1247
1248static enum nss_status
1249gaih_getanswer (const querybuf *answer1, int anslen1, const querybuf *answer2,
1250 int anslen2, const char *qname,
1251 struct gaih_addrtuple **pat, char *buffer, size_t buflen,
1252 int *errnop, int *h_errnop, int32_t *ttlp)
1253{
1254 int first = 1;
1255
1256 enum nss_status status = NSS_STATUS_NOTFOUND;
1257
1258 /* Combining the NSS status of two distinct queries requires some
1259 compromise and attention to symmetry (A or AAAA queries can be
1260 returned in any order). What follows is a breakdown of how this
1261 code is expected to work and why. We discuss only SUCCESS,
1262 TRYAGAIN, NOTFOUND and UNAVAIL, since they are the only returns
1263 that apply (though RETURN and MERGE exist). We make a distinction
1264 between TRYAGAIN (recoverable) and TRYAGAIN' (not-recoverable).
1265 A recoverable TRYAGAIN is almost always due to buffer size issues
1266 and returns ERANGE in errno and the caller is expected to retry
1267 with a larger buffer.
1268
1269 Lastly, you may be tempted to make significant changes to the
1270 conditions in this code to bring about symmetry between responses.
1271 Please don't change anything without due consideration for
1272 expected application behaviour. Some of the synthesized responses
1273 aren't very well thought out and sometimes appear to imply that
1274 IPv4 responses are always answer 1, and IPv6 responses are always
1275 answer 2, but that's not true (see the implementation of send_dg
1276 and send_vc to see response can arrive in any order, particularly
1277 for UDP). However, we expect it holds roughly enough of the time
1278 that this code works, but certainly needs to be fixed to make this
1279 a more robust implementation.
1280
1281 ----------------------------------------------
1282 | Answer 1 Status / | Synthesized | Reason |
1283 | Answer 2 Status | Status | |
1284 |--------------------------------------------|
1285 | SUCCESS/SUCCESS | SUCCESS | [1] |
1286 | SUCCESS/TRYAGAIN | TRYAGAIN | [5] |
1287 | SUCCESS/TRYAGAIN' | SUCCESS | [1] |
1288 | SUCCESS/NOTFOUND | SUCCESS | [1] |
1289 | SUCCESS/UNAVAIL | SUCCESS | [1] |
1290 | TRYAGAIN/SUCCESS | TRYAGAIN | [2] |
1291 | TRYAGAIN/TRYAGAIN | TRYAGAIN | [2] |
1292 | TRYAGAIN/TRYAGAIN' | TRYAGAIN | [2] |
1293 | TRYAGAIN/NOTFOUND | TRYAGAIN | [2] |
1294 | TRYAGAIN/UNAVAIL | TRYAGAIN | [2] |
1295 | TRYAGAIN'/SUCCESS | SUCCESS | [3] |
1296 | TRYAGAIN'/TRYAGAIN | TRYAGAIN | [3] |
1297 | TRYAGAIN'/TRYAGAIN' | TRYAGAIN' | [3] |
1298 | TRYAGAIN'/NOTFOUND | TRYAGAIN' | [3] |
1299 | TRYAGAIN'/UNAVAIL | UNAVAIL | [3] |
1300 | NOTFOUND/SUCCESS | SUCCESS | [3] |
1301 | NOTFOUND/TRYAGAIN | TRYAGAIN | [3] |
1302 | NOTFOUND/TRYAGAIN' | TRYAGAIN' | [3] |
1303 | NOTFOUND/NOTFOUND | NOTFOUND | [3] |
1304 | NOTFOUND/UNAVAIL | UNAVAIL | [3] |
1305 | UNAVAIL/SUCCESS | UNAVAIL | [4] |
1306 | UNAVAIL/TRYAGAIN | UNAVAIL | [4] |
1307 | UNAVAIL/TRYAGAIN' | UNAVAIL | [4] |
1308 | UNAVAIL/NOTFOUND | UNAVAIL | [4] |
1309 | UNAVAIL/UNAVAIL | UNAVAIL | [4] |
1310 ----------------------------------------------
1311
1312 [1] If the first response is a success we return success.
1313 This ignores the state of the second answer and in fact
1314 incorrectly sets errno and h_errno to that of the second
1315 answer. However because the response is a success we ignore
1316 *errnop and *h_errnop (though that means you touched errno on
1317 success). We are being conservative here and returning the
1318 likely IPv4 response in the first answer as a success.
1319
1320 [2] If the first response is a recoverable TRYAGAIN we return
1321 that instead of looking at the second response. The
1322 expectation here is that we have failed to get an IPv4 response
1323 and should retry both queries.
1324
1325 [3] If the first response was not a SUCCESS and the second
1326 response is not NOTFOUND (had a SUCCESS, need to TRYAGAIN,
1327 or failed entirely e.g. TRYAGAIN' and UNAVAIL) then use the
1328 result from the second response, otherwise the first responses
1329 status is used. Again we have some odd side-effects when the
1330 second response is NOTFOUND because we overwrite *errnop and
1331 *h_errnop that means that a first answer of NOTFOUND might see
1332 its *errnop and *h_errnop values altered. Whether it matters
1333 in practice that a first response NOTFOUND has the wrong
1334 *errnop and *h_errnop is undecided.
1335
1336 [4] If the first response is UNAVAIL we return that instead of
1337 looking at the second response. The expectation here is that
1338 it will have failed similarly e.g. configuration failure.
1339
1340 [5] Testing this code is complicated by the fact that truncated
1341 second response buffers might be returned as SUCCESS if the
1342 first answer is a SUCCESS. To fix this we add symmetry to
1343 TRYAGAIN with the second response. If the second response
1344 is a recoverable error we now return TRYAGIN even if the first
1345 response was SUCCESS. */
1346
1347 if (anslen1 > 0)
1348 status = gaih_getanswer_slice(answer1, anslen1, qname,
1349 &pat, &buffer, &buflen,
1350 errnop, h_errnop, ttlp,
1351 &first);
1352
1353 if ((status == NSS_STATUS_SUCCESS || status == NSS_STATUS_NOTFOUND
1354 || (status == NSS_STATUS_TRYAGAIN
1355 /* We want to look at the second answer in case of an
1356 NSS_STATUS_TRYAGAIN only if the error is non-recoverable, i.e.
1357 *h_errnop is NO_RECOVERY. If not, and if the failure was due to
1358 an insufficient buffer (ERANGE), then we need to drop the results
1359 and pass on the NSS_STATUS_TRYAGAIN to the caller so that it can
1360 repeat the query with a larger buffer. */
1361 && (*errnop != ERANGE || *h_errnop == NO_RECOVERY)))
1362 && answer2 != NULL && anslen2 > 0)
1363 {
1364 enum nss_status status2 = gaih_getanswer_slice(answer2, anslen2, qname,
1365 &pat, &buffer, &buflen,
1366 errnop, h_errnop, ttlp,
1367 &first);
1368 /* Use the second response status in some cases. */
1369 if (status != NSS_STATUS_SUCCESS && status2 != NSS_STATUS_NOTFOUND)
1370 status = status2;
1371 /* Do not return a truncated second response (unless it was
1372 unavoidable e.g. unrecoverable TRYAGAIN). */
1373 if (status == NSS_STATUS_SUCCESS
1374 && (status2 == NSS_STATUS_TRYAGAIN
1375 && *errnop == ERANGE && *h_errnop != NO_RECOVERY))
1376 status = NSS_STATUS_TRYAGAIN;
1377 }
1378
1379 return status;
1380}
1381