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