1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-08-08 17:42:12 +03:00

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.
This commit is contained in:
Florian Weimer
2017-06-30 21:10:23 +02:00
parent 4e45d83c92
commit 352f4ff9a2
24 changed files with 1032 additions and 370 deletions

View File

@@ -88,6 +88,7 @@
#include <arpa/nameser.h>
#include <netdb.h>
#include <resolv/resolv-internal.h>
#include <resolv/resolv_context.h>
#include <string.h>
#include <sys/time.h>
#include <shlib-compat.h>
@@ -98,22 +99,10 @@
# define RANDOM_BITS(Var) { uint64_t v64; HP_TIMING_NOW (v64); Var = v64; }
#endif
/* Form all types of queries. Returns the size of the result or -1 on
error.
STATP points to an initialized resolver state. OP is the opcode of
the query. DNAME is the domain. CLASS and TYPE are the DNS query
class and type. DATA can be NULL; otherwise, it is a pointer to a
domain name which is included in the generated packet (if op ==
NS_NOTIFY_OP). BUF must point to the out buffer of BUFLEN bytes.
DATALEN and NEWRR_IN are currently ignored. */
int
res_nmkquery (res_state statp, int op, const char *dname,
int class, int type,
const unsigned char *data, int datalen,
const unsigned char *newrr_in,
unsigned char *buf, int buflen)
__res_context_mkquery (struct resolv_context *ctx, int op, const char *dname,
int class, int type, const unsigned char *data,
unsigned char *buf, int buflen)
{
HEADER *hp;
unsigned char *cp;
@@ -132,22 +121,17 @@ res_nmkquery (res_state statp, int op, const char *dname,
by one after the initial randomization which still predictable if
the application does multiple requests. */
int randombits;
do
{
#ifdef RANDOM_BITS
RANDOM_BITS (randombits);
RANDOM_BITS (randombits);
#else
struct timeval tv;
__gettimeofday (&tv, NULL);
randombits = (tv.tv_sec << 8) ^ tv.tv_usec;
struct timeval tv;
__gettimeofday (&tv, NULL);
randombits = (tv.tv_sec << 8) ^ tv.tv_usec;
#endif
}
while ((randombits & 0xffff) == 0);
statp->id = (statp->id + randombits) & 0xffff;
hp->id = statp->id;
hp->id = randombits;
hp->opcode = op;
hp->rd = (statp->options & RES_RECURSE) != 0;
hp->rd = (ctx->resp->options & RES_RECURSE) != 0;
hp->rcode = NOERROR;
cp = buf + HFIXEDSZ;
buflen -= HFIXEDSZ;
@@ -201,7 +185,45 @@ res_nmkquery (res_state statp, int op, const char *dname,
}
return cp - buf;
}
libresolv_hidden_def (res_nmkquery)
/* Common part of res_nmkquery and res_mkquery. */
static int
context_mkquery_common (struct resolv_context *ctx,
int op, const char *dname, int class, int type,
const unsigned char *data,
unsigned char *buf, int buflen)
{
if (ctx == NULL)
return -1;
int result = __res_context_mkquery
(ctx, op, dname, class, type, data, buf, buflen);
if (result >= 2)
memcpy (&ctx->resp->id, buf, 2);
__resolv_context_put (ctx);
return result;
}
/* Form all types of queries. Returns the size of the result or -1 on
error.
STATP points to an initialized resolver state. OP is the opcode of
the query. DNAME is the domain. CLASS and TYPE are the DNS query
class and type. DATA can be NULL; otherwise, it is a pointer to a
domain name which is included in the generated packet (if op ==
NS_NOTIFY_OP). BUF must point to the out buffer of BUFLEN bytes.
DATALEN and NEWRR_IN are currently ignored. */
int
res_nmkquery (res_state statp, int op, const char *dname,
int class, int type,
const unsigned char *data, int datalen,
const unsigned char *newrr_in,
unsigned char *buf, int buflen)
{
return context_mkquery_common
(__resolv_context_get_override (statp),
op, dname, class, type, data, buf, buflen);
}
int
res_mkquery (int op, const char *dname, int class, int type,
@@ -209,13 +231,9 @@ res_mkquery (int op, const char *dname, int class, int type,
const unsigned char *newrr_in,
unsigned char *buf, int buflen)
{
if (__res_maybe_init (&_res, 1) == -1)
{
RES_SET_H_ERRNO (&_res, NETDB_INTERNAL);
return -1;
}
return res_nmkquery (&_res, op, dname, class, type,
data, datalen, newrr_in, buf, buflen);
return context_mkquery_common
(__resolv_context_get_preinit (),
op, dname, class, type, data, buf, buflen);
}
/* Create an OPT resource record. Return the length of the final
@@ -227,8 +245,8 @@ res_mkquery (int op, const char *dname, int class, int type,
pointers to must be BUFLEN bytes long. ANSLEN is the advertised
EDNS buffer size (to be included in the OPT resource record). */
int
__res_nopt (res_state statp, int n0, unsigned char *buf, int buflen,
int anslen)
__res_nopt (struct resolv_context *ctx,
int n0, unsigned char *buf, int buflen, int anslen)
{
uint16_t flags = 0;
HEADER *hp = (HEADER *) buf;
@@ -269,7 +287,7 @@ __res_nopt (res_state statp, int n0, unsigned char *buf, int buflen,
*cp++ = NOERROR; /* Extended RCODE. */
*cp++ = 0; /* EDNS version. */
if (statp->options & RES_USE_DNSSEC)
if (ctx->resp->options & RES_USE_DNSSEC)
flags |= NS_OPT_DNSSEC_OK;
NS_PUT16 (flags, cp);