]> git.ipfire.org Git - thirdparty/glibc.git/blame - resolv/nss_dns/dns-host.c
Update.
[thirdparty/glibc.git] / resolv / nss_dns / dns-host.c
CommitLineData
b455972f 1/* Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
84384f5b
UD
2 This file is part of the GNU C Library.
3 Extended from original form by Ulrich Drepper <drepper@cygnus.com>, 1996.
5f0e6fc7 4
84384f5b
UD
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
5f0e6fc7 9
84384f5b
UD
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 Library General Public License for more details.
5f0e6fc7 14
84384f5b
UD
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
5f0e6fc7 19
df21c858 20/* Parts of this file are plain copies of the file `gethtnamadr.c' from
5f0e6fc7
RM
21 the bind package and it has the following copyright. */
22
5f0e6fc7 23/*
df21c858
UD
24 * ++Copyright++ 1985, 1988, 1993
25 * -
26 * Copyright (c) 1985, 1988, 1993
27 * The Regents of the University of California. All rights reserved.
5f0e6fc7
RM
28 *
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
31 * are met:
32 * 1. Redistributions of source code must retain the above copyright
33 * notice, this list of conditions and the following disclaimer.
34 * 2. Redistributions in binary form must reproduce the above copyright
35 * notice, this list of conditions and the following disclaimer in the
36 * documentation and/or other materials provided with the distribution.
5f0e6fc7
RM
37 * 4. Neither the name of the University nor the names of its contributors
38 * may be used to endorse or promote products derived from this software
39 * without specific prior written permission.
40 *
41 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 * SUCH DAMAGE.
df21c858
UD
52 * -
53 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
54 *
55 * Permission to use, copy, modify, and distribute this software for any
56 * purpose with or without fee is hereby granted, provided that the above
57 * copyright notice and this permission notice appear in all copies, and that
58 * the name of Digital Equipment Corporation not be used in advertising or
59 * publicity pertaining to distribution of the document or software without
60 * specific, written prior permission.
61 *
62 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
63 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
64 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
65 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
66 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
67 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
68 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
69 * SOFTWARE.
70 * -
71 * --Copyright--
5f0e6fc7
RM
72 */
73
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
5f0e6fc7
RM
83#include "nsswitch.h"
84
85/* Get implementation for some internal functions. */
da2d1bc5
UD
86#include <resolv/mapv4v6addr.h>
87#include <resolv/mapv4v6hostent.h>
5f0e6fc7
RM
88
89/* Maximum number of aliases we allow. */
90#define MAX_NR_ALIASES 48
91#define MAX_NR_ADDRS 48
92
93#if PACKETSZ > 1024
94# define MAXPACKET PACKETSZ
95#else
96# define MAXPACKET 1024
97#endif
1522c368
UD
98/* As per RFC 1034 and 1035 a host name cannot exceed 255 octets in length. */
99#ifdef MAXHOSTNAMELEN
100# undef MAXHOSTNAMELEN
101#endif
102#define MAXHOSTNAMELEN 256
5f0e6fc7
RM
103
104static const char AskedForGot[] = "\
105gethostby*.getanswer: asked for \"%s\", got \"%s\"";
106
107
108/* We need this time later. */
109typedef union querybuf
110{
111 HEADER hdr;
112 u_char buf[MAXPACKET];
113} querybuf;
114
8d8c6efa
UD
115/* These functions are defined in res_comp.c. */
116#define NS_MAXCDNAME 255 /* maximum compressed domain name */
b455972f
UD
117extern int __ns_name_ntop (const u_char *, char *, size_t);
118extern int __ns_name_unpack (const u_char *, const u_char *,
119 const u_char *, u_char *, size_t);
8d8c6efa 120
5f0e6fc7
RM
121
122static enum nss_status getanswer_r (const querybuf *answer, int anslen,
123 const char *qname, int qtype,
df4ef2ab 124 struct hostent *result, char *buffer,
b455972f
UD
125 size_t buflen, int *errnop, int *h_errnop,
126 int map);
5f0e6fc7
RM
127
128enum nss_status
129_nss_dns_gethostbyname2_r (const char *name, int af, struct hostent *result,
67479a70
UD
130 char *buffer, size_t buflen, int *errnop,
131 int *h_errnop)
5f0e6fc7 132{
5f0e6fc7 133 querybuf host_buffer;
f80f1a4a 134 char tmp[NS_MAXDNAME];
5f0e6fc7
RM
135 int size, type, n;
136 const char *cp;
b455972f 137 int map = 0;
5f0e6fc7 138
b43b13ac
UD
139 if ((_res.options & RES_INIT) == 0 && __res_ninit (&_res) == -1)
140 return NSS_STATUS_UNAVAIL;
141
5f0e6fc7
RM
142 switch (af) {
143 case AF_INET:
144 size = INADDRSZ;
145 type = T_A;
146 break;
147 case AF_INET6:
148 size = IN6ADDRSZ;
149 type = T_AAAA;
150 break;
151 default:
0cc70fcf 152 *h_errnop = NO_DATA;
67479a70 153 *errnop = EAFNOSUPPORT;
5f0e6fc7
RM
154 return NSS_STATUS_UNAVAIL;
155 }
156
157 result->h_addrtype = af;
158 result->h_length = size;
159
160 /*
161 * if there aren't any dots, it could be a user-level alias.
162 * this is also done in res_query() since we are not the only
163 * function that looks up host names.
164 */
f80f1a4a
UD
165 if (strchr (name, '.') == NULL
166 && (cp = res_hostalias (&_res, name, tmp, sizeof (tmp))) != NULL)
5f0e6fc7
RM
167 name = cp;
168
b43b13ac
UD
169 n = res_nsearch (&_res, name, C_IN, type, host_buffer.buf,
170 sizeof (host_buffer.buf));
5f0e6fc7 171 if (n < 0)
dd7d45e8 172 {
b455972f
UD
173 enum nss_status status = (errno == ECONNREFUSED
174 ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND);
dd7d45e8 175 *h_errnop = h_errno;
b455972f
UD
176 *errnop = h_errno == TRY_AGAIN ? EAGAIN : ENOENT;
177
178 /* If we are looking for a IPv6 address and mapping is enabled
179 by having the RES_USE_INET6 bit in _res.options set, we try
180 another lookup. */
181 if (af == AF_INET6 && (_res.options & RES_USE_INET6))
182 n = res_nsearch (&_res, name, C_IN, T_A, host_buffer.buf,
183 sizeof (host_buffer.buf));
184
185 if (n < 0)
186 return status;
187
188 map = 1;
189
190 result->h_addrtype = AF_INET;
191 result->h_length = INADDRSZ;;
dd7d45e8 192 }
5f0e6fc7
RM
193
194 return getanswer_r (&host_buffer, n, name, type, result, buffer, buflen,
b455972f 195 errnop, h_errnop, map);
5f0e6fc7
RM
196}
197
198
199enum nss_status
200_nss_dns_gethostbyname_r (const char *name, struct hostent *result,
67479a70
UD
201 char *buffer, size_t buflen, int *errnop,
202 int *h_errnop)
5f0e6fc7
RM
203{
204 enum nss_status status = NSS_STATUS_NOTFOUND;
205
206 if (_res.options & RES_USE_INET6)
207 status = _nss_dns_gethostbyname2_r (name, AF_INET6, result, buffer,
67479a70 208 buflen, errnop, h_errnop);
5f0e6fc7
RM
209 if (status == NSS_STATUS_NOTFOUND)
210 status = _nss_dns_gethostbyname2_r (name, AF_INET, result, buffer,
67479a70 211 buflen, errnop, h_errnop);
5f0e6fc7
RM
212
213 return status;
214}
215
216
217enum nss_status
51eecc4a 218_nss_dns_gethostbyaddr_r (const void *addr, socklen_t len, int af,
df4ef2ab 219 struct hostent *result, char *buffer, size_t buflen,
67479a70 220 int *errnop, int *h_errnop)
5f0e6fc7
RM
221{
222 static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
223 static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
20cc4c87 224 static const u_char v6local[] = { 0,0, 0,1 };
5f0e6fc7
RM
225 const u_char *uaddr = (const u_char *)addr;
226 struct host_data
227 {
228 char *aliases[MAX_NR_ALIASES];
229 unsigned char host_addr[16]; /* IPv4 or IPv6 */
230 char *h_addr_ptrs[MAX_NR_ADDRS + 1];
231 char linebuffer[0];
232 } *host_data = (struct host_data *) buffer;
233 querybuf host_buffer;
234 char qbuf[MAXDNAME+1], *qp;
30f22ab1
UD
235 size_t size;
236 int n, status;
5f0e6fc7 237
b43b13ac
UD
238 if ((_res.options & RES_INIT) == 0 && __res_ninit (&_res) == -1)
239 return NSS_STATUS_UNAVAIL;
240
20cc4c87
UD
241 if (af == AF_INET6 && len == IN6ADDRSZ
242 && (memcmp (uaddr, mapped, sizeof mapped) == 0
243 || (memcmp (uaddr, tunnelled, sizeof tunnelled) == 0
244 && memcmp (&uaddr[sizeof tunnelled], v6local, sizeof v6local))))
5f0e6fc7
RM
245 {
246 /* Unmap. */
247 addr += sizeof mapped;
248 uaddr += sizeof mapped;
249 af = AF_INET;
250 len = INADDRSZ;
251 }
252
253 switch (af)
254 {
255 case AF_INET:
256 size = INADDRSZ;
257 break;
258 case AF_INET6:
259 size = IN6ADDRSZ;
260 break;
261 default:
67479a70 262 *errnop = EAFNOSUPPORT;
5f0e6fc7
RM
263 *h_errnop = NETDB_INTERNAL;
264 return NSS_STATUS_UNAVAIL;
265 }
20cc4c87 266 if (size > len)
5f0e6fc7 267 {
67479a70 268 *errnop = EAFNOSUPPORT;
5f0e6fc7
RM
269 *h_errnop = NETDB_INTERNAL;
270 return NSS_STATUS_UNAVAIL;
271 }
272
273 switch (af)
274 {
275 case AF_INET:
276 sprintf (qbuf, "%u.%u.%u.%u.in-addr.arpa", (uaddr[3] & 0xff),
277 (uaddr[2] & 0xff), (uaddr[1] & 0xff), (uaddr[0] & 0xff));
278 break;
279 case AF_INET6:
280 qp = qbuf;
281 for (n = IN6ADDRSZ - 1; n >= 0; n--)
282 qp += sprintf (qp, "%x.%x.", uaddr[n] & 0xf, (uaddr[n] >> 4) & 0xf);
da2d1bc5 283 strcpy (qp, "ip6.int");
5f0e6fc7
RM
284 break;
285 default:
286 /* Cannot happen. */
9fea9ed6 287 break;
5f0e6fc7
RM
288 }
289
b43b13ac
UD
290 n = res_nquery (&_res, qbuf, C_IN, T_PTR, (u_char *)host_buffer.buf,
291 sizeof host_buffer);
5f0e6fc7 292 if (n < 0)
dd7d45e8
UD
293 {
294 *h_errnop = h_errno;
67479a70 295 *errnop = errno;
dd7d45e8
UD
296 return errno == ECONNREFUSED ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND;
297 }
5f0e6fc7
RM
298
299 status = getanswer_r (&host_buffer, n, qbuf, T_PTR, result, buffer, buflen,
b455972f 300 errnop, h_errnop, 0 /* XXX */);
5f0e6fc7 301 if (status != NSS_STATUS_SUCCESS)
dd7d45e8
UD
302 {
303 *h_errnop = h_errno;
67479a70 304 *errnop = errno;
dd7d45e8
UD
305 return status;
306 }
5f0e6fc7
RM
307
308#ifdef SUNSECURITY
309 This is not implemented because it is not possible to use the current
310 source from bind in a multi-threaded program.
311#endif
312
313 result->h_addrtype = af;
314 result->h_length = len;
63551311 315 memcpy (host_data->host_addr, addr, len);
5f0e6fc7
RM
316 host_data->h_addr_ptrs[0] = (char *) host_data->host_addr;
317 host_data->h_addr_ptrs[1] = NULL;
b455972f
UD
318#if 0
319 /* XXX I think this is wrong. Why should an IPv4 address be
320 converted to IPv6 if the user explicitly asked for IPv4? */
5f0e6fc7
RM
321 if (af == AF_INET && (_res.options & RES_USE_INET6))
322 {
323 map_v4v6_address ((char *) host_data->host_addr,
324 (char *) host_data->host_addr);
325 result->h_addrtype = AF_INET6;
326 result->h_length = IN6ADDRSZ;
327 }
b455972f 328#endif
5f0e6fc7
RM
329 *h_errnop = NETDB_SUCCESS;
330 return NSS_STATUS_SUCCESS;
331}
332
333
334static enum nss_status
335getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
df4ef2ab 336 struct hostent *result, char *buffer, size_t buflen,
b455972f 337 int *errnop, int *h_errnop, int map)
5f0e6fc7
RM
338{
339 struct host_data
340 {
341 char *aliases[MAX_NR_ALIASES];
342 unsigned char host_addr[16]; /* IPv4 or IPv6 */
343 char *h_addr_ptrs[MAX_NR_ADDRS + 1];
344 char linebuffer[0];
345 } *host_data = (struct host_data *) buffer;
346 int linebuflen = buflen - offsetof (struct host_data, linebuffer);
347 register const HEADER *hp;
348 const u_char *end_of_message, *cp;
349 int n, ancount, qdcount;
350 int haveanswer, had_error;
351 char *bp, **ap, **hap;
845dcb57 352 char tbuf[MAXDNAME];
5f0e6fc7 353 const char *tname;
b455972f 354 int (*name_ok) (const char *);
8d8c6efa 355 u_char packtmp[NS_MAXCDNAME];
b455972f 356 int have_to_map = 0;
5f0e6fc7 357
b455972f 358 if (__builtin_expect (linebuflen, 0) < 0)
560d3b76
UD
359 {
360 /* The buffer is too small. */
361 too_small:
362 *errnop = ERANGE;
363 *h_errnop = NETDB_INTERNAL;
364 return NSS_STATUS_TRYAGAIN;
365 }
366
5f0e6fc7
RM
367 tname = qname;
368 result->h_name = NULL;
369 end_of_message = answer->buf + anslen;
370 switch (qtype)
371 {
372 case T_A:
373 case T_AAAA:
374 name_ok = res_hnok;
375 break;
376 case T_PTR:
377 name_ok = res_dnok;
378 break;
379 default:
a0bf6ac7 380 *errnop = ENOENT;
5f0e6fc7
RM
381 return NSS_STATUS_UNAVAIL; /* XXX should be abort(); */
382 }
383
384 /*
385 * find first satisfactory answer
386 */
387 hp = &answer->hdr;
388 bp = host_data->linebuffer;
389 ancount = ntohs (hp->ancount);
390 qdcount = ntohs (hp->qdcount);
391 cp = answer->buf + HFIXEDSZ;
b455972f 392 if (__builtin_expect (qdcount, 1) != 1)
5f0e6fc7
RM
393 {
394 *h_errnop = NO_RECOVERY;
a0bf6ac7 395 *errnop = ENOENT;
5f0e6fc7
RM
396 return NSS_STATUS_UNAVAIL;
397 }
398
8d8c6efa
UD
399 n = __ns_name_unpack (answer->buf, end_of_message, cp,
400 packtmp, sizeof packtmp);
401 if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
5f0e6fc7 402 {
b455972f 403 if (__builtin_expect (errno, 0) == EMSGSIZE)
560d3b76 404 goto too_small;
8d8c6efa
UD
405
406 n = -1;
407 }
408
409 if (n > 0 && bp[0] == '.')
410 bp[0] = '\0';
411
412 if (n < 0 || (*name_ok) (bp) == 0)
413 {
414 *errnop = errno;
415 *h_errnop = NO_RECOVERY;
5f0e6fc7
RM
416 return NSS_STATUS_UNAVAIL;
417 }
418 cp += n + QFIXEDSZ;
419
420 if (qtype == T_A || qtype == T_AAAA)
421 {
422 /* res_send() has already verified that the query name is the
423 * same as the one we sent; this just gets the expanded name
424 * (i.e., with the succeeding search-domain tacked on).
425 */
426 n = strlen (bp) + 1; /* for the \0 */
76b87c03
UD
427 if (n >= MAXHOSTNAMELEN)
428 {
67479a70 429 *h_errnop = NO_RECOVERY;
a0bf6ac7 430 *errnop = ENOENT;
76b87c03
UD
431 return NSS_STATUS_TRYAGAIN;
432 }
5f0e6fc7
RM
433 result->h_name = bp;
434 bp += n;
435 linebuflen -= n;
560d3b76
UD
436 if (linebuflen < 0)
437 goto too_small;
5f0e6fc7
RM
438 /* The qname can be abbreviated, but h_name is now absolute. */
439 qname = result->h_name;
440 }
441
442 ap = host_data->aliases;
443 *ap = NULL;
444 result->h_aliases = host_data->aliases;
445 hap = host_data->h_addr_ptrs;
446 *hap = NULL;
447 result->h_addr_list = host_data->h_addr_ptrs;
448 haveanswer = 0;
449 had_error = 0;
450
451 while (ancount-- > 0 && cp < end_of_message && had_error == 0)
452 {
453 int type, class;
454
8d8c6efa
UD
455 n = __ns_name_unpack (answer->buf, end_of_message, cp,
456 packtmp, sizeof packtmp);
457 if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
458 {
b455972f 459 if (__builtin_expect (errno, 0) == EMSGSIZE)
0cc70fcf 460 goto too_small;
8d8c6efa
UD
461
462 n = -1;
463 }
464
5f0e6fc7
RM
465 if (n < 0 || (*name_ok) (bp) == 0)
466 {
467 ++had_error;
468 continue;
469 }
470 cp += n; /* name */
b43b13ac 471 type = ns_get16 (cp);
5f0e6fc7 472 cp += INT16SZ; /* type */
b43b13ac 473 class = ns_get16 (cp);
5f0e6fc7 474 cp += INT16SZ + INT32SZ; /* class, TTL */
b43b13ac 475 n = ns_get16 (cp);
5f0e6fc7
RM
476 cp += INT16SZ; /* len */
477 if (class != C_IN)
478 {
479 /* XXX - debug? syslog? */
480 cp += n;
481 continue; /* XXX - had_error++ ? */
482 }
483
484 if ((qtype ==T_A || qtype == T_AAAA) && type == T_CNAME)
485 {
486 if (ap >= &host_data->aliases[MAX_NR_ALIASES - 1])
487 continue;
488 n = dn_expand (answer->buf, end_of_message, cp, tbuf, sizeof tbuf);
489 if (n < 0 || (*name_ok) (tbuf) == 0)
490 {
491 ++had_error;
492 continue;
493 }
494 cp += n;
495 /* Store alias. */
496 *ap++ = bp;
497 n = strlen (bp) + 1; /* For the \0. */
b455972f 498 if (__builtin_expect (n, 0) >= MAXHOSTNAMELEN)
76b87c03
UD
499 {
500 ++had_error;
501 continue;
502 }
5f0e6fc7
RM
503 bp += n;
504 linebuflen -= n;
505 /* Get canonical name. */
506 n = strlen (tbuf) + 1; /* For the \0. */
b455972f 507 if (__builtin_expect (n > linebuflen, 0))
0cc70fcf 508 goto too_small;
b455972f 509 if (__builtin_expect (n, 0) >= MAXHOSTNAMELEN)
5f0e6fc7
RM
510 {
511 ++had_error;
512 continue;
513 }
8d8c6efa
UD
514 result->h_name = bp;
515 bp = __mempcpy (bp, tbuf, n); /* Cannot overflow. */
5f0e6fc7
RM
516 linebuflen -= n;
517 continue;
518 }
519
520 if (qtype == T_PTR && type == T_CNAME)
521 {
522 n = dn_expand (answer->buf, end_of_message, cp, tbuf, sizeof tbuf);
da2d1bc5 523 if (n < 0 || res_dnok (tbuf) == 0)
5f0e6fc7
RM
524 {
525 ++had_error;
526 continue;
527 }
528 cp += n;
da2d1bc5 529 /* Get canonical name. */
5f0e6fc7 530 n = strlen (tbuf) + 1; /* For the \0. */
b455972f 531 if (__builtin_expect (n > linebuflen, 0))
0cc70fcf 532 goto too_small;
b455972f 533 if (__builtin_expect (n, 0) >= MAXHOSTNAMELEN)
5f0e6fc7
RM
534 {
535 ++had_error;
536 continue;
537 }
8d8c6efa
UD
538 tname = bp;
539 bp = __mempcpy (bp, tbuf, n); /* Cannot overflow. */
5f0e6fc7
RM
540 linebuflen -= n;
541 continue;
542 }
b455972f
UD
543 if (__builtin_expect (type == T_SIG, 0)
544 || __builtin_expect (type == T_KEY, 0)
545 || __builtin_expect (type == T_NXT, 0))
1bc21e7a
UD
546 {
547 /* We don't support DNSSEC yet. For now, ignore the record
548 and send a low priority message to syslog. */
549 syslog (LOG_DEBUG | LOG_AUTH,
550 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
551 qname, p_class (C_IN), p_type(qtype), p_type (type));
552 cp += n;
553 continue;
554 }
b455972f
UD
555
556 if (type == T_A && qtype == T_AAAA && map)
557 have_to_map = 1;
558 else if (__builtin_expect (type != qtype, 0))
5f0e6fc7
RM
559 {
560 syslog (LOG_NOTICE | LOG_AUTH,
561 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
562 qname, p_class (C_IN), p_type (qtype), p_type (type));
563 cp += n;
564 continue; /* XXX - had_error++ ? */
565 }
566
567 switch (type)
568 {
569 case T_PTR:
8d8c6efa 570 if (__strcasecmp (tname, bp) != 0)
5f0e6fc7
RM
571 {
572 syslog (LOG_NOTICE | LOG_AUTH, AskedForGot, qname, bp);
573 cp += n;
574 continue; /* XXX - had_error++ ? */
575 }
8d8c6efa
UD
576
577 n = __ns_name_unpack (answer->buf, end_of_message, cp,
578 packtmp, sizeof packtmp);
579 if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
580 {
b455972f 581 if (__builtin_expect (errno, 0) == EMSGSIZE)
0cc70fcf 582 goto too_small;
8d8c6efa
UD
583
584 n = -1;
585 }
586
5f0e6fc7
RM
587 if (n < 0 || res_hnok (bp) == 0)
588 {
589 ++had_error;
590 break;
591 }
592#if MULTI_PTRS_ARE_ALIASES
593 cp += n;
594 if (haveanswer == 0)
595 result->h_name = bp;
596 else if (ap < &host_data->aliases[MAXALIASES-1])
597 *ap++ = bp;
598 else
599 n = -1;
600 if (n != -1)
601 {
602 n = strlen (bp) + 1; /* for the \0 */
b455972f 603 if (__builtin_expect (n, 0) >= MAXHOSTNAMELEN)
76b87c03
UD
604 {
605 ++had_error;
606 break;
607 }
5f0e6fc7
RM
608 bp += n;
609 linebuflen -= n;
610 }
611 break;
612#else
613 result->h_name = bp;
b455972f 614 if (have_to_map)
5f0e6fc7
RM
615 {
616 n = strlen (bp) + 1; /* for the \0 */
76b87c03
UD
617 if (n >= MAXHOSTNAMELEN)
618 {
619 ++had_error;
620 break;
621 }
5f0e6fc7
RM
622 bp += n;
623 linebuflen -= n;
624 map_v4v6_hostent (result, &bp, &linebuflen);
625 }
626 *h_errnop = NETDB_SUCCESS;
627 return NSS_STATUS_SUCCESS;
628#endif
629 case T_A:
630 case T_AAAA:
b455972f 631 if (__builtin_expect (strcasecmp (result->h_name, bp), 0) != 0)
5f0e6fc7
RM
632 {
633 syslog (LOG_NOTICE | LOG_AUTH, AskedForGot, result->h_name, bp);
634 cp += n;
635 continue; /* XXX - had_error++ ? */
636 }
1f64ac13 637 if (n != result->h_length)
5f0e6fc7 638 {
1f64ac13
UD
639 cp += n;
640 continue;
5f0e6fc7 641 }
1f64ac13 642 if (!haveanswer)
5f0e6fc7
RM
643 {
644 register int nn;
645
646 result->h_name = bp;
647 nn = strlen (bp) + 1; /* for the \0 */
648 bp += nn;
649 linebuflen -= nn;
650 }
651
560d3b76 652 linebuflen -= sizeof (align) - ((u_long) bp % sizeof (align));
5f0e6fc7
RM
653 bp += sizeof (align) - ((u_long) bp % sizeof (align));
654
b455972f 655 if (__builtin_expect (n > linebuflen, 0))
0cc70fcf 656 goto too_small;
5f0e6fc7
RM
657 if (hap >= &host_data->h_addr_ptrs[MAX_NR_ADDRS-1])
658 {
659 cp += n;
660 continue;
661 }
8d8c6efa 662 bp = __mempcpy (*hap++ = bp, cp, n);
5f0e6fc7
RM
663 cp += n;
664 linebuflen -= n;
665 break;
666 default:
667 abort ();
668 }
669 if (had_error == 0)
670 ++haveanswer;
671 }
672
673 if (haveanswer > 0)
674 {
675 *ap = NULL;
676 *hap = NULL;
da2d1bc5 677#if defined RESOLVSORT
5f0e6fc7
RM
678 /*
679 * Note: we sort even if host can take only one address
680 * in its return structures - should give it the "best"
681 * address in that case, not some random one
682 */
683 if (_res.nsort && haveanswer > 1 && qtype == T_A)
684 addrsort (host_data->h_addr_ptrs, haveanswer);
685#endif /*RESOLVSORT*/
686
687 if (result->h_name == NULL)
688 {
689 n = strlen (qname) + 1; /* For the \0. */
8d8c6efa 690 if (n > linebuflen)
0cc70fcf 691 goto too_small;
8d8c6efa 692 if (n >= MAXHOSTNAMELEN)
76b87c03 693 goto no_recovery;
8d8c6efa
UD
694 result->h_name = bp;
695 bp = __mempcpy (bp, qname, n); /* Cannot overflow. */
5f0e6fc7
RM
696 linebuflen -= n;
697 }
698
b455972f 699 if (have_to_map)
5f0e6fc7
RM
700 map_v4v6_hostent (result, &bp, &linebuflen);
701 *h_errnop = NETDB_SUCCESS;
702 return NSS_STATUS_SUCCESS;
703 }
76b87c03
UD
704 no_recovery:
705 *h_errnop = NO_RECOVERY;
a0bf6ac7 706 *errnop = ENOENT;
5f0e6fc7
RM
707 return NSS_STATUS_TRYAGAIN;
708}