mirror of
https://sourceware.org/git/glibc.git
synced 2025-06-15 06:41:47 +03:00
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.
This commit is contained in:
@ -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);
|
||||
|
Reference in New Issue
Block a user