]>
git.proxmox.com Git - mirror_edk2.git/blob - StdLib/BsdSocketLib/res_query.c
2 * Copyright (c) 1988, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Portions copyright (c) 1999, 2000
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * 3. All advertising materials mentioning features or use of this software
21 * must display the following acknowledgement:
23 * This product includes software developed by the University of
24 * California, Berkeley, Intel Corporation, and its contributors.
26 * 4. Neither the name of University, Intel Corporation, or their respective
27 * contributors may be used to endorse or promote products derived from
28 * this software without specific prior written permission.
30 * THIS SOFTWARE IS PROVIDED BY THE REGENTS, INTEL CORPORATION AND
31 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
32 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
33 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS,
34 * INTEL CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
35 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
36 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
37 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
38 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
40 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
47 * Permission to use, copy, modify, and distribute this software for any
48 * purpose with or without fee is hereby granted, provided that the above
49 * copyright notice and this permission notice appear in all copies, and that
50 * the name of Digital Equipment Corporation not be used in advertising or
51 * publicity pertaining to distribution of the document or software without
52 * specific, written prior permission.
54 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
55 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
56 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
57 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
58 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
59 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
60 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
65 * Portions Copyright (c) 1996 by Internet Software Consortium.
67 * Permission to use, copy, modify, and distribute this software for any
68 * purpose with or without fee is hereby granted, provided that the above
69 * copyright notice and this permission notice appear in all copies.
71 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
72 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
73 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
74 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
75 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
76 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
77 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
81 #if defined(LIBC_SCCS) && !defined(lint)
82 static char sccsid
[] = "@(#)res_query.c 8.1 (Berkeley) 6/4/93";
83 static char orig_rcsid
= "From: Id: res_query.c,v 8.14 1997/06/09 17:47:05 halley Exp $";
84 static char rcsid
[] = "$Id: res_query.c,v 1.1.1.1 2003/11/19 01:51:38 kyu3 Exp $";
85 #endif /* LIBC_SCCS and not lint */
87 #include <sys/types.h>
88 #include <sys/param.h>
89 #include <netinet/in.h>
90 #include <arpa/inet.h>
91 #include <arpa/nameser.h>
100 #include "res_config.h"
103 #define MAXPACKET PACKETSZ
105 #define MAXPACKET 1024
109 * Formulate a normal query, send, and await answer.
110 * Returned answer is placed in supplied buffer "answer".
111 * Perform preliminary check of answer, returning success only
112 * if no error is indicated and the answer count is nonzero.
113 * Return the size of the response on success, -1 on error.
114 * Error number is left in h_errno.
116 * Caller must parse answer and determine whether it answers the question.
120 const char *name
, /* domain name */
121 int class, /* class of query */
122 int type
, /* type of query */
123 u_char
*answer
, /* buffer to put answer */
124 int anslen
/* size of answer buffer */
127 u_char buf
[MAXPACKET
];
128 HEADER
*hp
= (HEADER
*) answer
;
131 hp
->rcode
= NOERROR
; /* default */
133 if ((_res
.options
& RES_INIT
) == 0 && res_init() == -1) {
134 h_errno
= NETDB_INTERNAL
;
138 if (_res
.options
& RES_DEBUG
)
139 printf(";; res_query(%s, %d, %d)\n", name
, class, type
);
142 n
= res_mkquery(QUERY
, name
, class, type
, NULL
, 0, NULL
,
146 if (_res
.options
& RES_DEBUG
)
147 printf(";; res_query: mkquery failed\n");
149 h_errno
= NO_RECOVERY
;
152 n
= res_send(buf
, n
, answer
, anslen
);
155 if (_res
.options
& RES_DEBUG
)
156 printf(";; res_query: send error\n");
162 if (hp
->rcode
!= NOERROR
|| ntohs(hp
->ancount
) == 0) {
164 if (_res
.options
& RES_DEBUG
)
165 printf(";; rcode = %d, ancount=%d\n", hp
->rcode
,
170 h_errno
= HOST_NOT_FOUND
;
182 h_errno
= NO_RECOVERY
;
191 * Formulate a normal query, send, and retrieve answer in supplied buffer.
192 * Return the size of the response on success, -1 on error.
193 * If enabled, implement search rules until answer or unrecoverable failure
194 * is detected. Error code, if any, is left in h_errno.
198 const char *name
, /* domain name */
199 int class, /* class of query */
200 int type
, /* type of query */
201 u_char
*answer
, /* buffer to put answer */
202 int anslen
/* size of answer */
205 const char *cp
, * const *domain
;
206 HEADER
*hp
= (HEADER
*) answer
;
208 int trailing_dot
, ret
, saved_herrno
;
209 int got_nodata
= 0, got_servfail
= 0, tried_as_is
= 0;
211 if ((_res
.options
& RES_INIT
) == 0 && res_init() == -1) {
212 h_errno
= NETDB_INTERNAL
;
216 h_errno
= HOST_NOT_FOUND
; /* default, if we never query */
218 for (cp
= name
; *cp
; cp
++)
219 dots
+= (*cp
== '.');
221 if (cp
> name
&& *--cp
== '.')
224 /* If there aren't any dots, it could be a user-level alias */
225 if (!dots
&& (cp
= hostalias(name
)) != NULL
)
226 return (res_query(cp
, class, type
, answer
, anslen
));
229 * If there are dots in the name already, let's just give it a try
230 * 'as is'. The threshold can be set with the "ndots" option.
233 if (dots
>= _res
.ndots
) {
234 ret
= res_querydomain(name
, NULL
, class, type
, answer
, anslen
);
237 saved_herrno
= h_errno
;
242 * We do at least one level of search if
243 * - there is no dot and RES_DEFNAME is set, or
244 * - there is at least one dot, there is no trailing dot,
245 * and RES_DNSRCH is set.
247 if ((!dots
&& (_res
.options
& RES_DEFNAMES
)) ||
248 (dots
&& !trailing_dot
&& (_res
.options
& RES_DNSRCH
))) {
251 for (domain
= (const char * const *)_res
.dnsrch
;
255 ret
= res_querydomain(name
, *domain
, class, type
,
261 * If no server present, give up.
262 * If name isn't found in this domain,
263 * keep trying higher domains in the search list
264 * (if that's enabled).
265 * On a NO_DATA error, keep trying, otherwise
266 * a wildcard entry of another type could keep us
267 * from finding this entry higher in the domain.
268 * If we get some other error (negative answer or
269 * server failure), then stop searching up,
270 * but try the input name below in case it's
273 if (errno
== ECONNREFUSED
) {
286 if (hp
->rcode
== SERVFAIL
) {
287 /* try next search element, if any */
293 /* anything else implies that we're done */
297 /* if we got here for some reason other than DNSRCH,
298 * we only wanted one iteration of the loop, so stop.
300 if (!(_res
.options
& RES_DNSRCH
))
306 * If we have not already tried the name "as is", do that now.
307 * note that we do this regardless of how many dots were in the
308 * name or whether it ends with a dot unless NOTLDQUERY is set.
310 if (!tried_as_is
&& (dots
|| !(_res
.options
& RES_NOTLDQUERY
))) {
311 ret
= res_querydomain(name
, NULL
, class, type
, answer
, anslen
);
316 /* if we got here, we didn't satisfy the search.
317 * if we did an initial full query, return that query's h_errno
318 * (note that we wouldn't be here if that query had succeeded).
319 * else if we ever got a nodata, send that back as the reason.
320 * else send back meaningless h_errno, that being the one from
321 * the last DNSRCH we did.
323 if (saved_herrno
!= -1)
324 h_errno
= saved_herrno
;
327 else if (got_servfail
)
333 * Perform a call on res_query on the concatenation of name and domain,
334 * removing a trailing dot from name if domain is NULL.
340 int class, /* class of query */
341 int type
, /* type of query */
342 u_char
*answer
, /* buffer to put answer */
343 int anslen
/* size of answer */
347 const char *longname
= nbuf
;
350 if ((_res
.options
& RES_INIT
) == 0 && res_init() == -1) {
351 h_errno
= NETDB_INTERNAL
;
355 if (_res
.options
& RES_DEBUG
)
356 printf(";; res_querydomain(%s, %s, %d, %d)\n",
357 name
, domain
?domain
:"<Nil>", class, type
);
359 if (domain
== NULL
) {
361 * Check for trailing '.';
362 * copy without '.' if present.
364 n
= (int)strlen(name
);
366 h_errno
= NO_RECOVERY
;
370 if (n
>= 0 && name
[n
] == '.') {
371 strncpy(nbuf
, name
, n
);
376 n
= (int)strlen(name
);
377 d
= (int)strlen(domain
);
378 if (n
+ d
+ 1 >= MAXDNAME
) {
379 h_errno
= NO_RECOVERY
;
382 sprintf(nbuf
, "%s.%s", name
, domain
);
384 return (res_query(longname
, class, type
, answer
, anslen
));
392 register char *cp1
, *cp2
;
396 static char abuf
[MAXDNAME
];
398 if (_res
.options
& RES_NOALIASES
)
404 file
= getenv("HOSTALIASES");
405 if (file
== NULL
|| (fp
= fopen(file
, "r")) == NULL
)
408 buf
[sizeof(buf
) - 1] = '\0';
409 while (fgets(buf
, sizeof(buf
), fp
)) {
410 for (cp1
= buf
; *cp1
&& !isspace(*cp1
); ++cp1
)
415 if (!strcasecmp(buf
, name
)) {
416 while (isspace(*++cp1
))
420 for (cp2
= cp1
+ 1; *cp2
&& !isspace(*cp2
); ++cp2
)
422 abuf
[sizeof(abuf
) - 1] = *cp2
= '\0';
423 strncpy(abuf
, cp1
, sizeof(abuf
) - 1);