]> git.ipfire.org Git - thirdparty/glibc.git/blame - resolv/res_query.c
Fix race in tst-mqueue5
[thirdparty/glibc.git] / resolv / res_query.c
CommitLineData
28f540f4 1/*
28f540f4
RM
2 * Copyright (c) 1988, 1993
3 * The Regents of the University of California. All rights reserved.
52ee6223 4 *
28f540f4
RM
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.
28f540f4
RM
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.
52ee6223 16 *
28f540f4
RM
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.
b43b13ac
UD
28 */
29
30/*
28f540f4 31 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
52ee6223 32 *
28f540f4
RM
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.
52ee6223 39 *
28f540f4
RM
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.
b43b13ac
UD
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.
28f540f4
RM
65 */
66
67#if defined(LIBC_SCCS) && !defined(lint)
b43b13ac 68static const char sccsid[] = "@(#)res_query.c 8.1 (Berkeley) 6/4/93";
e685e07d 69static const char rcsid[] = "$BINDId: res_query.c,v 8.20 2000/02/29 05:39:12 vixie Exp $";
28f540f4
RM
70#endif /* LIBC_SCCS and not lint */
71
acf82eaf 72#include <assert.h>
df21c858 73#include <sys/types.h>
28f540f4
RM
74#include <sys/param.h>
75#include <netinet/in.h>
76#include <arpa/inet.h>
77#include <arpa/nameser.h>
28f540f4
RM
78#include <ctype.h>
79#include <errno.h>
b43b13ac
UD
80#include <netdb.h>
81#include <resolv.h>
82#include <stdio.h>
83#include <stdlib.h>
84#include <string.h>
28f540f4 85
b43b13ac
UD
86/* Options. Leave them on. */
87/* #undef DEBUG */
28f540f4 88
e2dced82 89#if PACKETSZ > 65536
28f540f4
RM
90#define MAXPACKET PACKETSZ
91#else
e2dced82 92#define MAXPACKET 65536
28f540f4
RM
93#endif
94
0420d888
UD
95#define QUERYSIZE (HFIXEDSZ + QFIXEDSZ + MAXCDNAME + 1)
96
97static int
98__libc_res_nquerydomain(res_state statp, const char *name, const char *domain,
99 int class, int type, u_char *answer, int anslen,
b7da31a1 100 u_char **answerp, u_char **answerp2, int *nanswerp2,
ab09bf61 101 int *resplen2, int *answerp2_malloced);
0420d888 102
28f540f4
RM
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.
b43b13ac 109 * Error number is left in H_ERRNO.
28f540f4
RM
110 *
111 * Caller must parse answer and determine whether it answers the question.
112 */
113int
0420d888
UD
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 */
1eb946b9
UD
119 u_char **answerp, /* if buffer needs to be enlarged */
120 u_char **answerp2,
b7da31a1 121 int *nanswerp2,
ab09bf61
AS
122 int *resplen2,
123 int *answerp2_malloced)
28f540f4 124{
b43b13ac 125 HEADER *hp = (HEADER *) answer;
cc8bb21c 126 HEADER *hp2;
6166815d 127 int n, use_malloc = 0;
f87dfb1f 128 u_int oflags = statp->_flags;
28f540f4 129
1eb946b9
UD
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;
28f540f4 136
2bbb7d5b
UD
137 again:
138 hp->rcode = NOERROR; /* default */
6166815d 139
28f540f4 140#ifdef DEBUG
b43b13ac 141 if (statp->options & RES_DEBUG)
28f540f4
RM
142 printf(";; res_query(%s, %d, %d)\n", name, class, type);
143#endif
144
1eb946b9
UD
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
2d0671cb 152 && (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0)
44abc397
UD
153 {
154 n = __res_nopt(statp, n, query1, bufsize, anslen / 2);
155 if (n < 0)
156 goto unspec_nomem;
157 }
1eb946b9
UD
158
159 nquery1 = n;
44abc397
UD
160 /* Align the buffer. */
161 int npad = ((nquery1 + __alignof__ (HEADER) - 1)
fdc769f6 162 & ~(__alignof__ (HEADER) - 1)) - nquery1;
44abc397
UD
163 if (n > bufsize - npad)
164 {
165 n = -1;
166 goto unspec_nomem;
167 }
44abc397 168 int nused = n + npad;
fdc769f6 169 query2 = buf + nused;
1eb946b9 170 n = res_nmkquery(statp, QUERY, name, class, T_AAAA, NULL, 0,
44abc397 171 NULL, query2, bufsize - nused);
1eb946b9
UD
172 if (n > 0
173 && (oflags & RES_F_EDNS0ERR) == 0
2d0671cb 174 && (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0)
44abc397
UD
175 n = __res_nopt(statp, n, query2, bufsize - nused - n,
176 anslen / 2);
1eb946b9
UD
177 nquery2 = n;
178 }
44abc397
UD
179
180 unspec_nomem:;
1eb946b9
UD
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
2d0671cb 189 && (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0)
1eb946b9
UD
190 n = __res_nopt(statp, n, query1, bufsize, anslen);
191
192 nquery1 = n;
193 }
194
2bbb7d5b 195 if (__builtin_expect (n <= 0, 0) && !use_malloc) {
0420d888
UD
196 /* Retry just in case res_nmkquery failed because of too
197 short buffer. Shouldn't happen. */
1eb946b9 198 bufsize = (type == T_UNSPEC ? 2 : 1) * MAXPACKET;
2bbb7d5b 199 buf = malloc (bufsize);
0420d888 200 if (buf != NULL) {
1eb946b9 201 query1 = buf;
0420d888 202 use_malloc = 1;
2bbb7d5b 203 goto again;
78512c00 204 }
0420d888 205 }
a1ffb40e 206 if (__glibc_unlikely (n <= 0)) {
2bbb7d5b 207 /* If the query choked with EDNS0, retry without EDNS0. */
2d0671cb 208 if ((statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0
2bbb7d5b
UD
209 && ((oflags ^ statp->_flags) & RES_F_EDNS0ERR) != 0) {
210 statp->_flags |= RES_F_EDNS0ERR;
fdc769f6 211#ifdef DEBUG
2bbb7d5b
UD
212 if (statp->options & RES_DEBUG)
213 printf(";; res_nquery: retry without EDNS0\n");
fdc769f6 214#endif
f87dfb1f 215 goto again;
2bbb7d5b 216 }
28f540f4 217#ifdef DEBUG
b43b13ac 218 if (statp->options & RES_DEBUG)
28f540f4
RM
219 printf(";; res_query: mkquery failed\n");
220#endif
b43b13ac 221 RES_SET_H_ERRNO(statp, NO_RECOVERY);
6166815d
UD
222 if (use_malloc)
223 free (buf);
28f540f4
RM
224 return (n);
225 }
acf82eaf 226 assert (answerp == NULL || (void *) *answerp == (void *) answer);
1eb946b9 227 n = __libc_res_nsend(statp, query1, nquery1, query2, nquery2, answer,
ab09bf61
AS
228 anslen, answerp, answerp2, nanswerp2, resplen2,
229 answerp2_malloced);
6166815d
UD
230 if (use_malloc)
231 free (buf);
28f540f4
RM
232 if (n < 0) {
233#ifdef DEBUG
b43b13ac 234 if (statp->options & RES_DEBUG)
28f540f4
RM
235 printf(";; res_query: send error\n");
236#endif
b43b13ac 237 RES_SET_H_ERRNO(statp, TRY_AGAIN);
28f540f4
RM
238 return (n);
239 }
240
acf82eaf
UD
241 if (answerp != NULL)
242 /* __libc_res_nsend might have reallocated the buffer. */
243 hp = (HEADER *) *answerp;
244
cc8bb21c
AJ
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))
5908f779 249 {
cc8bb21c 250 hp2 = hp;
5908f779 251 }
cc8bb21c 252 else
5908f779 253 {
cc8bb21c
AJ
254 hp2 = (HEADER *) *answerp2;
255 if (n < (int) sizeof (HEADER))
256 {
257 hp = hp2;
258 }
5908f779
UD
259 }
260
cc8bb21c
AJ
261 /* Make sure both hp and hp2 are defined */
262 assert((hp != NULL) && (hp2 != NULL));
263
1eb946b9
UD
264 if ((hp->rcode != NOERROR || ntohs(hp->ancount) == 0)
265 && (hp2->rcode != NOERROR || ntohs(hp2->ancount) == 0)) {
28f540f4 266#ifdef DEBUG
1eb946b9 267 if (statp->options & RES_DEBUG) {
28f540f4
RM
268 printf(";; rcode = %d, ancount=%d\n", hp->rcode,
269 ntohs(hp->ancount));
1eb946b9
UD
270 if (hp != hp2)
271 printf(";; rcode2 = %d, ancount2=%d\n", hp2->rcode,
272 ntohs(hp2->ancount));
273 }
28f540f4 274#endif
1eb946b9 275 switch (hp->rcode == NOERROR ? hp2->rcode : hp->rcode) {
28f540f4 276 case NXDOMAIN:
1eb946b9
UD
277 if ((hp->rcode == NOERROR && ntohs (hp->ancount) != 0)
278 || (hp2->rcode == NOERROR
279 && ntohs (hp2->ancount) != 0))
280 goto success;
b43b13ac 281 RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
28f540f4
RM
282 break;
283 case SERVFAIL:
b43b13ac 284 RES_SET_H_ERRNO(statp, TRY_AGAIN);
28f540f4
RM
285 break;
286 case NOERROR:
1eb946b9
UD
287 if (ntohs (hp->ancount) != 0
288 || ntohs (hp2->ancount) != 0)
289 goto success;
b43b13ac 290 RES_SET_H_ERRNO(statp, NO_DATA);
28f540f4
RM
291 break;
292 case FORMERR:
293 case NOTIMP:
cf4f16cc
UD
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 */
28f540f4
RM
301 case REFUSED:
302 default:
b43b13ac 303 RES_SET_H_ERRNO(statp, NO_RECOVERY);
28f540f4
RM
304 break;
305 }
306 return (-1);
307 }
1eb946b9 308 success:
28f540f4
RM
309 return (n);
310}
6f9d8e68 311libresolv_hidden_def (__libc_res_nquery)
28f540f4 312
0420d888
UD
313int
314res_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,
ab09bf61 321 NULL, NULL, NULL, NULL, NULL);
0420d888 322}
6f9d8e68 323libresolv_hidden_def (res_nquery)
0420d888 324
28f540f4
RM
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
b43b13ac 329 * is detected. Error code, if any, is left in H_ERRNO.
28f540f4
RM
330 */
331int
0420d888 332__libc_res_nsearch(res_state statp,
1eb946b9
UD
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,
b7da31a1 339 int *nanswerp2,
ab09bf61
AS
340 int *resplen2,
341 int *answerp2_malloced)
28f540f4 342{
b43b13ac 343 const char *cp, * const *domain;
28f540f4 344 HEADER *hp = (HEADER *) answer;
b43b13ac 345 char tmp[NS_MAXDNAME];
28f540f4 346 u_int dots;
e685e07d 347 int trailing_dot, ret, saved_herrno;
b43b13ac 348 int got_nodata = 0, got_servfail = 0, root_on_list = 0;
e685e07d 349 int tried_as_is = 0;
f87dfb1f 350 int searched = 0;
28f540f4 351
c4029823 352 __set_errno (0);
b43b13ac
UD
353 RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); /* True if we never query. */
354
28f540f4 355 dots = 0;
b43b13ac 356 for (cp = name; *cp != '\0'; cp++)
28f540f4
RM
357 dots += (*cp == '.');
358 trailing_dot = 0;
359 if (cp > name && *--cp == '.')
360 trailing_dot++;
361
b43b13ac
UD
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)
0420d888 364 return (__libc_res_nquery(statp, cp, class, type, answer,
1eb946b9 365 anslen, answerp, answerp2,
ab09bf61 366 nanswerp2, resplen2, answerp2_malloced));
28f540f4 367
2566e5f3
UD
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
78512c00 373
28f540f4 374 /*
e685e07d
UD
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.
28f540f4 378 */
e685e07d
UD
379 saved_herrno = -1;
380 if (dots >= statp->ndots || trailing_dot) {
0420d888 381 ret = __libc_res_nquerydomain(statp, name, NULL, class, type,
1eb946b9 382 answer, anslen, answerp,
ab09bf61
AS
383 answerp2, nanswerp2, resplen2,
384 answerp2_malloced);
16b293a7
SP
385 if (ret > 0 || trailing_dot
386 /* If the second response is valid then we use that. */
e35c53e3 387 || (ret == 0 && resplen2 != NULL && *resplen2 > 0))
e685e07d
UD
388 return (ret);
389 saved_herrno = h_errno;
390 tried_as_is++;
0420d888
UD
391 if (answerp && *answerp != answer) {
392 answer = *answerp;
393 anslen = MAXPACKET;
394 }
ab09bf61 395 if (answerp2 && *answerp2_malloced)
1eb946b9
UD
396 {
397 free (*answerp2);
398 *answerp2 = NULL;
ab09bf61 399 *answerp2_malloced = 0;
1eb946b9 400 }
e685e07d 401 }
28f540f4
RM
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 */
b43b13ac
UD
409 if ((!dots && (statp->options & RES_DEFNAMES) != 0) ||
410 (dots && !trailing_dot && (statp->options & RES_DNSRCH) != 0)) {
28f540f4
RM
411 int done = 0;
412
b43b13ac 413 for (domain = (const char * const *)statp->dnsrch;
28f540f4
RM
414 *domain && !done;
415 domain++) {
b59d114b 416 const char *dname = domain[0];
f87dfb1f 417 searched = 1;
28f540f4 418
b59d114b
AO
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')
b43b13ac
UD
431 root_on_list++;
432
b59d114b 433 ret = __libc_res_nquerydomain(statp, name, dname,
0420d888 434 class, type,
1eb946b9 435 answer, anslen, answerp,
b7da31a1 436 answerp2, nanswerp2,
ab09bf61 437 resplen2, answerp2_malloced);
e35c53e3
SP
438 if (ret > 0 || (ret == 0 && resplen2 != NULL
439 && *resplen2 > 0))
28f540f4
RM
440 return (ret);
441
0420d888
UD
442 if (answerp && *answerp != answer) {
443 answer = *answerp;
444 anslen = MAXPACKET;
445 }
ab09bf61 446 if (answerp2 && *answerp2_malloced)
1eb946b9
UD
447 {
448 free (*answerp2);
449 *answerp2 = NULL;
ab09bf61 450 *answerp2_malloced = 0;
1eb946b9 451 }
0420d888 452
28f540f4
RM
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) {
b43b13ac 467 RES_SET_H_ERRNO(statp, TRY_AGAIN);
28f540f4
RM
468 return (-1);
469 }
470
b43b13ac 471 switch (statp->res_h_errno) {
28f540f4
RM
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 */
b43b13ac 493 if ((statp->options & RES_DNSRCH) == 0)
28f540f4
RM
494 done++;
495 }
496 }
497
b43b13ac 498 /*
c12e9f37 499 * If the query has not already been tried as is then try it
f87dfb1f 500 * unless RES_NOTLDQUERY is set and there were no dots.
28f540f4 501 */
f87dfb1f
UD
502 if ((dots || !searched || (statp->options & RES_NOTLDQUERY) == 0)
503 && !(tried_as_is || root_on_list)) {
0420d888 504 ret = __libc_res_nquerydomain(statp, name, NULL, class, type,
1eb946b9 505 answer, anslen, answerp,
ab09bf61
AS
506 answerp2, nanswerp2, resplen2,
507 answerp2_malloced);
e35c53e3
SP
508 if (ret > 0 || (ret == 0 && resplen2 != NULL
509 && *resplen2 > 0))
28f540f4
RM
510 return (ret);
511 }
512
513 /* if we got here, we didn't satisfy the search.
b43b13ac 514 * if we did an initial full query, return that query's H_ERRNO
28f540f4
RM
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.
b43b13ac 517 * else send back meaningless H_ERRNO, that being the one from
28f540f4
RM
518 * the last DNSRCH we did.
519 */
ab09bf61 520 if (answerp2 && *answerp2_malloced)
1eb946b9
UD
521 {
522 free (*answerp2);
523 *answerp2 = NULL;
ab09bf61 524 *answerp2_malloced = 0;
1eb946b9 525 }
e685e07d
UD
526 if (saved_herrno != -1)
527 RES_SET_H_ERRNO(statp, saved_herrno);
528 else if (got_nodata)
b43b13ac 529 RES_SET_H_ERRNO(statp, NO_DATA);
28f540f4 530 else if (got_servfail)
b43b13ac 531 RES_SET_H_ERRNO(statp, TRY_AGAIN);
28f540f4
RM
532 return (-1);
533}
6f9d8e68 534libresolv_hidden_def (__libc_res_nsearch)
28f540f4 535
0420d888
UD
536int
537res_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,
ab09bf61 544 anslen, NULL, NULL, NULL, NULL, NULL);
0420d888 545}
6f9d8e68 546libresolv_hidden_def (res_nsearch)
0420d888 547
28f540f4 548/*
f3d945d5 549 * Perform a call on res_query on the concatenation of name and domain.
28f540f4 550 */
0420d888
UD
551static int
552__libc_res_nquerydomain(res_state statp,
1eb946b9
UD
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,
b7da31a1 560 int *nanswerp2,
ab09bf61
AS
561 int *resplen2,
562 int *answerp2_malloced)
28f540f4 563{
b43b13ac 564 char nbuf[MAXDNAME];
28f540f4 565 const char *longname = nbuf;
28b59fca 566 size_t n, d;
28f540f4
RM
567
568#ifdef DEBUG
b43b13ac
UD
569 if (statp->options & RES_DEBUG)
570 printf(";; res_nquerydomain(%s, %s, %d, %d)\n",
28f540f4
RM
571 name, domain?domain:"<Nil>", class, type);
572#endif
573 if (domain == NULL) {
b43b13ac 574 n = strlen(name);
8fdceb2e
JL
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) {
b43b13ac
UD
581 RES_SET_H_ERRNO(statp, NO_RECOVERY);
582 return (-1);
583 }
f3d945d5 584 longname = name;
b43b13ac
UD
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 }
c14e9135 594 return (__libc_res_nquery(statp, longname, class, type, answer,
b7da31a1 595 anslen, answerp, answerp2, nanswerp2,
ab09bf61 596 resplen2, answerp2_malloced));
0420d888
UD
597}
598
599int
600res_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,
ab09bf61
AS
608 answer, anslen, NULL, NULL, NULL, NULL,
609 NULL);
28f540f4 610}
6f9d8e68 611libresolv_hidden_def (res_nquerydomain)
28f540f4 612
845dcb57 613const char *
b43b13ac
UD
614res_hostalias(const res_state statp, const char *name, char *dst, size_t siz) {
615 char *file, *cp1, *cp2;
28f540f4 616 char buf[BUFSIZ];
b43b13ac 617 FILE *fp;
28f540f4 618
b43b13ac 619 if (statp->options & RES_NOALIASES)
3d61b63c 620 return (NULL);
52ee6223 621 file = getenv("HOSTALIASES");
312be3f9 622 if (file == NULL || (fp = fopen(file, "rce")) == NULL)
28f540f4 623 return (NULL);
3d61b63c 624 setbuf(fp, NULL);
28f540f4
RM
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';
b43b13ac 632 if (ns_samename(buf, name) == 1) {
28f540f4
RM
633 while (isspace(*++cp1))
634 ;
635 if (!*cp1)
636 break;
637 for (cp2 = cp1 + 1; *cp2 && !isspace(*cp2); ++cp2)
638 ;
b43b13ac
UD
639 *cp2 = '\0';
640 strncpy(dst, cp1, siz - 1);
641 dst[siz - 1] = '\0';
28f540f4 642 fclose(fp);
b43b13ac 643 return (dst);
28f540f4
RM
644 }
645 }
646 fclose(fp);
647 return (NULL);
648}
6f9d8e68 649libresolv_hidden_def (res_hostalias)