diff options
Diffstat (limited to 'lib/libc/resolv')
-rw-r--r-- | lib/libc/resolv/Makefile.inc | 9 | ||||
-rw-r--r-- | lib/libc/resolv/Symbol.map | 105 | ||||
-rw-r--r-- | lib/libc/resolv/h_errno.c | 49 | ||||
-rw-r--r-- | lib/libc/resolv/herror.c | 11 | ||||
-rw-r--r-- | lib/libc/resolv/mtctxres.c | 14 | ||||
-rw-r--r-- | lib/libc/resolv/res_comp.c | 11 | ||||
-rw-r--r-- | lib/libc/resolv/res_data.c | 41 | ||||
-rw-r--r-- | lib/libc/resolv/res_debug.c | 27 | ||||
-rw-r--r-- | lib/libc/resolv/res_init.c | 87 | ||||
-rw-r--r-- | lib/libc/resolv/res_mkquery.c | 14 | ||||
-rw-r--r-- | lib/libc/resolv/res_query.c | 55 | ||||
-rw-r--r-- | lib/libc/resolv/res_send.c | 118 | ||||
-rw-r--r-- | lib/libc/resolv/res_state.c | 96 |
13 files changed, 585 insertions, 52 deletions
diff --git a/lib/libc/resolv/Makefile.inc b/lib/libc/resolv/Makefile.inc new file mode 100644 index 0000000..c185b47 --- /dev/null +++ b/lib/libc/resolv/Makefile.inc @@ -0,0 +1,9 @@ +# $FreeBSD$ + +# resolv sources +.PATH: ${.CURDIR}/resolv + +SRCS+= herror.c h_errno.c mtctxres.c res_comp.c res_data.c res_debug.c \ + res_init.c res_mkquery.c res_query.c res_send.c res_state.c + +SYM_MAPS+= ${.CURDIR}/resolv/Symbol.map diff --git a/lib/libc/resolv/Symbol.map b/lib/libc/resolv/Symbol.map new file mode 100644 index 0000000..7aa2256 --- /dev/null +++ b/lib/libc/resolv/Symbol.map @@ -0,0 +1,105 @@ +# $FreeBSD$ + +FBSD_1.0 { + #h_nerr; # Why is this not staticized in net/herror.c? + h_errlist; + herror; + hstrerror; + __dn_expand; + __dn_comp; + __dn_skipname; + __res_hnok; + __res_ownok; + __res_mailok; + __res_dnok; + __putlong; + __putshort; + _getlong; + _getshort; + dn_comp; + dn_expand; + __fp_resstat; + __p_query; + __fp_query; + __fp_nquery; + __p_cdnname; + __p_cdname; + __p_fqnname; + __p_fqname; + __p_cert_syms; + __p_class_syms; + __p_key_syms; + __p_type_syms; + __sym_ston; + __sym_ntos; + __sym_ntop; + __p_rcode; + __p_sockun; + __p_type; + __p_section; + __p_class; + __p_option; + __p_time; + __loc_aton; + __loc_ntoa; + __dn_count_labels; + __p_secstodate; + fp_resstat; + p_query; + p_fqnname; + sym_ston; + sym_ntos; + sym_ntop; + dn_count_labels; + p_secstodate; + __res_init; + __res_randomid; + ___res; + ___res_ext; + __h_errno; + __h_errno_set; + __h_error; + h_errno; + res_init; + __res_mkquery; + res_mkquery; + __res_opt; + __res_freeupdrec; + #__res_get_nibblesuffix; # Excluded + #__res_get_nibblesuffix2; # Excluded + __res_getservers; + __res_hostalias; + __res_nametoclass; + __res_nametotype; + __res_nclose; + __res_ndestroy; + __res_ninit; + __res_nmkquery; + __res_nopt; + __res_nquery; + __res_nquerydomain; + __res_nsearch; + __res_nsend; + __res_ourserver_p; + __res_pquery; + __res_query; + __res_search; + __res_querydomain; + __res_setservers; + _res; + __res_state; + __res_vinit; + __hostalias; + res_query; + res_search; + res_querydomain; + __res_isourserver; + __res_nameinquery; + __res_queriesmatch; + __res_send; + __res_close; + _res_close; + res_send; + __res_mkupdate; + res_update; # Why is this not __res_update? +}; diff --git a/lib/libc/resolv/h_errno.c b/lib/libc/resolv/h_errno.c new file mode 100644 index 0000000..4d471b4 --- /dev/null +++ b/lib/libc/resolv/h_errno.c @@ -0,0 +1,49 @@ +/*- + * Copyright (c) 2006 The FreeBSD Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * 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. + * + * $FreeBSD$ + */ + +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> + +#undef h_errno +extern int h_errno; + +int * +__h_errno(void) +{ + return (&__res_state()->res_h_errno); +} + +void +__h_errno_set(res_state res, int err) +{ + h_errno = res->res_h_errno = err; +} + +/* binary backward compatibility for FreeBSD 5.x and 6.x */ +__weak_reference(__h_errno, __h_error); diff --git a/lib/libc/resolv/herror.c b/lib/libc/resolv/herror.c index 58807e9..be4b43e 100644 --- a/lib/libc/resolv/herror.c +++ b/lib/libc/resolv/herror.c @@ -52,9 +52,12 @@ static const char sccsid[] = "@(#)herror.c 8.1 (Berkeley) 6/4/93"; static const char rcsid[] = "$Id: herror.c,v 1.2.206.1 2004/03/09 08:33:54 marka Exp $"; #endif /* LIBC_SCCS and not lint */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); #include "port_before.h" +#include "namespace.h" #include <sys/types.h> #include <sys/param.h> #include <sys/uio.h> @@ -66,7 +69,7 @@ static const char rcsid[] = "$Id: herror.c,v 1.2.206.1 2004/03/09 08:33:54 marka #include <resolv.h> #include <string.h> #include <unistd.h> -#include <irs.h> +#include "un-namespace.h" #include "port_after.h" @@ -77,12 +80,10 @@ const char *h_errlist[] = { "Unknown server error", /* 3 NO_RECOVERY */ "No address associated with name", /* 4 NO_ADDRESS */ }; -int h_nerr = { sizeof h_errlist / sizeof h_errlist[0] }; +const int h_nerr = { sizeof h_errlist / sizeof h_errlist[0] }; -#if !(__GLIBC__ > 2 || __GLIBC__ == 2 && __GLIBC_MINOR__ >= 3) #undef h_errno int h_errno; -#endif /* * herror -- @@ -110,7 +111,7 @@ herror(const char *s) { DE_CONST("\n", t); v->iov_base = t; v->iov_len = 1; - writev(STDERR_FILENO, iov, (v - iov) + 1); + _writev(STDERR_FILENO, iov, (v - iov) + 1); } /* diff --git a/lib/libc/resolv/mtctxres.c b/lib/libc/resolv/mtctxres.c index f33cf11..86b5a79 100644 --- a/lib/libc/resolv/mtctxres.c +++ b/lib/libc/resolv/mtctxres.c @@ -1,13 +1,18 @@ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + #include <port_before.h> #ifdef DO_PTHREADS #include <pthread.h> +#ifdef _LIBC +#include <pthread_np.h> +#endif #endif #include <errno.h> #include <netdb.h> #include <stdlib.h> #include <string.h> #include <resolv_mt.h> -#include <irs.h> #include <port_after.h> #ifdef DO_PTHREADS @@ -40,6 +45,7 @@ _mtctxres_init(void) { } #endif +#ifndef _LIBC /* * To support binaries that used the private MT-safe interface in * Solaris 8, we still need to provide the __res_enable_mt() @@ -54,6 +60,7 @@ int __res_disable_mt(void) { return (0); } +#endif #ifdef DO_PTHREADS static int @@ -99,6 +106,11 @@ ___mtctxres(void) { #ifdef DO_PTHREADS mtctxres_t *mt; +#ifdef _LIBC + if (pthread_main_np() != 0) + return (&sharedctx); +#endif + /* * This if clause should only be executed if we are linking * statically. When linked dynamically _mtctxres_init() should diff --git a/lib/libc/resolv/res_comp.c b/lib/libc/resolv/res_comp.c index 8cc99a7..cf45f07 100644 --- a/lib/libc/resolv/res_comp.c +++ b/lib/libc/resolv/res_comp.c @@ -72,6 +72,8 @@ static const char sccsid[] = "@(#)res_comp.c 8.1 (Berkeley) 6/4/93"; static const char rcsid[] = "$Id: res_comp.c,v 1.1.2.1.4.2 2005/07/28 07:43:22 marka Exp $"; #endif /* LIBC_SCCS and not lint */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); #include "port_before.h" #include <sys/types.h> @@ -261,3 +263,12 @@ u_int32_t _getlong(const u_char *src) { return (ns_get32(src)); } u_int16_t _getshort(const u_char *src) { return (ns_get16(src)); } #endif /*__ultrix__*/ #endif /*BIND_4_COMPAT*/ + +/* + * Weak aliases for applications that use certain private entry points, + * and fail to include <resolv.h>. + */ +#undef dn_comp +__weak_reference(__dn_comp, dn_comp); +#undef dn_expand +__weak_reference(__dn_expand, dn_expand); diff --git a/lib/libc/resolv/res_data.c b/lib/libc/resolv/res_data.c index 204e03d..ab6d575 100644 --- a/lib/libc/resolv/res_data.c +++ b/lib/libc/resolv/res_data.c @@ -18,6 +18,8 @@ #if defined(LIBC_SCCS) && !defined(lint) static const char rcsid[] = "$Id: res_data.c,v 1.1.206.2 2004/03/16 12:34:18 marka Exp $"; #endif /* LIBC_SCCS and not lint */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); #include "port_before.h" @@ -40,7 +42,6 @@ static const char rcsid[] = "$Id: res_data.c,v 1.1.206.2 2004/03/16 12:34:18 mar #include <unistd.h> #include "port_after.h" -#undef _res const char *_res_opcodes[] = { "QUERY", @@ -71,11 +72,6 @@ const char *_res_sectioncodes[] = { #endif #ifndef __BIND_NOSTATIC -struct __res_state _res -# if defined(__BIND_RES_TEXT) - = { RES_TIMEOUT, } /* Motorola, et al. */ -# endif - ; /* Proto. */ @@ -107,7 +103,7 @@ res_init(void) { if (!_res.retrans) _res.retrans = RES_TIMEOUT; if (!_res.retry) - _res.retry = 4; + _res.retry = RES_DFLRETRY; if (!(_res.options & RES_INIT)) _res.options = RES_DEFAULT; @@ -181,6 +177,7 @@ res_query(const char *name, /* domain name */ return (res_nquery(&_res, name, class, type, answer, anslen)); } +#ifndef _LIBC void res_send_setqhook(res_send_qhook hook) { _res.qhook = hook; @@ -190,6 +187,7 @@ void res_send_setrhook(res_send_rhook hook) { _res.rhook = hook; } +#endif int res_isourserver(const struct sockaddr_in *inp) { @@ -206,6 +204,7 @@ res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) { return (res_nsend(&_res, buf, buflen, ans, anssiz)); } +#ifndef _LIBC int res_sendsigned(const u_char *buf, int buflen, ns_tsig_key *key, u_char *ans, int anssiz) @@ -217,6 +216,7 @@ res_sendsigned(const u_char *buf, int buflen, ns_tsig_key *key, return (res_nsendsigned(&_res, buf, buflen, key, ans, anssiz)); } +#endif void res_close(void) { @@ -264,6 +264,12 @@ res_querydomain(const char *name, answer, anslen)); } +int +res_opt(int n0, u_char *buf, int buflen, int anslen) +{ + return (res_nopt(&_res, n0, buf, buflen, anslen)); +} + const char * hostalias(const char *name) { static char abuf[MAXDNAME]; @@ -288,4 +294,25 @@ local_hostname_length(const char *hostname) { } #endif /*ultrix*/ +/* + * Weak aliases for applications that use certain private entry points, + * and fail to include <resolv.h>. + */ +#undef res_init +__weak_reference(__res_init, res_init); +#undef p_query +__weak_reference(__p_query, p_query); +#undef res_mkquery +__weak_reference(__res_mkquery, res_mkquery); +#undef res_query +__weak_reference(__res_query, res_query); +#undef res_send +__weak_reference(__res_send, res_send); +#undef res_close +__weak_reference(__res_close, _res_close); +#undef res_search +__weak_reference(__res_search, res_search); +#undef res_querydomain +__weak_reference(__res_querydomain, res_querydomain); + #endif diff --git a/lib/libc/resolv/res_debug.c b/lib/libc/resolv/res_debug.c index 8dda12c..29c6ef4 100644 --- a/lib/libc/resolv/res_debug.c +++ b/lib/libc/resolv/res_debug.c @@ -97,6 +97,8 @@ static const char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93"; static const char rcsid[] = "$Id: res_debug.c,v 1.3.2.5.4.6 2005/07/28 07:43:22 marka Exp $"; #endif /* LIBC_SCCS and not lint */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); #include "port_before.h" @@ -375,7 +377,7 @@ const struct res_sym __p_class_syms[] = { /* * Names of message sections. */ -const struct res_sym __p_default_section_syms[] = { +static const struct res_sym __p_default_section_syms[] = { {ns_s_qd, "QUERY", (char *)0}, {ns_s_an, "ANSWER", (char *)0}, {ns_s_ns, "AUTHORITY", (char *)0}, @@ -383,7 +385,7 @@ const struct res_sym __p_default_section_syms[] = { {0, (char *)0, (char *)0} }; -const struct res_sym __p_update_section_syms[] = { +static const struct res_sym __p_update_section_syms[] = { {S_ZONE, "ZONE", (char *)0}, {S_PREREQ, "PREREQUISITE", (char *)0}, {S_UPDATE, "UPDATE", (char *)0}, @@ -470,7 +472,7 @@ const struct res_sym __p_type_syms[] = { /* * Names of DNS rcodes. */ -const struct res_sym __p_rcode_syms[] = { +static const struct res_sym __p_rcode_syms[] = { {ns_r_noerror, "NOERROR", "no error"}, {ns_r_formerr, "FORMERR", "format error"}, {ns_r_servfail, "SERVFAIL", "server failed"}, @@ -1161,3 +1163,22 @@ res_nametotype(const char *buf, int *successp) { *successp = success; return (result); } + +/* + * Weak aliases for applications that use certain private entry points, + * and fail to include <resolv.h>. + */ +#undef fp_resstat +__weak_reference(__fp_resstat, fp_resstat); +#undef p_fqnname +__weak_reference(__p_fqnname, p_fqnname); +#undef sym_ston +__weak_reference(__sym_ston, sym_ston); +#undef sym_ntos +__weak_reference(__sym_ntos, sym_ntos); +#undef sym_ntop +__weak_reference(__sym_ntop, sym_ntop); +#undef dn_count_labels +__weak_reference(__dn_count_labels, dn_count_labels); +#undef p_secstodate +__weak_reference(__p_secstodate, p_secstodate); diff --git a/lib/libc/resolv/res_init.c b/lib/libc/resolv/res_init.c index 28a3ebd..30ff9dc 100644 --- a/lib/libc/resolv/res_init.c +++ b/lib/libc/resolv/res_init.c @@ -72,6 +72,8 @@ static const char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93"; static const char rcsid[] = "$Id: res_init.c,v 1.9.2.5.4.5 2005/11/03 00:00:52 marka Exp $"; #endif /* LIBC_SCCS and not lint */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); #include "port_before.h" @@ -106,12 +108,12 @@ static const char rcsid[] = "$Id: res_init.c,v 1.9.2.5.4.5 2005/11/03 00:00:52 m #include <sys/systeminfo.h> #endif -static void res_setoptions __P((res_state, const char *, const char *)); +static void res_setoptions(res_state, const char *, const char *); #ifdef RESOLVSORT static const char sort_mask[] = "/&"; #define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL) -static u_int32_t net_mask __P((struct in_addr)); +static u_int32_t net_mask(struct in_addr); #endif #if !defined(isascii) /* XXX - could be a function */ @@ -153,9 +155,9 @@ res_ninit(res_state statp) { /* This function has to be reachable by res_data.c but not publically. */ int __res_vinit(res_state statp, int preinit) { - register FILE *fp; - register char *cp, **pp; - register int n; + FILE *fp; + char *cp, **pp; + int n; char buf[BUFSIZ]; int nserv = 0; /* number of nameserver records read from file */ int haveenv = 0; @@ -253,7 +255,7 @@ __res_vinit(res_state statp, int preinit) { #endif /* SOLARIS2 */ /* Allow user to override the local domain definition */ - if ((cp = getenv("LOCALDOMAIN")) != NULL) { + if (issetugid() == 0 && (cp = getenv("LOCALDOMAIN")) != NULL) { (void)strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1); statp->defdname[sizeof(statp->defdname) - 1] = '\0'; haveenv++; @@ -390,6 +392,10 @@ __res_vinit(res_state statp, int preinit) { #ifdef RESOLVSORT if (MATCH(buf, "sortlist")) { struct in_addr a; + struct in6_addr a6; + int m, i; + u_char *u; + struct __res_state_ext *ext = statp->_u._ext.ext; cp = buf + sizeof("sortlist") - 1; while (nsort < MAXRESOLVSORT) { @@ -424,6 +430,57 @@ __res_vinit(res_state statp, int preinit) { statp->sort_list[nsort].mask = net_mask(statp->sort_list[nsort].addr); } + ext->sort_list[nsort].af = AF_INET; + ext->sort_list[nsort].addr.ina = + statp->sort_list[nsort].addr; + ext->sort_list[nsort].mask.ina.s_addr = + statp->sort_list[nsort].mask; + nsort++; + } + else if (inet_pton(AF_INET6, net, &a6) == 1) { + + ext->sort_list[nsort].af = AF_INET6; + ext->sort_list[nsort].addr.in6a = a6; + u = (u_char *)&ext->sort_list[nsort].mask.in6a; + *cp++ = n; + net = cp; + while (*cp && *cp != ';' && + isascii(*cp) && !isspace(*cp)) + cp++; + m = n; + n = *cp; + *cp = 0; + switch (m) { + case '/': + m = atoi(net); + break; + case '&': + if (inet_pton(AF_INET6, net, u) == 1) { + m = -1; + break; + } + /*FALLTHROUGH*/ + default: + m = sizeof(struct in6_addr) * CHAR_BIT; + break; + } + if (m >= 0) { + for (i = 0; i < sizeof(struct in6_addr); i++) { + if (m <= 0) { + *u = 0; + } else { + m -= CHAR_BIT; + *u = (u_char)~0; + if (m < 0) + *u <<= -m; + } + u++; + } + } + statp->sort_list[nsort].addr.s_addr = + (u_int32_t)0xffffffff; + statp->sort_list[nsort].mask = + (u_int32_t)0xffffffff; nsort++; } *cp = n; @@ -486,7 +543,9 @@ __res_vinit(res_state statp, int preinit) { #endif } - if ((cp = getenv("RES_OPTIONS")) != NULL) + if (issetugid()) + statp->options |= RES_NOALIASES; + else if ((cp = getenv("RES_OPTIONS")) != NULL) res_setoptions(statp, cp, "env"); statp->options |= RES_INIT; return (0); @@ -506,7 +565,9 @@ res_setoptions(res_state statp, const char *options, const char *source) { const char *cp = options; int i; +#ifndef _LIBC struct __res_state_ext *ext = statp->_u._ext.ext; +#endif #ifdef DEBUG if (statp->options & RES_DEBUG) @@ -580,6 +641,10 @@ res_setoptions(res_state statp, const char *options, const char *source) statp->options |= RES_NOTLDQUERY; } else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) { statp->options |= RES_USE_INET6; + } else if (!strncmp(cp, "insecure1", sizeof("insecure1") - 1)) { + statp->options |= RES_INSECURE1; + } else if (!strncmp(cp, "insecure2", sizeof("insecure2") - 1)) { + statp->options |= RES_INSECURE2; } else if (!strncmp(cp, "rotate", sizeof("rotate") - 1)) { statp->options |= RES_ROTATE; } else if (!strncmp(cp, "no-check-names", @@ -591,6 +656,7 @@ res_setoptions(res_state statp, const char *options, const char *source) statp->options |= RES_USE_EDNS0; } #endif +#ifndef _LIBC else if (!strncmp(cp, "dname", sizeof("dname") - 1)) { statp->options |= RES_USE_DNAME; } @@ -620,10 +686,13 @@ res_setoptions(res_state statp, const char *options, const char *source) ~RES_NO_NIBBLE2; } } +#endif else { /* XXX - print a warning here? */ } +#ifndef _LIBC skip: +#endif /* skip to next run of spaces */ while (*cp && *cp != ' ' && *cp != '\t') cp++; @@ -636,7 +705,7 @@ static u_int32_t net_mask(in) /* XXX - should really use system's version of this */ struct in_addr in; { - register u_int32_t i = ntohl(in.s_addr); + u_int32_t i = ntohl(in.s_addr); if (IN_CLASSA(i)) return (htonl(IN_CLASSA_NET)); @@ -687,6 +756,7 @@ res_ndestroy(res_state statp) { statp->_u._ext.ext = NULL; } +#ifndef _LIBC const char * res_get_nibblesuffix(res_state statp) { if (statp->_u._ext.ext) @@ -700,6 +770,7 @@ res_get_nibblesuffix2(res_state statp) { return (statp->_u._ext.ext->nsuffix2); return ("ip6.int"); } +#endif void res_setservers(res_state statp, const union res_sockaddr_union *set, int cnt) { diff --git a/lib/libc/resolv/res_mkquery.c b/lib/libc/resolv/res_mkquery.c index 89000ed..60f1efc1 100644 --- a/lib/libc/resolv/res_mkquery.c +++ b/lib/libc/resolv/res_mkquery.c @@ -72,6 +72,8 @@ static const char sccsid[] = "@(#)res_mkquery.c 8.1 (Berkeley) 6/4/93"; static const char rcsid[] = "$Id: res_mkquery.c,v 1.1.2.2.4.2 2004/03/16 12:34:18 marka Exp $"; #endif /* LIBC_SCCS and not lint */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); #include "port_before.h" #include <sys/types.h> @@ -104,9 +106,9 @@ res_nmkquery(res_state statp, u_char *buf, /* buffer to put query */ int buflen) /* size of buffer */ { - register HEADER *hp; - register u_char *cp, *ep; - register int n; + HEADER *hp; + u_char *cp, *ep; + int n; u_char *dnptrs[20], **dpp, **lastdnptr; UNUSED(newrr_in); @@ -214,8 +216,8 @@ res_nopt(res_state statp, int buflen, /* size of buffer */ int anslen) /* UDP answer buffer size */ { - register HEADER *hp; - register u_char *cp, *ep; + HEADER *hp; + u_char *cp, *ep; u_int16_t flags = 0; #ifdef DEBUG @@ -234,6 +236,8 @@ res_nopt(res_state statp, ns_put16(T_OPT, cp); /* TYPE */ cp += INT16SZ; + if (anslen > 0xffff) + anslen = 0xffff; /* limit to 16bit value */ ns_put16(anslen & 0xffff, cp); /* CLASS = UDP payload size */ cp += INT16SZ; *cp++ = NOERROR; /* extended RCODE */ diff --git a/lib/libc/resolv/res_query.c b/lib/libc/resolv/res_query.c index 5156ce8..e715b85 100644 --- a/lib/libc/resolv/res_query.c +++ b/lib/libc/resolv/res_query.c @@ -72,6 +72,8 @@ static const char sccsid[] = "@(#)res_query.c 8.1 (Berkeley) 6/4/93"; static const char rcsid[] = "$Id: res_query.c,v 1.2.2.3.4.2 2004/03/16 12:34:19 marka Exp $"; #endif /* LIBC_SCCS and not lint */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); #include "port_before.h" #include <sys/types.h> @@ -86,6 +88,7 @@ static const char rcsid[] = "$Id: res_query.c,v 1.2.2.3.4.2 2004/03/16 12:34:19 #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <unistd.h> #include "port_after.h" /* Options. Leave them on. */ @@ -242,6 +245,21 @@ res_nsearch(res_state statp, answer, anslen); if (ret > 0 || trailing_dot) return (ret); + if (errno == ECONNREFUSED) { + RES_SET_H_ERRNO(statp, TRY_AGAIN); + return (-1); + } + switch (statp->res_h_errno) { + case NO_DATA: + case HOST_NOT_FOUND: + break; + case TRY_AGAIN: + if (hp->rcode == SERVFAIL) + break; + /* FALLTHROUGH */ + default: + return (-1); + } saved_herrno = statp->res_h_errno; tried_as_is++; } @@ -265,6 +283,9 @@ res_nsearch(res_state statp, (domain[0][0] == '.' && domain[0][1] == '\0')) root_on_list++; + if (root_on_list && tried_as_is) + continue; + ret = res_nquerydomain(statp, name, *domain, class, type, answer, anslen); @@ -297,9 +318,26 @@ res_nsearch(res_state statp, /* keep trying */ break; case TRY_AGAIN: + /* + * This can occur due to a server failure + * (that is, all listed servers have failed), + * or all listed servers have timed out. + * ((HEADER *)answer)->rcode may not be set + * to SERVFAIL in the case of a timeout. + * + * Either way we must return TRY_AGAIN in + * order to avoid non-deterministic + * return codes. + * For example, loaded name servers or races + * against network startup/validation (dhcp, + * ppp, etc) can cause the search to timeout + * on one search element, e.g. 'fu.bar.com', + * and return a definitive failure on the + * next search element, e.g. 'fu.'. + */ + got_servfail++; if (hp->rcode == SERVFAIL) { /* try next search element, if any */ - got_servfail++; break; } /* FALLTHROUGH */ @@ -316,6 +354,18 @@ res_nsearch(res_state statp, } } + switch (statp->res_h_errno) { + case NO_DATA: + case HOST_NOT_FOUND: + break; + case TRY_AGAIN: + if (hp->rcode == SERVFAIL) + break; + /* FALLTHROUGH */ + default: + goto giveup; + } + /* * If the query has not already been tried as is then try it * unless RES_NOTLDQUERY is set and there were no dots. @@ -335,6 +385,7 @@ res_nsearch(res_state statp, * else send back meaningless H_ERRNO, that being the one from * the last DNSRCH we did. */ +giveup: if (saved_herrno != -1) RES_SET_H_ERRNO(statp, saved_herrno); else if (got_nodata) @@ -401,6 +452,8 @@ res_hostalias(const res_state statp, const char *name, char *dst, size_t siz) { if (statp->options & RES_NOALIASES) return (NULL); + if (issetugid()) + return (NULL); file = getenv("HOSTALIASES"); if (file == NULL || (fp = fopen(file, "r")) == NULL) return (NULL); diff --git a/lib/libc/resolv/res_send.c b/lib/libc/resolv/res_send.c index 5be2489..f31abf1 100644 --- a/lib/libc/resolv/res_send.c +++ b/lib/libc/resolv/res_send.c @@ -72,14 +72,19 @@ static const char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93"; static const char rcsid[] = "$Id: res_send.c,v 1.5.2.2.4.7 2005/08/15 02:04:41 marka Exp $"; #endif /* LIBC_SCCS and not lint */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); /* * Send query to name server and wait for reply. */ #include "port_before.h" +#ifndef USE_KQUEUE #include "fd_setsize.h" +#endif +#include "namespace.h" #include <sys/types.h> #include <sys/param.h> #include <sys/time.h> @@ -103,12 +108,18 @@ static const char rcsid[] = "$Id: res_send.c,v 1.5.2.2.4.7 2005/08/15 02:04:41 m #include "port_after.h" +#ifdef USE_KQUEUE +#include <sys/event.h> +#else #ifdef USE_POLL #ifdef HAVE_STROPTS_H #include <stropts.h> #endif #include <poll.h> #endif /* USE_POLL */ +#endif + +#include "un-namespace.h" /* Options. Leave them on. */ #define DEBUG @@ -125,18 +136,22 @@ static int highestFD = 0; /* Forward. */ -static int get_salen __P((const struct sockaddr *)); -static struct sockaddr * get_nsaddr __P((res_state, size_t)); +static int get_salen(const struct sockaddr *); +static struct sockaddr * get_nsaddr(res_state, size_t); static int send_vc(res_state, const u_char *, int, u_char *, int, int *, int); -static int send_dg(res_state, const u_char *, int, +static int send_dg(res_state, +#ifdef USE_KQUEUE + int kq, +#endif + const u_char *, int, u_char *, int, int *, int, int *, int *); static void Aerror(const res_state, FILE *, const char *, int, const struct sockaddr *, int); static void Perror(const res_state, FILE *, const char *, int); static int sock_eq(struct sockaddr *, struct sockaddr *); -#if defined(NEED_PSELECT) && !defined(USE_POLL) +#if defined(NEED_PSELECT) && !defined(USE_POLL) && !defined(USE_KQUEUE) static int pselect(int, void *, void *, void *, struct timespec *, const sigset_t *); @@ -289,6 +304,9 @@ res_nsend(res_state statp, const u_char *buf, int buflen, u_char *ans, int anssiz) { int gotsomewhere, terrno, try, v_circuit, resplen, ns, n; +#ifdef USE_KQUEUE + int kq; +#endif char abuf[NI_MAXHOST]; #ifdef USE_POLL @@ -309,6 +327,13 @@ res_nsend(res_state statp, gotsomewhere = 0; terrno = ETIMEDOUT; +#ifdef USE_KQUEUE + if ((kq = kqueue()) < 0) { + Perror(statp, stderr, "kqueue", errno); + return (-1); + } +#endif + /* * If the ns_addr_list in the resolver context has changed, then * invalidate our cached copy and the associated timing data. @@ -332,7 +357,7 @@ res_nsend(res_state statp, if (EXT(statp).nssocks[ns] == -1) continue; peerlen = sizeof(peer); - if (getsockname(EXT(statp).nssocks[ns], + if (_getsockname(EXT(statp).nssocks[ns], (struct sockaddr *)&peer, &peerlen) < 0) { needclose++; break; @@ -424,6 +449,9 @@ res_nsend(res_state statp, res_nclose(statp); goto next_ns; case res_done: +#ifdef USE_KQUEUE + _close(kq); +#endif return (resplen); case res_modified: /* give the hook another try */ @@ -457,7 +485,11 @@ res_nsend(res_state statp, resplen = n; } else { /* Use datagrams. */ - n = send_dg(statp, buf, buflen, ans, anssiz, &terrno, + n = send_dg(statp, +#ifdef USE_KQUEUE + kq, +#endif + buf, buflen, ans, anssiz, &terrno, ns, &v_circuit, &gotsomewhere); if (n < 0) goto fail; @@ -516,11 +548,17 @@ res_nsend(res_state statp, } while (!done); } +#ifdef USE_KQUEUE + _close(kq); +#endif return (resplen); next_ns: ; } /*foreach ns*/ } /*foreach retry*/ res_nclose(statp); +#ifdef USE_KQUEUE + _close(kq); +#endif if (!v_circuit) { if (!gotsomewhere) errno = ECONNREFUSED; /* no nameservers found */ @@ -531,6 +569,9 @@ res_nsend(res_state statp, return (-1); fail: res_nclose(statp); +#ifdef USE_KQUEUE + _close(kq); +#endif return (-1); } @@ -608,7 +649,7 @@ send_vc(res_state statp, struct sockaddr_storage peer; ISC_SOCKLEN_T size = sizeof peer; - if (getpeername(statp->_vcsock, + if (_getpeername(statp->_vcsock, (struct sockaddr *)&peer, &size) < 0 || !sock_eq((struct sockaddr *)&peer, nsap)) { res_nclose(statp); @@ -620,7 +661,7 @@ send_vc(res_state statp, if (statp->_vcsock >= 0) res_nclose(statp); - statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM, 0); + statp->_vcsock = _socket(nsap->sa_family, SOCK_STREAM, 0); if (statp->_vcsock > highestFD) { res_nclose(statp); errno = ENOTSOCK; @@ -641,7 +682,7 @@ send_vc(res_state statp, } } errno = 0; - if (connect(statp->_vcsock, nsap, nsaplen) < 0) { + if (_connect(statp->_vcsock, nsap, nsaplen) < 0) { *terrno = errno; Aerror(statp, stderr, "connect/vc", errno, nsap, nsaplen); @@ -658,7 +699,7 @@ send_vc(res_state statp, iov[0] = evConsIovec(&len, INT16SZ); DE_CONST(buf, tmp); iov[1] = evConsIovec(tmp, buflen); - if (writev(statp->_vcsock, iov, 2) != (INT16SZ + buflen)) { + if (_writev(statp->_vcsock, iov, 2) != (INT16SZ + buflen)) { *terrno = errno; Perror(statp, stderr, "write failed", errno); res_nclose(statp); @@ -670,7 +711,7 @@ send_vc(res_state statp, read_len: cp = ans; len = INT16SZ; - while ((n = read(statp->_vcsock, (char *)cp, (int)len)) > 0) { + while ((n = _read(statp->_vcsock, (char *)cp, (int)len)) > 0) { cp += n; if ((len -= n) == 0) break; @@ -716,7 +757,8 @@ send_vc(res_state statp, return (0); } cp = ans; - while (len != 0 && (n = read(statp->_vcsock, (char *)cp, (int)len)) > 0){ + while (len != 0 && + (n = _read(statp->_vcsock, (char *)cp, (int)len)) > 0) { cp += n; len -= n; } @@ -735,8 +777,8 @@ send_vc(res_state statp, while (len != 0) { char junk[PACKETSZ]; - n = read(statp->_vcsock, junk, - (len > sizeof junk) ? sizeof junk : len); + n = _read(statp->_vcsock, junk, + (len > sizeof junk) ? sizeof junk : len); if (n > 0) len -= n; else @@ -767,6 +809,9 @@ send_vc(res_state statp, static int send_dg(res_state statp, +#ifdef USE_KQUEUE + int kq, +#endif const u_char *buf, int buflen, u_char *ans, int anssiz, int *terrno, int ns, int *v_circuit, int *gotsomewhere) { @@ -778,17 +823,22 @@ send_dg(res_state statp, struct sockaddr_storage from; ISC_SOCKLEN_T fromlen; int resplen, seconds, n, s; +#ifdef USE_KQUEUE + struct kevent kv; +#else #ifdef USE_POLL int polltimeout; struct pollfd pollfd; #else fd_set dsmask; #endif +#endif nsap = get_nsaddr(statp, ns); nsaplen = get_salen(nsap); if (EXT(statp).nssocks[ns] == -1) { - EXT(statp).nssocks[ns] = socket(nsap->sa_family, SOCK_DGRAM, 0); + EXT(statp).nssocks[ns] = _socket(nsap->sa_family, + SOCK_DGRAM, 0); if (EXT(statp).nssocks[ns] > highestFD) { res_nclose(statp); errno = ENOTSOCK; @@ -819,8 +869,16 @@ send_dg(res_state statp, * socket operation, and select returns if the * error message is received. We can thus detect * the absence of a nameserver without timing out. + * + * When the option "insecure1" is specified, we'd + * rather expect to see responses from an "unknown" + * address. In order to let the kernel accept such + * responses, do not connect the socket here. + * XXX: or do we need an explicit option to disable + * connecting? */ - if (connect(EXT(statp).nssocks[ns], nsap, nsaplen) < 0) { + if (!(statp->options & RES_INSECURE1) && + _connect(EXT(statp).nssocks[ns], nsap, nsaplen) < 0) { Aerror(statp, stderr, "connect(dg)", errno, nsap, nsaplen); res_nclose(statp); @@ -832,13 +890,20 @@ send_dg(res_state statp, } s = EXT(statp).nssocks[ns]; #ifndef CANNOT_CONNECT_DGRAM - if (send(s, (const char*)buf, buflen, 0) != buflen) { + if (statp->options & RES_INSECURE1) { + if (_sendto(s, + (const char*)buf, buflen, 0, nsap, nsaplen) != buflen) { + Aerror(statp, stderr, "sendto", errno, nsap, nsaplen); + res_nclose(statp); + return (0); + } + } else if (send(s, (const char*)buf, buflen, 0) != buflen) { Perror(statp, stderr, "send", errno); res_nclose(statp); return (0); } #else /* !CANNOT_CONNECT_DGRAM */ - if (sendto(s, (const char*)buf, buflen, 0, nsap, nsaplen) != buflen) + if (_sendto(s, (const char*)buf, buflen, 0, nsap, nsaplen) != buflen) { Aerror(statp, stderr, "sendto", errno, nsap, nsaplen); res_nclose(statp); @@ -862,13 +927,18 @@ send_dg(res_state statp, now = evNowTime(); nonow: #ifndef USE_POLL - FD_ZERO(&dsmask); - FD_SET(s, &dsmask); if (evCmpTime(finish, now) > 0) timeout = evSubTime(finish, now); else timeout = evConsTime(0, 0); +#ifdef USE_KQUEUE + EV_SET(&kv, s, EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, 0); + n = _kevent(kq, &kv, 1, &kv, 1, &timeout); +#else + FD_ZERO(&dsmask); + FD_SET(s, &dsmask); n = pselect(s + 1, &dsmask, NULL, NULL, &timeout, NULL); +#endif #else timeout = evSubTime(finish, now); if (timeout.tv_sec < 0) @@ -888,17 +958,21 @@ send_dg(res_state statp, if (n < 0) { if (errno == EINTR) goto wait; +#ifdef USE_KQUEUE + Perror(statp, stderr, "kevent", errno); +#else #ifndef USE_POLL Perror(statp, stderr, "select", errno); #else Perror(statp, stderr, "poll", errno); #endif /* USE_POLL */ +#endif res_nclose(statp); return (0); } errno = 0; fromlen = sizeof(from); - resplen = recvfrom(s, (char*)ans, anssiz,0, + resplen = _recvfrom(s, (char*)ans, anssiz,0, (struct sockaddr *)&from, &fromlen); if (resplen <= 0) { Perror(statp, stderr, "recvfrom", errno); @@ -1061,7 +1135,7 @@ sock_eq(struct sockaddr *a, struct sockaddr *b) { } } -#if defined(NEED_PSELECT) && !defined(USE_POLL) +#if defined(NEED_PSELECT) && !defined(USE_POLL) && !defined(USE_KQUEUE) /* XXX needs to move to the porting library. */ static int pselect(int nfds, void *rfds, void *wfds, void *efds, diff --git a/lib/libc/resolv/res_state.c b/lib/libc/resolv/res_state.c new file mode 100644 index 0000000..b2742ce --- /dev/null +++ b/lib/libc/resolv/res_state.c @@ -0,0 +1,96 @@ +/*- + * Copyright (c) 2006 The FreeBSD Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * 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. + * + * $FreeBSD$ + */ + +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> +#include <stdlib.h> + +#include "namespace.h" +#include "reentrant.h" +#include "un-namespace.h" + +#undef _res + +struct __res_state _res; + +static thread_key_t res_key; +static once_t res_init_once = ONCE_INITIALIZER; +static int res_thr_keycreated = 0; + +static void +free_res(void *ptr) +{ + res_state statp = ptr; + + if (statp->_u._ext.ext != NULL) + res_ndestroy(statp); + free(statp); +} + +static void +res_keycreate(void) +{ + res_thr_keycreated = thr_keycreate(&res_key, free_res) == 0; +} + +res_state +__res_state(void) +{ + res_state statp; + + if (thr_main() != 0) + return (&_res); + + if (thr_once(&res_init_once, res_keycreate) != 0 || + !res_thr_keycreated) + return (&_res); + + statp = thr_getspecific(res_key); + if (statp != NULL) + return (statp); + statp = calloc(1, sizeof(*statp)); + if (statp == NULL) + return (&_res); +#ifdef __BIND_RES_TEXT + statp->options = RES_TIMEOUT; /* Motorola, et al. */ +#endif + if (thr_setspecific(res_key, statp) == 0) + return (statp); + free(statp); + return (&_res); +} + +/* binary backward compatibility for FreeBSD 5.x and 6.x */ +struct __res_state_ext * +___res_ext(void) +{ + return (__res_state()->_u._ext.ext); +} + +__weak_reference(__res_state, ___res); |