PERFORCE change 99427 for review
Michael Bushkov
bushman at FreeBSD.org
Sat Jun 17 14:34:52 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=99427
Change 99427 by bushman at bushman_nss_ldap_cached on 2006/06/17 14:34:21
changes in the resolver-related parts that allow painless code migration from libc to nss-modules
Affected files ...
.. //depot/projects/soc2006/nss_ldap_cached/src/lib/libc/net/getaddrinfo.c#2 edit
.. //depot/projects/soc2006/nss_ldap_cached/src/lib/libc/net/gethostnamadr.c#3 edit
.. //depot/projects/soc2006/nss_ldap_cached/src/lib/libc/net/name6.c#2 edit
.. //depot/projects/soc2006/nss_ldap_cached/src/lib/libc/net/netdb_private.h#3 edit
Differences ...
==== //depot/projects/soc2006/nss_ldap_cached/src/lib/libc/net/getaddrinfo.c#2 (text+ko) ====
@@ -93,11 +93,11 @@
#include <stdio.h>
#include <errno.h>
-#include "res_config.h"
+//#include "res_config.h"
-#ifdef DEBUG
-#include <syslog.h>
-#endif
+//#ifdef DEBUG
+//#include <syslog.h>
+//#endif
#include <stdarg.h>
#include <nsswitch.h>
@@ -127,14 +127,6 @@
};
#endif
-struct policyqueue {
- TAILQ_ENTRY(policyqueue) pc_entry;
-#ifdef INET6
- struct in6_addrpolicy pc_policy;
-#endif
-};
-TAILQ_HEAD(policyhead, policyqueue);
-
static const struct afd {
int a_af;
int a_addrlen;
@@ -161,6 +153,14 @@
{0, 0, 0, 0, NULL, NULL, 0},
};
+struct policyqueue {
+ TAILQ_ENTRY(policyqueue) pc_entry;
+#ifdef INET6
+ struct in6_addrpolicy pc_policy;
+#endif
+};
+TAILQ_HEAD(policyhead, policyqueue);
+
struct explore {
int e_af;
int e_socktype;
@@ -219,22 +219,6 @@
{ 0 }
};
-struct res_target {
- struct res_target *next;
- const char *name; /* domain name */
- int qclass, qtype; /* class and type of query */
- u_char *answer; /* buffer to put answer */
- int anslen; /* size of answer buffer */
- int n; /* result length */
-};
-
-#define MAXPACKET (64*1024)
-
-typedef union {
- HEADER hdr;
- u_char buf[MAXPACKET];
-} querybuf;
-
static int str2number(const char *);
static int explore_null(const struct addrinfo *,
const char *, struct addrinfo **);
@@ -267,7 +251,7 @@
struct policyhead *);
static int matchlen(struct sockaddr *, struct sockaddr *);
-static struct addrinfo *getanswer(const querybuf *, int, const char *, int,
+/*static struct addrinfo *getanswer(const querybuf *, int, const char *, int,
const struct addrinfo *, res_state);
#if defined(RESOLVSORT)
static int addr4sort(struct addrinfo *, res_state);
@@ -281,17 +265,17 @@
#ifdef YP
static struct addrinfo *_yphostent(char *, const struct addrinfo *);
static int _yp_getaddrinfo(void *, void *, va_list);
-#endif
+#endif*/
#ifdef NS_CACHING
static int addrinfo_id_func(char *, size_t *, va_list, void *);
static int addrinfo_marshal_func(char *, size_t *, void *, va_list, void *);
static int addrinfo_unmarshal_func(char *, size_t, void *, va_list, void *);
#endif
-static int res_queryN(const char *, struct res_target *, res_state);
+/*static int res_queryN(const char *, struct res_target *, res_state);
static int res_searchN(const char *, struct res_target *, res_state);
static int res_querydomainN(const char *, const char *,
- struct res_target *, res_state);
+ struct res_target *, res_state);*/
/* XXX macros that make external reference is BAD. */
@@ -1730,9 +1714,6 @@
addrinfo_unmarshal_func);
#endif
static const ns_dtab dtab[] = {
- NS_FILES_CB(_files_getaddrinfo, NULL)
- { NSSRC_DNS, _dns_getaddrinfo, NULL }, /* force -DHESIOD */
- NS_NIS_CB(_yp_getaddrinfo, NULL)
#ifdef NS_CACHING
NS_CACHE_CB(&cache_info)
#endif
@@ -1776,997 +1757,3 @@
freeaddrinfo(result);
return error;
}
-
-#ifdef DEBUG
-static const char AskedForGot[] =
- "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
-#endif
-
-static struct addrinfo *
-getanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
- const struct addrinfo *pai, res_state res)
-{
- struct addrinfo sentinel, *cur;
- struct addrinfo ai;
- const struct afd *afd;
- char *canonname;
- const HEADER *hp;
- const u_char *cp;
- int n;
- const u_char *eom;
- char *bp, *ep;
- int type, class, ancount, qdcount;
- int haveanswer, had_error;
- char tbuf[MAXDNAME];
- int (*name_ok)(const char *);
- char hostbuf[8*1024];
-
- memset(&sentinel, 0, sizeof(sentinel));
- cur = &sentinel;
-
- canonname = NULL;
- eom = answer->buf + anslen;
- switch (qtype) {
- case T_A:
- case T_AAAA:
- case T_ANY: /*use T_ANY only for T_A/T_AAAA lookup*/
- name_ok = res_hnok;
- break;
- default:
- return (NULL); /* XXX should be abort(); */
- }
- /*
- * find first satisfactory answer
- */
- hp = &answer->hdr;
- ancount = ntohs(hp->ancount);
- qdcount = ntohs(hp->qdcount);
- bp = hostbuf;
- ep = hostbuf + sizeof hostbuf;
- cp = answer->buf + HFIXEDSZ;
- if (qdcount != 1) {
- RES_SET_H_ERRNO(res, NO_RECOVERY);
- return (NULL);
- }
- n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
- if ((n < 0) || !(*name_ok)(bp)) {
- RES_SET_H_ERRNO(res, NO_RECOVERY);
- return (NULL);
- }
- cp += n + QFIXEDSZ;
- if (qtype == T_A || qtype == T_AAAA || qtype == T_ANY) {
- /* res_send() has already verified that the query name is the
- * same as the one we sent; this just gets the expanded name
- * (i.e., with the succeeding search-domain tacked on).
- */
- n = strlen(bp) + 1; /* for the \0 */
- if (n >= MAXHOSTNAMELEN) {
- RES_SET_H_ERRNO(res, NO_RECOVERY);
- return (NULL);
- }
- canonname = bp;
- bp += n;
- /* The qname can be abbreviated, but h_name is now absolute. */
- qname = canonname;
- }
- haveanswer = 0;
- had_error = 0;
- while (ancount-- > 0 && cp < eom && !had_error) {
- n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
- if ((n < 0) || !(*name_ok)(bp)) {
- had_error++;
- continue;
- }
- cp += n; /* name */
- type = _getshort(cp);
- cp += INT16SZ; /* type */
- class = _getshort(cp);
- cp += INT16SZ + INT32SZ; /* class, TTL */
- n = _getshort(cp);
- cp += INT16SZ; /* len */
- if (class != C_IN) {
- /* XXX - debug? syslog? */
- cp += n;
- continue; /* XXX - had_error++ ? */
- }
- if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) &&
- type == T_CNAME) {
- n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
- if ((n < 0) || !(*name_ok)(tbuf)) {
- had_error++;
- continue;
- }
- cp += n;
- /* Get canonical name. */
- n = strlen(tbuf) + 1; /* for the \0 */
- if (n > ep - bp || n >= MAXHOSTNAMELEN) {
- had_error++;
- continue;
- }
- strlcpy(bp, tbuf, ep - bp);
- canonname = bp;
- bp += n;
- continue;
- }
- if (qtype == T_ANY) {
- if (!(type == T_A || type == T_AAAA)) {
- cp += n;
- continue;
- }
- } else if (type != qtype) {
-#ifdef DEBUG
- if (type != T_KEY && type != T_SIG)
- syslog(LOG_NOTICE|LOG_AUTH,
- "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
- qname, p_class(C_IN), p_type(qtype),
- p_type(type));
-#endif
- cp += n;
- continue; /* XXX - had_error++ ? */
- }
- switch (type) {
- case T_A:
- case T_AAAA:
- if (strcasecmp(canonname, bp) != 0) {
-#ifdef DEBUG
- syslog(LOG_NOTICE|LOG_AUTH,
- AskedForGot, canonname, bp);
-#endif
- cp += n;
- continue; /* XXX - had_error++ ? */
- }
- if (type == T_A && n != INADDRSZ) {
- cp += n;
- continue;
- }
- if (type == T_AAAA && n != IN6ADDRSZ) {
- cp += n;
- continue;
- }
-#ifdef FILTER_V4MAPPED
- if (type == T_AAAA) {
- struct in6_addr in6;
- memcpy(&in6, cp, sizeof(in6));
- if (IN6_IS_ADDR_V4MAPPED(&in6)) {
- cp += n;
- continue;
- }
- }
-#endif
- if (!haveanswer) {
- int nn;
-
- canonname = bp;
- nn = strlen(bp) + 1; /* for the \0 */
- bp += nn;
- }
-
- /* don't overwrite pai */
- ai = *pai;
- ai.ai_family = (type == T_A) ? AF_INET : AF_INET6;
- afd = find_afd(ai.ai_family);
- if (afd == NULL) {
- cp += n;
- continue;
- }
- cur->ai_next = get_ai(&ai, afd, (const char *)cp);
- if (cur->ai_next == NULL)
- had_error++;
- while (cur && cur->ai_next)
- cur = cur->ai_next;
- cp += n;
- break;
- default:
- abort();
- }
- if (!had_error)
- haveanswer++;
- }
- if (haveanswer) {
-#if defined(RESOLVSORT)
- /*
- * We support only IPv4 address for backward
- * compatibility against gethostbyname(3).
- */
- if (res->nsort && qtype == T_A) {
- if (addr4sort(&sentinel, res) < 0) {
- freeaddrinfo(sentinel.ai_next);
- RES_SET_H_ERRNO(res, NO_RECOVERY);
- return NULL;
- }
- }
-#endif /*RESOLVSORT*/
- if (!canonname)
- (void)get_canonname(pai, sentinel.ai_next, qname);
- else
- (void)get_canonname(pai, sentinel.ai_next, canonname);
- RES_SET_H_ERRNO(res, NETDB_SUCCESS);
- return sentinel.ai_next;
- }
-
- RES_SET_H_ERRNO(res, NO_RECOVERY);
- return NULL;
-}
-
-#ifdef RESOLVSORT
-struct addr_ptr {
- struct addrinfo *ai;
- int aval;
-};
-
-static int
-addr4sort(struct addrinfo *sentinel, res_state res)
-{
- struct addrinfo *ai;
- struct addr_ptr *addrs, addr;
- struct sockaddr_in *sin;
- int naddrs, i, j;
- int needsort = 0;
-
- if (!sentinel)
- return -1;
- naddrs = 0;
- for (ai = sentinel->ai_next; ai; ai = ai->ai_next)
- naddrs++;
- if (naddrs < 2)
- return 0; /* We don't need sorting. */
- if ((addrs = malloc(sizeof(struct addr_ptr) * naddrs)) == NULL)
- return -1;
- i = 0;
- for (ai = sentinel->ai_next; ai; ai = ai->ai_next) {
- sin = (struct sockaddr_in *)ai->ai_addr;
- for (j = 0; (unsigned)j < res->nsort; j++) {
- if (res->sort_list[j].addr.s_addr ==
- (sin->sin_addr.s_addr & res->sort_list[j].mask))
- break;
- }
- addrs[i].ai = ai;
- addrs[i].aval = j;
- if (needsort == 0 && i > 0 && j < addrs[i - 1].aval)
- needsort = i;
- i++;
- }
- if (!needsort) {
- free(addrs);
- return 0;
- }
-
- while (needsort < naddrs) {
- for (j = needsort - 1; j >= 0; j--) {
- if (addrs[j].aval > addrs[j+1].aval) {
- addr = addrs[j];
- addrs[j] = addrs[j + 1];
- addrs[j + 1] = addr;
- } else
- break;
- }
- needsort++;
- }
-
- ai = sentinel;
- for (i = 0; i < naddrs; ++i) {
- ai->ai_next = addrs[i].ai;
- ai = ai->ai_next;
- }
- ai->ai_next = NULL;
- free(addrs);
- return 0;
-}
-#endif /*RESOLVSORT*/
-
-/*ARGSUSED*/
-static int
-_dns_getaddrinfo(void *rv, void *cb_data, va_list ap)
-{
- struct addrinfo *ai;
- querybuf *buf, *buf2;
- const char *hostname;
- const struct addrinfo *pai;
- struct addrinfo sentinel, *cur;
- struct res_target q, q2;
- res_state res;
-
- hostname = va_arg(ap, char *);
- pai = va_arg(ap, const struct addrinfo *);
-
- memset(&q, 0, sizeof(q));
- memset(&q2, 0, sizeof(q2));
- memset(&sentinel, 0, sizeof(sentinel));
- cur = &sentinel;
-
- buf = malloc(sizeof(*buf));
- if (!buf) {
- RES_SET_H_ERRNO(res, NETDB_INTERNAL);
- return NS_NOTFOUND;
- }
- buf2 = malloc(sizeof(*buf2));
- if (!buf2) {
- free(buf);
- RES_SET_H_ERRNO(res, NETDB_INTERNAL);
- return NS_NOTFOUND;
- }
-
- switch (pai->ai_family) {
- case AF_UNSPEC:
- q.name = hostname;
- q.qclass = C_IN;
- q.qtype = T_A;
- q.answer = buf->buf;
- q.anslen = sizeof(buf->buf);
- q.next = &q2;
- q2.name = hostname;
- q2.qclass = C_IN;
- q2.qtype = T_AAAA;
- q2.answer = buf2->buf;
- q2.anslen = sizeof(buf2->buf);
- break;
- case AF_INET:
- q.name = hostname;
- q.qclass = C_IN;
- q.qtype = T_A;
- q.answer = buf->buf;
- q.anslen = sizeof(buf->buf);
- break;
- case AF_INET6:
- q.name = hostname;
- q.qclass = C_IN;
- q.qtype = T_AAAA;
- q.answer = buf->buf;
- q.anslen = sizeof(buf->buf);
- break;
- default:
- free(buf);
- free(buf2);
- return NS_UNAVAIL;
- }
-
- res = __res_state();
- if ((res->options & RES_INIT) == 0 && res_ninit(res) == -1) {
- RES_SET_H_ERRNO(res, NETDB_INTERNAL);
- free(buf);
- free(buf2);
- return NS_NOTFOUND;
- }
-
- if (res_searchN(hostname, &q, res) < 0) {
- free(buf);
- free(buf2);
- return NS_NOTFOUND;
- }
- /* prefer IPv6 */
- if (q.next) {
- ai = getanswer(buf2, q2.n, q2.name, q2.qtype, pai, res);
- if (ai) {
- cur->ai_next = ai;
- while (cur && cur->ai_next)
- cur = cur->ai_next;
- }
- }
- ai = getanswer(buf, q.n, q.name, q.qtype, pai, res);
- if (ai)
- cur->ai_next = ai;
- free(buf);
- free(buf2);
- if (sentinel.ai_next == NULL)
- switch (res->res_h_errno) {
- case HOST_NOT_FOUND:
- return NS_NOTFOUND;
- case TRY_AGAIN:
- return NS_TRYAGAIN;
- default:
- return NS_UNAVAIL;
- }
- *((struct addrinfo **)rv) = sentinel.ai_next;
- return NS_SUCCESS;
-}
-
-static void
-_sethtent(FILE **hostf)
-{
- if (!*hostf)
- *hostf = fopen(_PATH_HOSTS, "r");
- else
- rewind(*hostf);
-}
-
-static void
-_endhtent(FILE **hostf)
-{
- if (*hostf) {
- (void) fclose(*hostf);
- *hostf = NULL;
- }
-}
-
-static struct addrinfo *
-_gethtent(FILE **hostf, const char *name, const struct addrinfo *pai)
-{
- char *p;
- char *cp, *tname, *cname;
- struct addrinfo hints, *res0, *res;
- int error;
- const char *addr;
- char hostbuf[8*1024];
-
- if (!*hostf && !(*hostf = fopen(_PATH_HOSTS, "r")))
- return (NULL);
-again:
- if (!(p = fgets(hostbuf, sizeof hostbuf, *hostf)))
- return (NULL);
- if (*p == '#')
- goto again;
- cp = strpbrk(p, "#\n");
- if (cp != NULL)
- *cp = '\0';
- if (!(cp = strpbrk(p, " \t")))
- goto again;
- *cp++ = '\0';
- addr = p;
- cname = NULL;
- /* if this is not something we're looking for, skip it. */
- while (cp && *cp) {
- if (*cp == ' ' || *cp == '\t') {
- cp++;
- continue;
- }
- tname = cp;
- if (cname == NULL)
- cname = cp;
- if ((cp = strpbrk(cp, " \t")) != NULL)
- *cp++ = '\0';
- if (strcasecmp(name, tname) == 0)
- goto found;
- }
- goto again;
-
-found:
- /* we should not glob socktype/protocol here */
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = pai->ai_family;
- hints.ai_socktype = SOCK_DGRAM;
- hints.ai_protocol = 0;
- hints.ai_flags = AI_NUMERICHOST;
- error = getaddrinfo(addr, "0", &hints, &res0);
- if (error)
- goto again;
-#ifdef FILTER_V4MAPPED
- /* XXX should check all items in the chain */
- if (res0->ai_family == AF_INET6 &&
- IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)res0->ai_addr)->sin6_addr)) {
- freeaddrinfo(res0);
- goto again;
- }
-#endif
- for (res = res0; res; res = res->ai_next) {
- /* cover it up */
- res->ai_flags = pai->ai_flags;
- res->ai_socktype = pai->ai_socktype;
- res->ai_protocol = pai->ai_protocol;
-
- if (pai->ai_flags & AI_CANONNAME) {
- if (get_canonname(pai, res, cname) != 0) {
- freeaddrinfo(res0);
- goto again;
- }
- }
- }
- return res0;
-}
-
-/*ARGSUSED*/
-static int
-_files_getaddrinfo(void *rv, void *cb_data, va_list ap)
-{
- const char *name;
- const struct addrinfo *pai;
- struct addrinfo sentinel, *cur;
- struct addrinfo *p;
- FILE *hostf = NULL;
-
- name = va_arg(ap, char *);
- pai = va_arg(ap, struct addrinfo *);
-
- memset(&sentinel, 0, sizeof(sentinel));
- cur = &sentinel;
-
- _sethtent(&hostf);
- while ((p = _gethtent(&hostf, name, pai)) != NULL) {
- cur->ai_next = p;
- while (cur && cur->ai_next)
- cur = cur->ai_next;
- }
- _endhtent(&hostf);
-
- *((struct addrinfo **)rv) = sentinel.ai_next;
- if (sentinel.ai_next == NULL)
- return NS_NOTFOUND;
- return NS_SUCCESS;
-}
-
-#ifdef YP
-/*ARGSUSED*/
-static struct addrinfo *
-_yphostent(char *line, const struct addrinfo *pai)
-{
- struct addrinfo sentinel, *cur;
- struct addrinfo hints, *res, *res0;
- int error;
- char *p = line;
- const char *addr, *canonname;
- char *nextline;
- char *cp;
-
- addr = canonname = NULL;
-
- memset(&sentinel, 0, sizeof(sentinel));
- cur = &sentinel;
-
-nextline:
- /* terminate line */
- cp = strchr(p, '\n');
- if (cp) {
- *cp++ = '\0';
- nextline = cp;
- } else
- nextline = NULL;
-
- cp = strpbrk(p, " \t");
- if (cp == NULL) {
- if (canonname == NULL)
- return (NULL);
- else
- goto done;
- }
- *cp++ = '\0';
-
- addr = p;
-
- while (cp && *cp) {
- if (*cp == ' ' || *cp == '\t') {
- cp++;
- continue;
- }
- if (!canonname)
- canonname = cp;
- if ((cp = strpbrk(cp, " \t")) != NULL)
- *cp++ = '\0';
- }
-
- hints = *pai;
- hints.ai_flags = AI_NUMERICHOST;
- error = getaddrinfo(addr, NULL, &hints, &res0);
- if (error == 0) {
- for (res = res0; res; res = res->ai_next) {
- /* cover it up */
- res->ai_flags = pai->ai_flags;
-
- if (pai->ai_flags & AI_CANONNAME)
- (void)get_canonname(pai, res, canonname);
- }
- } else
- res0 = NULL;
- if (res0) {
- cur->ai_next = res0;
- while (cur && cur->ai_next)
- cur = cur->ai_next;
- }
-
- if (nextline) {
- p = nextline;
- goto nextline;
- }
-
-done:
- return sentinel.ai_next;
-}
-
-/*ARGSUSED*/
-static int
-_yp_getaddrinfo(void *rv, void *cb_data, va_list ap)
-{
- struct addrinfo sentinel, *cur;
- struct addrinfo *ai = NULL;
- char *ypbuf;
- int ypbuflen, r;
- const char *name;
- const struct addrinfo *pai;
- char *ypdomain;
-
- if (_yp_check(&ypdomain) == 0)
- return NS_UNAVAIL;
-
- name = va_arg(ap, char *);
- pai = va_arg(ap, const struct addrinfo *);
-
- memset(&sentinel, 0, sizeof(sentinel));
- cur = &sentinel;
-
- /* hosts.byname is only for IPv4 (Solaris8) */
- if (pai->ai_family == PF_UNSPEC || pai->ai_family == PF_INET) {
- r = yp_match(ypdomain, "hosts.byname", name,
- (int)strlen(name), &ypbuf, &ypbuflen);
- if (r == 0) {
- struct addrinfo ai4;
-
- ai4 = *pai;
- ai4.ai_family = AF_INET;
- ai = _yphostent(ypbuf, &ai4);
- if (ai) {
- cur->ai_next = ai;
- while (cur && cur->ai_next)
- cur = cur->ai_next;
- }
- free(ypbuf);
- }
- }
-
- /* ipnodes.byname can hold both IPv4/v6 */
- r = yp_match(ypdomain, "ipnodes.byname", name,
- (int)strlen(name), &ypbuf, &ypbuflen);
- if (r == 0) {
- ai = _yphostent(ypbuf, pai);
- if (ai)
- cur->ai_next = ai;
- free(ypbuf);
- }
-
- if (sentinel.ai_next == NULL) {
- RES_SET_H_ERRNO(__res_state(), HOST_NOT_FOUND);
- return NS_NOTFOUND;
- }
- *((struct addrinfo **)rv) = sentinel.ai_next;
- return NS_SUCCESS;
-}
-#endif
-
-/* resolver logic */
-
-/*
- * 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.
- *
- * Caller must parse answer and determine whether it answers the question.
- */
-static int
-res_queryN(const char *name, struct res_target *target, res_state res)
-{
- u_char *buf;
- HEADER *hp;
- int n;
- u_int oflags;
- struct res_target *t;
- int rcode;
- int ancount;
-
- rcode = NOERROR;
- ancount = 0;
-
- buf = malloc(MAXPACKET);
- if (!buf) {
- RES_SET_H_ERRNO(res, NETDB_INTERNAL);
- return -1;
- }
-
- for (t = target; t; t = t->next) {
- int class, type;
- u_char *answer;
- int anslen;
-
- hp = (HEADER *)(void *)t->answer;
-
- /* make it easier... */
- class = t->qclass;
- type = t->qtype;
- answer = t->answer;
- anslen = t->anslen;
-
- oflags = res->_flags;
-
-again:
- hp->rcode = NOERROR; /* default */
-
-#ifdef DEBUG
- if (res->options & RES_DEBUG)
- printf(";; res_query(%s, %d, %d)\n", name, class, type);
-#endif
-
- n = res_nmkquery(res, QUERY, name, class, type, NULL, 0, NULL,
- buf, MAXPACKET);
- if (n > 0 && (res->_flags & RES_F_EDNS0ERR) == 0 &&
- (res->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0U)
- n = res_nopt(res, n, buf, MAXPACKET, anslen);
- if (n <= 0) {
-#ifdef DEBUG
- if (res->options & RES_DEBUG)
- printf(";; res_query: mkquery failed\n");
-#endif
- free(buf);
- RES_SET_H_ERRNO(res, NO_RECOVERY);
- return (n);
- }
- n = res_nsend(res, buf, n, answer, anslen);
- if (n < 0) {
- /*
- * if the query choked with EDNS0, retry
- * without EDNS0
- */
- if ((res->options & (RES_USE_EDNS0|RES_USE_DNSSEC))
- != 0U &&
- ((oflags ^ res->_flags) & RES_F_EDNS0ERR) != 0) {
- res->_flags |= RES_F_EDNS0ERR;
- if (res->options & RES_DEBUG)
- printf(";; res_nquery: retry without EDNS0\n");
- goto again;
- }
- rcode = hp->rcode; /* record most recent error */
-#ifdef DEBUG
- if (res->options & RES_DEBUG)
- printf(";; res_query: send error\n");
-#endif
- continue;
- }
-
- if (n > anslen)
- hp->rcode = FORMERR; /* XXX not very informative */
- if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
- rcode = hp->rcode; /* record most recent error */
-#ifdef DEBUG
- if (res->options & RES_DEBUG)
- printf(";; rcode = %u, ancount=%u\n", hp->rcode,
- ntohs(hp->ancount));
-#endif
- continue;
- }
-
- ancount += ntohs(hp->ancount);
-
- t->n = n;
- }
-
- free(buf);
-
- if (ancount == 0) {
- switch (rcode) {
- case NXDOMAIN:
- RES_SET_H_ERRNO(res, HOST_NOT_FOUND);
- break;
- case SERVFAIL:
- RES_SET_H_ERRNO(res, TRY_AGAIN);
- break;
- case NOERROR:
- RES_SET_H_ERRNO(res, NO_DATA);
- break;
- case FORMERR:
- case NOTIMP:
- case REFUSED:
- default:
- RES_SET_H_ERRNO(res, NO_RECOVERY);
- break;
- }
- return (-1);
- }
- return (ancount);
-}
-
-/*
- * 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.
- */
-static int
-res_searchN(const char *name, struct res_target *target, res_state res)
-{
- const char *cp, * const *domain;
- HEADER *hp = (HEADER *)(void *)target->answer; /*XXX*/
- u_int dots;
- int trailing_dot, ret, saved_herrno;
- int got_nodata = 0, got_servfail = 0, root_on_list = 0;
- int tried_as_is = 0;
- int searched = 0;
- char abuf[MAXDNAME];
-
- errno = 0;
- RES_SET_H_ERRNO(res, HOST_NOT_FOUND); /* default, if we never query */
- dots = 0;
- for (cp = name; *cp; 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 = res_hostalias(res, name, abuf, sizeof(abuf))) != NULL)
- return (res_queryN(cp, target, res));
-
- /*
- * If there are enough dots in the name, let's just give it a
- * try 'as is'. The threshold can be set with the "ndots" option.
- * Also, query 'as is', if there is a trailing dot in the name.
- */
- saved_herrno = -1;
- if (dots >= res->ndots || trailing_dot) {
- ret = res_querydomainN(name, NULL, target, res);
- if (ret > 0 || trailing_dot)
- return (ret);
- if (errno == ECONNREFUSED) {
- RES_SET_H_ERRNO(res, TRY_AGAIN);
- return (-1);
- }
- switch (res->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 = res->res_h_errno;
- tried_as_is++;
- }
-
- /*
- * We do at least one level of search if
- * - there is no dot and RES_DEFNAME is set, or
- * - 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))) {
- int done = 0;
-
- for (domain = (const char * const *)res->dnsrch;
- *domain && !done;
- domain++) {
- searched = 1;
-
- if (domain[0][0] == '\0' ||
- (domain[0][0] == '.' && domain[0][1] == '\0'))
- root_on_list++;
-
- if (root_on_list && tried_as_is)
- continue;
-
- ret = res_querydomainN(name, *domain, target, res);
- if (ret > 0)
- return (ret);
-
- /*
- * If no server present, give up.
- * If name isn't found in this domain,
- * keep trying higher domains in the search list
- * (if that's enabled).
- * On a NO_DATA error, keep trying, otherwise
- * a wildcard entry of another type could keep us
>>> TRUNCATED FOR MAIL (1000 lines) <<<
More information about the p4-projects
mailing list