diff options
author | Ulrich Drepper <drepper@redhat.com> | 1999-12-04 18:05:55 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 1999-12-04 18:05:55 +0000 |
commit | b43b13ac2544b11f35be301d1589b51a8473e32b (patch) | |
tree | 6520da2e17c933ebc29b4572cdcc27410b10a4c4 /resolv/res_query.c | |
parent | 591e1ffbf8db5e059b9bcf3bde6d7758f018a46d (diff) | |
download | glibc-b43b13ac2544b11f35be301d1589b51a8473e32b.tar.gz glibc-b43b13ac2544b11f35be301d1589b51a8473e32b.tar.xz glibc-b43b13ac2544b11f35be301d1589b51a8473e32b.zip |
Update.
1999-12-03 Andreas Jaeger <aj@suse.de> * nss/getXXbyYY.c: Include <resolv.h> (FUNCTION_NAME): Use res_ninit instead of res_init. * nss/getXXbyYY_r.c [NEED__RES]: Include <resolv.h> for _res declaration and prototypes. Remove extra _res declaration. (INTERNAL): Use thread aware res_ninit function. * inet/gethstbyad_r.c: Include <resolv.h>. * resolv/res_data.c: Update from Bind 8.2.2-P5. Moved res_init to res_libc.c. Disabled unneeded functions. * resolv/res_libc.c: New file. * Versions.def: Add version GLIBC_2.2 for libpthread. Add versions GLIBC_2.1 and GLIBC_2.2 for libresolv. * include/resolv.h: Add internal interfaces. * resolv/Makefile (routines): Add new files. (libresolv-routines): Likewise. (distribute): Likewise. * resolv/gethnamaddr.c: Use thread safe resolver functions. * resolv/nss_dns/dns-host.c: Likewise. * resolv/nss_dns/dns-network.c: Likewise. * resolv/arpa/nameser.h: Update from Bind 8.2.2-P5. * resolv/nsap_addr.c: Likewise. * resolv/res_comp.c: Likewise. * resolv/res_debug.c: Likewise. * resolv/res_init.c: Likewise. * resolv/res_mkquery.c: Likewise. * resolv/res_query.c: Likewise. * resolv/res_send.c: Likewise. * resolv/resolv.h: Likewise. * resolv/Versions: Add __res_state and __res_ninit with version GLIBC_2.2 to libc. Add new interfaces with version GLIBC_2.2 to libresolv. * resolv/Banner: Update. * include/arpa/nameser_compat.h: New file. * resolv/ns_name.c: New file from Bind 8.2.2-P5. * resolv/ns_netint.c: Likewise. * resolv/ns_parse.c: Likewise. * resolv/ns_print.c: Likewise. * resolv/ns_samedomain.c: Likewise. * resolv/ns_ttl.c: Likewise. * resolv/arpa/nameser_compat.h: Likewise. * resolv/res_debug.h: Likewise. Some patches are based on work done by Adam D. Bradley <artdodge@cs.bu.edu>. * sysdeps/unix/sysv/linux/configure.in: Remove check for ldconfig, set always use_ldconfig instead.
Diffstat (limited to 'resolv/res_query.c')
-rw-r--r-- | resolv/res_query.c | 261 |
1 files changed, 131 insertions, 130 deletions
diff --git a/resolv/res_query.c b/resolv/res_query.c index 80c10344f9..deebf4c62b 100644 --- a/resolv/res_query.c +++ b/resolv/res_query.c @@ -1,6 +1,4 @@ /* - * ++Copyright++ 1988, 1993 - * - * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * @@ -27,7 +25,9 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - + */ + +/* * Portions Copyright (c) 1993 by Digital Equipment Corporation. * * Permission to use, copy, modify, and distribute this software for any @@ -45,13 +45,28 @@ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. - * - - * --Copyright-- + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. */ #if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)res_query.c 8.1 (Berkeley) 6/4/93"; -static char rcsid[] = "$Id$"; +static const char sccsid[] = "@(#)res_query.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id$"; #endif /* LIBC_SCCS and not lint */ #include <sys/types.h> @@ -59,22 +74,16 @@ static char rcsid[] = "$Id$"; #include <netinet/in.h> #include <arpa/inet.h> #include <arpa/nameser.h> - -#include <stdio.h> -#include <netdb.h> -#include <resolv.h> #include <ctype.h> #include <errno.h> -#if defined(BSD) && (BSD >= 199306) -# include <stdlib.h> -# include <string.h> -#else -# include "../conf/portability.h" -#endif +#include <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> -#if defined(USE_OPTIONS_H) -# include <../conf/options.h> -#endif +/* Options. Leave them on. */ +/* #undef DEBUG */ #if PACKETSZ > 1024 #define MAXPACKET PACKETSZ @@ -82,82 +91,75 @@ static char rcsid[] = "$Id$"; #define MAXPACKET 1024 #endif -const char *hostalias __P((const char *)); - - /* * Formulate a normal query, send, and await answer. * Returned answer is placed in supplied buffer "answer". * Perform preliminary check of answer, returning success only * if no error is indicated and the answer count is nonzero. * Return the size of the response on success, -1 on error. - * Error number is left in h_errno. + * Error number is left in H_ERRNO. * * Caller must parse answer and determine whether it answers the question. */ int -res_query(name, class, type, answer, anslen) - const char *name; /* domain name */ - int class, type; /* class and type of query */ - u_char *answer; /* buffer to put answer */ - int anslen; /* size of answer buffer */ +res_nquery(res_state statp, + const char *name, /* domain name */ + int class, int type, /* class and type of query */ + u_char *answer, /* buffer to put answer */ + int anslen) /* size of answer buffer */ { u_char buf[MAXPACKET]; - register HEADER *hp = (HEADER *) answer; + HEADER *hp = (HEADER *) answer; int n; hp->rcode = NOERROR; /* default */ - if ((_res.options & RES_INIT) == 0 && res_init() == -1) { - __set_h_errno (NETDB_INTERNAL); - return (-1); - } #ifdef DEBUG - if (_res.options & RES_DEBUG) + if (statp->options & RES_DEBUG) printf(";; res_query(%s, %d, %d)\n", name, class, type); #endif - n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL, - buf, sizeof(buf)); + n = res_nmkquery(statp, QUERY, name, class, type, NULL, 0, NULL, + buf, sizeof(buf)); if (n <= 0) { #ifdef DEBUG - if (_res.options & RES_DEBUG) + if (statp->options & RES_DEBUG) printf(";; res_query: mkquery failed\n"); #endif - __set_h_errno (NO_RECOVERY); + RES_SET_H_ERRNO(statp, NO_RECOVERY); return (n); } - n = res_send(buf, n, answer, anslen); + n = res_nsend(statp, buf, n, answer, anslen); if (n < 0) { #ifdef DEBUG - if (_res.options & RES_DEBUG) + if (statp->options & RES_DEBUG) printf(";; res_query: send error\n"); #endif - __set_h_errno (TRY_AGAIN); + RES_SET_H_ERRNO(statp, TRY_AGAIN); return (n); } if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) { #ifdef DEBUG - if (_res.options & RES_DEBUG) + if (statp->options & RES_DEBUG) printf(";; rcode = %d, ancount=%d\n", hp->rcode, ntohs(hp->ancount)); #endif switch (hp->rcode) { case NXDOMAIN: - __set_h_errno (HOST_NOT_FOUND); + RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); break; case SERVFAIL: - __set_h_errno (TRY_AGAIN); + RES_SET_H_ERRNO(statp, TRY_AGAIN); break; case NOERROR: - __set_h_errno (NO_DATA); + RES_SET_H_ERRNO(statp, NO_DATA); break; case FORMERR: case NOTIMP: case REFUSED: default: - __set_h_errno (NO_RECOVERY); + RES_SET_H_ERRNO(statp, NO_RECOVERY); break; } return (-1); @@ -169,52 +171,43 @@ res_query(name, class, type, answer, anslen) * Formulate a normal query, send, and retrieve answer in supplied buffer. * Return the size of the response on success, -1 on error. * If enabled, implement search rules until answer or unrecoverable failure - * is detected. Error code, if any, is left in h_errno. + * is detected. Error code, if any, is left in H_ERRNO. */ int -res_search(name, class, type, answer, anslen) - const char *name; /* domain name */ - int class, type; /* class and type of query */ - u_char *answer; /* buffer to put answer */ - int anslen; /* size of answer */ +res_nsearch(res_state statp, + const char *name, /* domain name */ + int class, int type, /* class and type of query */ + u_char *answer, /* buffer to put answer */ + int anslen) /* size of answer */ { - register const char *cp, * const *domain; + const char *cp, * const *domain; HEADER *hp = (HEADER *) answer; + char tmp[NS_MAXDNAME]; u_int dots; - int trailing_dot, ret, saved_herrno; - int got_nodata = 0, got_servfail = 0, tried_as_is = 0; + int trailing_dot, ret; + int got_nodata = 0, got_servfail = 0, root_on_list = 0; - if ((_res.options & RES_INIT) == 0 && res_init() == -1) { - __set_h_errno (NETDB_INTERNAL); - return (-1); - } __set_errno (0); - __set_h_errno (HOST_NOT_FOUND); /* default, if we never query */ + RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); /* True if we never query. */ + dots = 0; - for (cp = name; *cp; cp++) + for (cp = name; *cp != '\0'; cp++) dots += (*cp == '.'); trailing_dot = 0; if (cp > name && *--cp == '.') trailing_dot++; - /* - * if there aren't any dots, it could be a user-level alias - */ - if (!dots && (cp = __hostalias(name)) != NULL) - return (res_query(cp, class, type, answer, anslen)); + /* If there aren't any dots, it could be a user-level alias. */ + if (!dots && (cp = res_hostalias(statp, name, tmp, sizeof tmp))!= NULL) + return (res_nquery(statp, cp, class, type, answer, anslen)); /* - * If there are dots in the name already, let's just give it a try - * 'as is'. The threshold can be set with the "ndots" option. + * If there are enough dots in the name, do no searching. + * (The threshold can be set with the "ndots" option.) */ - saved_herrno = -1; - if (dots >= _res.ndots) { - ret = res_querydomain(name, NULL, class, type, answer, anslen); - if (ret > 0) - return (ret); - saved_herrno = h_errno; - tried_as_is++; - } + if (dots >= statp->ndots || trailing_dot) + return (res_nquerydomain(statp, name, NULL, class, type, + answer, anslen)); /* * We do at least one level of search if @@ -222,16 +215,21 @@ res_search(name, class, type, answer, anslen) * - there is at least one dot, there is no trailing dot, * and RES_DNSRCH is set. */ - if ((!dots && (_res.options & RES_DEFNAMES)) || - (dots && !trailing_dot && (_res.options & RES_DNSRCH))) { + if ((!dots && (statp->options & RES_DEFNAMES) != 0) || + (dots && !trailing_dot && (statp->options & RES_DNSRCH) != 0)) { int done = 0; - for (domain = (const char * const *)_res.dnsrch; + for (domain = (const char * const *)statp->dnsrch; *domain && !done; domain++) { - ret = res_querydomain(name, *domain, class, type, - answer, anslen); + if (domain[0][0] == '\0' || + (domain[0][0] == '.' && domain[0][1] == '\0')) + root_on_list++; + + ret = res_nquerydomain(statp, name, *domain, + class, type, + answer, anslen); if (ret > 0) return (ret); @@ -249,11 +247,11 @@ res_search(name, class, type, answer, anslen) * fully-qualified. */ if (errno == ECONNREFUSED) { - __set_h_errno (TRY_AGAIN); + RES_SET_H_ERRNO(statp, TRY_AGAIN); return (-1); } - switch (h_errno) { + switch (statp->res_h_errno) { case NO_DATA: got_nodata++; /* FALLTHROUGH */ @@ -275,34 +273,33 @@ res_search(name, class, type, answer, anslen) /* if we got here for some reason other than DNSRCH, * we only wanted one iteration of the loop, so stop. */ - if (!(_res.options & RES_DNSRCH)) + if ((statp->options & RES_DNSRCH) == 0) done++; } } - /* if we have not already tried the name "as is", do that now. - * note that we do this regardless of how many dots were in the - * name or whether it ends with a dot. + /* + * If the name has any dots at all, and "." is not on the search + * list, then try an as-is query now. */ - if (!tried_as_is) { - ret = res_querydomain(name, NULL, class, type, answer, anslen); + if (statp->ndots) { + ret = res_nquerydomain(statp, name, NULL, class, type, + answer, anslen); if (ret > 0) return (ret); } /* if we got here, we didn't satisfy the search. - * if we did an initial full query, return that query's h_errno + * if we did an initial full query, return that query's H_ERRNO * (note that we wouldn't be here if that query had succeeded). * else if we ever got a nodata, send that back as the reason. - * else send back meaningless h_errno, that being the one from + * else send back meaningless H_ERRNO, that being the one from * the last DNSRCH we did. */ - if (saved_herrno != -1) - __set_h_errno (saved_herrno); - else if (got_nodata) - __set_h_errno (NO_DATA); + if (got_nodata) + RES_SET_H_ERRNO(statp, NO_DATA); else if (got_servfail) - __set_h_errno (TRY_AGAIN); + RES_SET_H_ERRNO(statp, TRY_AGAIN); return (-1); } @@ -311,23 +308,20 @@ res_search(name, class, type, answer, anslen) * removing a trailing dot from name if domain is NULL. */ int -res_querydomain(name, domain, class, type, answer, anslen) - const char *name, *domain; - int class, type; /* class and type of query */ - u_char *answer; /* buffer to put answer */ - int anslen; /* size of answer */ +res_nquerydomain(res_state statp, + const char *name, + const char *domain, + int class, int type, /* class and type of query */ + u_char *answer, /* buffer to put answer */ + int anslen) /* size of answer */ { - char nbuf[MAXDNAME * 2 + 2]; + char nbuf[MAXDNAME]; const char *longname = nbuf; - int n; + int n, d; - if ((_res.options & RES_INIT) == 0 && res_init() == -1) { - __set_h_errno (NETDB_INTERNAL); - return (-1); - } #ifdef DEBUG - if (_res.options & RES_DEBUG) - printf(";; res_querydomain(%s, %s, %d, %d)\n", + if (statp->options & RES_DEBUG) + printf(";; res_nquerydomain(%s, %s, %d, %d)\n", name, domain?domain:"<Nil>", class, type); #endif if (domain == NULL) { @@ -335,30 +329,36 @@ res_querydomain(name, domain, class, type, answer, anslen) * Check for trailing '.'; * copy without '.' if present. */ - n = strlen(name) - 1; - if (n != (0 - 1) && name[n] == '.' - && n < (int) (sizeof(nbuf) - 1)) { - bcopy(name, nbuf, n); + n = strlen(name); + if (n >= MAXDNAME) { + RES_SET_H_ERRNO(statp, NO_RECOVERY); + return (-1); + } + n--; + if (n >= 0 && name[n] == '.') { + strncpy(nbuf, name, n); nbuf[n] = '\0'; } else longname = name; - } else - sprintf(nbuf, "%.*s.%.*s", MAXDNAME, name, MAXDNAME, domain); - - return (res_query(longname, class, type, answer, anslen)); + } else { + n = strlen(name); + d = strlen(domain); + if (n + d + 1 >= MAXDNAME) { + RES_SET_H_ERRNO(statp, NO_RECOVERY); + return (-1); + } + sprintf(nbuf, "%s.%s", name, domain); + } + return (res_nquery(statp, longname, class, type, answer, anslen)); } const char * -hostalias(name) - register const char *name; -{ - register char *cp1, *cp2; - FILE *fp; - char *file; +res_hostalias(const res_state statp, const char *name, char *dst, size_t siz) { + char *file, *cp1, *cp2; char buf[BUFSIZ]; - static char abuf[MAXDNAME]; + FILE *fp; - if (_res.options & RES_NOALIASES) + if (statp->options & RES_NOALIASES) return (NULL); file = __secure_getenv("HOSTALIASES"); if (file == NULL || (fp = fopen(file, "r")) == NULL) @@ -371,17 +371,18 @@ hostalias(name) if (!*cp1) break; *cp1 = '\0'; - if (!strcasecmp(buf, name)) { + if (ns_samename(buf, name) == 1) { while (isspace(*++cp1)) ; if (!*cp1) break; for (cp2 = cp1 + 1; *cp2 && !isspace(*cp2); ++cp2) ; - abuf[sizeof(abuf) - 1] = *cp2 = '\0'; - strncpy(abuf, cp1, sizeof(abuf) - 1); + *cp2 = '\0'; + strncpy(dst, cp1, siz - 1); + dst[siz - 1] = '\0'; fclose(fp); - return (abuf); + return (dst); } } fclose(fp); |