mips: align stack in clone [BZ #28223]
[glibc.git] / resolv / nss_dns / dns-host.c
blob7248ade18db5ba471bb47ea6bdf963e2f5ed6deb
1 /* Copyright (C) 1996-2021 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Extended from original form by Ulrich Drepper <drepper@cygnus.com>, 1996.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
19 /* Parts of this file are plain copies of the file `gethtnamadr.c' from
20 the bind package and it has the following copyright. */
23 * ++Copyright++ 1985, 1988, 1993
24 * -
25 * Copyright (c) 1985, 1988, 1993
26 * The Regents of the University of California. All rights reserved.
28 * Redistribution and use in source and binary forms, with or without
29 * modification, are permitted provided that the following conditions
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.
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.
54 * Permission to use, copy, modify, and distribute this software for any
55 * purpose with or without fee is hereby granted, provided that the above
56 * copyright notice and this permission notice appear in all copies, and that
57 * the name of Digital Equipment Corporation not be used in advertising or
58 * publicity pertaining to distribution of the document or software without
59 * specific, written prior permission.
61 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
62 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
63 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
64 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
65 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
66 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
67 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
68 * SOFTWARE.
69 * -
70 * --Copyright--
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 <libc-pointer-arith.h>
83 #include "nsswitch.h"
84 #include <arpa/nameser.h>
85 #include <nss_dns.h>
87 #include <resolv/resolv-internal.h>
88 #include <resolv/resolv_context.h>
90 /* Get implementations of some internal functions. */
91 #include <resolv/mapv4v6addr.h>
92 #include <resolv/mapv4v6hostent.h>
94 #define RESOLVSORT
96 #if PACKETSZ > 65536
97 # define MAXPACKET PACKETSZ
98 #else
99 # define MAXPACKET 65536
100 #endif
101 /* As per RFC 1034 and 1035 a host name cannot exceed 255 octets in length. */
102 #ifdef MAXHOSTNAMELEN
103 # undef MAXHOSTNAMELEN
104 #endif
105 #define MAXHOSTNAMELEN 256
107 /* We need this time later. */
108 typedef union querybuf
110 HEADER hdr;
111 u_char buf[MAXPACKET];
112 } querybuf;
114 static enum nss_status getanswer_r (struct resolv_context *ctx,
115 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);
121 static 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);
129 static enum nss_status gethostbyname3_context (struct resolv_context *ctx,
130 const char *name, int af,
131 struct hostent *result,
132 char *buffer, size_t buflen,
133 int *errnop, int *h_errnop,
134 int32_t *ttlp,
135 char **canonp);
137 /* Return the expected RDATA length for an address record type (A or
138 AAAA). */
139 static int
140 rrtype_to_rdata_length (int type)
142 switch (type)
144 case T_A:
145 return INADDRSZ;
146 case T_AAAA:
147 return IN6ADDRSZ;
148 default:
149 return -1;
154 enum nss_status
155 _nss_dns_gethostbyname3_r (const char *name, int af, struct hostent *result,
156 char *buffer, size_t buflen, int *errnop,
157 int *h_errnop, int32_t *ttlp, char **canonp)
159 struct resolv_context *ctx = __resolv_context_get ();
160 if (ctx == NULL)
162 *errnop = errno;
163 *h_errnop = NETDB_INTERNAL;
164 return NSS_STATUS_UNAVAIL;
166 enum nss_status status = gethostbyname3_context
167 (ctx, name, af, result, buffer, buflen, errnop, h_errnop, ttlp, canonp);
168 __resolv_context_put (ctx);
169 return status;
171 libc_hidden_def (_nss_dns_gethostbyname3_r)
173 static enum nss_status
174 gethostbyname3_context (struct resolv_context *ctx,
175 const char *name, int af, struct hostent *result,
176 char *buffer, size_t buflen, int *errnop,
177 int *h_errnop, int32_t *ttlp, char **canonp)
179 union
181 querybuf *buf;
182 u_char *ptr;
183 } host_buffer;
184 querybuf *orig_host_buffer;
185 char tmp[NS_MAXDNAME];
186 int size, type, n;
187 const char *cp;
188 int map = 0;
189 int olderr = errno;
190 enum nss_status status;
192 switch (af) {
193 case AF_INET:
194 size = INADDRSZ;
195 type = T_A;
196 break;
197 case AF_INET6:
198 size = IN6ADDRSZ;
199 type = T_AAAA;
200 break;
201 default:
202 *h_errnop = NO_DATA;
203 *errnop = EAFNOSUPPORT;
204 return NSS_STATUS_UNAVAIL;
207 result->h_addrtype = af;
208 result->h_length = size;
211 * if there aren't any dots, it could be a user-level alias.
212 * this is also done in res_query() since we are not the only
213 * function that looks up host names.
215 if (strchr (name, '.') == NULL
216 && (cp = __res_context_hostalias (ctx, name, tmp, sizeof (tmp))) != NULL)
217 name = cp;
219 host_buffer.buf = orig_host_buffer = (querybuf *) alloca (1024);
221 n = __res_context_search (ctx, name, C_IN, type, host_buffer.buf->buf,
222 1024, &host_buffer.ptr, NULL, NULL, NULL, NULL);
223 if (n < 0)
225 switch (errno)
227 case ESRCH:
228 status = NSS_STATUS_TRYAGAIN;
229 h_errno = TRY_AGAIN;
230 break;
231 /* System has run out of file descriptors. */
232 case EMFILE:
233 case ENFILE:
234 h_errno = NETDB_INTERNAL;
235 /* Fall through. */
236 case ECONNREFUSED:
237 case ETIMEDOUT:
238 status = NSS_STATUS_UNAVAIL;
239 break;
240 default:
241 status = NSS_STATUS_NOTFOUND;
242 break;
244 *h_errnop = h_errno;
245 if (h_errno == TRY_AGAIN)
246 *errnop = EAGAIN;
247 else
248 __set_errno (olderr);
250 /* If we are looking for an IPv6 address and mapping is enabled
251 by having the RES_USE_INET6 bit in _res.options set, we try
252 another lookup. */
253 if (af == AF_INET6 && res_use_inet6 ())
254 n = __res_context_search (ctx, name, C_IN, T_A, host_buffer.buf->buf,
255 host_buffer.buf != orig_host_buffer
256 ? MAXPACKET : 1024, &host_buffer.ptr,
257 NULL, NULL, NULL, NULL);
259 if (n < 0)
261 if (host_buffer.buf != orig_host_buffer)
262 free (host_buffer.buf);
263 return status;
266 map = 1;
268 result->h_addrtype = AF_INET;
269 result->h_length = INADDRSZ;
272 status = getanswer_r
273 (ctx, host_buffer.buf, n, name, type, result, buffer, buflen,
274 errnop, h_errnop, map, ttlp, canonp);
275 if (host_buffer.buf != orig_host_buffer)
276 free (host_buffer.buf);
277 return status;
280 /* Verify that the name looks like a host name. There is no point in
281 sending a query which will not produce a usable name in the
282 response. */
283 static enum nss_status
284 check_name (const char *name, int *h_errnop)
286 if (__libc_res_hnok (name))
287 return NSS_STATUS_SUCCESS;
288 *h_errnop = HOST_NOT_FOUND;
289 return NSS_STATUS_NOTFOUND;
292 enum nss_status
293 _nss_dns_gethostbyname2_r (const char *name, int af, struct hostent *result,
294 char *buffer, size_t buflen, int *errnop,
295 int *h_errnop)
297 enum nss_status status = check_name (name, h_errnop);
298 if (status != NSS_STATUS_SUCCESS)
299 return status;
300 return _nss_dns_gethostbyname3_r (name, af, result, buffer, buflen, errnop,
301 h_errnop, NULL, NULL);
303 libc_hidden_def (_nss_dns_gethostbyname2_r)
305 enum nss_status
306 _nss_dns_gethostbyname_r (const char *name, struct hostent *result,
307 char *buffer, size_t buflen, int *errnop,
308 int *h_errnop)
310 enum nss_status status = check_name (name, h_errnop);
311 if (status != NSS_STATUS_SUCCESS)
312 return status;
313 struct resolv_context *ctx = __resolv_context_get ();
314 if (ctx == NULL)
316 *errnop = errno;
317 *h_errnop = NETDB_INTERNAL;
318 return NSS_STATUS_UNAVAIL;
320 status = NSS_STATUS_NOTFOUND;
321 if (res_use_inet6 ())
322 status = gethostbyname3_context (ctx, name, AF_INET6, result, buffer,
323 buflen, errnop, h_errnop, NULL, NULL);
324 if (status == NSS_STATUS_NOTFOUND)
325 status = gethostbyname3_context (ctx, name, AF_INET, result, buffer,
326 buflen, errnop, h_errnop, NULL, NULL);
327 __resolv_context_put (ctx);
328 return status;
330 libc_hidden_def (_nss_dns_gethostbyname_r)
332 enum nss_status
333 _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
334 char *buffer, size_t buflen, int *errnop,
335 int *herrnop, int32_t *ttlp)
337 enum nss_status status = check_name (name, herrnop);
338 if (status != NSS_STATUS_SUCCESS)
339 return status;
340 struct resolv_context *ctx = __resolv_context_get ();
341 if (ctx == NULL)
343 *errnop = errno;
344 *herrnop = NETDB_INTERNAL;
345 return NSS_STATUS_UNAVAIL;
349 * if there aren't any dots, it could be a user-level alias.
350 * this is also done in res_query() since we are not the only
351 * function that looks up host names.
353 if (strchr (name, '.') == NULL)
355 char *tmp = alloca (NS_MAXDNAME);
356 const char *cp = __res_context_hostalias (ctx, name, tmp, NS_MAXDNAME);
357 if (cp != NULL)
358 name = cp;
361 union
363 querybuf *buf;
364 u_char *ptr;
365 } host_buffer;
366 querybuf *orig_host_buffer;
367 host_buffer.buf = orig_host_buffer = (querybuf *) alloca (2048);
368 u_char *ans2p = NULL;
369 int nans2p = 0;
370 int resplen2 = 0;
371 int ans2p_malloced = 0;
373 int olderr = errno;
374 int n = __res_context_search (ctx, name, C_IN, T_QUERY_A_AND_AAAA,
375 host_buffer.buf->buf, 2048, &host_buffer.ptr,
376 &ans2p, &nans2p, &resplen2, &ans2p_malloced);
377 if (n >= 0)
379 status = gaih_getanswer (host_buffer.buf, n, (const querybuf *) ans2p,
380 resplen2, name, pat, buffer, buflen,
381 errnop, herrnop, ttlp);
383 else
385 switch (errno)
387 case ESRCH:
388 status = NSS_STATUS_TRYAGAIN;
389 h_errno = TRY_AGAIN;
390 break;
391 /* System has run out of file descriptors. */
392 case EMFILE:
393 case ENFILE:
394 h_errno = NETDB_INTERNAL;
395 /* Fall through. */
396 case ECONNREFUSED:
397 case ETIMEDOUT:
398 status = NSS_STATUS_UNAVAIL;
399 break;
400 default:
401 status = NSS_STATUS_NOTFOUND;
402 break;
405 *herrnop = h_errno;
406 if (h_errno == TRY_AGAIN)
407 *errnop = EAGAIN;
408 else
409 __set_errno (olderr);
412 /* Check whether ans2p was separately allocated. */
413 if (ans2p_malloced)
414 free (ans2p);
416 if (host_buffer.buf != orig_host_buffer)
417 free (host_buffer.buf);
419 __resolv_context_put (ctx);
420 return status;
422 libc_hidden_def (_nss_dns_gethostbyname4_r)
424 enum nss_status
425 _nss_dns_gethostbyaddr2_r (const void *addr, socklen_t len, int af,
426 struct hostent *result, char *buffer, size_t buflen,
427 int *errnop, int *h_errnop, int32_t *ttlp)
429 static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
430 static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
431 static const u_char v6local[] = { 0,0, 0,1 };
432 const u_char *uaddr = (const u_char *)addr;
433 struct host_data
435 char *aliases[MAX_NR_ALIASES];
436 unsigned char host_addr[16]; /* IPv4 or IPv6 */
437 char *h_addr_ptrs[MAX_NR_ADDRS + 1];
438 char linebuffer[0];
439 } *host_data = (struct host_data *) buffer;
440 union
442 querybuf *buf;
443 u_char *ptr;
444 } host_buffer;
445 querybuf *orig_host_buffer;
446 char qbuf[MAXDNAME+1], *qp = NULL;
447 size_t size;
448 int n, status;
449 int olderr = errno;
451 uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct host_data);
452 buffer += pad;
453 buflen = buflen > pad ? buflen - pad : 0;
455 if (__glibc_unlikely (buflen < sizeof (struct host_data)))
457 *errnop = ERANGE;
458 *h_errnop = NETDB_INTERNAL;
459 return NSS_STATUS_TRYAGAIN;
462 host_data = (struct host_data *) buffer;
464 struct resolv_context *ctx = __resolv_context_get ();
465 if (ctx == NULL)
467 *errnop = errno;
468 *h_errnop = NETDB_INTERNAL;
469 return NSS_STATUS_UNAVAIL;
472 if (af == AF_INET6 && len == IN6ADDRSZ
473 && (memcmp (uaddr, mapped, sizeof mapped) == 0
474 || (memcmp (uaddr, tunnelled, sizeof tunnelled) == 0
475 && memcmp (&uaddr[sizeof tunnelled], v6local, sizeof v6local))))
477 /* Unmap. */
478 addr += sizeof mapped;
479 uaddr += sizeof mapped;
480 af = AF_INET;
481 len = INADDRSZ;
484 switch (af)
486 case AF_INET:
487 size = INADDRSZ;
488 break;
489 case AF_INET6:
490 size = IN6ADDRSZ;
491 break;
492 default:
493 *errnop = EAFNOSUPPORT;
494 *h_errnop = NETDB_INTERNAL;
495 __resolv_context_put (ctx);
496 return NSS_STATUS_UNAVAIL;
498 if (size > len)
500 *errnop = EAFNOSUPPORT;
501 *h_errnop = NETDB_INTERNAL;
502 __resolv_context_put (ctx);
503 return NSS_STATUS_UNAVAIL;
506 host_buffer.buf = orig_host_buffer = (querybuf *) alloca (1024);
508 switch (af)
510 case AF_INET:
511 sprintf (qbuf, "%u.%u.%u.%u.in-addr.arpa", (uaddr[3] & 0xff),
512 (uaddr[2] & 0xff), (uaddr[1] & 0xff), (uaddr[0] & 0xff));
513 break;
514 case AF_INET6:
515 qp = qbuf;
516 for (n = IN6ADDRSZ - 1; n >= 0; n--)
518 static const char nibblechar[16] = "0123456789abcdef";
519 *qp++ = nibblechar[uaddr[n] & 0xf];
520 *qp++ = '.';
521 *qp++ = nibblechar[(uaddr[n] >> 4) & 0xf];
522 *qp++ = '.';
524 strcpy(qp, "ip6.arpa");
525 break;
526 default:
527 /* Cannot happen. */
528 break;
531 n = __res_context_query (ctx, qbuf, C_IN, T_PTR, host_buffer.buf->buf,
532 1024, &host_buffer.ptr, NULL, NULL, NULL, NULL);
533 if (n < 0)
535 *h_errnop = h_errno;
536 __set_errno (olderr);
537 if (host_buffer.buf != orig_host_buffer)
538 free (host_buffer.buf);
539 __resolv_context_put (ctx);
540 return errno == ECONNREFUSED ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND;
543 status = getanswer_r
544 (ctx, host_buffer.buf, n, qbuf, T_PTR, result, buffer, buflen,
545 errnop, h_errnop, 0 /* XXX */, ttlp, NULL);
546 if (host_buffer.buf != orig_host_buffer)
547 free (host_buffer.buf);
548 if (status != NSS_STATUS_SUCCESS)
550 __resolv_context_put (ctx);
551 return status;
554 result->h_addrtype = af;
555 result->h_length = len;
556 memcpy (host_data->host_addr, addr, len);
557 host_data->h_addr_ptrs[0] = (char *) host_data->host_addr;
558 host_data->h_addr_ptrs[1] = NULL;
559 *h_errnop = NETDB_SUCCESS;
560 __resolv_context_put (ctx);
561 return NSS_STATUS_SUCCESS;
563 libc_hidden_def (_nss_dns_gethostbyaddr2_r)
566 enum nss_status
567 _nss_dns_gethostbyaddr_r (const void *addr, socklen_t len, int af,
568 struct hostent *result, char *buffer, size_t buflen,
569 int *errnop, int *h_errnop)
571 return _nss_dns_gethostbyaddr2_r (addr, len, af, result, buffer, buflen,
572 errnop, h_errnop, NULL);
574 libc_hidden_def (_nss_dns_gethostbyaddr_r)
576 static void
577 addrsort (struct resolv_context *ctx, char **ap, int num)
579 int i, j;
580 char **p;
581 short aval[MAX_NR_ADDRS];
582 int needsort = 0;
583 size_t nsort = __resolv_context_sort_count (ctx);
585 p = ap;
586 if (num > MAX_NR_ADDRS)
587 num = MAX_NR_ADDRS;
588 for (i = 0; i < num; i++, p++)
590 for (j = 0 ; (unsigned)j < nsort; j++)
592 struct resolv_sortlist_entry e
593 = __resolv_context_sort_entry (ctx, j);
594 if (e.addr.s_addr == (((struct in_addr *)(*p))->s_addr & e.mask))
595 break;
597 aval[i] = j;
598 if (needsort == 0 && i > 0 && j < aval[i-1])
599 needsort = i;
601 if (!needsort)
602 return;
604 while (needsort++ < num)
605 for (j = needsort - 2; j >= 0; j--)
606 if (aval[j] > aval[j+1])
608 char *hp;
610 i = aval[j];
611 aval[j] = aval[j+1];
612 aval[j+1] = i;
614 hp = ap[j];
615 ap[j] = ap[j+1];
616 ap[j+1] = hp;
618 else
619 break;
622 static enum nss_status
623 getanswer_r (struct resolv_context *ctx,
624 const querybuf *answer, int anslen, const char *qname, int qtype,
625 struct hostent *result, char *buffer, size_t buflen,
626 int *errnop, int *h_errnop, int map, int32_t *ttlp, char **canonp)
628 struct host_data
630 char *aliases[MAX_NR_ALIASES];
631 unsigned char host_addr[16]; /* IPv4 or IPv6 */
632 char *h_addr_ptrs[0];
633 } *host_data;
634 int linebuflen;
635 const HEADER *hp;
636 const u_char *end_of_message, *cp;
637 int n, ancount, qdcount;
638 int haveanswer, had_error;
639 char *bp, **ap, **hap;
640 char tbuf[MAXDNAME];
641 const char *tname;
642 int (*name_ok) (const char *);
643 u_char packtmp[NS_MAXCDNAME];
644 int have_to_map = 0;
645 uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct host_data);
646 buffer += pad;
647 buflen = buflen > pad ? buflen - pad : 0;
648 if (__glibc_unlikely (buflen < sizeof (struct host_data)))
650 /* The buffer is too small. */
651 too_small:
652 *errnop = ERANGE;
653 *h_errnop = NETDB_INTERNAL;
654 return NSS_STATUS_TRYAGAIN;
656 host_data = (struct host_data *) buffer;
657 linebuflen = buflen - sizeof (struct host_data);
658 if (buflen - sizeof (struct host_data) != linebuflen)
659 linebuflen = INT_MAX;
661 tname = qname;
662 result->h_name = NULL;
663 end_of_message = answer->buf + anslen;
664 switch (qtype)
666 case T_A:
667 case T_AAAA:
668 name_ok = __libc_res_hnok;
669 break;
670 case T_PTR:
671 name_ok = __libc_res_dnok;
672 break;
673 default:
674 *errnop = ENOENT;
675 return NSS_STATUS_UNAVAIL; /* XXX should be abort(); */
679 * find first satisfactory answer
681 hp = &answer->hdr;
682 ancount = ntohs (hp->ancount);
683 qdcount = ntohs (hp->qdcount);
684 cp = answer->buf + HFIXEDSZ;
685 if (__glibc_unlikely (qdcount != 1))
687 *h_errnop = NO_RECOVERY;
688 return NSS_STATUS_UNAVAIL;
690 if (sizeof (struct host_data) + (ancount + 1) * sizeof (char *) >= buflen)
691 goto too_small;
692 bp = (char *) &host_data->h_addr_ptrs[ancount + 1];
693 linebuflen -= (ancount + 1) * sizeof (char *);
695 n = __ns_name_unpack (answer->buf, end_of_message, cp,
696 packtmp, sizeof packtmp);
697 if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
699 if (__glibc_unlikely (errno == EMSGSIZE))
700 goto too_small;
702 n = -1;
705 if (__glibc_unlikely (n < 0))
707 *errnop = errno;
708 *h_errnop = NO_RECOVERY;
709 return NSS_STATUS_UNAVAIL;
711 if (__glibc_unlikely (name_ok (bp) == 0))
713 errno = EBADMSG;
714 *errnop = EBADMSG;
715 *h_errnop = NO_RECOVERY;
716 return NSS_STATUS_UNAVAIL;
718 cp += n + QFIXEDSZ;
720 if (qtype == T_A || qtype == T_AAAA)
722 /* res_send() has already verified that the query name is the
723 * same as the one we sent; this just gets the expanded name
724 * (i.e., with the succeeding search-domain tacked on).
726 n = strlen (bp) + 1; /* for the \0 */
727 if (n >= MAXHOSTNAMELEN)
729 *h_errnop = NO_RECOVERY;
730 *errnop = ENOENT;
731 return NSS_STATUS_TRYAGAIN;
733 result->h_name = bp;
734 bp += n;
735 linebuflen -= n;
736 if (linebuflen < 0)
737 goto too_small;
738 /* The qname can be abbreviated, but h_name is now absolute. */
739 qname = result->h_name;
742 ap = host_data->aliases;
743 *ap = NULL;
744 result->h_aliases = host_data->aliases;
745 hap = host_data->h_addr_ptrs;
746 *hap = NULL;
747 result->h_addr_list = host_data->h_addr_ptrs;
748 haveanswer = 0;
749 had_error = 0;
751 while (ancount-- > 0 && cp < end_of_message && had_error == 0)
753 int type, class;
755 n = __ns_name_unpack (answer->buf, end_of_message, cp,
756 packtmp, sizeof packtmp);
757 if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
759 if (__glibc_unlikely (errno == EMSGSIZE))
760 goto too_small;
762 n = -1;
765 if (__glibc_unlikely (n < 0 || (*name_ok) (bp) == 0))
767 ++had_error;
768 continue;
770 cp += n; /* name */
772 if (__glibc_unlikely (cp + 10 > end_of_message))
774 ++had_error;
775 continue;
778 NS_GET16 (type, cp);
779 NS_GET16 (class, cp);
780 int32_t ttl;
781 NS_GET32 (ttl, cp);
782 NS_GET16 (n, cp); /* RDATA length. */
784 if (end_of_message - cp < n)
786 /* RDATA extends beyond the end of the packet. */
787 ++had_error;
788 continue;
791 if (__glibc_unlikely (class != C_IN))
793 /* XXX - debug? syslog? */
794 cp += n;
795 continue; /* XXX - had_error++ ? */
798 if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME)
800 /* A CNAME could also have a TTL entry. */
801 if (ttlp != NULL && ttl < *ttlp)
802 *ttlp = ttl;
804 if (ap >= &host_data->aliases[MAX_NR_ALIASES - 1])
805 continue;
806 n = __libc_dn_expand (answer->buf, end_of_message, cp,
807 tbuf, sizeof tbuf);
808 if (__glibc_unlikely (n < 0 || (*name_ok) (tbuf) == 0))
810 ++had_error;
811 continue;
813 cp += n;
814 /* Store alias. */
815 *ap++ = bp;
816 n = strlen (bp) + 1; /* For the \0. */
817 if (__glibc_unlikely (n >= MAXHOSTNAMELEN))
819 ++had_error;
820 continue;
822 bp += n;
823 linebuflen -= n;
824 /* Get canonical name. */
825 n = strlen (tbuf) + 1; /* For the \0. */
826 if (__glibc_unlikely (n > linebuflen))
827 goto too_small;
828 if (__glibc_unlikely (n >= MAXHOSTNAMELEN))
830 ++had_error;
831 continue;
833 result->h_name = bp;
834 bp = __mempcpy (bp, tbuf, n); /* Cannot overflow. */
835 linebuflen -= n;
836 continue;
839 if (qtype == T_PTR && type == T_CNAME)
841 /* A CNAME could also have a TTL entry. */
842 if (ttlp != NULL && ttl < *ttlp)
843 *ttlp = ttl;
845 n = __libc_dn_expand (answer->buf, end_of_message, cp,
846 tbuf, sizeof tbuf);
847 if (__glibc_unlikely (n < 0 || __libc_res_dnok (tbuf) == 0))
849 ++had_error;
850 continue;
852 cp += n;
853 /* Get canonical name. */
854 n = strlen (tbuf) + 1; /* For the \0. */
855 if (__glibc_unlikely (n > linebuflen))
856 goto too_small;
857 if (__glibc_unlikely (n >= MAXHOSTNAMELEN))
859 ++had_error;
860 continue;
862 tname = bp;
863 bp = __mempcpy (bp, tbuf, n); /* Cannot overflow. */
864 linebuflen -= n;
865 continue;
868 if (type == T_A && qtype == T_AAAA && map)
869 have_to_map = 1;
870 else if (__glibc_unlikely (type != qtype))
872 cp += n;
873 continue; /* XXX - had_error++ ? */
876 switch (type)
878 case T_PTR:
879 if (__glibc_unlikely (__strcasecmp (tname, bp) != 0))
881 cp += n;
882 continue; /* XXX - had_error++ ? */
885 n = __ns_name_unpack (answer->buf, end_of_message, cp,
886 packtmp, sizeof packtmp);
887 if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
889 if (__glibc_unlikely (errno == EMSGSIZE))
890 goto too_small;
892 n = -1;
895 if (__glibc_unlikely (n < 0 || __libc_res_hnok (bp) == 0))
897 ++had_error;
898 break;
900 if (ttlp != NULL && ttl < *ttlp)
901 *ttlp = ttl;
902 /* bind would put multiple PTR records as aliases, but we don't do
903 that. */
904 result->h_name = bp;
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))
911 cp += n;
912 continue; /* XXX - had_error++ ? */
915 /* Stop parsing at a record whose length is incorrect. */
916 if (n != rrtype_to_rdata_length (type))
918 ++had_error;
919 break;
922 /* Skip records of the wrong type. */
923 if (n != result->h_length)
925 cp += n;
926 continue;
928 if (!haveanswer)
930 int nn;
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;
945 /* Provide sufficient alignment for both address
946 families. */
947 enum { align = 4 };
948 _Static_assert ((align % __alignof__ (struct in_addr)) == 0,
949 "struct in_addr alignment");
950 _Static_assert ((align % __alignof__ (struct in6_addr)) == 0,
951 "struct in6_addr alignment");
953 char *new_bp = PTR_ALIGN_UP (bp, align);
954 linebuflen -= new_bp - bp;
955 bp = new_bp;
958 if (__glibc_unlikely (n > linebuflen))
959 goto too_small;
960 bp = __mempcpy (*hap++ = bp, cp, n);
961 cp += n;
962 linebuflen -= n;
963 break;
964 default:
965 abort ();
967 if (had_error == 0)
968 ++haveanswer;
971 if (haveanswer > 0)
973 *ap = NULL;
974 *hap = NULL;
976 * Note: we sort even if host can take only one address
977 * in its return structures - should give it the "best"
978 * address in that case, not some random one
980 if (haveanswer > 1 && qtype == T_A
981 && __resolv_context_sort_count (ctx) > 0)
982 addrsort (ctx, host_data->h_addr_ptrs, haveanswer);
984 if (result->h_name == NULL)
986 n = strlen (qname) + 1; /* For the \0. */
987 if (n > linebuflen)
988 goto too_small;
989 if (n >= MAXHOSTNAMELEN)
990 goto no_recovery;
991 result->h_name = bp;
992 bp = __mempcpy (bp, qname, n); /* Cannot overflow. */
993 linebuflen -= n;
996 if (have_to_map)
997 if (map_v4v6_hostent (result, &bp, &linebuflen))
998 goto too_small;
999 *h_errnop = NETDB_SUCCESS;
1000 return NSS_STATUS_SUCCESS;
1002 no_recovery:
1003 *h_errnop = NO_RECOVERY;
1004 *errnop = ENOENT;
1005 /* Special case here: if the resolver sent a result but it only
1006 contains a CNAME while we are looking for a T_A or T_AAAA record,
1007 we fail with NOTFOUND instead of TRYAGAIN. */
1008 return ((qtype == T_A || qtype == T_AAAA) && ap != host_data->aliases
1009 ? NSS_STATUS_NOTFOUND : NSS_STATUS_TRYAGAIN);
1013 static enum nss_status
1014 gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
1015 struct gaih_addrtuple ***patp,
1016 char **bufferp, size_t *buflenp,
1017 int *errnop, int *h_errnop, int32_t *ttlp, int *firstp)
1019 char *buffer = *bufferp;
1020 size_t buflen = *buflenp;
1022 struct gaih_addrtuple **pat = *patp;
1023 const HEADER *hp = &answer->hdr;
1024 int ancount = ntohs (hp->ancount);
1025 int qdcount = ntohs (hp->qdcount);
1026 const u_char *cp = answer->buf + HFIXEDSZ;
1027 const u_char *end_of_message = answer->buf + anslen;
1028 if (__glibc_unlikely (qdcount != 1))
1030 *h_errnop = NO_RECOVERY;
1031 return NSS_STATUS_UNAVAIL;
1034 u_char packtmp[NS_MAXCDNAME];
1035 int n = __ns_name_unpack (answer->buf, end_of_message, cp,
1036 packtmp, sizeof packtmp);
1037 /* We unpack the name to check it for validity. But we do not need
1038 it later. */
1039 if (n != -1 && __ns_name_ntop (packtmp, buffer, buflen) == -1)
1041 if (__glibc_unlikely (errno == EMSGSIZE))
1043 too_small:
1044 *errnop = ERANGE;
1045 *h_errnop = NETDB_INTERNAL;
1046 return NSS_STATUS_TRYAGAIN;
1049 n = -1;
1052 if (__glibc_unlikely (n < 0))
1054 *errnop = errno;
1055 *h_errnop = NO_RECOVERY;
1056 return NSS_STATUS_UNAVAIL;
1058 if (__glibc_unlikely (__libc_res_hnok (buffer) == 0))
1060 errno = EBADMSG;
1061 *errnop = EBADMSG;
1062 *h_errnop = NO_RECOVERY;
1063 return NSS_STATUS_UNAVAIL;
1065 cp += n + QFIXEDSZ;
1067 int haveanswer = 0;
1068 int had_error = 0;
1069 char *canon = NULL;
1070 char *h_name = NULL;
1071 int h_namelen = 0;
1073 if (ancount == 0)
1075 *h_errnop = HOST_NOT_FOUND;
1076 return NSS_STATUS_NOTFOUND;
1079 while (ancount-- > 0 && cp < end_of_message && had_error == 0)
1081 n = __ns_name_unpack (answer->buf, end_of_message, cp,
1082 packtmp, sizeof packtmp);
1083 if (n != -1 &&
1084 (h_namelen = __ns_name_ntop (packtmp, buffer, buflen)) == -1)
1086 if (__glibc_unlikely (errno == EMSGSIZE))
1087 goto too_small;
1089 n = -1;
1091 if (__glibc_unlikely (n < 0 || __libc_res_hnok (buffer) == 0))
1093 ++had_error;
1094 continue;
1096 if (*firstp && canon == NULL)
1098 h_name = buffer;
1099 buffer += h_namelen;
1100 buflen -= h_namelen;
1103 cp += n; /* name */
1105 if (__glibc_unlikely (cp + 10 > end_of_message))
1107 ++had_error;
1108 continue;
1111 uint16_t type;
1112 NS_GET16 (type, cp);
1113 uint16_t class;
1114 NS_GET16 (class, cp);
1115 int32_t ttl;
1116 NS_GET32 (ttl, cp);
1117 NS_GET16 (n, cp); /* RDATA length. */
1119 if (end_of_message - cp < n)
1121 /* RDATA extends beyond the end of the packet. */
1122 ++had_error;
1123 continue;
1126 if (class != C_IN)
1128 cp += n;
1129 continue;
1132 if (type == T_CNAME)
1134 char tbuf[MAXDNAME];
1136 /* A CNAME could also have a TTL entry. */
1137 if (ttlp != NULL && ttl < *ttlp)
1138 *ttlp = ttl;
1140 n = __libc_dn_expand (answer->buf, end_of_message, cp,
1141 tbuf, sizeof tbuf);
1142 if (__glibc_unlikely (n < 0 || __libc_res_hnok (tbuf) == 0))
1144 ++had_error;
1145 continue;
1147 cp += n;
1149 if (*firstp)
1151 /* Reclaim buffer space. */
1152 if (h_name + h_namelen == buffer)
1154 buffer = h_name;
1155 buflen += h_namelen;
1158 n = strlen (tbuf) + 1;
1159 if (__glibc_unlikely (n > buflen))
1160 goto too_small;
1161 if (__glibc_unlikely (n >= MAXHOSTNAMELEN))
1163 ++had_error;
1164 continue;
1167 canon = buffer;
1168 buffer = __mempcpy (buffer, tbuf, n);
1169 buflen -= n;
1170 h_namelen = 0;
1172 continue;
1175 /* Stop parsing if we encounter a record with incorrect RDATA
1176 length. */
1177 if (type == T_A || type == T_AAAA)
1179 if (n != rrtype_to_rdata_length (type))
1181 ++had_error;
1182 continue;
1185 else
1187 /* Skip unknown records. */
1188 cp += n;
1189 continue;
1192 assert (type == T_A || type == T_AAAA);
1193 if (*pat == NULL)
1195 uintptr_t pad = (-(uintptr_t) buffer
1196 % __alignof__ (struct gaih_addrtuple));
1197 buffer += pad;
1198 buflen = buflen > pad ? buflen - pad : 0;
1200 if (__glibc_unlikely (buflen < sizeof (struct gaih_addrtuple)))
1201 goto too_small;
1203 *pat = (struct gaih_addrtuple *) buffer;
1204 buffer += sizeof (struct gaih_addrtuple);
1205 buflen -= sizeof (struct gaih_addrtuple);
1208 (*pat)->name = NULL;
1209 (*pat)->next = NULL;
1211 if (*firstp)
1213 /* We compose a single hostent out of the entire chain of
1214 entries, so the TTL of the hostent is essentially the lowest
1215 TTL in the chain. */
1216 if (ttlp != NULL && ttl < *ttlp)
1217 *ttlp = ttl;
1219 (*pat)->name = canon ?: h_name;
1221 *firstp = 0;
1224 (*pat)->family = type == T_A ? AF_INET : AF_INET6;
1225 memcpy ((*pat)->addr, cp, n);
1226 cp += n;
1227 (*pat)->scopeid = 0;
1229 pat = &((*pat)->next);
1231 haveanswer = 1;
1234 if (haveanswer)
1236 *patp = pat;
1237 *bufferp = buffer;
1238 *buflenp = buflen;
1240 *h_errnop = NETDB_SUCCESS;
1241 return NSS_STATUS_SUCCESS;
1244 /* Special case here: if the resolver sent a result but it only
1245 contains a CNAME while we are looking for a T_A or T_AAAA record,
1246 we fail with NOTFOUND instead of TRYAGAIN. */
1247 if (canon != NULL)
1249 *h_errnop = HOST_NOT_FOUND;
1250 return NSS_STATUS_NOTFOUND;
1253 *h_errnop = NETDB_INTERNAL;
1254 return NSS_STATUS_TRYAGAIN;
1258 static enum nss_status
1259 gaih_getanswer (const querybuf *answer1, int anslen1, const querybuf *answer2,
1260 int anslen2, const char *qname,
1261 struct gaih_addrtuple **pat, char *buffer, size_t buflen,
1262 int *errnop, int *h_errnop, int32_t *ttlp)
1264 int first = 1;
1266 enum nss_status status = NSS_STATUS_NOTFOUND;
1268 /* Combining the NSS status of two distinct queries requires some
1269 compromise and attention to symmetry (A or AAAA queries can be
1270 returned in any order). What follows is a breakdown of how this
1271 code is expected to work and why. We discuss only SUCCESS,
1272 TRYAGAIN, NOTFOUND and UNAVAIL, since they are the only returns
1273 that apply (though RETURN and MERGE exist). We make a distinction
1274 between TRYAGAIN (recoverable) and TRYAGAIN' (not-recoverable).
1275 A recoverable TRYAGAIN is almost always due to buffer size issues
1276 and returns ERANGE in errno and the caller is expected to retry
1277 with a larger buffer.
1279 Lastly, you may be tempted to make significant changes to the
1280 conditions in this code to bring about symmetry between responses.
1281 Please don't change anything without due consideration for
1282 expected application behaviour. Some of the synthesized responses
1283 aren't very well thought out and sometimes appear to imply that
1284 IPv4 responses are always answer 1, and IPv6 responses are always
1285 answer 2, but that's not true (see the implementation of send_dg
1286 and send_vc to see response can arrive in any order, particularly
1287 for UDP). However, we expect it holds roughly enough of the time
1288 that this code works, but certainly needs to be fixed to make this
1289 a more robust implementation.
1291 ----------------------------------------------
1292 | Answer 1 Status / | Synthesized | Reason |
1293 | Answer 2 Status | Status | |
1294 |--------------------------------------------|
1295 | SUCCESS/SUCCESS | SUCCESS | [1] |
1296 | SUCCESS/TRYAGAIN | TRYAGAIN | [5] |
1297 | SUCCESS/TRYAGAIN' | SUCCESS | [1] |
1298 | SUCCESS/NOTFOUND | SUCCESS | [1] |
1299 | SUCCESS/UNAVAIL | SUCCESS | [1] |
1300 | TRYAGAIN/SUCCESS | TRYAGAIN | [2] |
1301 | TRYAGAIN/TRYAGAIN | TRYAGAIN | [2] |
1302 | TRYAGAIN/TRYAGAIN' | TRYAGAIN | [2] |
1303 | TRYAGAIN/NOTFOUND | TRYAGAIN | [2] |
1304 | TRYAGAIN/UNAVAIL | TRYAGAIN | [2] |
1305 | TRYAGAIN'/SUCCESS | SUCCESS | [3] |
1306 | TRYAGAIN'/TRYAGAIN | TRYAGAIN | [3] |
1307 | TRYAGAIN'/TRYAGAIN' | TRYAGAIN' | [3] |
1308 | TRYAGAIN'/NOTFOUND | TRYAGAIN' | [3] |
1309 | TRYAGAIN'/UNAVAIL | UNAVAIL | [3] |
1310 | NOTFOUND/SUCCESS | SUCCESS | [3] |
1311 | NOTFOUND/TRYAGAIN | TRYAGAIN | [3] |
1312 | NOTFOUND/TRYAGAIN' | TRYAGAIN' | [3] |
1313 | NOTFOUND/NOTFOUND | NOTFOUND | [3] |
1314 | NOTFOUND/UNAVAIL | UNAVAIL | [3] |
1315 | UNAVAIL/SUCCESS | UNAVAIL | [4] |
1316 | UNAVAIL/TRYAGAIN | UNAVAIL | [4] |
1317 | UNAVAIL/TRYAGAIN' | UNAVAIL | [4] |
1318 | UNAVAIL/NOTFOUND | UNAVAIL | [4] |
1319 | UNAVAIL/UNAVAIL | UNAVAIL | [4] |
1320 ----------------------------------------------
1322 [1] If the first response is a success we return success.
1323 This ignores the state of the second answer and in fact
1324 incorrectly sets errno and h_errno to that of the second
1325 answer. However because the response is a success we ignore
1326 *errnop and *h_errnop (though that means you touched errno on
1327 success). We are being conservative here and returning the
1328 likely IPv4 response in the first answer as a success.
1330 [2] If the first response is a recoverable TRYAGAIN we return
1331 that instead of looking at the second response. The
1332 expectation here is that we have failed to get an IPv4 response
1333 and should retry both queries.
1335 [3] If the first response was not a SUCCESS and the second
1336 response is not NOTFOUND (had a SUCCESS, need to TRYAGAIN,
1337 or failed entirely e.g. TRYAGAIN' and UNAVAIL) then use the
1338 result from the second response, otherwise the first responses
1339 status is used. Again we have some odd side-effects when the
1340 second response is NOTFOUND because we overwrite *errnop and
1341 *h_errnop that means that a first answer of NOTFOUND might see
1342 its *errnop and *h_errnop values altered. Whether it matters
1343 in practice that a first response NOTFOUND has the wrong
1344 *errnop and *h_errnop is undecided.
1346 [4] If the first response is UNAVAIL we return that instead of
1347 looking at the second response. The expectation here is that
1348 it will have failed similarly e.g. configuration failure.
1350 [5] Testing this code is complicated by the fact that truncated
1351 second response buffers might be returned as SUCCESS if the
1352 first answer is a SUCCESS. To fix this we add symmetry to
1353 TRYAGAIN with the second response. If the second response
1354 is a recoverable error we now return TRYAGIN even if the first
1355 response was SUCCESS. */
1357 if (anslen1 > 0)
1358 status = gaih_getanswer_slice(answer1, anslen1, qname,
1359 &pat, &buffer, &buflen,
1360 errnop, h_errnop, ttlp,
1361 &first);
1363 if ((status == NSS_STATUS_SUCCESS || status == NSS_STATUS_NOTFOUND
1364 || (status == NSS_STATUS_TRYAGAIN
1365 /* We want to look at the second answer in case of an
1366 NSS_STATUS_TRYAGAIN only if the error is non-recoverable, i.e.
1367 *h_errnop is NO_RECOVERY. If not, and if the failure was due to
1368 an insufficient buffer (ERANGE), then we need to drop the results
1369 and pass on the NSS_STATUS_TRYAGAIN to the caller so that it can
1370 repeat the query with a larger buffer. */
1371 && (*errnop != ERANGE || *h_errnop == NO_RECOVERY)))
1372 && answer2 != NULL && anslen2 > 0)
1374 enum nss_status status2 = gaih_getanswer_slice(answer2, anslen2, qname,
1375 &pat, &buffer, &buflen,
1376 errnop, h_errnop, ttlp,
1377 &first);
1378 /* Use the second response status in some cases. */
1379 if (status != NSS_STATUS_SUCCESS && status2 != NSS_STATUS_NOTFOUND)
1380 status = status2;
1381 /* Do not return a truncated second response (unless it was
1382 unavoidable e.g. unrecoverable TRYAGAIN). */
1383 if (status == NSS_STATUS_SUCCESS
1384 && (status2 == NSS_STATUS_TRYAGAIN
1385 && *errnop == ERANGE && *h_errnop != NO_RECOVERY))
1386 status = NSS_STATUS_TRYAGAIN;
1389 return status;