]> 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
8d8c6efa 1/* Copyright (C) 1996, 1997, 1998, 1999 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 */
117extern int __ns_name_ntop __P ((const u_char *, char *, size_t));
118extern int __ns_name_unpack __P ((const u_char *, const u_char *,
119 const u_char *, u_char *, size_t));
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,
67479a70 125 size_t buflen, int *errnop, int *h_errnop);
5f0e6fc7
RM
126
127enum nss_status
128_nss_dns_gethostbyname2_r (const char *name, int af, struct hostent *result,
67479a70
UD
129 char *buffer, size_t buflen, int *errnop,
130 int *h_errnop)
5f0e6fc7 131{
5f0e6fc7
RM
132 querybuf host_buffer;
133 int size, type, n;
134 const char *cp;
135
136 switch (af) {
137 case AF_INET:
138 size = INADDRSZ;
139 type = T_A;
140 break;
141 case AF_INET6:
142 size = IN6ADDRSZ;
143 type = T_AAAA;
144 break;
145 default:
146 *h_errnop = NETDB_INTERNAL;
67479a70 147 *errnop = EAFNOSUPPORT;
5f0e6fc7
RM
148 return NSS_STATUS_UNAVAIL;
149 }
150
151 result->h_addrtype = af;
152 result->h_length = size;
153
154 /*
155 * if there aren't any dots, it could be a user-level alias.
156 * this is also done in res_query() since we are not the only
157 * function that looks up host names.
158 */
159 if (strchr (name, '.') == NULL && (cp = __hostalias (name)) != NULL)
160 name = cp;
161
795fbc9a 162 n = res_search (name, C_IN, type, host_buffer.buf, sizeof (host_buffer.buf));
5f0e6fc7 163 if (n < 0)
dd7d45e8
UD
164 {
165 *h_errnop = h_errno;
67479a70 166 *errnop = errno;
dd7d45e8
UD
167 return errno == ECONNREFUSED ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND;
168 }
5f0e6fc7
RM
169
170 return getanswer_r (&host_buffer, n, name, type, result, buffer, buflen,
67479a70 171 errnop, h_errnop);
5f0e6fc7
RM
172}
173
174
175enum nss_status
176_nss_dns_gethostbyname_r (const char *name, struct hostent *result,
67479a70
UD
177 char *buffer, size_t buflen, int *errnop,
178 int *h_errnop)
5f0e6fc7
RM
179{
180 enum nss_status status = NSS_STATUS_NOTFOUND;
181
182 if (_res.options & RES_USE_INET6)
183 status = _nss_dns_gethostbyname2_r (name, AF_INET6, result, buffer,
67479a70 184 buflen, errnop, h_errnop);
5f0e6fc7
RM
185 if (status == NSS_STATUS_NOTFOUND)
186 status = _nss_dns_gethostbyname2_r (name, AF_INET, result, buffer,
67479a70 187 buflen, errnop, h_errnop);
5f0e6fc7
RM
188
189 return status;
190}
191
192
193enum nss_status
194_nss_dns_gethostbyaddr_r (const char *addr, int len, int af,
df4ef2ab 195 struct hostent *result, char *buffer, size_t buflen,
67479a70 196 int *errnop, int *h_errnop)
5f0e6fc7
RM
197{
198 static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
199 static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
200 const u_char *uaddr = (const u_char *)addr;
201 struct host_data
202 {
203 char *aliases[MAX_NR_ALIASES];
204 unsigned char host_addr[16]; /* IPv4 or IPv6 */
205 char *h_addr_ptrs[MAX_NR_ADDRS + 1];
206 char linebuffer[0];
207 } *host_data = (struct host_data *) buffer;
208 querybuf host_buffer;
209 char qbuf[MAXDNAME+1], *qp;
210 int size, n, status;
211
212 if (af == AF_INET6 && len == IN6ADDRSZ &&
63551311
UD
213 (memcmp (uaddr, mapped, sizeof mapped) == 0
214 || memcmp (uaddr, tunnelled, sizeof tunnelled) == 0))
5f0e6fc7
RM
215 {
216 /* Unmap. */
217 addr += sizeof mapped;
218 uaddr += sizeof mapped;
219 af = AF_INET;
220 len = INADDRSZ;
221 }
222
223 switch (af)
224 {
225 case AF_INET:
226 size = INADDRSZ;
227 break;
228 case AF_INET6:
229 size = IN6ADDRSZ;
230 break;
231 default:
67479a70 232 *errnop = EAFNOSUPPORT;
5f0e6fc7
RM
233 *h_errnop = NETDB_INTERNAL;
234 return NSS_STATUS_UNAVAIL;
235 }
236 if (size != len)
237 {
67479a70 238 *errnop = EAFNOSUPPORT;
5f0e6fc7
RM
239 *h_errnop = NETDB_INTERNAL;
240 return NSS_STATUS_UNAVAIL;
241 }
242
243 switch (af)
244 {
245 case AF_INET:
246 sprintf (qbuf, "%u.%u.%u.%u.in-addr.arpa", (uaddr[3] & 0xff),
247 (uaddr[2] & 0xff), (uaddr[1] & 0xff), (uaddr[0] & 0xff));
248 break;
249 case AF_INET6:
250 qp = qbuf;
251 for (n = IN6ADDRSZ - 1; n >= 0; n--)
252 qp += sprintf (qp, "%x.%x.", uaddr[n] & 0xf, (uaddr[n] >> 4) & 0xf);
da2d1bc5 253 strcpy (qp, "ip6.int");
5f0e6fc7
RM
254 break;
255 default:
256 /* Cannot happen. */
257 }
258
259 n = res_query (qbuf, C_IN, T_PTR, (u_char *)host_buffer.buf,
260 sizeof host_buffer);
261 if (n < 0)
dd7d45e8
UD
262 {
263 *h_errnop = h_errno;
67479a70 264 *errnop = errno;
dd7d45e8
UD
265 return errno == ECONNREFUSED ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND;
266 }
5f0e6fc7
RM
267
268 status = getanswer_r (&host_buffer, n, qbuf, T_PTR, result, buffer, buflen,
67479a70 269 errnop, h_errnop);
5f0e6fc7 270 if (status != NSS_STATUS_SUCCESS)
dd7d45e8
UD
271 {
272 *h_errnop = h_errno;
67479a70 273 *errnop = errno;
dd7d45e8
UD
274 return status;
275 }
5f0e6fc7
RM
276
277#ifdef SUNSECURITY
278 This is not implemented because it is not possible to use the current
279 source from bind in a multi-threaded program.
280#endif
281
282 result->h_addrtype = af;
283 result->h_length = len;
63551311 284 memcpy (host_data->host_addr, addr, len);
5f0e6fc7
RM
285 host_data->h_addr_ptrs[0] = (char *) host_data->host_addr;
286 host_data->h_addr_ptrs[1] = NULL;
287 if (af == AF_INET && (_res.options & RES_USE_INET6))
288 {
289 map_v4v6_address ((char *) host_data->host_addr,
290 (char *) host_data->host_addr);
291 result->h_addrtype = AF_INET6;
292 result->h_length = IN6ADDRSZ;
293 }
294 *h_errnop = NETDB_SUCCESS;
295 return NSS_STATUS_SUCCESS;
296}
297
298
299static enum nss_status
300getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
df4ef2ab 301 struct hostent *result, char *buffer, size_t buflen,
67479a70 302 int *errnop, int *h_errnop)
5f0e6fc7
RM
303{
304 struct host_data
305 {
306 char *aliases[MAX_NR_ALIASES];
307 unsigned char host_addr[16]; /* IPv4 or IPv6 */
308 char *h_addr_ptrs[MAX_NR_ADDRS + 1];
309 char linebuffer[0];
310 } *host_data = (struct host_data *) buffer;
311 int linebuflen = buflen - offsetof (struct host_data, linebuffer);
312 register const HEADER *hp;
313 const u_char *end_of_message, *cp;
314 int n, ancount, qdcount;
315 int haveanswer, had_error;
316 char *bp, **ap, **hap;
845dcb57 317 char tbuf[MAXDNAME];
5f0e6fc7
RM
318 const char *tname;
319 int (*name_ok) __P ((const char *));
8d8c6efa 320 u_char packtmp[NS_MAXCDNAME];
5f0e6fc7
RM
321
322 tname = qname;
323 result->h_name = NULL;
324 end_of_message = answer->buf + anslen;
325 switch (qtype)
326 {
327 case T_A:
328 case T_AAAA:
329 name_ok = res_hnok;
330 break;
331 case T_PTR:
332 name_ok = res_dnok;
333 break;
334 default:
335 return NSS_STATUS_UNAVAIL; /* XXX should be abort(); */
336 }
337
338 /*
339 * find first satisfactory answer
340 */
341 hp = &answer->hdr;
342 bp = host_data->linebuffer;
343 ancount = ntohs (hp->ancount);
344 qdcount = ntohs (hp->qdcount);
345 cp = answer->buf + HFIXEDSZ;
346 if (qdcount != 1)
347 {
348 *h_errnop = NO_RECOVERY;
349 return NSS_STATUS_UNAVAIL;
350 }
351
8d8c6efa
UD
352 n = __ns_name_unpack (answer->buf, end_of_message, cp,
353 packtmp, sizeof packtmp);
354 if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
5f0e6fc7 355 {
67479a70
UD
356 if (errno == EMSGSIZE)
357 {
67479a70
UD
358 *errnop = ERANGE;
359 *h_errnop = NETDB_INTERNAL;
8d8c6efa 360 return NSS_STATUS_TRYAGAIN;
67479a70 361 }
8d8c6efa
UD
362
363 n = -1;
364 }
365
366 if (n > 0 && bp[0] == '.')
367 bp[0] = '\0';
368
369 if (n < 0 || (*name_ok) (bp) == 0)
370 {
371 *errnop = errno;
372 *h_errnop = NO_RECOVERY;
5f0e6fc7
RM
373 return NSS_STATUS_UNAVAIL;
374 }
375 cp += n + QFIXEDSZ;
376
377 if (qtype == T_A || qtype == T_AAAA)
378 {
379 /* res_send() has already verified that the query name is the
380 * same as the one we sent; this just gets the expanded name
381 * (i.e., with the succeeding search-domain tacked on).
382 */
383 n = strlen (bp) + 1; /* for the \0 */
76b87c03
UD
384 if (n >= MAXHOSTNAMELEN)
385 {
67479a70 386 *h_errnop = NO_RECOVERY;
76b87c03
UD
387 return NSS_STATUS_TRYAGAIN;
388 }
5f0e6fc7
RM
389 result->h_name = bp;
390 bp += n;
391 linebuflen -= n;
392 /* The qname can be abbreviated, but h_name is now absolute. */
393 qname = result->h_name;
394 }
395
396 ap = host_data->aliases;
397 *ap = NULL;
398 result->h_aliases = host_data->aliases;
399 hap = host_data->h_addr_ptrs;
400 *hap = NULL;
401 result->h_addr_list = host_data->h_addr_ptrs;
402 haveanswer = 0;
403 had_error = 0;
404
405 while (ancount-- > 0 && cp < end_of_message && had_error == 0)
406 {
407 int type, class;
408
8d8c6efa
UD
409 n = __ns_name_unpack (answer->buf, end_of_message, cp,
410 packtmp, sizeof packtmp);
411 if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
412 {
413 if (errno == EMSGSIZE)
414 {
415 *errnop = ERANGE;
416 *h_errnop = NETDB_INTERNAL;
417 return NSS_STATUS_TRYAGAIN;
418 }
419
420 n = -1;
421 }
422
5f0e6fc7
RM
423 if (n < 0 || (*name_ok) (bp) == 0)
424 {
425 ++had_error;
426 continue;
427 }
428 cp += n; /* name */
429 type = _getshort (cp);
430 cp += INT16SZ; /* type */
8d8c6efa 431 class = _getshort (cp);
5f0e6fc7 432 cp += INT16SZ + INT32SZ; /* class, TTL */
8d8c6efa 433 n = _getshort (cp);
5f0e6fc7
RM
434 cp += INT16SZ; /* len */
435 if (class != C_IN)
436 {
437 /* XXX - debug? syslog? */
438 cp += n;
439 continue; /* XXX - had_error++ ? */
440 }
441
442 if ((qtype ==T_A || qtype == T_AAAA) && type == T_CNAME)
443 {
444 if (ap >= &host_data->aliases[MAX_NR_ALIASES - 1])
445 continue;
446 n = dn_expand (answer->buf, end_of_message, cp, tbuf, sizeof tbuf);
447 if (n < 0 || (*name_ok) (tbuf) == 0)
448 {
449 ++had_error;
450 continue;
451 }
452 cp += n;
453 /* Store alias. */
454 *ap++ = bp;
455 n = strlen (bp) + 1; /* For the \0. */
76b87c03
UD
456 if (n >= MAXHOSTNAMELEN)
457 {
458 ++had_error;
459 continue;
460 }
5f0e6fc7
RM
461 bp += n;
462 linebuflen -= n;
463 /* Get canonical name. */
464 n = strlen (tbuf) + 1; /* For the \0. */
76b87c03 465 if ((size_t) n > buflen || n >= MAXHOSTNAMELEN)
5f0e6fc7
RM
466 {
467 ++had_error;
468 continue;
469 }
8d8c6efa
UD
470 result->h_name = bp;
471 bp = __mempcpy (bp, tbuf, n); /* Cannot overflow. */
5f0e6fc7
RM
472 linebuflen -= n;
473 continue;
474 }
475
476 if (qtype == T_PTR && type == T_CNAME)
477 {
478 n = dn_expand (answer->buf, end_of_message, cp, tbuf, sizeof tbuf);
da2d1bc5 479 if (n < 0 || res_dnok (tbuf) == 0)
5f0e6fc7
RM
480 {
481 ++had_error;
482 continue;
483 }
484 cp += n;
da2d1bc5 485 /* Get canonical name. */
5f0e6fc7 486 n = strlen (tbuf) + 1; /* For the \0. */
76b87c03 487 if ((size_t) n > buflen || n >= MAXHOSTNAMELEN)
5f0e6fc7
RM
488 {
489 ++had_error;
490 continue;
491 }
8d8c6efa
UD
492 tname = bp;
493 bp = __mempcpy (bp, tbuf, n); /* Cannot overflow. */
5f0e6fc7
RM
494 linebuflen -= n;
495 continue;
496 }
1bc21e7a
UD
497 if (type == T_SIG || type == T_KEY || type == T_NXT)
498 {
499 /* We don't support DNSSEC yet. For now, ignore the record
500 and send a low priority message to syslog. */
501 syslog (LOG_DEBUG | LOG_AUTH,
502 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
503 qname, p_class (C_IN), p_type(qtype), p_type (type));
504 cp += n;
505 continue;
506 }
5f0e6fc7
RM
507 if (type != qtype)
508 {
509 syslog (LOG_NOTICE | LOG_AUTH,
510 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
511 qname, p_class (C_IN), p_type (qtype), p_type (type));
512 cp += n;
513 continue; /* XXX - had_error++ ? */
514 }
515
516 switch (type)
517 {
518 case T_PTR:
8d8c6efa 519 if (__strcasecmp (tname, bp) != 0)
5f0e6fc7
RM
520 {
521 syslog (LOG_NOTICE | LOG_AUTH, AskedForGot, qname, bp);
522 cp += n;
523 continue; /* XXX - had_error++ ? */
524 }
8d8c6efa
UD
525
526 n = __ns_name_unpack (answer->buf, end_of_message, cp,
527 packtmp, sizeof packtmp);
528 if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
529 {
530 if (errno == EMSGSIZE)
531 {
532 *errnop = ERANGE;
533 *h_errnop = NETDB_INTERNAL;
534 return NSS_STATUS_TRYAGAIN;
535 }
536
537 n = -1;
538 }
539
5f0e6fc7
RM
540 if (n < 0 || res_hnok (bp) == 0)
541 {
542 ++had_error;
543 break;
544 }
545#if MULTI_PTRS_ARE_ALIASES
546 cp += n;
547 if (haveanswer == 0)
548 result->h_name = bp;
549 else if (ap < &host_data->aliases[MAXALIASES-1])
550 *ap++ = bp;
551 else
552 n = -1;
553 if (n != -1)
554 {
555 n = strlen (bp) + 1; /* for the \0 */
76b87c03
UD
556 if (n >= MAXHOSTNAMELEN)
557 {
558 ++had_error;
559 break;
560 }
5f0e6fc7
RM
561 bp += n;
562 linebuflen -= n;
563 }
564 break;
565#else
566 result->h_name = bp;
567 if (_res.options & RES_USE_INET6)
568 {
569 n = strlen (bp) + 1; /* for the \0 */
76b87c03
UD
570 if (n >= MAXHOSTNAMELEN)
571 {
572 ++had_error;
573 break;
574 }
5f0e6fc7
RM
575 bp += n;
576 linebuflen -= n;
577 map_v4v6_hostent (result, &bp, &linebuflen);
578 }
579 *h_errnop = NETDB_SUCCESS;
580 return NSS_STATUS_SUCCESS;
581#endif
582 case T_A:
583 case T_AAAA:
584 if (strcasecmp (result->h_name, bp) != 0)
585 {
586 syslog (LOG_NOTICE | LOG_AUTH, AskedForGot, result->h_name, bp);
587 cp += n;
588 continue; /* XXX - had_error++ ? */
589 }
1f64ac13 590 if (n != result->h_length)
5f0e6fc7 591 {
1f64ac13
UD
592 cp += n;
593 continue;
5f0e6fc7 594 }
1f64ac13 595 if (!haveanswer)
5f0e6fc7
RM
596 {
597 register int nn;
598
599 result->h_name = bp;
600 nn = strlen (bp) + 1; /* for the \0 */
601 bp += nn;
602 linebuflen -= nn;
603 }
604
605 bp += sizeof (align) - ((u_long) bp % sizeof (align));
606
607 if (n >= linebuflen)
608 {
609 ++had_error;
610 continue;
611 }
612 if (hap >= &host_data->h_addr_ptrs[MAX_NR_ADDRS-1])
613 {
614 cp += n;
615 continue;
616 }
8d8c6efa 617 bp = __mempcpy (*hap++ = bp, cp, n);
5f0e6fc7
RM
618 cp += n;
619 linebuflen -= n;
620 break;
621 default:
622 abort ();
623 }
624 if (had_error == 0)
625 ++haveanswer;
626 }
627
628 if (haveanswer > 0)
629 {
630 *ap = NULL;
631 *hap = NULL;
da2d1bc5 632#if defined RESOLVSORT
5f0e6fc7
RM
633 /*
634 * Note: we sort even if host can take only one address
635 * in its return structures - should give it the "best"
636 * address in that case, not some random one
637 */
638 if (_res.nsort && haveanswer > 1 && qtype == T_A)
639 addrsort (host_data->h_addr_ptrs, haveanswer);
640#endif /*RESOLVSORT*/
641
642 if (result->h_name == NULL)
643 {
644 n = strlen (qname) + 1; /* For the \0. */
8d8c6efa
UD
645 if (n > linebuflen)
646 {
647 *errnop = ERANGE;
648 *h_errnop = NETDB_INTERNAL;
649 return NSS_STATUS_TRYAGAIN;
650 }
651 if (n >= MAXHOSTNAMELEN)
76b87c03 652 goto no_recovery;
8d8c6efa
UD
653 result->h_name = bp;
654 bp = __mempcpy (bp, qname, n); /* Cannot overflow. */
5f0e6fc7
RM
655 linebuflen -= n;
656 }
657
658 if (_res.options & RES_USE_INET6)
659 map_v4v6_hostent (result, &bp, &linebuflen);
660 *h_errnop = NETDB_SUCCESS;
661 return NSS_STATUS_SUCCESS;
662 }
76b87c03
UD
663 no_recovery:
664 *h_errnop = NO_RECOVERY;
5f0e6fc7
RM
665 return NSS_STATUS_TRYAGAIN;
666}