aboutsummaryrefslogtreecommitdiff
path: root/resolv/res_query.c
diff options
context:
space:
mode:
authorFlorian Weimer <fweimer@redhat.com>2017-06-30 21:10:23 +0200
committerFlorian Weimer <fweimer@redhat.com>2017-07-03 20:52:59 +0200
commit352f4ff9a268b81ef5d4b2413f582565806e4790 (patch)
treefb27056dfdeafe43c021f6127c9544c016e78019 /resolv/res_query.c
parent4e45d83c92dbb5b8dc20654f32395108d18cf739 (diff)
downloadglibc-352f4ff9a268b81ef5d4b2413f582565806e4790.zip
glibc-352f4ff9a268b81ef5d4b2413f582565806e4790.tar.gz
glibc-352f4ff9a268b81ef5d4b2413f582565806e4790.tar.bz2
resolv: Introduce struct resolv_context [BZ #21668]
struct resolv_context objects provide a temporary resolver context which does not change during a name lookup operation. Only when the outmost context is created, the stub resolver configuration is verified to be current (at present, only against previous res_init calls). Subsequent attempts to obtain the context will reuse the result of the initial verification operation. struct resolv_context can also be extended in the future to store data which needs to be deallocated during thread cancellation.
Diffstat (limited to 'resolv/res_query.c')
-rw-r--r--resolv/res_query.c298
1 files changed, 172 insertions, 126 deletions
diff --git a/resolv/res_query.c b/resolv/res_query.c
index 760bf32..33249e3 100644
--- a/resolv/res_query.c
+++ b/resolv/res_query.c
@@ -75,6 +75,7 @@
#include <netdb.h>
#include <resolv.h>
#include <resolv/resolv-internal.h>
+#include <resolv/resolv_context.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -89,33 +90,28 @@
#define QUERYSIZE (HFIXEDSZ + QFIXEDSZ + MAXCDNAME + 1)
static int
-__libc_res_nquerydomain(res_state statp, const char *name, const char *domain,
- int class, int type, u_char *answer, int anslen,
- u_char **answerp, u_char **answerp2, int *nanswerp2,
- int *resplen2, int *answerp2_malloced);
-
-/*
- * 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.
- */
+__res_context_querydomain (struct resolv_context *,
+ const char *name, const char *domain,
+ int class, int type, unsigned char *answer, int anslen,
+ unsigned char **answerp, unsigned char **answerp2, int *nanswerp2,
+ int *resplen2, int *answerp2_malloced);
+
+/* 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. */
int
-__libc_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 **answerp, /* if buffer needs to be enlarged */
- u_char **answerp2,
- int *nanswerp2,
- int *resplen2,
- int *answerp2_malloced)
+__res_context_query (struct resolv_context *ctx, const char *name,
+ int class, int type,
+ unsigned char *answer, int anslen,
+ unsigned char **answerp, unsigned char **answerp2,
+ int *nanswerp2, int *resplen2, int *answerp2_malloced)
{
+ struct __res_state *statp = ctx->resp;
HEADER *hp = (HEADER *) answer;
HEADER *hp2;
int n, use_malloc = 0;
@@ -132,15 +128,15 @@ __libc_res_nquery(res_state statp,
if (type == T_QUERY_A_AND_AAAA)
{
- n = res_nmkquery(statp, QUERY, name, class, T_A, NULL, 0, NULL,
- query1, bufsize);
+ n = __res_context_mkquery (ctx, QUERY, name, class, T_A, NULL,
+ query1, bufsize);
if (n > 0)
{
if ((statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0)
{
/* Use RESOLV_EDNS_BUFFER_SIZE because the receive
buffer can be reallocated. */
- n = __res_nopt (statp, n, query1, bufsize,
+ n = __res_nopt (ctx, n, query1, bufsize,
RESOLV_EDNS_BUFFER_SIZE);
if (n < 0)
goto unspec_nomem;
@@ -157,13 +153,13 @@ __libc_res_nquery(res_state statp,
}
int nused = n + npad;
query2 = buf + nused;
- n = res_nmkquery(statp, QUERY, name, class, T_AAAA, NULL, 0,
- NULL, query2, bufsize - nused);
+ n = __res_context_mkquery (ctx, QUERY, name, class, T_AAAA,
+ NULL, query2, bufsize - nused);
if (n > 0
&& (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0)
/* Use RESOLV_EDNS_BUFFER_SIZE because the receive
buffer can be reallocated. */
- n = __res_nopt (statp, n, query2, bufsize,
+ n = __res_nopt (ctx, n, query2, bufsize,
RESOLV_EDNS_BUFFER_SIZE);
nquery2 = n;
}
@@ -172,8 +168,8 @@ __libc_res_nquery(res_state statp,
}
else
{
- n = res_nmkquery(statp, QUERY, name, class, type, NULL, 0, NULL,
- query1, bufsize);
+ n = __res_context_mkquery (ctx, QUERY, name, class, type, NULL,
+ query1, bufsize);
if (n > 0
&& (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0)
@@ -185,7 +181,7 @@ __libc_res_nquery(res_state statp,
advertise = anslen;
else
advertise = RESOLV_EDNS_BUFFER_SIZE;
- n = __res_nopt (statp, n, query1, bufsize, advertise);
+ n = __res_nopt (ctx, n, query1, bufsize, advertise);
}
nquery1 = n;
@@ -209,9 +205,9 @@ __libc_res_nquery(res_state statp,
return (n);
}
assert (answerp == NULL || (void *) *answerp == (void *) answer);
- n = __libc_res_nsend(statp, query1, nquery1, query2, nquery2, answer,
- anslen, answerp, answerp2, nanswerp2, resplen2,
- answerp2_malloced);
+ n = __res_context_send (ctx, query1, nquery1, query2, nquery2, answer,
+ anslen, answerp, answerp2, nanswerp2, resplen2,
+ answerp2_malloced);
if (use_malloc)
free (buf);
if (n < 0) {
@@ -220,7 +216,7 @@ __libc_res_nquery(res_state statp,
}
if (answerp != NULL)
- /* __libc_res_nsend might have reallocated the buffer. */
+ /* __res_context_send might have reallocated the buffer. */
hp = (HEADER *) *answerp;
/* We simplify the following tests by assigning HP to HP2 or
@@ -280,7 +276,24 @@ __libc_res_nquery(res_state statp,
success:
return (n);
}
-libresolv_hidden_def (__libc_res_nquery)
+libresolv_hidden_def (__res_context_query)
+
+/* Common part of res_nquery and res_query. */
+static int
+context_query_common (struct resolv_context *ctx,
+ const char *name, int class, int type,
+ unsigned char *answer, int anslen)
+{
+ if (ctx == NULL)
+ {
+ RES_SET_H_ERRNO (&_res, NETDB_INTERNAL);
+ return -1;
+ }
+ int result = __res_context_query (ctx, name, class, type, answer, anslen,
+ NULL, NULL, NULL, NULL, NULL);
+ __resolv_context_put (ctx);
+ return result;
+}
int
res_nquery(res_state statp,
@@ -289,41 +302,30 @@ res_nquery(res_state statp,
u_char *answer, /* buffer to put answer */
int anslen) /* size of answer buffer */
{
- return __libc_res_nquery(statp, name, class, type, answer, anslen,
- NULL, NULL, NULL, NULL, NULL);
+ return context_query_common
+ (__resolv_context_get_override (statp), name, class, type, answer, anslen);
}
-libresolv_hidden_def (res_nquery)
int
res_query (const char *name, int class, int type,
unsigned char *answer, int anslen)
{
- if (__res_maybe_init (&_res, 1) == -1)
- {
- RES_SET_H_ERRNO (&_res, NETDB_INTERNAL);
- return -1;
- }
- return res_nquery (&_res, name, class, type, answer, anslen);
+ return context_query_common
+ (__resolv_context_get (), 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.
- */
+/* 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. */
int
-__libc_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 */
- u_char **answerp,
- u_char **answerp2,
- int *nanswerp2,
- int *resplen2,
- int *answerp2_malloced)
+__res_context_search (struct resolv_context *ctx,
+ const char *name, int class, int type,
+ unsigned char *answer, int anslen,
+ unsigned char **answerp, unsigned char **answerp2,
+ int *nanswerp2, int *resplen2, int *answerp2_malloced)
{
+ struct __res_state *statp = ctx->resp;
const char *cp, * const *domain;
HEADER *hp = (HEADER *) answer;
char tmp[NS_MAXDNAME];
@@ -344,10 +346,11 @@ __libc_res_nsearch(res_state statp,
trailing_dot++;
/* 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 (__libc_res_nquery(statp, cp, class, type, answer,
- anslen, answerp, answerp2,
- nanswerp2, resplen2, answerp2_malloced));
+ if (!dots && (cp = __res_context_hostalias
+ (ctx, name, tmp, sizeof tmp))!= NULL)
+ return __res_context_query (ctx, cp, class, type, answer,
+ anslen, answerp, answerp2,
+ nanswerp2, resplen2, answerp2_malloced);
/*
* If there are enough dots in the name, let's just give it a
@@ -356,10 +359,10 @@ __libc_res_nsearch(res_state statp,
*/
saved_herrno = -1;
if (dots >= statp->ndots || trailing_dot) {
- ret = __libc_res_nquerydomain(statp, name, NULL, class, type,
- answer, anslen, answerp,
- answerp2, nanswerp2, resplen2,
- answerp2_malloced);
+ ret = __res_context_querydomain (ctx, name, NULL, class, type,
+ answer, anslen, answerp,
+ answerp2, nanswerp2, resplen2,
+ answerp2_malloced);
if (ret > 0 || trailing_dot
/* If the second response is valid then we use that. */
|| (ret == 0 && resplen2 != NULL && *resplen2 > 0))
@@ -395,7 +398,7 @@ __libc_res_nsearch(res_state statp,
const char *dname = domain[0];
searched = 1;
- /* __libc_res_nquerydoman concatenates name
+ /* __res_context_querydoman concatenates name
with dname with a "." in between. If we
pass it in dname the "." we got from the
configured default search path, we'll end
@@ -409,11 +412,10 @@ __libc_res_nsearch(res_state statp,
if (dname[0] == '\0')
root_on_list++;
- ret = __libc_res_nquerydomain(statp, name, dname,
- class, type,
- answer, anslen, answerp,
- answerp2, nanswerp2,
- resplen2, answerp2_malloced);
+ ret = __res_context_querydomain
+ (ctx, name, dname, class, type,
+ answer, anslen, answerp, answerp2, nanswerp2,
+ resplen2, answerp2_malloced);
if (ret > 0 || (ret == 0 && resplen2 != NULL
&& *resplen2 > 0))
return (ret);
@@ -481,10 +483,10 @@ __libc_res_nsearch(res_state statp,
*/
if ((dots || !searched || (statp->options & RES_NOTLDQUERY) == 0)
&& !(tried_as_is || root_on_list)) {
- ret = __libc_res_nquerydomain(statp, name, NULL, class, type,
- answer, anslen, answerp,
- answerp2, nanswerp2, resplen2,
- answerp2_malloced);
+ ret = __res_context_querydomain
+ (ctx, name, NULL, class, type,
+ answer, anslen, answerp, answerp2, nanswerp2,
+ resplen2, answerp2_malloced);
if (ret > 0 || (ret == 0 && resplen2 != NULL
&& *resplen2 > 0))
return (ret);
@@ -512,7 +514,24 @@ __libc_res_nsearch(res_state statp,
RES_SET_H_ERRNO(statp, TRY_AGAIN);
return (-1);
}
-libresolv_hidden_def (__libc_res_nsearch)
+libresolv_hidden_def (__res_context_search)
+
+/* Common part of res_nsearch and res_search. */
+static int
+context_search_common (struct resolv_context *ctx,
+ const char *name, int class, int type,
+ unsigned char *answer, int anslen)
+{
+ if (ctx == NULL)
+ {
+ RES_SET_H_ERRNO (&_res, NETDB_INTERNAL);
+ return -1;
+ }
+ int result = __res_context_search (ctx, name, class, type, answer, anslen,
+ NULL, NULL, NULL, NULL, NULL);
+ __resolv_context_put (ctx);
+ return result;
+}
int
res_nsearch(res_state statp,
@@ -521,40 +540,30 @@ res_nsearch(res_state statp,
u_char *answer, /* buffer to put answer */
int anslen) /* size of answer */
{
- return __libc_res_nsearch(statp, name, class, type, answer,
- anslen, NULL, NULL, NULL, NULL, NULL);
+ return context_search_common
+ (__resolv_context_get_override (statp), name, class, type, answer, anslen);
}
-libresolv_hidden_def (res_nsearch)
int
res_search (const char *name, int class, int type,
unsigned char *answer, int anslen)
{
- if (__res_maybe_init (&_res, 1) == -1)
- {
- RES_SET_H_ERRNO (&_res, NETDB_INTERNAL);
- return -1;
- }
-
- return res_nsearch (&_res, name, class, type, answer, anslen);
+ return context_search_common
+ (__resolv_context_get (), name, class, type, answer, anslen);
}
-/*
- * Perform a call on res_query on the concatenation of name and domain.
- */
+/* Perform a call on res_query on the concatenation of name and
+ domain. */
static int
-__libc_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 */
- u_char **answerp,
- u_char **answerp2,
- int *nanswerp2,
- int *resplen2,
- int *answerp2_malloced)
+__res_context_querydomain (struct resolv_context *ctx,
+ const char *name, const char *domain,
+ int class, int type,
+ unsigned char *answer, int anslen,
+ unsigned char **answerp, unsigned char **answerp2,
+ int *nanswerp2, int *resplen2,
+ int *answerp2_malloced)
{
+ struct __res_state *statp = ctx->resp;
char nbuf[MAXDNAME];
const char *longname = nbuf;
size_t n, d;
@@ -580,9 +589,28 @@ __libc_res_nquerydomain(res_state statp,
}
sprintf(nbuf, "%s.%s", name, domain);
}
- return (__libc_res_nquery(statp, longname, class, type, answer,
- anslen, answerp, answerp2, nanswerp2,
- resplen2, answerp2_malloced));
+ return __res_context_query (ctx, longname, class, type, answer,
+ anslen, answerp, answerp2, nanswerp2,
+ resplen2, answerp2_malloced);
+}
+
+/* Common part of res_nquerydomain and res_querydomain. */
+static int
+context_querydomain_common (struct resolv_context *ctx,
+ const char *name, const char *domain,
+ int class, int type,
+ unsigned char *answer, int anslen)
+{
+ if (ctx == NULL)
+ {
+ RES_SET_H_ERRNO (&_res, NETDB_INTERNAL);
+ return -1;
+ }
+ int result = __res_context_querydomain (ctx, name, domain, class, type,
+ answer, anslen,
+ NULL, NULL, NULL, NULL, NULL);
+ __resolv_context_put (ctx);
+ return result;
}
int
@@ -593,32 +621,28 @@ res_nquerydomain(res_state statp,
u_char *answer, /* buffer to put answer */
int anslen) /* size of answer */
{
- return __libc_res_nquerydomain(statp, name, domain, class, type,
- answer, anslen, NULL, NULL, NULL, NULL,
- NULL);
+ return context_querydomain_common
+ (__resolv_context_get_override (statp),
+ name, domain, class, type, answer, anslen);
}
-libresolv_hidden_def (res_nquerydomain)
int
res_querydomain (const char *name, const char *domain, int class, int type,
unsigned char *answer, int anslen)
{
- if (__res_maybe_init (&_res, 1) == -1)
- {
- RES_SET_H_ERRNO (&_res, NETDB_INTERNAL);
- return -1;
- }
-
- return res_nquerydomain (&_res, name, domain, class, type, answer, anslen);
+ return context_querydomain_common
+ (__resolv_context_get (), name, domain, class, type, answer, anslen);
}
const char *
-res_hostalias(const res_state statp, const char *name, char *dst, size_t siz) {
+__res_context_hostalias (struct resolv_context *ctx,
+ const char *name, char *dst, size_t siz)
+{
char *file, *cp1, *cp2;
char buf[BUFSIZ];
FILE *fp;
- if (statp->options & RES_NOALIASES)
+ if (ctx->resp->options & RES_NOALIASES)
return (NULL);
file = getenv("HOSTALIASES");
if (file == NULL || (fp = fopen(file, "rce")) == NULL)
@@ -648,15 +672,37 @@ res_hostalias(const res_state statp, const char *name, char *dst, size_t siz) {
fclose(fp);
return (NULL);
}
-libresolv_hidden_def (res_hostalias)
+libresolv_hidden_def (__res_context_hostalias)
+
+/* Common part of res_hostalias and hostalias. */
+static const char *
+context_hostalias_common (struct resolv_context *ctx,
+ const char *name, char *dst, size_t siz)
+{
+ if (ctx == NULL)
+ {
+ RES_SET_H_ERRNO (&_res, NETDB_INTERNAL);
+ return NULL;
+ }
+ const char *result = __res_context_hostalias (ctx, name, dst, siz);
+ __resolv_context_put (ctx);
+ return result;
+}
+
+const char *
+res_hostalias (res_state statp, const char *name, char *dst, size_t siz)
+{
+ return context_hostalias_common
+ (__resolv_context_get_override (statp), name, dst, siz);
+}
const char *
hostalias (const char *name)
{
static char abuf[MAXDNAME];
- return res_hostalias (&_res, name, abuf, sizeof abuf);
+ return context_hostalias_common
+ (__resolv_context_get (), name, abuf, sizeof (abuf));
}
-libresolv_hidden_def (hostalias)
#if SHLIB_COMPAT (libresolv, GLIBC_2_0, GLIBC_2_2)
# undef res_query