diff options
author | Florian Weimer <fweimer@redhat.com> | 2017-06-30 21:10:23 +0200 |
---|---|---|
committer | Florian Weimer <fweimer@redhat.com> | 2017-07-03 20:52:59 +0200 |
commit | 352f4ff9a268b81ef5d4b2413f582565806e4790 (patch) | |
tree | fb27056dfdeafe43c021f6127c9544c016e78019 /resolv/nss_dns | |
parent | 4e45d83c92dbb5b8dc20654f32395108d18cf739 (diff) | |
download | glibc-352f4ff9a268b81ef5d4b2413f582565806e4790.tar.gz glibc-352f4ff9a268b81ef5d4b2413f582565806e4790.tar.xz glibc-352f4ff9a268b81ef5d4b2413f582565806e4790.zip |
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/nss_dns')
-rw-r--r-- | resolv/nss_dns/dns-canon.c | 19 | ||||
-rw-r--r-- | resolv/nss_dns/dns-host.c | 104 | ||||
-rw-r--r-- | resolv/nss_dns/dns-network.c | 21 |
3 files changed, 95 insertions, 49 deletions
diff --git a/resolv/nss_dns/dns-canon.c b/resolv/nss_dns/dns-canon.c index 4276eb6542..7a5c39dc20 100644 --- a/resolv/nss_dns/dns-canon.c +++ b/resolv/nss_dns/dns-canon.c @@ -23,7 +23,8 @@ #include <stdint.h> #include <arpa/nameser.h> #include <nsswitch.h> - +#include <resolv/resolv_context.h> +#include <resolv/resolv-internal.h> #if PACKETSZ > 65536 # define MAXPACKET PACKETSZ @@ -58,11 +59,19 @@ _nss_dns_getcanonname_r (const char *name, char *buffer, size_t buflen, } ansp = { .ptr = buf }; enum nss_status status = NSS_STATUS_UNAVAIL; + struct resolv_context *ctx = __resolv_context_get (); + if (ctx == NULL) + { + *errnop = errno; + *h_errnop = NETDB_INTERNAL; + return NSS_STATUS_UNAVAIL; + } + for (int i = 0; i < nqtypes; ++i) { - int r = __libc_res_nquery (&_res, name, ns_c_in, qtypes[i], - buf, sizeof (buf), &ansp.ptr, NULL, NULL, - NULL, NULL); + int r = __res_context_query (ctx, name, ns_c_in, qtypes[i], + buf, sizeof (buf), &ansp.ptr, NULL, NULL, + NULL, NULL); if (r > 0) { /* We need to decode the response. Just one question record. @@ -168,6 +177,6 @@ _nss_dns_getcanonname_r (const char *name, char *buffer, size_t buflen, if (ansp.ptr != buf) free (ansp.ptr); - + __resolv_context_put (ctx); return status; } diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c index 206924de86..9d7ceb1691 100644 --- a/resolv/nss_dns/dns-host.c +++ b/resolv/nss_dns/dns-host.c @@ -84,6 +84,7 @@ /* Get implementeation for some internal functions. */ #include <resolv/resolv-internal.h> +#include <resolv/resolv_context.h> #include <resolv/mapv4v6addr.h> #include <resolv/mapv4v6hostent.h> @@ -121,13 +122,13 @@ static enum nss_status gaih_getanswer (const querybuf *answer1, int anslen1, int *errnop, int *h_errnop, int32_t *ttlp); -extern enum nss_status _nss_dns_gethostbyname3_r (const char *name, int af, - struct hostent *result, - char *buffer, size_t buflen, - int *errnop, int *h_errnop, - int32_t *ttlp, - char **canonp); -hidden_proto (_nss_dns_gethostbyname3_r) +static enum nss_status gethostbyname3_context (struct resolv_context *ctx, + const char *name, int af, + struct hostent *result, + char *buffer, size_t buflen, + int *errnop, int *h_errnop, + int32_t *ttlp, + char **canonp); /* Return the expected RDATA length for an address record type (A or AAAA). */ @@ -145,11 +146,31 @@ rrtype_to_rdata_length (int type) } } + enum nss_status _nss_dns_gethostbyname3_r (const char *name, int af, struct hostent *result, char *buffer, size_t buflen, int *errnop, int *h_errnop, int32_t *ttlp, char **canonp) { + struct resolv_context *ctx = __resolv_context_get (); + if (ctx == NULL) + { + *errnop = errno; + *h_errnop = NETDB_INTERNAL; + return NSS_STATUS_UNAVAIL; + } + enum nss_status status = gethostbyname3_context + (ctx, name, af, result, buffer, buflen, errnop, h_errnop, ttlp, canonp); + __resolv_context_put (ctx); + return status; +} + +static enum nss_status +gethostbyname3_context (struct resolv_context *ctx, + const char *name, int af, struct hostent *result, + char *buffer, size_t buflen, int *errnop, + int *h_errnop, int32_t *ttlp, char **canonp) +{ union { querybuf *buf; @@ -163,13 +184,6 @@ _nss_dns_gethostbyname3_r (const char *name, int af, struct hostent *result, int olderr = errno; enum nss_status status; - if (__res_maybe_init (&_res, 0) == -1) - { - *errnop = errno; - *h_errnop = NETDB_INTERNAL; - return NSS_STATUS_UNAVAIL; - } - switch (af) { case AF_INET: size = INADDRSZ; @@ -194,13 +208,13 @@ _nss_dns_gethostbyname3_r (const char *name, int af, struct hostent *result, * function that looks up host names. */ if (strchr (name, '.') == NULL - && (cp = res_hostalias (&_res, name, tmp, sizeof (tmp))) != NULL) + && (cp = __res_context_hostalias (ctx, name, tmp, sizeof (tmp))) != NULL) name = cp; host_buffer.buf = orig_host_buffer = (querybuf *) alloca (1024); - n = __libc_res_nsearch (&_res, name, C_IN, type, host_buffer.buf->buf, - 1024, &host_buffer.ptr, NULL, NULL, NULL, NULL); + n = __res_context_search (ctx, name, C_IN, type, host_buffer.buf->buf, + 1024, &host_buffer.ptr, NULL, NULL, NULL, NULL); if (n < 0) { switch (errno) @@ -232,10 +246,10 @@ _nss_dns_gethostbyname3_r (const char *name, int af, struct hostent *result, by having the RES_USE_INET6 bit in _res.options set, we try another lookup. */ if (af == AF_INET6 && res_use_inet6 ()) - n = __libc_res_nsearch (&_res, name, C_IN, T_A, host_buffer.buf->buf, - host_buffer.buf != orig_host_buffer - ? MAXPACKET : 1024, &host_buffer.ptr, - NULL, NULL, NULL, NULL); + n = __res_context_search (ctx, name, C_IN, T_A, host_buffer.buf->buf, + host_buffer.buf != orig_host_buffer + ? MAXPACKET : 1024, &host_buffer.ptr, + NULL, NULL, NULL, NULL); if (n < 0) { @@ -256,8 +270,6 @@ _nss_dns_gethostbyname3_r (const char *name, int af, struct hostent *result, free (host_buffer.buf); return status; } -hidden_def (_nss_dns_gethostbyname3_r) - enum nss_status _nss_dns_gethostbyname2_r (const char *name, int af, struct hostent *result, @@ -274,15 +286,21 @@ _nss_dns_gethostbyname_r (const char *name, struct hostent *result, char *buffer, size_t buflen, int *errnop, int *h_errnop) { + struct resolv_context *ctx = __resolv_context_get (); + if (ctx == NULL) + { + *errnop = errno; + *h_errnop = NETDB_INTERNAL; + return NSS_STATUS_UNAVAIL; + } enum nss_status status = NSS_STATUS_NOTFOUND; - if (res_use_inet6 ()) - status = _nss_dns_gethostbyname3_r (name, AF_INET6, result, buffer, - buflen, errnop, h_errnop, NULL, NULL); + status = gethostbyname3_context (ctx, name, AF_INET6, result, buffer, + buflen, errnop, h_errnop, NULL, NULL); if (status == NSS_STATUS_NOTFOUND) - status = _nss_dns_gethostbyname3_r (name, AF_INET, result, buffer, - buflen, errnop, h_errnop, NULL, NULL); - + status = gethostbyname3_context (ctx, name, AF_INET, result, buffer, + buflen, errnop, h_errnop, NULL, NULL); + __resolv_context_put (ctx); return status; } @@ -292,7 +310,8 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat, char *buffer, size_t buflen, int *errnop, int *herrnop, int32_t *ttlp) { - if (__res_maybe_init (&_res, 0) == -1) + struct resolv_context *ctx = __resolv_context_get (); + if (ctx == NULL) { *errnop = errno; *herrnop = NETDB_INTERNAL; @@ -307,7 +326,7 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat, if (strchr (name, '.') == NULL) { char *tmp = alloca (NS_MAXDNAME); - const char *cp = res_hostalias (&_res, name, tmp, NS_MAXDNAME); + const char *cp = __res_context_hostalias (ctx, name, tmp, NS_MAXDNAME); if (cp != NULL) name = cp; } @@ -326,9 +345,9 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat, int olderr = errno; enum nss_status status; - int n = __libc_res_nsearch (&_res, name, C_IN, T_QUERY_A_AND_AAAA, - host_buffer.buf->buf, 2048, &host_buffer.ptr, - &ans2p, &nans2p, &resplen2, &ans2p_malloced); + int n = __res_context_search (ctx, name, C_IN, T_QUERY_A_AND_AAAA, + host_buffer.buf->buf, 2048, &host_buffer.ptr, + &ans2p, &nans2p, &resplen2, &ans2p_malloced); if (n >= 0) { status = gaih_getanswer (host_buffer.buf, n, (const querybuf *) ans2p, @@ -371,6 +390,7 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat, if (host_buffer.buf != orig_host_buffer) free (host_buffer.buf); + __resolv_context_put (ctx); return status; } @@ -423,7 +443,8 @@ _nss_dns_gethostbyaddr2_r (const void *addr, socklen_t len, int af, host_data = (struct host_data *) buffer; - if (__res_maybe_init (&_res, 0) == -1) + struct resolv_context *ctx = __resolv_context_get (); + if (ctx == NULL) { *errnop = errno; *h_errnop = NETDB_INTERNAL; @@ -453,12 +474,14 @@ _nss_dns_gethostbyaddr2_r (const void *addr, socklen_t len, int af, default: *errnop = EAFNOSUPPORT; *h_errnop = NETDB_INTERNAL; + __resolv_context_put (ctx); return NSS_STATUS_UNAVAIL; } if (size > len) { *errnop = EAFNOSUPPORT; *h_errnop = NETDB_INTERNAL; + __resolv_context_put (ctx); return NSS_STATUS_UNAVAIL; } @@ -487,14 +510,15 @@ _nss_dns_gethostbyaddr2_r (const void *addr, socklen_t len, int af, break; } - n = __libc_res_nquery (&_res, qbuf, C_IN, T_PTR, host_buffer.buf->buf, - 1024, &host_buffer.ptr, NULL, NULL, NULL, NULL); + n = __res_context_query (ctx, qbuf, C_IN, T_PTR, host_buffer.buf->buf, + 1024, &host_buffer.ptr, NULL, NULL, NULL, NULL); if (n < 0) { *h_errnop = h_errno; __set_errno (olderr); if (host_buffer.buf != orig_host_buffer) free (host_buffer.buf); + __resolv_context_put (ctx); return errno == ECONNREFUSED ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND; } @@ -503,7 +527,10 @@ _nss_dns_gethostbyaddr2_r (const void *addr, socklen_t len, int af, if (host_buffer.buf != orig_host_buffer) free (host_buffer.buf); if (status != NSS_STATUS_SUCCESS) - return status; + { + __resolv_context_put (ctx); + return status; + } result->h_addrtype = af; result->h_length = len; @@ -511,6 +538,7 @@ _nss_dns_gethostbyaddr2_r (const void *addr, socklen_t len, int af, host_data->h_addr_ptrs[0] = (char *) host_data->host_addr; host_data->h_addr_ptrs[1] = NULL; *h_errnop = NETDB_SUCCESS; + __resolv_context_put (ctx); return NSS_STATUS_SUCCESS; } hidden_def (_nss_dns_gethostbyaddr2_r) diff --git a/resolv/nss_dns/dns-network.c b/resolv/nss_dns/dns-network.c index dc1599b471..f190eb2225 100644 --- a/resolv/nss_dns/dns-network.c +++ b/resolv/nss_dns/dns-network.c @@ -67,6 +67,8 @@ #include "nsswitch.h" #include <arpa/inet.h> #include <arpa/nameser.h> +#include <resolv/resolv-internal.h> +#include <resolv/resolv_context.h> /* Maximum number of aliases we allow. */ #define MAX_NR_ALIASES 48 @@ -115,7 +117,8 @@ _nss_dns_getnetbyname_r (const char *name, struct netent *result, int anslen; enum nss_status status; - if (__res_maybe_init (&_res, 0) == -1) + struct resolv_context *ctx = __resolv_context_get (); + if (ctx == NULL) { *errnop = errno; *herrnop = NETDB_INTERNAL; @@ -124,14 +127,16 @@ _nss_dns_getnetbyname_r (const char *name, struct netent *result, net_buffer.buf = orig_net_buffer = (querybuf *) alloca (1024); - anslen = __libc_res_nsearch (&_res, name, C_IN, T_PTR, net_buffer.buf->buf, - 1024, &net_buffer.ptr, NULL, NULL, NULL, NULL); + anslen = __res_context_search + (ctx, name, C_IN, T_PTR, net_buffer.buf->buf, + 1024, &net_buffer.ptr, NULL, NULL, NULL, NULL); if (anslen < 0) { /* Nothing found. */ *errnop = errno; if (net_buffer.buf != orig_net_buffer) free (net_buffer.buf); + __resolv_context_put (ctx); return (errno == ECONNREFUSED || errno == EPFNOSUPPORT || errno == EAFNOSUPPORT) @@ -142,6 +147,7 @@ _nss_dns_getnetbyname_r (const char *name, struct netent *result, errnop, herrnop, BYNAME); if (net_buffer.buf != orig_net_buffer) free (net_buffer.buf); + __resolv_context_put (ctx); return status; } @@ -169,7 +175,8 @@ _nss_dns_getnetbyaddr_r (uint32_t net, int type, struct netent *result, if (type != AF_INET) return NSS_STATUS_UNAVAIL; - if (__res_maybe_init (&_res, 0) == -1) + struct resolv_context *ctx = __resolv_context_get (); + if (ctx == NULL) { *errnop = errno; *herrnop = NETDB_INTERNAL; @@ -204,8 +211,8 @@ _nss_dns_getnetbyaddr_r (uint32_t net, int type, struct netent *result, net_buffer.buf = orig_net_buffer = (querybuf *) alloca (1024); - anslen = __libc_res_nquery (&_res, qbuf, C_IN, T_PTR, net_buffer.buf->buf, - 1024, &net_buffer.ptr, NULL, NULL, NULL, NULL); + anslen = __res_context_query (ctx, qbuf, C_IN, T_PTR, net_buffer.buf->buf, + 1024, &net_buffer.ptr, NULL, NULL, NULL, NULL); if (anslen < 0) { /* Nothing found. */ @@ -213,6 +220,7 @@ _nss_dns_getnetbyaddr_r (uint32_t net, int type, struct netent *result, __set_errno (olderr); if (net_buffer.buf != orig_net_buffer) free (net_buffer.buf); + __resolv_context_put (ctx); return (err == ECONNREFUSED || err == EPFNOSUPPORT || err == EAFNOSUPPORT) @@ -233,6 +241,7 @@ _nss_dns_getnetbyaddr_r (uint32_t net, int type, struct netent *result, result->n_net = u_net; } + __resolv_context_put (ctx); return status; } |