Include <signal.h> in sysdeps/nptl/allocrtsig.c
[platform/upstream/glibc.git] / resolv / res_query.c
1 /*
2  * Copyright (c) 1988, 1993
3  *    The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 4. Neither the name of the University nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29
30 /*
31  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
32  *
33  * Permission to use, copy, modify, and distribute this software for any
34  * purpose with or without fee is hereby granted, provided that the above
35  * copyright notice and this permission notice appear in all copies, and that
36  * the name of Digital Equipment Corporation not be used in advertising or
37  * publicity pertaining to distribution of the document or software without
38  * specific, written prior permission.
39  *
40  * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
41  * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
42  * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
43  * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
44  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
45  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
46  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
47  * SOFTWARE.
48  */
49
50 /*
51  * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
52  *
53  * Permission to use, copy, modify, and distribute this software for any
54  * purpose with or without fee is hereby granted, provided that the above
55  * copyright notice and this permission notice appear in all copies.
56  *
57  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
58  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
59  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
60  * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
61  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
62  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
63  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
64  * SOFTWARE.
65  */
66
67 #if defined(LIBC_SCCS) && !defined(lint)
68 static const char sccsid[] = "@(#)res_query.c   8.1 (Berkeley) 6/4/93";
69 static const char rcsid[] = "$BINDId: res_query.c,v 8.20 2000/02/29 05:39:12 vixie Exp $";
70 #endif /* LIBC_SCCS and not lint */
71
72 #include <assert.h>
73 #include <sys/types.h>
74 #include <sys/param.h>
75 #include <netinet/in.h>
76 #include <arpa/inet.h>
77 #include <arpa/nameser.h>
78 #include <ctype.h>
79 #include <errno.h>
80 #include <netdb.h>
81 #include <resolv.h>
82 #include <stdio.h>
83 #include <stdlib.h>
84 #include <string.h>
85
86 /* Options.  Leave them on. */
87 /* #undef DEBUG */
88
89 #if PACKETSZ > 65536
90 #define MAXPACKET       PACKETSZ
91 #else
92 #define MAXPACKET       65536
93 #endif
94
95 #define QUERYSIZE       (HFIXEDSZ + QFIXEDSZ + MAXCDNAME + 1)
96
97 static int
98 __libc_res_nquerydomain(res_state statp, const char *name, const char *domain,
99                         int class, int type, u_char *answer, int anslen,
100                         u_char **answerp, u_char **answerp2, int *nanswerp2,
101                         int *resplen2, int *answerp2_malloced);
102
103 /*
104  * Formulate a normal query, send, and await answer.
105  * Returned answer is placed in supplied buffer "answer".
106  * Perform preliminary check of answer, returning success only
107  * if no error is indicated and the answer count is nonzero.
108  * Return the size of the response on success, -1 on error.
109  * Error number is left in H_ERRNO.
110  *
111  * Caller must parse answer and determine whether it answers the question.
112  */
113 int
114 __libc_res_nquery(res_state statp,
115                   const char *name,     /* domain name */
116                   int class, int type,  /* class and type of query */
117                   u_char *answer,       /* buffer to put answer */
118                   int anslen,           /* size of answer buffer */
119                   u_char **answerp,     /* if buffer needs to be enlarged */
120                   u_char **answerp2,
121                   int *nanswerp2,
122                   int *resplen2,
123                   int *answerp2_malloced)
124 {
125         HEADER *hp = (HEADER *) answer;
126         HEADER *hp2;
127         int n, use_malloc = 0;
128         u_int oflags = statp->_flags;
129
130         size_t bufsize = (type == T_UNSPEC ? 2 : 1) * QUERYSIZE;
131         u_char *buf = alloca (bufsize);
132         u_char *query1 = buf;
133         int nquery1 = -1;
134         u_char *query2 = NULL;
135         int nquery2 = 0;
136
137  again:
138         hp->rcode = NOERROR;    /* default */
139
140 #ifdef DEBUG
141         if (statp->options & RES_DEBUG)
142                 printf(";; res_query(%s, %d, %d)\n", name, class, type);
143 #endif
144
145         if (type == T_UNSPEC)
146           {
147             n = res_nmkquery(statp, QUERY, name, class, T_A, NULL, 0, NULL,
148                              query1, bufsize);
149             if (n > 0)
150               {
151                 if ((oflags & RES_F_EDNS0ERR) == 0
152                     && (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0)
153                   {
154                     n = __res_nopt(statp, n, query1, bufsize, anslen / 2);
155                     if (n < 0)
156                       goto unspec_nomem;
157                   }
158
159                 nquery1 = n;
160                 /* Align the buffer.  */
161                 int npad = ((nquery1 + __alignof__ (HEADER) - 1)
162                             & ~(__alignof__ (HEADER) - 1)) - nquery1;
163                 if (n > bufsize - npad)
164                   {
165                     n = -1;
166                     goto unspec_nomem;
167                   }
168                 int nused = n + npad;
169                 query2 = buf + nused;
170                 n = res_nmkquery(statp, QUERY, name, class, T_AAAA, NULL, 0,
171                                  NULL, query2, bufsize - nused);
172                 if (n > 0
173                     && (oflags & RES_F_EDNS0ERR) == 0
174                     && (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0)
175                   n = __res_nopt(statp, n, query2, bufsize - nused - n,
176                                  anslen / 2);
177                 nquery2 = n;
178               }
179
180           unspec_nomem:;
181           }
182         else
183           {
184             n = res_nmkquery(statp, QUERY, name, class, type, NULL, 0, NULL,
185                              query1, bufsize);
186
187             if (n > 0
188                 && (oflags & RES_F_EDNS0ERR) == 0
189                 && (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0)
190               n = __res_nopt(statp, n, query1, bufsize, anslen);
191
192             nquery1 = n;
193           }
194
195         if (__builtin_expect (n <= 0, 0) && !use_malloc) {
196                 /* Retry just in case res_nmkquery failed because of too
197                    short buffer.  Shouldn't happen.  */
198                 bufsize = (type == T_UNSPEC ? 2 : 1) * MAXPACKET;
199                 buf = malloc (bufsize);
200                 if (buf != NULL) {
201                         query1 = buf;
202                         use_malloc = 1;
203                         goto again;
204                 }
205         }
206         if (__glibc_unlikely (n <= 0))       {
207                 /* If the query choked with EDNS0, retry without EDNS0.  */
208                 if ((statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0
209                     && ((oflags ^ statp->_flags) & RES_F_EDNS0ERR) != 0) {
210                         statp->_flags |= RES_F_EDNS0ERR;
211 #ifdef DEBUG
212                         if (statp->options & RES_DEBUG)
213                                 printf(";; res_nquery: retry without EDNS0\n");
214 #endif
215                         goto again;
216                 }
217 #ifdef DEBUG
218                 if (statp->options & RES_DEBUG)
219                         printf(";; res_query: mkquery failed\n");
220 #endif
221                 RES_SET_H_ERRNO(statp, NO_RECOVERY);
222                 if (use_malloc)
223                         free (buf);
224                 return (n);
225         }
226         assert (answerp == NULL || (void *) *answerp == (void *) answer);
227         n = __libc_res_nsend(statp, query1, nquery1, query2, nquery2, answer,
228                              anslen, answerp, answerp2, nanswerp2, resplen2,
229                              answerp2_malloced);
230         if (use_malloc)
231                 free (buf);
232         if (n < 0) {
233 #ifdef DEBUG
234                 if (statp->options & RES_DEBUG)
235                         printf(";; res_query: send error\n");
236 #endif
237                 RES_SET_H_ERRNO(statp, TRY_AGAIN);
238                 return (n);
239         }
240
241         if (answerp != NULL)
242           /* __libc_res_nsend might have reallocated the buffer.  */
243           hp = (HEADER *) *answerp;
244
245         /* We simplify the following tests by assigning HP to HP2 or
246            vice versa.  It is easy to verify that this is the same as
247            ignoring all tests of HP or HP2.  */
248         if (answerp2 == NULL || *resplen2 < (int) sizeof (HEADER))
249           {
250             hp2 = hp;
251           }
252         else
253           {
254             hp2 = (HEADER *) *answerp2;
255             if (n < (int) sizeof (HEADER))
256               {
257                 hp = hp2;
258               }
259           }
260
261         /* Make sure both hp and hp2 are defined */
262         assert((hp != NULL) && (hp2 != NULL));
263
264         if ((hp->rcode != NOERROR || ntohs(hp->ancount) == 0)
265             && (hp2->rcode != NOERROR || ntohs(hp2->ancount) == 0)) {
266 #ifdef DEBUG
267                 if (statp->options & RES_DEBUG) {
268                         printf(";; rcode = %d, ancount=%d\n", hp->rcode,
269                             ntohs(hp->ancount));
270                         if (hp != hp2)
271                           printf(";; rcode2 = %d, ancount2=%d\n", hp2->rcode,
272                                  ntohs(hp2->ancount));
273                 }
274 #endif
275                 switch (hp->rcode == NOERROR ? hp2->rcode : hp->rcode) {
276                 case NXDOMAIN:
277                         if ((hp->rcode == NOERROR && ntohs (hp->ancount) != 0)
278                             || (hp2->rcode == NOERROR
279                                 && ntohs (hp2->ancount) != 0))
280                                 goto success;
281                         RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
282                         break;
283                 case SERVFAIL:
284                         RES_SET_H_ERRNO(statp, TRY_AGAIN);
285                         break;
286                 case NOERROR:
287                         if (ntohs (hp->ancount) != 0
288                             || ntohs (hp2->ancount) != 0)
289                                 goto success;
290                         RES_SET_H_ERRNO(statp, NO_DATA);
291                         break;
292                 case FORMERR:
293                 case NOTIMP:
294                         /* Servers must not reply to AAAA queries with
295                            NOTIMP etc but some of them do.  */
296                         if ((hp->rcode == NOERROR && ntohs (hp->ancount) != 0)
297                             || (hp2->rcode == NOERROR
298                                 && ntohs (hp2->ancount) != 0))
299                                 goto success;
300                         /* FALLTHROUGH */
301                 case REFUSED:
302                 default:
303                         RES_SET_H_ERRNO(statp, NO_RECOVERY);
304                         break;
305                 }
306                 return (-1);
307         }
308  success:
309         return (n);
310 }
311 libresolv_hidden_def (__libc_res_nquery)
312
313 int
314 res_nquery(res_state statp,
315            const char *name,    /* domain name */
316            int class, int type, /* class and type of query */
317            u_char *answer,      /* buffer to put answer */
318            int anslen)          /* size of answer buffer */
319 {
320         return __libc_res_nquery(statp, name, class, type, answer, anslen,
321                                  NULL, NULL, NULL, NULL, NULL);
322 }
323 libresolv_hidden_def (res_nquery)
324
325 /*
326  * Formulate a normal query, send, and retrieve answer in supplied buffer.
327  * Return the size of the response on success, -1 on error.
328  * If enabled, implement search rules until answer or unrecoverable failure
329  * is detected.  Error code, if any, is left in H_ERRNO.
330  */
331 int
332 __libc_res_nsearch(res_state statp,
333                    const char *name,    /* domain name */
334                    int class, int type, /* class and type of query */
335                    u_char *answer,      /* buffer to put answer */
336                    int anslen,          /* size of answer */
337                    u_char **answerp,
338                    u_char **answerp2,
339                    int *nanswerp2,
340                    int *resplen2,
341                    int *answerp2_malloced)
342 {
343         const char *cp, * const *domain;
344         HEADER *hp = (HEADER *) answer;
345         char tmp[NS_MAXDNAME];
346         u_int dots;
347         int trailing_dot, ret, saved_herrno;
348         int got_nodata = 0, got_servfail = 0, root_on_list = 0;
349         int tried_as_is = 0;
350         int searched = 0;
351
352         __set_errno (0);
353         RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);  /* True if we never query. */
354
355         dots = 0;
356         for (cp = name; *cp != '\0'; cp++)
357                 dots += (*cp == '.');
358         trailing_dot = 0;
359         if (cp > name && *--cp == '.')
360                 trailing_dot++;
361
362         /* If there aren't any dots, it could be a user-level alias. */
363         if (!dots && (cp = res_hostalias(statp, name, tmp, sizeof tmp))!= NULL)
364                 return (__libc_res_nquery(statp, cp, class, type, answer,
365                                           anslen, answerp, answerp2,
366                                           nanswerp2, resplen2, answerp2_malloced));
367
368 #ifdef DEBUG
369         if (statp->options & RES_DEBUG)
370                 printf("dots=%d, statp->ndots=%d, trailing_dot=%d, name=%s\n",
371                        (int)dots,(int)statp->ndots,(int)trailing_dot,name);
372 #endif
373
374         /*
375          * If there are enough dots in the name, let's just give it a
376          * try 'as is'. The threshold can be set with the "ndots" option.
377          * Also, query 'as is', if there is a trailing dot in the name.
378          */
379         saved_herrno = -1;
380         if (dots >= statp->ndots || trailing_dot) {
381                 ret = __libc_res_nquerydomain(statp, name, NULL, class, type,
382                                               answer, anslen, answerp,
383                                               answerp2, nanswerp2, resplen2,
384                                               answerp2_malloced);
385                 if (ret > 0 || trailing_dot
386                     /* If the second response is valid then we use that.  */
387                     || (ret == 0 && resplen2 != NULL && *resplen2 > 0))
388                         return (ret);
389                 saved_herrno = h_errno;
390                 tried_as_is++;
391                 if (answerp && *answerp != answer) {
392                         answer = *answerp;
393                         anslen = MAXPACKET;
394                 }
395                 if (answerp2 && *answerp2_malloced)
396                   {
397                     free (*answerp2);
398                     *answerp2 = NULL;
399                     *answerp2_malloced = 0;
400                   }
401         }
402
403         /*
404          * We do at least one level of search if
405          *      - there is no dot and RES_DEFNAME is set, or
406          *      - there is at least one dot, there is no trailing dot,
407          *        and RES_DNSRCH is set.
408          */
409         if ((!dots && (statp->options & RES_DEFNAMES) != 0) ||
410             (dots && !trailing_dot && (statp->options & RES_DNSRCH) != 0)) {
411                 int done = 0;
412
413                 for (domain = (const char * const *)statp->dnsrch;
414                      *domain && !done;
415                      domain++) {
416                         const char *dname = domain[0];
417                         searched = 1;
418
419                         /* __libc_res_nquerydoman concatenates name
420                            with dname with a "." in between.  If we
421                            pass it in dname the "." we got from the
422                            configured default search path, we'll end
423                            up with "name..", which won't resolve.
424                            OTOH, passing it "" will result in "name.",
425                            which has the intended effect for both
426                            possible representations of the root
427                            domain.  */
428                         if (dname[0] == '.')
429                                 dname++;
430                         if (dname[0] == '\0')
431                                 root_on_list++;
432
433                         ret = __libc_res_nquerydomain(statp, name, dname,
434                                                       class, type,
435                                                       answer, anslen, answerp,
436                                                       answerp2, nanswerp2,
437                                                       resplen2, answerp2_malloced);
438                         if (ret > 0 || (ret == 0 && resplen2 != NULL
439                                         && *resplen2 > 0))
440                                 return (ret);
441
442                         if (answerp && *answerp != answer) {
443                                 answer = *answerp;
444                                 anslen = MAXPACKET;
445                         }
446                         if (answerp2 && *answerp2_malloced)
447                           {
448                             free (*answerp2);
449                             *answerp2 = NULL;
450                             *answerp2_malloced = 0;
451                           }
452
453                         /*
454                          * If no server present, give up.
455                          * If name isn't found in this domain,
456                          * keep trying higher domains in the search list
457                          * (if that's enabled).
458                          * On a NO_DATA error, keep trying, otherwise
459                          * a wildcard entry of another type could keep us
460                          * from finding this entry higher in the domain.
461                          * If we get some other error (negative answer or
462                          * server failure), then stop searching up,
463                          * but try the input name below in case it's
464                          * fully-qualified.
465                          */
466                         if (errno == ECONNREFUSED) {
467                                 RES_SET_H_ERRNO(statp, TRY_AGAIN);
468                                 return (-1);
469                         }
470
471                         switch (statp->res_h_errno) {
472                         case NO_DATA:
473                                 got_nodata++;
474                                 /* FALLTHROUGH */
475                         case HOST_NOT_FOUND:
476                                 /* keep trying */
477                                 break;
478                         case TRY_AGAIN:
479                                 if (hp->rcode == SERVFAIL) {
480                                         /* try next search element, if any */
481                                         got_servfail++;
482                                         break;
483                                 }
484                                 /* FALLTHROUGH */
485                         default:
486                                 /* anything else implies that we're done */
487                                 done++;
488                         }
489
490                         /* if we got here for some reason other than DNSRCH,
491                          * we only wanted one iteration of the loop, so stop.
492                          */
493                         if ((statp->options & RES_DNSRCH) == 0)
494                                 done++;
495                 }
496         }
497
498         /*
499          * If the query has not already been tried as is then try it
500          * unless RES_NOTLDQUERY is set and there were no dots.
501          */
502         if ((dots || !searched || (statp->options & RES_NOTLDQUERY) == 0)
503             && !(tried_as_is || root_on_list)) {
504                 ret = __libc_res_nquerydomain(statp, name, NULL, class, type,
505                                               answer, anslen, answerp,
506                                               answerp2, nanswerp2, resplen2,
507                                               answerp2_malloced);
508                 if (ret > 0 || (ret == 0 && resplen2 != NULL
509                                 && *resplen2 > 0))
510                         return (ret);
511         }
512
513         /* if we got here, we didn't satisfy the search.
514          * if we did an initial full query, return that query's H_ERRNO
515          * (note that we wouldn't be here if that query had succeeded).
516          * else if we ever got a nodata, send that back as the reason.
517          * else send back meaningless H_ERRNO, that being the one from
518          * the last DNSRCH we did.
519          */
520         if (answerp2 && *answerp2_malloced)
521           {
522             free (*answerp2);
523             *answerp2 = NULL;
524             *answerp2_malloced = 0;
525           }
526         if (saved_herrno != -1)
527                 RES_SET_H_ERRNO(statp, saved_herrno);
528         else if (got_nodata)
529                 RES_SET_H_ERRNO(statp, NO_DATA);
530         else if (got_servfail)
531                 RES_SET_H_ERRNO(statp, TRY_AGAIN);
532         return (-1);
533 }
534 libresolv_hidden_def (__libc_res_nsearch)
535
536 int
537 res_nsearch(res_state statp,
538             const char *name,   /* domain name */
539             int class, int type,        /* class and type of query */
540             u_char *answer,     /* buffer to put answer */
541             int anslen)         /* size of answer */
542 {
543         return __libc_res_nsearch(statp, name, class, type, answer,
544                                   anslen, NULL, NULL, NULL, NULL, NULL);
545 }
546 libresolv_hidden_def (res_nsearch)
547
548 /*
549  * Perform a call on res_query on the concatenation of name and domain.
550  */
551 static int
552 __libc_res_nquerydomain(res_state statp,
553                         const char *name,
554                         const char *domain,
555                         int class, int type,    /* class and type of query */
556                         u_char *answer,         /* buffer to put answer */
557                         int anslen,                     /* size of answer */
558                         u_char **answerp,
559                         u_char **answerp2,
560                         int *nanswerp2,
561                         int *resplen2,
562                         int *answerp2_malloced)
563 {
564         char nbuf[MAXDNAME];
565         const char *longname = nbuf;
566         size_t n, d;
567
568 #ifdef DEBUG
569         if (statp->options & RES_DEBUG)
570                 printf(";; res_nquerydomain(%s, %s, %d, %d)\n",
571                        name, domain?domain:"<Nil>", class, type);
572 #endif
573         if (domain == NULL) {
574                 n = strlen(name);
575
576                 /* Decrement N prior to checking it against MAXDNAME
577                    so that we detect a wrap to SIZE_MAX and return
578                    a reasonable error.  */
579                 n--;
580                 if (n >= MAXDNAME - 1) {
581                         RES_SET_H_ERRNO(statp, NO_RECOVERY);
582                         return (-1);
583                 }
584                 longname = name;
585         } else {
586                 n = strlen(name);
587                 d = strlen(domain);
588                 if (n + d + 1 >= MAXDNAME) {
589                         RES_SET_H_ERRNO(statp, NO_RECOVERY);
590                         return (-1);
591                 }
592                 sprintf(nbuf, "%s.%s", name, domain);
593         }
594         return (__libc_res_nquery(statp, longname, class, type, answer,
595                                   anslen, answerp, answerp2, nanswerp2,
596                                   resplen2, answerp2_malloced));
597 }
598
599 int
600 res_nquerydomain(res_state statp,
601             const char *name,
602             const char *domain,
603             int class, int type,        /* class and type of query */
604             u_char *answer,             /* buffer to put answer */
605             int anslen)         /* size of answer */
606 {
607         return __libc_res_nquerydomain(statp, name, domain, class, type,
608                                        answer, anslen, NULL, NULL, NULL, NULL,
609                                        NULL);
610 }
611 libresolv_hidden_def (res_nquerydomain)
612
613 const char *
614 res_hostalias(const res_state statp, const char *name, char *dst, size_t siz) {
615         char *file, *cp1, *cp2;
616         char buf[BUFSIZ];
617         FILE *fp;
618
619         if (statp->options & RES_NOALIASES)
620                 return (NULL);
621         file = getenv("HOSTALIASES");
622         if (file == NULL || (fp = fopen(file, "rce")) == NULL)
623                 return (NULL);
624         setbuf(fp, NULL);
625         buf[sizeof(buf) - 1] = '\0';
626         while (fgets(buf, sizeof(buf), fp)) {
627                 for (cp1 = buf; *cp1 && !isspace(*cp1); ++cp1)
628                         ;
629                 if (!*cp1)
630                         break;
631                 *cp1 = '\0';
632                 if (ns_samename(buf, name) == 1) {
633                         while (isspace(*++cp1))
634                                 ;
635                         if (!*cp1)
636                                 break;
637                         for (cp2 = cp1 + 1; *cp2 && !isspace(*cp2); ++cp2)
638                                 ;
639                         *cp2 = '\0';
640                         strncpy(dst, cp1, siz - 1);
641                         dst[siz - 1] = '\0';
642                         fclose(fp);
643                         return (dst);
644                 }
645         }
646         fclose(fp);
647         return (NULL);
648 }
649 libresolv_hidden_def (res_hostalias)