]> git.ipfire.org Git - thirdparty/glibc.git/blame - resolv/res_query.c
hurd: Fix build
[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
acf82eaf 67#include <assert.h>
df21c858 68#include <sys/types.h>
28f540f4
RM
69#include <sys/param.h>
70#include <netinet/in.h>
71#include <arpa/inet.h>
72#include <arpa/nameser.h>
28f540f4
RM
73#include <ctype.h>
74#include <errno.h>
b43b13ac
UD
75#include <netdb.h>
76#include <resolv.h>
a7ff1da8 77#include <resolv/resolv-internal.h>
352f4ff9 78#include <resolv/resolv_context.h>
b43b13ac
UD
79#include <stdio.h>
80#include <stdlib.h>
81#include <string.h>
03775117 82#include <shlib-compat.h>
28f540f4 83
e2dced82 84#if PACKETSZ > 65536
28f540f4
RM
85#define MAXPACKET PACKETSZ
86#else
e2dced82 87#define MAXPACKET 65536
28f540f4
RM
88#endif
89
0420d888
UD
90#define QUERYSIZE (HFIXEDSZ + QFIXEDSZ + MAXCDNAME + 1)
91
92static int
352f4ff9
FW
93__res_context_querydomain (struct resolv_context *,
94 const char *name, const char *domain,
95 int class, int type, unsigned char *answer, int anslen,
96 unsigned char **answerp, unsigned char **answerp2, int *nanswerp2,
97 int *resplen2, int *answerp2_malloced);
98
99/* Formulate a normal query, send, and await answer. Returned answer
100 is placed in supplied buffer ANSWER. Perform preliminary check of
101 answer, returning success only if no error is indicated and the
102 answer count is nonzero. Return the size of the response on
103 success, -1 on error. Error number is left in h_errno.
104
105 Caller must parse answer and determine whether it answers the
106 question. */
28f540f4 107int
352f4ff9
FW
108__res_context_query (struct resolv_context *ctx, const char *name,
109 int class, int type,
110 unsigned char *answer, int anslen,
111 unsigned char **answerp, unsigned char **answerp2,
112 int *nanswerp2, int *resplen2, int *answerp2_malloced)
28f540f4 113{
352f4ff9 114 struct __res_state *statp = ctx->resp;
b43b13ac 115 HEADER *hp = (HEADER *) answer;
cc8bb21c 116 HEADER *hp2;
6166815d 117 int n, use_malloc = 0;
28f540f4 118
fc82b0a2 119 size_t bufsize = (type == T_QUERY_A_AND_AAAA ? 2 : 1) * QUERYSIZE;
1eb946b9
UD
120 u_char *buf = alloca (bufsize);
121 u_char *query1 = buf;
122 int nquery1 = -1;
123 u_char *query2 = NULL;
124 int nquery2 = 0;
28f540f4 125
2bbb7d5b
UD
126 again:
127 hp->rcode = NOERROR; /* default */
6166815d 128
fc82b0a2 129 if (type == T_QUERY_A_AND_AAAA)
1eb946b9 130 {
352f4ff9
FW
131 n = __res_context_mkquery (ctx, QUERY, name, class, T_A, NULL,
132 query1, bufsize);
1eb946b9
UD
133 if (n > 0)
134 {
44500cbb 135 if ((statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0)
44abc397 136 {
e14a2772
FW
137 /* Use RESOLV_EDNS_BUFFER_SIZE because the receive
138 buffer can be reallocated. */
352f4ff9 139 n = __res_nopt (ctx, n, query1, bufsize,
e14a2772 140 RESOLV_EDNS_BUFFER_SIZE);
44abc397
UD
141 if (n < 0)
142 goto unspec_nomem;
143 }
1eb946b9
UD
144
145 nquery1 = n;
44abc397
UD
146 /* Align the buffer. */
147 int npad = ((nquery1 + __alignof__ (HEADER) - 1)
fdc769f6 148 & ~(__alignof__ (HEADER) - 1)) - nquery1;
44abc397
UD
149 if (n > bufsize - npad)
150 {
151 n = -1;
152 goto unspec_nomem;
153 }
44abc397 154 int nused = n + npad;
fdc769f6 155 query2 = buf + nused;
352f4ff9
FW
156 n = __res_context_mkquery (ctx, QUERY, name, class, T_AAAA,
157 NULL, query2, bufsize - nused);
1eb946b9 158 if (n > 0
2d0671cb 159 && (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0)
e14a2772
FW
160 /* Use RESOLV_EDNS_BUFFER_SIZE because the receive
161 buffer can be reallocated. */
352f4ff9 162 n = __res_nopt (ctx, n, query2, bufsize,
e14a2772 163 RESOLV_EDNS_BUFFER_SIZE);
1eb946b9
UD
164 nquery2 = n;
165 }
44abc397
UD
166
167 unspec_nomem:;
1eb946b9
UD
168 }
169 else
170 {
352f4ff9
FW
171 n = __res_context_mkquery (ctx, QUERY, name, class, type, NULL,
172 query1, bufsize);
1eb946b9
UD
173
174 if (n > 0
2d0671cb 175 && (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0)
e14a2772
FW
176 {
177 /* Use RESOLV_EDNS_BUFFER_SIZE if the receive buffer
178 can be reallocated. */
179 size_t advertise;
180 if (answerp == NULL)
181 advertise = anslen;
182 else
183 advertise = RESOLV_EDNS_BUFFER_SIZE;
352f4ff9 184 n = __res_nopt (ctx, n, query1, bufsize, advertise);
e14a2772 185 }
1eb946b9
UD
186
187 nquery1 = n;
188 }
189
bee05c9d 190 if (__glibc_unlikely (n <= 0) && !use_malloc) {
0420d888
UD
191 /* Retry just in case res_nmkquery failed because of too
192 short buffer. Shouldn't happen. */
fc82b0a2 193 bufsize = (type == T_QUERY_A_AND_AAAA ? 2 : 1) * MAXPACKET;
2bbb7d5b 194 buf = malloc (bufsize);
0420d888 195 if (buf != NULL) {
1eb946b9 196 query1 = buf;
0420d888 197 use_malloc = 1;
2bbb7d5b 198 goto again;
78512c00 199 }
0420d888 200 }
a1ffb40e 201 if (__glibc_unlikely (n <= 0)) {
b43b13ac 202 RES_SET_H_ERRNO(statp, NO_RECOVERY);
6166815d
UD
203 if (use_malloc)
204 free (buf);
28f540f4
RM
205 return (n);
206 }
acf82eaf 207 assert (answerp == NULL || (void *) *answerp == (void *) answer);
352f4ff9
FW
208 n = __res_context_send (ctx, query1, nquery1, query2, nquery2, answer,
209 anslen, answerp, answerp2, nanswerp2, resplen2,
210 answerp2_malloced);
6166815d
UD
211 if (use_malloc)
212 free (buf);
28f540f4 213 if (n < 0) {
b43b13ac 214 RES_SET_H_ERRNO(statp, TRY_AGAIN);
28f540f4
RM
215 return (n);
216 }
217
acf82eaf 218 if (answerp != NULL)
352f4ff9 219 /* __res_context_send might have reallocated the buffer. */
acf82eaf
UD
220 hp = (HEADER *) *answerp;
221
cc8bb21c
AJ
222 /* We simplify the following tests by assigning HP to HP2 or
223 vice versa. It is easy to verify that this is the same as
224 ignoring all tests of HP or HP2. */
225 if (answerp2 == NULL || *resplen2 < (int) sizeof (HEADER))
5908f779 226 {
cc8bb21c 227 hp2 = hp;
5908f779 228 }
cc8bb21c 229 else
5908f779 230 {
cc8bb21c
AJ
231 hp2 = (HEADER *) *answerp2;
232 if (n < (int) sizeof (HEADER))
233 {
234 hp = hp2;
235 }
5908f779
UD
236 }
237
cc8bb21c
AJ
238 /* Make sure both hp and hp2 are defined */
239 assert((hp != NULL) && (hp2 != NULL));
240
1eb946b9
UD
241 if ((hp->rcode != NOERROR || ntohs(hp->ancount) == 0)
242 && (hp2->rcode != NOERROR || ntohs(hp2->ancount) == 0)) {
1eb946b9 243 switch (hp->rcode == NOERROR ? hp2->rcode : hp->rcode) {
28f540f4 244 case NXDOMAIN:
1eb946b9
UD
245 if ((hp->rcode == NOERROR && ntohs (hp->ancount) != 0)
246 || (hp2->rcode == NOERROR
247 && ntohs (hp2->ancount) != 0))
248 goto success;
b43b13ac 249 RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
28f540f4
RM
250 break;
251 case SERVFAIL:
b43b13ac 252 RES_SET_H_ERRNO(statp, TRY_AGAIN);
28f540f4
RM
253 break;
254 case NOERROR:
1eb946b9
UD
255 if (ntohs (hp->ancount) != 0
256 || ntohs (hp2->ancount) != 0)
257 goto success;
b43b13ac 258 RES_SET_H_ERRNO(statp, NO_DATA);
28f540f4
RM
259 break;
260 case FORMERR:
261 case NOTIMP:
cf4f16cc
UD
262 /* Servers must not reply to AAAA queries with
263 NOTIMP etc but some of them do. */
264 if ((hp->rcode == NOERROR && ntohs (hp->ancount) != 0)
265 || (hp2->rcode == NOERROR
266 && ntohs (hp2->ancount) != 0))
267 goto success;
268 /* FALLTHROUGH */
28f540f4
RM
269 case REFUSED:
270 default:
b43b13ac 271 RES_SET_H_ERRNO(statp, NO_RECOVERY);
28f540f4
RM
272 break;
273 }
274 return (-1);
275 }
1eb946b9 276 success:
28f540f4
RM
277 return (n);
278}
352f4ff9
FW
279libresolv_hidden_def (__res_context_query)
280
281/* Common part of res_nquery and res_query. */
282static int
283context_query_common (struct resolv_context *ctx,
284 const char *name, int class, int type,
285 unsigned char *answer, int anslen)
286{
287 if (ctx == NULL)
288 {
289 RES_SET_H_ERRNO (&_res, NETDB_INTERNAL);
290 return -1;
291 }
292 int result = __res_context_query (ctx, name, class, type, answer, anslen,
293 NULL, NULL, NULL, NULL, NULL);
294 __resolv_context_put (ctx);
295 return result;
296}
28f540f4 297
0420d888
UD
298int
299res_nquery(res_state statp,
300 const char *name, /* domain name */
301 int class, int type, /* class and type of query */
302 u_char *answer, /* buffer to put answer */
303 int anslen) /* size of answer buffer */
304{
352f4ff9
FW
305 return context_query_common
306 (__resolv_context_get_override (statp), name, class, type, answer, anslen);
0420d888
UD
307}
308
03775117
FW
309int
310res_query (const char *name, int class, int type,
311 unsigned char *answer, int anslen)
312{
352f4ff9
FW
313 return context_query_common
314 (__resolv_context_get (), name, class, type, answer, anslen);
03775117
FW
315}
316
352f4ff9
FW
317/* Formulate a normal query, send, and retrieve answer in supplied
318 buffer. Return the size of the response on success, -1 on error.
319 If enabled, implement search rules until answer or unrecoverable
320 failure is detected. Error code, if any, is left in h_errno. */
28f540f4 321int
352f4ff9
FW
322__res_context_search (struct resolv_context *ctx,
323 const char *name, int class, int type,
324 unsigned char *answer, int anslen,
325 unsigned char **answerp, unsigned char **answerp2,
326 int *nanswerp2, int *resplen2, int *answerp2_malloced)
28f540f4 327{
352f4ff9 328 struct __res_state *statp = ctx->resp;
3f853f22 329 const char *cp;
28f540f4 330 HEADER *hp = (HEADER *) answer;
b43b13ac 331 char tmp[NS_MAXDNAME];
28f540f4 332 u_int dots;
e685e07d 333 int trailing_dot, ret, saved_herrno;
b43b13ac 334 int got_nodata = 0, got_servfail = 0, root_on_list = 0;
e685e07d 335 int tried_as_is = 0;
f87dfb1f 336 int searched = 0;
28f540f4 337
c4029823 338 __set_errno (0);
b43b13ac
UD
339 RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); /* True if we never query. */
340
28f540f4 341 dots = 0;
b43b13ac 342 for (cp = name; *cp != '\0'; cp++)
28f540f4
RM
343 dots += (*cp == '.');
344 trailing_dot = 0;
345 if (cp > name && *--cp == '.')
346 trailing_dot++;
347
b43b13ac 348 /* If there aren't any dots, it could be a user-level alias. */
352f4ff9
FW
349 if (!dots && (cp = __res_context_hostalias
350 (ctx, name, tmp, sizeof tmp))!= NULL)
351 return __res_context_query (ctx, cp, class, type, answer,
352 anslen, answerp, answerp2,
353 nanswerp2, resplen2, answerp2_malloced);
28f540f4
RM
354
355 /*
e685e07d
UD
356 * If there are enough dots in the name, let's just give it a
357 * try 'as is'. The threshold can be set with the "ndots" option.
358 * Also, query 'as is', if there is a trailing dot in the name.
28f540f4 359 */
e685e07d
UD
360 saved_herrno = -1;
361 if (dots >= statp->ndots || trailing_dot) {
352f4ff9
FW
362 ret = __res_context_querydomain (ctx, name, NULL, class, type,
363 answer, anslen, answerp,
364 answerp2, nanswerp2, resplen2,
365 answerp2_malloced);
16b293a7
SP
366 if (ret > 0 || trailing_dot
367 /* If the second response is valid then we use that. */
e35c53e3 368 || (ret == 0 && resplen2 != NULL && *resplen2 > 0))
e685e07d
UD
369 return (ret);
370 saved_herrno = h_errno;
371 tried_as_is++;
0420d888
UD
372 if (answerp && *answerp != answer) {
373 answer = *answerp;
374 anslen = MAXPACKET;
375 }
ab09bf61 376 if (answerp2 && *answerp2_malloced)
1eb946b9
UD
377 {
378 free (*answerp2);
379 *answerp2 = NULL;
e9db92d3 380 *nanswerp2 = 0;
ab09bf61 381 *answerp2_malloced = 0;
1eb946b9 382 }
e685e07d 383 }
28f540f4
RM
384
385 /*
386 * We do at least one level of search if
387 * - there is no dot and RES_DEFNAME is set, or
388 * - there is at least one dot, there is no trailing dot,
389 * and RES_DNSRCH is set.
390 */
b43b13ac
UD
391 if ((!dots && (statp->options & RES_DEFNAMES) != 0) ||
392 (dots && !trailing_dot && (statp->options & RES_DNSRCH) != 0)) {
28f540f4
RM
393 int done = 0;
394
3f853f22
FW
395 for (size_t domain_index = 0; !done; ++domain_index) {
396 const char *dname = __resolv_context_search_list
397 (ctx, domain_index);
398 if (dname == NULL)
399 break;
f87dfb1f 400 searched = 1;
28f540f4 401
352f4ff9 402 /* __res_context_querydoman concatenates name
b59d114b
AO
403 with dname with a "." in between. If we
404 pass it in dname the "." we got from the
405 configured default search path, we'll end
406 up with "name..", which won't resolve.
407 OTOH, passing it "" will result in "name.",
408 which has the intended effect for both
409 possible representations of the root
410 domain. */
411 if (dname[0] == '.')
412 dname++;
413 if (dname[0] == '\0')
b43b13ac
UD
414 root_on_list++;
415
352f4ff9
FW
416 ret = __res_context_querydomain
417 (ctx, name, dname, class, type,
418 answer, anslen, answerp, answerp2, nanswerp2,
419 resplen2, answerp2_malloced);
e35c53e3
SP
420 if (ret > 0 || (ret == 0 && resplen2 != NULL
421 && *resplen2 > 0))
28f540f4
RM
422 return (ret);
423
0420d888
UD
424 if (answerp && *answerp != answer) {
425 answer = *answerp;
426 anslen = MAXPACKET;
427 }
ab09bf61 428 if (answerp2 && *answerp2_malloced)
1eb946b9
UD
429 {
430 free (*answerp2);
431 *answerp2 = NULL;
e9db92d3 432 *nanswerp2 = 0;
ab09bf61 433 *answerp2_malloced = 0;
1eb946b9 434 }
0420d888 435
28f540f4
RM
436 /*
437 * If no server present, give up.
438 * If name isn't found in this domain,
439 * keep trying higher domains in the search list
440 * (if that's enabled).
441 * On a NO_DATA error, keep trying, otherwise
442 * a wildcard entry of another type could keep us
443 * from finding this entry higher in the domain.
444 * If we get some other error (negative answer or
445 * server failure), then stop searching up,
446 * but try the input name below in case it's
447 * fully-qualified.
448 */
449 if (errno == ECONNREFUSED) {
b43b13ac 450 RES_SET_H_ERRNO(statp, TRY_AGAIN);
28f540f4
RM
451 return (-1);
452 }
453
b43b13ac 454 switch (statp->res_h_errno) {
28f540f4
RM
455 case NO_DATA:
456 got_nodata++;
457 /* FALLTHROUGH */
458 case HOST_NOT_FOUND:
459 /* keep trying */
460 break;
461 case TRY_AGAIN:
462 if (hp->rcode == SERVFAIL) {
463 /* try next search element, if any */
464 got_servfail++;
465 break;
466 }
467 /* FALLTHROUGH */
468 default:
469 /* anything else implies that we're done */
470 done++;
471 }
472
473 /* if we got here for some reason other than DNSRCH,
474 * we only wanted one iteration of the loop, so stop.
475 */
b43b13ac 476 if ((statp->options & RES_DNSRCH) == 0)
28f540f4
RM
477 done++;
478 }
479 }
480
b43b13ac 481 /*
c12e9f37 482 * If the query has not already been tried as is then try it
f87dfb1f 483 * unless RES_NOTLDQUERY is set and there were no dots.
28f540f4 484 */
f87dfb1f
UD
485 if ((dots || !searched || (statp->options & RES_NOTLDQUERY) == 0)
486 && !(tried_as_is || root_on_list)) {
352f4ff9
FW
487 ret = __res_context_querydomain
488 (ctx, name, NULL, class, type,
489 answer, anslen, answerp, answerp2, nanswerp2,
490 resplen2, answerp2_malloced);
e35c53e3
SP
491 if (ret > 0 || (ret == 0 && resplen2 != NULL
492 && *resplen2 > 0))
28f540f4
RM
493 return (ret);
494 }
495
496 /* if we got here, we didn't satisfy the search.
b43b13ac 497 * if we did an initial full query, return that query's H_ERRNO
28f540f4
RM
498 * (note that we wouldn't be here if that query had succeeded).
499 * else if we ever got a nodata, send that back as the reason.
b43b13ac 500 * else send back meaningless H_ERRNO, that being the one from
28f540f4
RM
501 * the last DNSRCH we did.
502 */
ab09bf61 503 if (answerp2 && *answerp2_malloced)
1eb946b9
UD
504 {
505 free (*answerp2);
506 *answerp2 = NULL;
e9db92d3 507 *nanswerp2 = 0;
ab09bf61 508 *answerp2_malloced = 0;
1eb946b9 509 }
e685e07d
UD
510 if (saved_herrno != -1)
511 RES_SET_H_ERRNO(statp, saved_herrno);
512 else if (got_nodata)
b43b13ac 513 RES_SET_H_ERRNO(statp, NO_DATA);
28f540f4 514 else if (got_servfail)
b43b13ac 515 RES_SET_H_ERRNO(statp, TRY_AGAIN);
28f540f4
RM
516 return (-1);
517}
352f4ff9
FW
518libresolv_hidden_def (__res_context_search)
519
520/* Common part of res_nsearch and res_search. */
521static int
522context_search_common (struct resolv_context *ctx,
523 const char *name, int class, int type,
524 unsigned char *answer, int anslen)
525{
526 if (ctx == NULL)
527 {
528 RES_SET_H_ERRNO (&_res, NETDB_INTERNAL);
529 return -1;
530 }
531 int result = __res_context_search (ctx, name, class, type, answer, anslen,
532 NULL, NULL, NULL, NULL, NULL);
533 __resolv_context_put (ctx);
534 return result;
535}
28f540f4 536
0420d888
UD
537int
538res_nsearch(res_state statp,
539 const char *name, /* domain name */
540 int class, int type, /* class and type of query */
541 u_char *answer, /* buffer to put answer */
542 int anslen) /* size of answer */
543{
352f4ff9
FW
544 return context_search_common
545 (__resolv_context_get_override (statp), name, class, type, answer, anslen);
0420d888
UD
546}
547
03775117
FW
548int
549res_search (const char *name, int class, int type,
550 unsigned char *answer, int anslen)
551{
352f4ff9
FW
552 return context_search_common
553 (__resolv_context_get (), name, class, type, answer, anslen);
03775117
FW
554}
555
352f4ff9
FW
556/* Perform a call on res_query on the concatenation of name and
557 domain. */
0420d888 558static int
352f4ff9
FW
559__res_context_querydomain (struct resolv_context *ctx,
560 const char *name, const char *domain,
561 int class, int type,
562 unsigned char *answer, int anslen,
563 unsigned char **answerp, unsigned char **answerp2,
564 int *nanswerp2, int *resplen2,
565 int *answerp2_malloced)
28f540f4 566{
352f4ff9 567 struct __res_state *statp = ctx->resp;
b43b13ac 568 char nbuf[MAXDNAME];
28f540f4 569 const char *longname = nbuf;
28b59fca 570 size_t n, d;
28f540f4 571
28f540f4 572 if (domain == NULL) {
b43b13ac 573 n = strlen(name);
8fdceb2e
JL
574
575 /* Decrement N prior to checking it against MAXDNAME
576 so that we detect a wrap to SIZE_MAX and return
577 a reasonable error. */
578 n--;
579 if (n >= MAXDNAME - 1) {
b43b13ac
UD
580 RES_SET_H_ERRNO(statp, NO_RECOVERY);
581 return (-1);
582 }
f3d945d5 583 longname = name;
b43b13ac
UD
584 } else {
585 n = strlen(name);
586 d = strlen(domain);
587 if (n + d + 1 >= MAXDNAME) {
588 RES_SET_H_ERRNO(statp, NO_RECOVERY);
589 return (-1);
590 }
591 sprintf(nbuf, "%s.%s", name, domain);
592 }
352f4ff9
FW
593 return __res_context_query (ctx, longname, class, type, answer,
594 anslen, answerp, answerp2, nanswerp2,
595 resplen2, answerp2_malloced);
596}
597
598/* Common part of res_nquerydomain and res_querydomain. */
599static int
600context_querydomain_common (struct resolv_context *ctx,
601 const char *name, const char *domain,
602 int class, int type,
603 unsigned char *answer, int anslen)
604{
605 if (ctx == NULL)
606 {
607 RES_SET_H_ERRNO (&_res, NETDB_INTERNAL);
608 return -1;
609 }
610 int result = __res_context_querydomain (ctx, name, domain, class, type,
611 answer, anslen,
612 NULL, NULL, NULL, NULL, NULL);
613 __resolv_context_put (ctx);
614 return result;
0420d888
UD
615}
616
617int
618res_nquerydomain(res_state statp,
619 const char *name,
620 const char *domain,
621 int class, int type, /* class and type of query */
622 u_char *answer, /* buffer to put answer */
623 int anslen) /* size of answer */
624{
352f4ff9
FW
625 return context_querydomain_common
626 (__resolv_context_get_override (statp),
627 name, domain, class, type, answer, anslen);
28f540f4
RM
628}
629
03775117
FW
630int
631res_querydomain (const char *name, const char *domain, int class, int type,
632 unsigned char *answer, int anslen)
633{
352f4ff9
FW
634 return context_querydomain_common
635 (__resolv_context_get (), name, domain, class, type, answer, anslen);
03775117
FW
636}
637
845dcb57 638const char *
352f4ff9
FW
639__res_context_hostalias (struct resolv_context *ctx,
640 const char *name, char *dst, size_t siz)
641{
b43b13ac 642 char *file, *cp1, *cp2;
28f540f4 643 char buf[BUFSIZ];
b43b13ac 644 FILE *fp;
28f540f4 645
352f4ff9 646 if (ctx->resp->options & RES_NOALIASES)
3d61b63c 647 return (NULL);
52ee6223 648 file = getenv("HOSTALIASES");
312be3f9 649 if (file == NULL || (fp = fopen(file, "rce")) == NULL)
28f540f4 650 return (NULL);
3d61b63c 651 setbuf(fp, NULL);
28f540f4
RM
652 buf[sizeof(buf) - 1] = '\0';
653 while (fgets(buf, sizeof(buf), fp)) {
654 for (cp1 = buf; *cp1 && !isspace(*cp1); ++cp1)
655 ;
656 if (!*cp1)
657 break;
658 *cp1 = '\0';
b43b13ac 659 if (ns_samename(buf, name) == 1) {
28f540f4
RM
660 while (isspace(*++cp1))
661 ;
662 if (!*cp1)
663 break;
664 for (cp2 = cp1 + 1; *cp2 && !isspace(*cp2); ++cp2)
665 ;
b43b13ac
UD
666 *cp2 = '\0';
667 strncpy(dst, cp1, siz - 1);
668 dst[siz - 1] = '\0';
28f540f4 669 fclose(fp);
b43b13ac 670 return (dst);
28f540f4
RM
671 }
672 }
673 fclose(fp);
674 return (NULL);
675}
352f4ff9
FW
676libresolv_hidden_def (__res_context_hostalias)
677
678/* Common part of res_hostalias and hostalias. */
679static const char *
680context_hostalias_common (struct resolv_context *ctx,
681 const char *name, char *dst, size_t siz)
682{
683 if (ctx == NULL)
684 {
685 RES_SET_H_ERRNO (&_res, NETDB_INTERNAL);
686 return NULL;
687 }
688 const char *result = __res_context_hostalias (ctx, name, dst, siz);
689 __resolv_context_put (ctx);
690 return result;
691}
692
693const char *
694res_hostalias (res_state statp, const char *name, char *dst, size_t siz)
695{
696 return context_hostalias_common
697 (__resolv_context_get_override (statp), name, dst, siz);
698}
03775117
FW
699
700const char *
701hostalias (const char *name)
702{
703 static char abuf[MAXDNAME];
352f4ff9
FW
704 return context_hostalias_common
705 (__resolv_context_get (), name, abuf, sizeof (abuf));
03775117 706}
03775117
FW
707
708#if SHLIB_COMPAT (libresolv, GLIBC_2_0, GLIBC_2_2)
709# undef res_query
710# undef res_querydomain
711# undef res_search
712weak_alias (__res_query, res_query);
713weak_alias (__res_querydomain, res_querydomain);
714weak_alias (__res_search, res_search);
715#endif