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