2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-22 01:59:26 +00:00

Merge branch '3886-xfrin-dispatch' into 'main'

refactor dns_xfrin to use dns_dispatch

Closes #3886

See merge request isc-projects/bind9!7573
This commit is contained in:
Evan Hunt 2023-02-24 08:30:48 +00:00
commit 14bba4688c
17 changed files with 355 additions and 398 deletions

View File

@ -1,3 +1,7 @@
6110. [cleanup] Refactor the dns_xfrin module to use dns_dispatch
to set up TCP connections and send and receive
messages. [GL #3886]
6109. [func] Infrastructure for QSBR, asynchronous safe memory
reclamation for lock-free data structures. [GL !7471]

View File

@ -4746,8 +4746,7 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
ndisp = 4 * ISC_MIN(named_g_udpdisp, MAX_UDP_DISPATCH);
CHECK(dns_view_createresolver(
view, named_g_loopmgr, ndisp, named_g_netmgr, resopts,
named_g_server->tlsctx_client_cache, named_g_dispatchmgr,
dispatch4, dispatch6));
named_g_server->tlsctx_client_cache, dispatch4, dispatch6));
if (resstats == NULL) {
CHECK(isc_stats_create(mctx, &resstats,
@ -6467,6 +6466,8 @@ create_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist,
return (result);
}
dns_view_setdispatchmgr(view, named_g_dispatchmgr);
isc_nonce_buf(view->secret, sizeof(view->secret));
ISC_LIST_APPEND(*viewlist, view, link);

View File

@ -37,7 +37,6 @@
#include <dns/name.h>
#include <dns/rdataset.h>
#include <dns/request.h>
#include <dns/resolver.h>
#include <dns/result.h>
#include <dns/types.h>
#include <dns/view.h>

View File

@ -431,7 +431,7 @@ $RNDCCMD 10.53.0.4 retransfer nil | sed 's/^/ns4 /' | cat_i
sleep 2
nextpart ns4/named.run | grep "unexpected message id" > /dev/null || {
nextpart ns4/named.run | grep "Transfer status: unexpected error" > /dev/null || {
echo_i "failed: expected status was not logged"
status=$((status+1))
}

View File

@ -48,7 +48,6 @@
#include <dns/rdataset.h>
#include <dns/rdatatype.h>
#include <dns/request.h>
#include <dns/resolver.h>
#include <dns/types.h>
#include <dns/view.h>

View File

@ -211,6 +211,8 @@ createview(isc_mem_t *mctx, dns_rdataclass_t rdclass, isc_loopmgr_t *loopmgr,
return (result);
}
dns_view_setdispatchmgr(view, dispatchmgr);
/* Initialize view security roots */
result = dns_view_initsecroots(view, mctx);
if (result != ISC_R_SUCCESS) {
@ -218,8 +220,8 @@ createview(isc_mem_t *mctx, dns_rdataclass_t rdclass, isc_loopmgr_t *loopmgr,
}
result = dns_view_createresolver(view, loopmgr, 1, nm, 0,
tlsctx_client_cache, dispatchmgr,
dispatchv4, dispatchv6);
tlsctx_client_cache, dispatchv4,
dispatchv6);
if (result != ISC_R_SUCCESS) {
goto cleanup_view;
}

View File

@ -193,9 +193,6 @@ udp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
static void
tcp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
void *arg);
static void
tcp_recv_done(dns_dispentry_t *resp, isc_result_t eresult,
isc_region_t *region);
static uint32_t
dns_hash(dns_qid_t *, const isc_sockaddr_t *, dns_messageid_t, in_port_t);
static void
@ -210,8 +207,7 @@ qid_destroy(isc_mem_t *mctx, dns_qid_t **qidp);
static void
udp_startrecv(isc_nmhandle_t *handle, dns_dispentry_t *resp);
static void
tcp_startrecv(isc_nmhandle_t *handle, dns_dispatch_t *disp,
dns_dispentry_t *resp);
tcp_startrecv(dns_dispatch_t *disp, dns_dispentry_t *resp);
static void
tcp_dispatch_getnext(dns_dispatch_t *disp, dns_dispentry_t *resp,
int32_t timeout);
@ -535,7 +531,7 @@ udp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
isc_sockaddr_t peer;
isc_netaddr_t netaddr;
int match, timeout = 0;
dispatch_cb_t response = NULL;
bool respond = true;
REQUIRE(VALID_RESPONSE(resp));
REQUIRE(VALID_DISPATCH(resp->disp));
@ -546,15 +542,13 @@ udp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
INSIST(resp->reading);
resp->reading = false;
response = resp->response;
if (resp->state == DNS_DISPATCHSTATE_CANCELED) {
/*
* Nobody is interested in the callback if the response
* has been canceled already. Detach from the response
* and the handle.
*/
response = NULL;
respond = false;
eresult = ISC_R_CANCELED;
}
@ -652,16 +646,16 @@ next:
* Do not invoke the read callback just yet and instead wait for the
* proper response to arrive until the original timeout fires.
*/
response = NULL;
respond = false;
udp_dispatch_getnext(resp, timeout);
done:
UNLOCK(&disp->lock);
if (response != NULL) {
if (respond) {
dispentry_log(resp, LVL(90), "UDP read callback on %p: %s",
handle, isc_result_totext(eresult));
response(eresult, region, resp->arg);
resp->response(eresult, region, resp->arg);
}
dns_dispentry_detach(&resp); /* DISPENTRY003 */
@ -729,7 +723,10 @@ tcp_recv_success(dns_dispatch_t *disp, isc_region_t *region, dns_qid_t *qid,
if (resp->reading) {
*respp = resp;
} else {
/* We already got our DNS message. */
/*
* We already got a message for this QID and weren't
* expecting any more.
*/
result = ISC_R_UNEXPECTED;
}
} else {
@ -769,16 +766,6 @@ tcp_recv_shutdown(dns_dispatch_t *disp, dns_displist_t *resps,
disp->state = DNS_DISPATCHSTATE_CANCELED;
}
static void
tcp_recv_done(dns_dispentry_t *resp, isc_result_t eresult,
isc_region_t *region) {
dispentry_log(resp, LVL(90), "read callback: %s",
isc_result_totext(eresult));
resp->response(eresult, region, resp->arg);
dns_dispentry_detach(&resp); /* DISPENTRY009 */
}
static void
tcp_recv_processall(dns_displist_t *resps, isc_region_t *region) {
dns_dispentry_t *resp = NULL, *next = NULL;
@ -786,7 +773,11 @@ tcp_recv_processall(dns_displist_t *resps, isc_region_t *region) {
for (resp = ISC_LIST_HEAD(*resps); resp != NULL; resp = next) {
next = ISC_LIST_NEXT(resp, rlink);
ISC_LIST_UNLINK(*resps, resp, rlink);
tcp_recv_done(resp, resp->result, region);
dispentry_log(resp, LVL(90), "read callback: %s",
isc_result_totext(resp->result));
resp->response(resp->result, region, resp->arg);
dns_dispentry_detach(&resp); /* DISPENTRY009 */
}
}
@ -864,7 +855,7 @@ tcp_recv(isc_nmhandle_t *handle, isc_result_t result, isc_region_t *region,
/*
* Phase 3: Trigger timeouts. It's possible that the responses would
* have been timedout out already, but non-matching TCP reads have
* have been timed out out already, but non-matching TCP reads have
* prevented this.
*/
dns_dispentry_t *next = NULL;
@ -910,7 +901,7 @@ tcp_recv(isc_nmhandle_t *handle, isc_result_t result, isc_region_t *region,
* Phase 5: Resume reading if there are still active responses
*/
if (!ISC_LIST_EMPTY(disp->active)) {
tcp_startrecv(NULL, disp, ISC_LIST_HEAD(disp->active));
tcp_startrecv(disp, ISC_LIST_HEAD(disp->active));
}
UNLOCK(&disp->lock);
@ -1586,6 +1577,8 @@ dns_dispatch_getnext(dns_dispentry_t *resp) {
isc_result_t result = ISC_R_SUCCESS;
int32_t timeout = -1;
dispentry_log(resp, LVL(90), "getnext for QID %d", resp->id);
LOCK(&disp->lock);
switch (disp->socktype) {
case isc_socktype_udp: {
@ -1618,7 +1611,7 @@ udp_dispentry_cancel(dns_dispentry_t *resp, isc_result_t result) {
dns_dispatch_t *disp = resp->disp;
dns_dispatchmgr_t *mgr = disp->mgr;
dns_qid_t *qid = mgr->qid;
dispatch_cb_t response = NULL;
bool respond = false;
LOCK(&disp->lock);
dispentry_log(resp, LVL(90),
@ -1643,9 +1636,7 @@ udp_dispentry_cancel(dns_dispentry_t *resp, isc_result_t result) {
case DNS_DISPATCHSTATE_CONNECTED:
if (resp->reading) {
dns_dispentry_ref(resp); /* DISPENTRY003 */
response = resp->response;
respond = true;
dispentry_log(resp, LVL(90), "canceling read on %p",
resp->handle);
isc_nm_cancelread(resp->handle);
@ -1669,11 +1660,10 @@ udp_dispentry_cancel(dns_dispentry_t *resp, isc_result_t result) {
unlock:
UNLOCK(&disp->lock);
if (response) {
if (respond) {
dispentry_log(resp, LVL(90), "read callback: %s",
isc_result_totext(result));
response(result, NULL, resp->arg);
dns_dispentry_detach(&resp); /* DISPENTRY003 */
resp->response(result, NULL, resp->arg);
}
}
@ -1739,7 +1729,7 @@ tcp_dispentry_cancel(dns_dispentry_t *resp, isc_result_t result) {
dispentry_log(resp, LVL(90),
"final 1 second timeout on %p",
disp->handle);
tcp_startrecv(NULL, disp, NULL);
tcp_startrecv(disp, NULL);
}
#else
if (disp->reading) {
@ -1825,14 +1815,10 @@ udp_startrecv(isc_nmhandle_t *handle, dns_dispentry_t *resp) {
}
static void
tcp_startrecv(isc_nmhandle_t *handle, dns_dispatch_t *disp,
dns_dispentry_t *resp) {
tcp_startrecv(dns_dispatch_t *disp, dns_dispentry_t *resp) {
REQUIRE(VALID_DISPATCH(disp));
REQUIRE(disp->socktype == isc_socktype_tcp);
if (handle != NULL) {
isc_nmhandle_attach(handle, &disp->handle);
}
dns_dispatch_ref(disp); /* DISPATCH002 */
if (resp != NULL) {
dispentry_log(resp, LVL(90), "reading from %p", disp->handle);
@ -1904,7 +1890,8 @@ tcp_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) {
disp->state = DNS_DISPATCHSTATE_CANCELED;
} else if (eresult == ISC_R_SUCCESS) {
disp->state = DNS_DISPATCHSTATE_CONNECTED;
tcp_startrecv(handle, disp, resp);
isc_nmhandle_attach(handle, &disp->handle);
tcp_startrecv(disp, resp);
} else {
disp->state = DNS_DISPATCHSTATE_NONE;
}
@ -2043,16 +2030,9 @@ tcp_dispatch_connect(dns_dispatch_t *disp, dns_dispentry_t *resp) {
"connecting from %s to %s, timeout %u", localbuf,
peerbuf, resp->timeout);
if (transport_type == DNS_TRANSPORT_TLS) {
isc_nm_streamdnsconnect(disp->mgr->nm, &disp->local,
&disp->peer, tcp_connected,
disp, resp->timeout, tlsctx,
sess_cache);
} else {
isc_nm_streamdnsconnect(
disp->mgr->nm, &disp->local, &disp->peer,
tcp_connected, disp, resp->timeout, NULL, NULL);
}
isc_nm_streamdnsconnect(disp->mgr->nm, &disp->local,
&disp->peer, tcp_connected, disp,
resp->timeout, tlsctx, sess_cache);
break;
case DNS_DISPATCHSTATE_CONNECTING:
@ -2073,7 +2053,7 @@ tcp_dispatch_connect(dns_dispatch_t *disp, dns_dispentry_t *resp) {
if (!disp->reading) {
/* Restart the reading */
tcp_startrecv(NULL, disp, resp);
tcp_startrecv(disp, resp);
}
UNLOCK(&disp->lock);
@ -2137,6 +2117,13 @@ tcp_dispatch_getnext(dns_dispatch_t *disp, dns_dispentry_t *resp,
int32_t timeout) {
REQUIRE(timeout <= INT16_MAX);
dispentry_log(resp, LVL(90), "continue reading");
if (!resp->reading) {
ISC_LIST_APPEND(disp->active, resp, alink);
resp->reading = true;
}
if (disp->reading) {
return;
}
@ -2145,14 +2132,9 @@ tcp_dispatch_getnext(dns_dispatch_t *disp, dns_dispentry_t *resp,
isc_nmhandle_settimeout(disp->handle, timeout);
}
dispentry_log(resp, LVL(90), "continue reading");
dns_dispatch_ref(disp); /* DISPATCH002 */
isc_nm_read(disp->handle, tcp_recv, disp);
disp->reading = true;
ISC_LIST_APPEND(disp->active, resp, alink);
resp->reading = true;
}
static void
@ -2181,6 +2163,8 @@ dns_dispatch_resume(dns_dispentry_t *resp, uint16_t timeout) {
dns_dispatch_t *disp = resp->disp;
dispentry_log(resp, LVL(90), "resume");
LOCK(&disp->lock);
switch (disp->socktype) {
case isc_socktype_udp: {
@ -2348,3 +2332,14 @@ dns_dispatchset_destroy(dns_dispatchset_t **dsetp) {
isc_mutex_destroy(&dset->lock);
isc_mem_putanddetach(&dset->mctx, dset, sizeof(dns_dispatchset_t));
}
isc_result_t
dns_dispatch_checkperm(dns_dispatch_t *disp) {
REQUIRE(VALID_DISPATCH(disp));
if (disp->handle == NULL || disp->socktype == isc_socktype_udp) {
return (ISC_R_NOPERM);
}
return (isc_nm_xfr_checkperm(disp->handle));
}

View File

@ -388,4 +388,14 @@ dns_dispatch_getnext(dns_dispentry_t *resp);
*\li resp is valid
*/
isc_result_t
dns_dispatch_checkperm(dns_dispatch_t *disp);
/*%<
* Check whether it is permitted to do a zone transfer over a dispatch.
* See isc_nm_xfr_checkperm().
*
* Requires:
*\li disp is valid
*/
ISC_LANG_ENDDECLS

View File

@ -183,8 +183,8 @@ isc_result_t
dns_resolver_create(dns_view_t *view, isc_loopmgr_t *loopmgr,
unsigned int ndisp, isc_nm_t *nm, unsigned int options,
isc_tlsctx_cache_t *tlsctx_cache,
dns_dispatchmgr_t *dispatchmgr, dns_dispatch_t *dispatchv4,
dns_dispatch_t *dispatchv6, dns_resolver_t **resp);
dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6,
dns_resolver_t **resp);
/*%<
* Create a resolver.
@ -204,8 +204,6 @@ dns_resolver_create(dns_view_t *view, isc_loopmgr_t *loopmgr,
*
*\li 'tlsctx_cache' != NULL.
*
*\li 'dispatchmgr' != NULL.
*
*\li 'dispatchv4' is a dispatch with an IPv4 UDP socket, or is NULL.
* If not NULL, 'ndisp' clones of it will be created by the resolver.
*
@ -404,9 +402,6 @@ dns_resolver_logfetch(dns_fetch_t *fetch, isc_log_t *lctx,
*\li 'fetch' is a valid fetch, and has completed.
*/
dns_dispatchmgr_t *
dns_resolver_dispatchmgr(dns_resolver_t *resolver);
dns_dispatch_t *
dns_resolver_dispatchv4(dns_resolver_t *resolver);

View File

@ -82,17 +82,18 @@ ISC_LANG_BEGINDECLS
struct dns_view {
/* Unlocked. */
unsigned int magic;
isc_mem_t *mctx;
dns_rdataclass_t rdclass;
char *name;
dns_zt_t *zonetable;
dns_resolver_t *resolver;
dns_adb_t *adb;
dns_requestmgr_t *requestmgr;
dns_cache_t *cache;
dns_db_t *cachedb;
dns_db_t *hints;
unsigned int magic;
isc_mem_t *mctx;
dns_rdataclass_t rdclass;
char *name;
dns_zt_t *zonetable;
dns_resolver_t *resolver;
dns_adb_t *adb;
dns_requestmgr_t *requestmgr;
dns_dispatchmgr_t *dispatchmgr;
dns_cache_t *cache;
dns_db_t *cachedb;
dns_db_t *hints;
/*
* security roots and negative trust anchors.
@ -389,7 +390,6 @@ isc_result_t
dns_view_createresolver(dns_view_t *view, isc_loopmgr_t *loopmgr,
unsigned int ndisp, isc_nm_t *netmgr,
unsigned int options, isc_tlsctx_cache_t *tlsctx_cache,
dns_dispatchmgr_t *dispatchmgr,
dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6);
/*%<
* Create a resolver and address database for the view.
@ -400,6 +400,9 @@ dns_view_createresolver(dns_view_t *view, isc_loopmgr_t *loopmgr,
*
*\li 'view' does not have a resolver already.
*
*\li A dispatch manager has been associated with the view by calling
* dns_view_setdispatchmgr().
*
*\li The requirements of dns_resolver_create() apply to 'ndisp',
* 'netmgr', 'options', 'tlsctx_cache', 'dispatchv4', and 'dispatchv6'.
*
@ -1316,4 +1319,13 @@ dns_view_getudpsize(dns_view_t *view);
* Get the current EDNS UDP buffer size.
*/
void
dns_view_setdispatchmgr(dns_view_t *view, dns_dispatchmgr_t *dispatchmgr);
dns_dispatchmgr_t *
dns_view_getdispatchmgr(dns_view_t *view);
/*%<
* Set/get the dispatch manager for the view; this wil be used
* by the resolver and request managers to send and receive DNS
* messages.
*/
ISC_LANG_ENDDECLS

View File

@ -32,6 +32,9 @@
#include <dns/transport.h>
#include <dns/types.h>
/* Define to 1 for detailed reference tracing */
#undef DNS_XFRIN_TRACE
/***
*** Types
***/
@ -39,7 +42,7 @@
/*%
* A transfer in progress. This is an opaque type.
*/
typedef struct dns_xfrin_ctx dns_xfrin_ctx_t;
typedef struct dns_xfrin dns_xfrin_t;
/***
*** Functions
@ -52,17 +55,24 @@ dns_xfrin_create(dns_zone_t *zone, dns_rdatatype_t xfrtype,
const isc_sockaddr_t *primaryaddr,
const isc_sockaddr_t *sourceaddr, dns_tsigkey_t *tsigkey,
dns_transport_t *transport, isc_tlsctx_cache_t *tlsctx_cache,
isc_mem_t *mctx, isc_nm_t *netmgr, dns_xfrindone_t done,
dns_xfrin_ctx_t **xfrp);
isc_mem_t *mctx, dns_xfrindone_t done, dns_xfrin_t **xfrp);
/*%<
* Attempt to start an incoming zone transfer of 'zone'
* from 'primaryaddr', creating a dns_xfrin_ctx_t object to
* from 'primaryaddr', creating a dns_xfrin_t object to
* manage it. Attach '*xfrp' to the newly created object.
*
* Iff ISC_R_SUCCESS is returned, '*done' is called with
* 'zone' and a result code as arguments when the transfer finishes.
*
* Requires:
*\li 'xfrp' != NULL and '*xfrp' == NULL.
*
*\li 'done' != NULL.
*
*\li 'primaryaddr' has a non-zero port number.
*
*\li 'zone' is a valid zone and is associated with a view.
*
*\li 'xfrtype' is dns_rdatatype_axfr, dns_rdatatype_ixfr
* or dns_rdatatype_soa (soa query followed by axfr if
* serial is greater than current serial).
@ -72,24 +82,22 @@ dns_xfrin_create(dns_zone_t *zone, dns_rdatatype_t xfrtype,
*/
void
dns_xfrin_shutdown(dns_xfrin_ctx_t *xfr);
dns_xfrin_shutdown(dns_xfrin_t *xfr);
/*%<
* If the zone transfer 'xfr' has already finished,
* do nothing. Otherwise, abort it and cause it to call
* its done callback with a status of ISC_R_CANCELED.
*/
void
dns_xfrin_detach(dns_xfrin_ctx_t **xfrp);
/*%<
* Detach a reference to a zone transfer object.
* Caller to maintain external locking if required.
*/
void
dns_xfrin_attach(dns_xfrin_ctx_t *source, dns_xfrin_ctx_t **target);
/*%<
* Caller to maintain external locking if required.
*/
#if DNS_XFRIN_TRACE
#define dns_xfrin_ref(ptr) dns_xfrin__ref(ptr, __func__, __FILE__, __LINE__)
#define dns_xfrin_unref(ptr) dns_xfrin__unref(ptr, __func__, __FILE__, __LINE__)
#define dns_xfrin_attach(ptr, ptrp) \
dns_xfrin__attach(ptr, ptrp, __func__, __FILE__, __LINE__)
#define dns_xfrin_detach(ptrp) \
dns_xfrin__detach(ptrp, __func__, __FILE__, __LINE__)
ISC_REFCOUNT_TRACE_DECL(dns_xfrin);
#else
ISC_REFCOUNT_DECL(dns_xfrin);
#endif
ISC_LANG_ENDDECLS

View File

@ -561,7 +561,6 @@ dns_request_create(dns_requestmgr_t *requestmgr, dns_message_t *message,
isc_mem_t *mctx = NULL;
dns_messageid_t id;
bool tcp = false;
bool connected = false;
REQUIRE(VALID_REQUESTMGR(requestmgr));
REQUIRE(message != NULL);
@ -672,21 +671,14 @@ again:
UNLOCK(&requestmgr->lock);
request->destaddr = *destaddr;
if (tcp && connected) {
req_send(request);
request->flags |= DNS_REQUEST_F_CONNECTING;
if (tcp) {
request->flags |= DNS_REQUEST_F_TCP;
}
/* no need to call req_connected(), unref here */
dns_request_unref(request);
} else {
request->flags |= DNS_REQUEST_F_CONNECTING;
if (tcp) {
request->flags |= DNS_REQUEST_F_TCP;
}
result = dns_dispatch_connect(request->dispentry);
if (result != ISC_R_SUCCESS) {
goto unlink;
}
result = dns_dispatch_connect(request->dispentry);
if (result != ISC_R_SUCCESS) {
goto unlink;
}
req_log(ISC_LOG_DEBUG(3), "dns_request_create: request %p", request);

View File

@ -549,7 +549,6 @@ struct dns_resolver {
bool frozen;
unsigned int options;
isc_tlsctx_cache_t *tlsctx_cache;
dns_dispatchmgr_t *dispatchmgr;
dns_dispatchset_t *dispatches4;
dns_dispatchset_t *dispatches6;
@ -2191,7 +2190,7 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
query = isc_mem_get(fctx->mctx, sizeof(*query));
*query = (resquery_t){ .options = options,
.addrinfo = addrinfo,
.dispatchmgr = res->dispatchmgr };
.dispatchmgr = res->view->dispatchmgr };
#if DNS_RESOLVER_TRACE
fprintf(stderr, "rctx_init:%s:%s:%d:%p->references = 1\n", __func__,
@ -2256,7 +2255,7 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
}
isc_sockaddr_setport(&addr, 0);
result = dns_dispatch_createtcp(res->dispatchmgr, &addr,
result = dns_dispatch_createtcp(res->view->dispatchmgr, &addr,
&addrinfo->sockaddr,
&query->dispatch);
if (result != ISC_R_SUCCESS) {
@ -2266,7 +2265,8 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
FCTXTRACE("connecting via TCP");
} else {
if (have_addr) {
result = dns_dispatch_createudp(res->dispatchmgr, &addr,
result = dns_dispatch_createudp(res->view->dispatchmgr,
&addr,
&query->dispatch);
if (result != ISC_R_SUCCESS) {
goto cleanup_query;
@ -3914,20 +3914,17 @@ out:
static void
possibly_mark(fetchctx_t *fctx, dns_adbaddrinfo_t *addr) {
isc_netaddr_t na;
isc_sockaddr_t *sa;
isc_sockaddr_t *sa = &addr->sockaddr;
bool aborted = false;
bool bogus;
dns_acl_t *blackhole;
isc_netaddr_t ipaddr;
dns_peer_t *peer = NULL;
dns_resolver_t *res;
dns_resolver_t *res = fctx->res;
const char *msg = NULL;
sa = &addr->sockaddr;
res = fctx->res;
isc_netaddr_fromsockaddr(&ipaddr, sa);
blackhole = dns_dispatchmgr_getblackhole(res->dispatchmgr);
blackhole = dns_dispatchmgr_getblackhole(res->view->dispatchmgr);
(void)dns_peerlist_peerbyaddr(res->view->peers, &ipaddr, &peer);
if (blackhole != NULL) {
@ -10116,8 +10113,8 @@ isc_result_t
dns_resolver_create(dns_view_t *view, isc_loopmgr_t *loopmgr,
unsigned int ndisp, isc_nm_t *nm, unsigned int options,
isc_tlsctx_cache_t *tlsctx_cache,
dns_dispatchmgr_t *dispatchmgr, dns_dispatch_t *dispatchv4,
dns_dispatch_t *dispatchv6, dns_resolver_t **resp) {
dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6,
dns_resolver_t **resp) {
isc_result_t result = ISC_R_SUCCESS;
dns_resolver_t *res = NULL;
@ -10129,7 +10126,6 @@ dns_resolver_create(dns_view_t *view, isc_loopmgr_t *loopmgr,
REQUIRE(ndisp > 0);
REQUIRE(resp != NULL && *resp == NULL);
REQUIRE(tlsctx_cache != NULL);
REQUIRE(dispatchmgr != NULL);
REQUIRE(dispatchv4 != NULL || dispatchv6 != NULL);
RTRACE("create");
@ -10139,7 +10135,6 @@ dns_resolver_create(dns_view_t *view, isc_loopmgr_t *loopmgr,
.loopmgr = loopmgr,
.rdclass = view->rdclass,
.nm = nm,
.dispatchmgr = dispatchmgr,
.options = options,
.tlsctx_cache = tlsctx_cache,
.spillatmin = 10,
@ -10848,12 +10843,6 @@ dns_resolver_logfetch(dns_fetch_t *fetch, isc_log_t *lctx,
UNLOCK(&fctx->lock);
}
dns_dispatchmgr_t *
dns_resolver_dispatchmgr(dns_resolver_t *resolver) {
REQUIRE(VALID_RESOLVER(resolver));
return (resolver->dispatchmgr);
}
dns_dispatch_t *
dns_resolver_dispatchv4(dns_resolver_t *resolver) {
REQUIRE(VALID_RESOLVER(resolver));

View File

@ -637,7 +637,6 @@ isc_result_t
dns_view_createresolver(dns_view_t *view, isc_loopmgr_t *loopmgr,
unsigned int ndisp, isc_nm_t *netmgr,
unsigned int options, isc_tlsctx_cache_t *tlsctx_cache,
dns_dispatchmgr_t *dispatchmgr,
dns_dispatch_t *dispatchv4,
dns_dispatch_t *dispatchv6) {
isc_result_t result;
@ -646,12 +645,13 @@ dns_view_createresolver(dns_view_t *view, isc_loopmgr_t *loopmgr,
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(!view->frozen);
REQUIRE(view->resolver == NULL);
REQUIRE(view->dispatchmgr != NULL);
view->loop = isc_loop_current(loopmgr);
result = dns_resolver_create(view, loopmgr, ndisp, netmgr, options,
tlsctx_cache, dispatchmgr, dispatchv4,
dispatchv6, &view->resolver);
tlsctx_cache, dispatchv4, dispatchv6,
&view->resolver);
if (result != ISC_R_SUCCESS) {
return (result);
}
@ -664,9 +664,9 @@ dns_view_createresolver(dns_view_t *view, isc_loopmgr_t *loopmgr,
goto cleanup_resolver;
}
result = dns_requestmgr_create(
view->mctx, dns_resolver_dispatchmgr(view->resolver),
dispatchv4, dispatchv6, &view->requestmgr);
result = dns_requestmgr_create(view->mctx, view->dispatchmgr,
dispatchv4, dispatchv6,
&view->requestmgr);
if (result != ISC_R_SUCCESS) {
goto cleanup_adb;
}
@ -2445,3 +2445,15 @@ dns_view_getudpsize(dns_view_t *view) {
REQUIRE(DNS_VIEW_VALID(view));
return (view->udpsize);
}
void
dns_view_setdispatchmgr(dns_view_t *view, dns_dispatchmgr_t *dispatchmgr) {
REQUIRE(DNS_VIEW_VALID(view));
view->dispatchmgr = dispatchmgr;
}
dns_dispatchmgr_t *
dns_view_getdispatchmgr(dns_view_t *view) {
REQUIRE(DNS_VIEW_VALID(view));
return (view->dispatchmgr);
}

View File

@ -17,7 +17,6 @@
#include <stdbool.h>
#include <isc/mem.h>
#include <isc/netmgr.h>
#include <isc/random.h>
#include <isc/result.h>
#include <isc/string.h>
@ -27,6 +26,7 @@
#include <dns/catz.h>
#include <dns/db.h>
#include <dns/diff.h>
#include <dns/dispatch.h>
#include <dns/journal.h>
#include <dns/log.h>
#include <dns/message.h>
@ -90,19 +90,14 @@ typedef enum {
* Incoming zone transfer context.
*/
struct dns_xfrin_ctx {
struct dns_xfrin {
unsigned int magic;
isc_mem_t *mctx;
dns_zone_t *zone;
dns_view_t *view;
isc_refcount_t references;
isc_nm_t *netmgr;
isc_refcount_t connects; /*%< Connect in progress */
isc_refcount_t sends; /*%< Send in progress */
isc_refcount_t recvs; /*%< Receive in progress */
atomic_bool shuttingdown;
isc_result_t shutdown_result;
@ -122,9 +117,8 @@ struct dns_xfrin_ctx {
isc_sockaddr_t primaryaddr;
isc_sockaddr_t sourceaddr;
isc_nmhandle_t *handle;
isc_nmhandle_t *readhandle;
isc_nmhandle_t *sendhandle;
dns_dispatch_t *disp;
dns_dispentry_t *dispentry;
/*% Buffer for IXFR/AXFR request message */
isc_buffer_t qbuffer;
@ -194,72 +188,67 @@ struct dns_xfrin_ctx {
*/
static void
xfrin_create(isc_mem_t *mctx, dns_zone_t *zone, dns_db_t *db, isc_nm_t *netmgr,
xfrin_create(isc_mem_t *mctx, dns_zone_t *zone, dns_db_t *db,
dns_name_t *zonename, dns_rdataclass_t rdclass,
dns_rdatatype_t reqtype, const isc_sockaddr_t *primaryaddr,
const isc_sockaddr_t *sourceaddr, dns_tsigkey_t *tsigkey,
dns_transport_t *transport, isc_tlsctx_cache_t *tlsctx_cache,
dns_xfrin_ctx_t **xfrp);
dns_xfrin_t **xfrp);
static isc_result_t
axfr_init(dns_xfrin_ctx_t *xfr);
axfr_init(dns_xfrin_t *xfr);
static isc_result_t
axfr_makedb(dns_xfrin_ctx_t *xfr, dns_db_t **dbp);
axfr_makedb(dns_xfrin_t *xfr, dns_db_t **dbp);
static isc_result_t
axfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op, dns_name_t *name,
dns_ttl_t ttl, dns_rdata_t *rdata);
axfr_putdata(dns_xfrin_t *xfr, dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
dns_rdata_t *rdata);
static isc_result_t
axfr_apply(dns_xfrin_ctx_t *xfr);
axfr_apply(dns_xfrin_t *xfr);
static isc_result_t
axfr_commit(dns_xfrin_ctx_t *xfr);
axfr_commit(dns_xfrin_t *xfr);
static isc_result_t
axfr_finalize(dns_xfrin_ctx_t *xfr);
axfr_finalize(dns_xfrin_t *xfr);
static isc_result_t
ixfr_init(dns_xfrin_ctx_t *xfr);
ixfr_init(dns_xfrin_t *xfr);
static isc_result_t
ixfr_apply(dns_xfrin_ctx_t *xfr);
ixfr_apply(dns_xfrin_t *xfr);
static isc_result_t
ixfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op, dns_name_t *name,
dns_ttl_t ttl, dns_rdata_t *rdata);
ixfr_putdata(dns_xfrin_t *xfr, dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
dns_rdata_t *rdata);
static isc_result_t
ixfr_commit(dns_xfrin_ctx_t *xfr);
ixfr_commit(dns_xfrin_t *xfr);
static isc_result_t
xfr_rr(dns_xfrin_ctx_t *xfr, dns_name_t *name, uint32_t ttl,
dns_rdata_t *rdata);
xfr_rr(dns_xfrin_t *xfr, dns_name_t *name, uint32_t ttl, dns_rdata_t *rdata);
static isc_result_t
xfrin_start(dns_xfrin_ctx_t *xfr);
xfrin_start(dns_xfrin_t *xfr);
static void
xfrin_connect_done(isc_nmhandle_t *handle, isc_result_t result, void *cbarg);
xfrin_connect_done(isc_result_t result, isc_region_t *region, void *arg);
static isc_result_t
xfrin_send_request(dns_xfrin_ctx_t *xfr);
xfrin_send_request(dns_xfrin_t *xfr);
static void
xfrin_send_done(isc_nmhandle_t *handle, isc_result_t result, void *cbarg);
xfrin_send_done(isc_result_t eresult, isc_region_t *region, void *arg);
static void
xfrin_recv_done(isc_nmhandle_t *handle, isc_result_t result,
isc_region_t *region, void *cbarg);
xfrin_recv_done(isc_result_t result, isc_region_t *region, void *arg);
static void
xfrin_destroy(dns_xfrin_ctx_t *xfr);
xfrin_destroy(dns_xfrin_t *xfr);
static void
xfrin_fail(dns_xfrin_ctx_t *xfr, isc_result_t result, const char *msg);
xfrin_fail(dns_xfrin_t *xfr, isc_result_t result, const char *msg);
static isc_result_t
render(dns_message_t *msg, isc_mem_t *mctx, isc_buffer_t *buf);
static void
xfrin_logv(int level, const char *zonetext, const isc_sockaddr_t *primaryaddr,
const char *fmt, va_list ap) ISC_FORMAT_PRINTF(4, 0);
xfrin_logv(dns_xfrin_t *xff, int level, const char *zonetext,
const isc_sockaddr_t *primaryaddr, const char *fmt, va_list ap)
ISC_FORMAT_PRINTF(5, 0);
static void
xfrin_log1(int level, const char *zonetext, const isc_sockaddr_t *primaryaddr,
const char *fmt, ...) ISC_FORMAT_PRINTF(4, 5);
static void
xfrin_log(dns_xfrin_ctx_t *xfr, int level, const char *fmt, ...)
xfrin_log(dns_xfrin_t *xfr, int level, const char *fmt, ...)
ISC_FORMAT_PRINTF(3, 4);
/**************************************************************************/
@ -268,7 +257,7 @@ xfrin_log(dns_xfrin_ctx_t *xfr, int level, const char *fmt, ...)
*/
static isc_result_t
axfr_init(dns_xfrin_ctx_t *xfr) {
axfr_init(dns_xfrin_t *xfr) {
isc_result_t result;
xfr->is_ixfr = false;
@ -286,7 +275,7 @@ failure:
}
static isc_result_t
axfr_makedb(dns_xfrin_ctx_t *xfr, dns_db_t **dbp) {
axfr_makedb(dns_xfrin_t *xfr, dns_db_t **dbp) {
isc_result_t result;
result = dns_db_create(xfr->mctx, /* XXX */
@ -302,8 +291,8 @@ axfr_makedb(dns_xfrin_ctx_t *xfr, dns_db_t **dbp) {
}
static isc_result_t
axfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op, dns_name_t *name,
dns_ttl_t ttl, dns_rdata_t *rdata) {
axfr_putdata(dns_xfrin_t *xfr, dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
dns_rdata_t *rdata) {
isc_result_t result;
dns_difftuple_t *tuple = NULL;
@ -328,7 +317,7 @@ failure:
* Store a set of AXFR RRs in the database.
*/
static isc_result_t
axfr_apply(dns_xfrin_ctx_t *xfr) {
axfr_apply(dns_xfrin_t *xfr) {
isc_result_t result;
uint64_t records;
@ -348,7 +337,7 @@ failure:
}
static isc_result_t
axfr_commit(dns_xfrin_ctx_t *xfr) {
axfr_commit(dns_xfrin_t *xfr) {
isc_result_t result;
CHECK(axfr_apply(xfr));
@ -361,7 +350,7 @@ failure:
}
static isc_result_t
axfr_finalize(dns_xfrin_ctx_t *xfr) {
axfr_finalize(dns_xfrin_t *xfr) {
isc_result_t result;
CHECK(dns_zone_replacedb(xfr->zone, xfr->db, true));
@ -377,7 +366,7 @@ failure:
*/
static isc_result_t
ixfr_init(dns_xfrin_ctx_t *xfr) {
ixfr_init(dns_xfrin_t *xfr) {
isc_result_t result;
char *journalfile = NULL;
@ -403,8 +392,8 @@ failure:
}
static isc_result_t
ixfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op, dns_name_t *name,
dns_ttl_t ttl, dns_rdata_t *rdata) {
ixfr_putdata(dns_xfrin_t *xfr, dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
dns_rdata_t *rdata) {
isc_result_t result;
dns_difftuple_t *tuple = NULL;
@ -430,7 +419,7 @@ failure:
* Apply a set of IXFR changes to the database.
*/
static isc_result_t
ixfr_apply(dns_xfrin_ctx_t *xfr) {
ixfr_apply(dns_xfrin_t *xfr) {
isc_result_t result;
uint64_t records;
@ -462,7 +451,7 @@ failure:
}
static isc_result_t
ixfr_commit(dns_xfrin_ctx_t *xfr) {
ixfr_commit(dns_xfrin_t *xfr) {
isc_result_t result;
CHECK(ixfr_apply(xfr));
@ -490,8 +479,7 @@ failure:
* state.
*/
static isc_result_t
xfr_rr(dns_xfrin_ctx_t *xfr, dns_name_t *name, uint32_t ttl,
dns_rdata_t *rdata) {
xfr_rr(dns_xfrin_t *xfr, dns_name_t *name, uint32_t ttl, dns_rdata_t *rdata) {
isc_result_t result;
xfr->nrecs++;
@ -694,16 +682,17 @@ dns_xfrin_create(dns_zone_t *zone, dns_rdatatype_t xfrtype,
const isc_sockaddr_t *primaryaddr,
const isc_sockaddr_t *sourceaddr, dns_tsigkey_t *tsigkey,
dns_transport_t *transport, isc_tlsctx_cache_t *tlsctx_cache,
isc_mem_t *mctx, isc_nm_t *netmgr, dns_xfrindone_t done,
dns_xfrin_ctx_t **xfrp) {
isc_mem_t *mctx, dns_xfrindone_t done, dns_xfrin_t **xfrp) {
dns_name_t *zonename = dns_zone_getorigin(zone);
dns_xfrin_ctx_t *xfr = NULL;
dns_xfrin_t *xfr = NULL;
isc_result_t result;
dns_db_t *db = NULL;
REQUIRE(xfrp != NULL && *xfrp == NULL);
REQUIRE(done != NULL);
REQUIRE(isc_sockaddr_getport(primaryaddr) != 0);
REQUIRE(zone != NULL);
REQUIRE(dns_zone_getview(zone) != NULL);
(void)dns_zone_getdb(zone, &db);
@ -711,9 +700,9 @@ dns_xfrin_create(dns_zone_t *zone, dns_rdatatype_t xfrtype,
REQUIRE(db != NULL);
}
xfrin_create(mctx, zone, db, netmgr, zonename, dns_zone_getclass(zone),
xfrtype, primaryaddr, sourceaddr, tsigkey, transport,
tlsctx_cache, &xfr);
xfrin_create(mctx, zone, db, zonename, dns_zone_getclass(zone), xfrtype,
primaryaddr, sourceaddr, tsigkey, transport, tlsctx_cache,
&xfr);
if (db != NULL) {
xfr->zone_had_db = true;
@ -724,11 +713,9 @@ dns_xfrin_create(dns_zone_t *zone, dns_rdatatype_t xfrtype,
isc_refcount_init(&xfr->references, 1);
/*
* Set *xfrp now, before calling xfrin_start(). Asynchronous
* netmgr processing could cause the 'done' callback to run in
* another thread before we reached the end of the present
* function. In that case, if *xfrp hadn't already been
* attached, the 'done' function would be unable to detach it.
* Set *xfrp now, before calling xfrin_start(), otherwise it's
* possible the 'done' callback could be run before *xfrp
* was attached.
*/
*xfrp = xfr;
@ -744,67 +731,40 @@ dns_xfrin_create(dns_zone_t *zone, dns_rdatatype_t xfrtype,
}
if (result != ISC_R_SUCCESS) {
char zonetext[DNS_NAME_MAXTEXT + 32];
dns_zone_name(zone, zonetext, sizeof(zonetext));
xfrin_log1(ISC_LOG_ERROR, zonetext, primaryaddr,
"zone transfer setup failed");
xfrin_log(xfr, ISC_LOG_ERROR, "zone transfer setup failed");
}
return (result);
}
static void
xfrin_cancelio(dns_xfrin_ctx_t *xfr);
void
dns_xfrin_shutdown(dns_xfrin_ctx_t *xfr) {
dns_xfrin_shutdown(dns_xfrin_t *xfr) {
REQUIRE(VALID_XFRIN(xfr));
xfrin_fail(xfr, ISC_R_CANCELED, "shut down");
/* we won't reach xfrin_recv_done(), so dereference xfr here */
dns_xfrin_unref(xfr);
}
void
dns_xfrin_attach(dns_xfrin_ctx_t *source, dns_xfrin_ctx_t **target) {
REQUIRE(VALID_XFRIN(source));
REQUIRE(target != NULL && *target == NULL);
(void)isc_refcount_increment(&source->references);
#if DNS_XFRIN_TRACE
ISC_REFCOUNT_TRACE_IMPL(dns_xfrin, xfrin_destroy);
#else
ISC_REFCOUNT_IMPL(dns_xfrin, xfrin_destroy);
#endif
*target = source;
}
void
dns_xfrin_detach(dns_xfrin_ctx_t **xfrp) {
dns_xfrin_ctx_t *xfr = NULL;
REQUIRE(xfrp != NULL && VALID_XFRIN(*xfrp));
xfr = *xfrp;
*xfrp = NULL;
if (isc_refcount_decrement(&xfr->references) == 1) {
xfrin_destroy(xfr);
}
static void
xfrin_cancelio(dns_xfrin_t *xfr) {
dns_dispatch_done(&xfr->dispentry);
dns_dispatch_detach(&xfr->disp);
}
static void
xfrin_cancelio(dns_xfrin_ctx_t *xfr) {
if (xfr->readhandle == NULL) {
return;
}
isc_nm_cancelread(xfr->readhandle);
/* The xfr->readhandle detach will happen in xfrin_recv_done callback */
}
static void
xfrin_reset(dns_xfrin_ctx_t *xfr) {
xfrin_reset(dns_xfrin_t *xfr) {
REQUIRE(VALID_XFRIN(xfr));
xfrin_log(xfr, ISC_LOG_INFO, "resetting");
REQUIRE(xfr->readhandle == NULL);
REQUIRE(xfr->sendhandle == NULL);
if (xfr->lasttsig != NULL) {
isc_buffer_free(&xfr->lasttsig);
}
@ -826,7 +786,9 @@ xfrin_reset(dns_xfrin_ctx_t *xfr) {
}
static void
xfrin_fail(dns_xfrin_ctx_t *xfr, isc_result_t result, const char *msg) {
xfrin_fail(dns_xfrin_t *xfr, isc_result_t result, const char *msg) {
dns_xfrin_ref(xfr);
/* Make sure only the first xfrin_fail() trumps */
if (atomic_compare_exchange_strong(&xfr->shuttingdown, &(bool){ false },
true))
@ -836,12 +798,14 @@ xfrin_fail(dns_xfrin_ctx_t *xfr, isc_result_t result, const char *msg) {
xfrin_log(xfr, ISC_LOG_ERROR, "%s: %s", msg,
isc_result_totext(result));
if (xfr->is_ixfr) {
/* Pass special result code to force AXFR retry
/*
* Pass special result code to force AXFR retry
*/
result = DNS_R_BADIXFR;
}
}
xfrin_cancelio(xfr);
/*
* Close the journal.
*/
@ -854,36 +818,33 @@ xfrin_fail(dns_xfrin_ctx_t *xfr, isc_result_t result, const char *msg) {
}
xfr->shutdown_result = result;
}
dns_xfrin_detach(&xfr);
}
static void
xfrin_create(isc_mem_t *mctx, dns_zone_t *zone, dns_db_t *db, isc_nm_t *netmgr,
xfrin_create(isc_mem_t *mctx, dns_zone_t *zone, dns_db_t *db,
dns_name_t *zonename, dns_rdataclass_t rdclass,
dns_rdatatype_t reqtype, const isc_sockaddr_t *primaryaddr,
const isc_sockaddr_t *sourceaddr, dns_tsigkey_t *tsigkey,
dns_transport_t *transport, isc_tlsctx_cache_t *tlsctx_cache,
dns_xfrin_ctx_t **xfrp) {
dns_xfrin_ctx_t *xfr = NULL;
dns_xfrin_t **xfrp) {
dns_xfrin_t *xfr = NULL;
xfr = isc_mem_get(mctx, sizeof(*xfr));
*xfr = (dns_xfrin_ctx_t){ .netmgr = netmgr,
.shutdown_result = ISC_R_UNSET,
.rdclass = rdclass,
.reqtype = reqtype,
.id = (dns_messageid_t)isc_random16(),
.maxrecords = dns_zone_getmaxrecords(zone),
.primaryaddr = *primaryaddr,
.sourceaddr = *sourceaddr,
.firstsoa = DNS_RDATA_INIT };
*xfr = (dns_xfrin_t){ .shutdown_result = ISC_R_UNSET,
.rdclass = rdclass,
.reqtype = reqtype,
.maxrecords = dns_zone_getmaxrecords(zone),
.primaryaddr = *primaryaddr,
.sourceaddr = *sourceaddr,
.firstsoa = DNS_RDATA_INIT };
isc_mem_attach(mctx, &xfr->mctx);
dns_zone_iattach(zone, &xfr->zone);
dns_view_weakattach(dns_zone_getview(zone), &xfr->view);
dns_name_init(&xfr->name, NULL);
isc_refcount_init(&xfr->connects, 0);
isc_refcount_init(&xfr->sends, 0);
isc_refcount_init(&xfr->recvs, 0);
atomic_init(&xfr->shuttingdown, false);
if (db != NULL) {
@ -927,51 +888,54 @@ xfrin_create(isc_mem_t *mctx, dns_zone_t *zone, dns_db_t *db, isc_nm_t *netmgr,
}
static isc_result_t
xfrin_start(dns_xfrin_ctx_t *xfr) {
isc_result_t result;
dns_xfrin_ctx_t *connect_xfr = NULL;
dns_transport_type_t transport_type = DNS_TRANSPORT_TCP;
isc_tlsctx_t *tlsctx = NULL;
isc_tlsctx_client_session_cache_t *sess_cache = NULL;
xfrin_start(dns_xfrin_t *xfr) {
isc_result_t result = ISC_R_FAILURE;
(void)isc_refcount_increment0(&xfr->connects);
dns_xfrin_attach(xfr, &connect_xfr);
dns_xfrin_ref(xfr);
if (xfr->transport != NULL) {
transport_type = dns_transport_get_type(xfr->transport);
/*
* Reuse an existing TCP connection if possible. For XoT, we can't
* do this because other connections could be using a different
* certificate, so we just create a new dispatch every time.
*/
if (xfr->transport == NULL ||
dns_transport_get_type(xfr->transport) == DNS_TRANSPORT_TCP)
{
result = dns_dispatch_gettcp(dns_view_getdispatchmgr(xfr->view),
&xfr->primaryaddr,
&xfr->sourceaddr, &xfr->disp);
}
if (result == ISC_R_SUCCESS) {
char peer[ISC_SOCKADDR_FORMATSIZE];
isc_sockaddr_format(&xfr->primaryaddr, peer, sizeof(peer));
xfrin_log(xfr, ISC_LOG_DEBUG(1),
"attached to TCP connection to %s", peer);
} else {
CHECK(dns_dispatch_createtcp(dns_view_getdispatchmgr(xfr->view),
&xfr->sourceaddr,
&xfr->primaryaddr, &xfr->disp));
}
/*
* XXX: timeouts are hard-coded to 30 seconds; this needs to be
* configurable.
*/
switch (transport_type) {
case DNS_TRANSPORT_TCP:
isc_nm_streamdnsconnect(xfr->netmgr, &xfr->sourceaddr,
&xfr->primaryaddr, xfrin_connect_done,
connect_xfr, 30000, NULL, NULL);
break;
case DNS_TRANSPORT_TLS: {
result = dns_transport_get_tlsctx(
xfr->transport, &xfr->primaryaddr, xfr->tlsctx_cache,
xfr->mctx, &tlsctx, &sess_cache);
if (result != ISC_R_SUCCESS) {
goto failure;
}
INSIST(tlsctx != NULL);
isc_nm_streamdnsconnect(xfr->netmgr, &xfr->sourceaddr,
&xfr->primaryaddr, xfrin_connect_done,
connect_xfr, 30000, tlsctx, sess_cache);
} break;
default:
UNREACHABLE();
}
CHECK(dns_dispatch_add(
xfr->disp, 0, 30000, &xfr->primaryaddr, xfr->transport,
xfr->tlsctx_cache, xfrin_connect_done, xfrin_send_done,
xfrin_recv_done, xfr, &xfr->id, &xfr->dispentry));
CHECK(dns_dispatch_connect(xfr->dispentry));
return (ISC_R_SUCCESS);
failure:
isc_refcount_decrement0(&xfr->connects);
dns_xfrin_detach(&connect_xfr);
if (xfr->dispentry != NULL) {
dns_dispatch_done(&xfr->dispentry);
}
if (xfr->disp != NULL) {
dns_dispatch_detach(&xfr->disp);
}
dns_xfrin_detach(&xfr);
return (result);
}
@ -999,26 +963,29 @@ failure:
* A connection has been established.
*/
static void
xfrin_connect_done(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *)cbarg;
char sourcetext[ISC_SOCKADDR_FORMATSIZE];
xfrin_connect_done(isc_result_t result, isc_region_t *region, void *arg) {
dns_xfrin_t *xfr = (dns_xfrin_t *)arg;
char addrtext[ISC_SOCKADDR_FORMATSIZE];
char signerbuf[DNS_NAME_FORMATSIZE];
const char *signer = "", *sep = "";
isc_sockaddr_t sockaddr;
dns_zonemgr_t *zmgr = NULL;
isc_time_t now;
REQUIRE(VALID_XFRIN(xfr));
UNUSED(region);
isc_refcount_decrement0(&xfr->connects);
REQUIRE(VALID_XFRIN(xfr));
if (atomic_load(&xfr->shuttingdown)) {
result = ISC_R_SHUTTINGDOWN;
}
CHECK(result);
if (result != ISC_R_SUCCESS) {
xfrin_fail(xfr, result, "failed to connect");
dns_xfrin_unref(xfr);
return;
}
CHECK(isc_nm_xfr_checkperm(handle));
CHECK(dns_dispatch_checkperm(xfr->disp));
zmgr = dns_zone_getmgr(xfr->zone);
if (zmgr != NULL) {
@ -1033,10 +1000,6 @@ xfrin_connect_done(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
}
}
xfr->handle = handle;
sockaddr = isc_nmhandle_peeraddr(handle);
isc_sockaddr_format(&sockaddr, sourcetext, sizeof(sourcetext));
if (xfr->tsigkey != NULL && xfr->tsigkey->key != NULL) {
dns_name_format(dst_key_name(xfr->tsigkey->key), signerbuf,
sizeof(signerbuf));
@ -1044,17 +1007,16 @@ xfrin_connect_done(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
signer = signerbuf;
}
xfrin_log(xfr, ISC_LOG_INFO, "connected using %s%s%s", sourcetext, sep,
isc_sockaddr_format(&xfr->primaryaddr, addrtext, sizeof(addrtext));
xfrin_log(xfr, ISC_LOG_INFO, "connected using %s%s%s", addrtext, sep,
signer);
CHECK(xfrin_send_request(xfr));
failure:
if (result != ISC_R_SUCCESS) {
xfrin_fail(xfr, result, "failed to connect");
xfrin_fail(xfr, result, "connected but unable to transfer");
}
dns_xfrin_detach(&xfr); /* connect_xfr */
}
/*
@ -1091,11 +1053,25 @@ tuple2msgname(dns_difftuple_t *tuple, dns_message_t *msg, dns_name_t **target) {
*target = name;
}
static const char *
request_type(dns_xfrin_t *xfr) {
switch (xfr->reqtype) {
case dns_rdatatype_soa:
return "SOA";
case dns_rdatatype_axfr:
return "AXFR";
case dns_rdatatype_ixfr:
return "IXFR";
default:
ISC_UNREACHABLE();
}
}
/*
* Build an *XFR request and send its length prefix.
*/
static isc_result_t
xfrin_send_request(dns_xfrin_ctx_t *xfr) {
xfrin_send_request(dns_xfrin_t *xfr) {
isc_result_t result;
isc_region_t region;
dns_rdataset_t *qrdataset = NULL;
@ -1104,7 +1080,6 @@ xfrin_send_request(dns_xfrin_ctx_t *xfr) {
dns_name_t *qname = NULL;
dns_dbversion_t *ver = NULL;
dns_name_t *msgsoaname = NULL;
dns_xfrin_ctx_t *send_xfr = NULL;
/* Create the request message */
dns_message_create(xfr->mctx, DNS_MESSAGE_INTENTRENDER, &msg);
@ -1125,7 +1100,6 @@ xfrin_send_request(dns_xfrin_ctx_t *xfr) {
if (xfr->reqtype == dns_rdatatype_ixfr) {
/* Get the SOA and add it to the authority section. */
/* XXX is using the current version the right thing? */
dns_db_currentversion(xfr->db, &ver);
CHECK(dns_db_createsoatuple(xfr->db, ver, xfr->mctx,
DNS_DIFFOP_EXISTS, &soatuple));
@ -1142,7 +1116,6 @@ xfrin_send_request(dns_xfrin_ctx_t *xfr) {
&xfr->ixfr.request_serial));
}
xfr->id++;
xfr->nmsg = 0;
xfr->nrecs = 0;
xfr->nbytes = 0;
@ -1169,10 +1142,10 @@ xfrin_send_request(dns_xfrin_ctx_t *xfr) {
isc_buffer_usedregion(&xfr->qbuffer, &region);
INSIST(region.length <= 65535);
dns_xfrin_attach(xfr, &send_xfr);
isc_nmhandle_attach(send_xfr->handle, &xfr->sendhandle);
isc_refcount_increment0(&send_xfr->sends);
isc_nm_send(xfr->handle, &region, xfrin_send_done, send_xfr);
dns_xfrin_ref(xfr);
dns_dispatch_send(xfr->dispentry, &region);
xfrin_log(xfr, ISC_LOG_DEBUG(3), "sending %s request, QID %d",
request_type(xfr), xfr->id);
failure:
dns_message_detach(&msg);
@ -1187,13 +1160,13 @@ failure:
}
static void
xfrin_send_done(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *)cbarg;
dns_xfrin_ctx_t *recv_xfr = NULL;
xfrin_send_done(isc_result_t result, isc_region_t *region, void *arg) {
dns_xfrin_t *xfr = (dns_xfrin_t *)arg;
UNUSED(region);
REQUIRE(VALID_XFRIN(xfr));
isc_refcount_decrement0(&xfr->sends);
if (atomic_load(&xfr->shuttingdown)) {
result = ISC_R_SHUTTINGDOWN;
}
@ -1202,34 +1175,24 @@ xfrin_send_done(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
xfrin_log(xfr, ISC_LOG_DEBUG(3), "sent request data");
dns_xfrin_attach(xfr, &recv_xfr);
isc_nmhandle_attach(handle, &recv_xfr->readhandle);
isc_refcount_increment0(&recv_xfr->recvs);
isc_nm_read(recv_xfr->handle, xfrin_recv_done, recv_xfr);
failure:
if (result != ISC_R_SUCCESS) {
xfrin_fail(xfr, result, "failed sending request data");
}
isc_nmhandle_detach(&xfr->sendhandle);
dns_xfrin_detach(&xfr); /* send_xfr */
dns_xfrin_detach(&xfr);
}
static void
xfrin_recv_done(isc_nmhandle_t *handle, isc_result_t result,
isc_region_t *region, void *cbarg) {
dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *)cbarg;
xfrin_recv_done(isc_result_t result, isc_region_t *region, void *arg) {
dns_xfrin_t *xfr = (dns_xfrin_t *)arg;
dns_message_t *msg = NULL;
dns_name_t *name = NULL;
const dns_name_t *tsigowner = NULL;
isc_buffer_t buffer;
isc_sockaddr_t peer;
REQUIRE(VALID_XFRIN(xfr));
isc_refcount_decrement0(&xfr->recvs);
if (atomic_load(&xfr->shuttingdown)) {
result = ISC_R_SHUTTINGDOWN;
}
@ -1254,23 +1217,21 @@ xfrin_recv_done(isc_nmhandle_t *handle, isc_result_t result,
isc_buffer_init(&buffer, region->base, region->length);
isc_buffer_add(&buffer, region->length);
peer = isc_nmhandle_peeraddr(handle);
result = dns_message_parse(msg, &buffer,
DNS_MESSAGEPARSE_PRESERVEORDER);
if (result == ISC_R_SUCCESS) {
dns_message_logpacket(msg, "received message from", &peer,
DNS_LOGCATEGORY_XFER_IN,
DNS_LOGMODULE_XFER_IN, ISC_LOG_DEBUG(10),
xfr->mctx);
dns_message_logpacket(
msg, "received message from", &xfr->primaryaddr,
DNS_LOGCATEGORY_XFER_IN, DNS_LOGMODULE_XFER_IN,
ISC_LOG_DEBUG(10), xfr->mctx);
} else {
xfrin_log(xfr, ISC_LOG_DEBUG(10), "dns_message_parse: %s",
isc_result_totext(result));
}
if (result != ISC_R_SUCCESS || msg->rcode != dns_rcode_noerror ||
msg->opcode != dns_opcode_query || msg->rdclass != xfr->rdclass ||
msg->id != xfr->id)
msg->opcode != dns_opcode_query || msg->rdclass != xfr->rdclass)
{
if (result == ISC_R_SUCCESS && msg->rcode != dns_rcode_noerror)
{
@ -1296,7 +1257,6 @@ xfrin_recv_done(isc_nmhandle_t *handle, isc_result_t result,
xfrin_log(xfr, ISC_LOG_DEBUG(3), "got %s, retrying with AXFR",
isc_result_totext(result));
try_axfr:
isc_nmhandle_detach(&xfr->readhandle);
dns_message_detach(&msg);
xfrin_reset(xfr);
xfr->reqtype = dns_rdatatype_soa;
@ -1305,7 +1265,7 @@ xfrin_recv_done(isc_nmhandle_t *handle, isc_result_t result,
if (result != ISC_R_SUCCESS) {
xfrin_fail(xfr, result, "failed setting up socket");
}
dns_xfrin_detach(&xfr); /* recv_xfr */
dns_xfrin_detach(&xfr);
return;
}
@ -1385,7 +1345,7 @@ xfrin_recv_done(isc_nmhandle_t *handle, isc_result_t result,
FAIL(DNS_R_NOTAUTHORITATIVE);
}
result = dns_message_checksig(msg, dns_zone_getview(xfr->zone));
result = dns_message_checksig(msg, xfr->view);
if (result != ISC_R_SUCCESS) {
xfrin_log(xfr, ISC_LOG_DEBUG(3), "TSIG check failed: %s",
isc_result_totext(result));
@ -1494,11 +1454,8 @@ xfrin_recv_done(isc_nmhandle_t *handle, isc_result_t result,
/*
* Read the next message.
*/
/* The readhandle is still attached */
/* The recv_xfr is still attached */
dns_message_detach(&msg);
isc_refcount_increment0(&xfr->recvs);
isc_nm_read(xfr->handle, xfrin_recv_done, xfr);
dns_dispatch_getnext(xfr->dispentry);
return;
}
@ -1510,24 +1467,18 @@ failure:
if (msg != NULL) {
dns_message_detach(&msg);
}
isc_nmhandle_detach(&xfr->readhandle);
dns_xfrin_detach(&xfr); /* recv_xfr */
dns_xfrin_detach(&xfr);
}
static void
xfrin_destroy(dns_xfrin_ctx_t *xfr) {
uint64_t msecs;
uint64_t persec;
const char *result_str;
xfrin_destroy(dns_xfrin_t *xfr) {
uint64_t msecs, persec;
REQUIRE(VALID_XFRIN(xfr));
/* Safe-guards */
REQUIRE(atomic_load(&xfr->shuttingdown));
isc_refcount_destroy(&xfr->references);
isc_refcount_destroy(&xfr->connects);
isc_refcount_destroy(&xfr->recvs);
isc_refcount_destroy(&xfr->sends);
INSIST(xfr->shutdown_result != ISC_R_UNSET);
@ -1536,8 +1487,8 @@ xfrin_destroy(dns_xfrin_ctx_t *xfr) {
* shutting down, we can't know what the transfer status is as
* we are only called when the last reference is lost.
*/
result_str = isc_result_totext(xfr->shutdown_result);
xfrin_log(xfr, ISC_LOG_INFO, "Transfer status: %s", result_str);
xfrin_log(xfr, ISC_LOG_INFO, "Transfer status: %s",
isc_result_totext(xfr->shutdown_result));
/*
* Calculate the length of time the transfer took,
@ -1557,11 +1508,11 @@ xfrin_destroy(dns_xfrin_ctx_t *xfr) {
(unsigned int)(msecs / 1000), (unsigned int)(msecs % 1000),
(unsigned int)persec, xfr->end_serial);
if (xfr->readhandle != NULL) {
isc_nmhandle_detach(&xfr->readhandle);
if (xfr->dispentry != NULL) {
dns_dispatch_done(&xfr->dispentry);
}
if (xfr->sendhandle != NULL) {
isc_nmhandle_detach(&xfr->sendhandle);
if (xfr->disp != NULL) {
dns_dispatch_detach(&xfr->disp);
}
if (xfr->transport != NULL) {
@ -1617,6 +1568,10 @@ xfrin_destroy(dns_xfrin_ctx_t *xfr) {
dns_zone_idetach(&xfr->zone);
}
if (xfr->view != NULL) {
dns_view_weakdetach(&xfr->view);
}
if (xfr->firstsoa_data != NULL) {
isc_mem_free(xfr->mctx, xfr->firstsoa_data);
}
@ -1633,8 +1588,8 @@ xfrin_destroy(dns_xfrin_ctx_t *xfr) {
* transfer of <zone> from <address>: <message>
*/
static void
xfrin_logv(int level, const char *zonetext, const isc_sockaddr_t *primaryaddr,
const char *fmt, va_list ap) {
xfrin_logv(dns_xfrin_t *xfr, int level, const char *zonetext,
const isc_sockaddr_t *primaryaddr, const char *fmt, va_list ap) {
char primarytext[ISC_SOCKADDR_FORMATSIZE];
char msgtext[2048];
@ -1642,34 +1597,16 @@ xfrin_logv(int level, const char *zonetext, const isc_sockaddr_t *primaryaddr,
vsnprintf(msgtext, sizeof(msgtext), fmt, ap);
isc_log_write(dns_lctx, DNS_LOGCATEGORY_XFER_IN, DNS_LOGMODULE_XFER_IN,
level, "transfer of '%s' from %s: %s", zonetext,
level, "%p: transfer of '%s' from %s: %s", xfr, zonetext,
primarytext, msgtext);
}
/*
* Logging function for use when a xfrin_ctx_t has not yet been created.
*/
static void
xfrin_log1(int level, const char *zonetext, const isc_sockaddr_t *primaryaddr,
const char *fmt, ...) {
va_list ap;
if (!isc_log_wouldlog(dns_lctx, level)) {
return;
}
va_start(ap, fmt);
xfrin_logv(level, zonetext, primaryaddr, fmt, ap);
va_end(ap);
}
/*
* Logging function for use when there is a xfrin_ctx_t.
*/
static void
xfrin_log(dns_xfrin_ctx_t *xfr, int level, const char *fmt, ...) {
xfrin_log(dns_xfrin_t *xfr, int level, const char *fmt, ...) {
va_list ap;
char zonetext[DNS_NAME_MAXTEXT + 32];
@ -1680,6 +1617,6 @@ xfrin_log(dns_xfrin_ctx_t *xfr, int level, const char *fmt, ...) {
dns_zone_name(xfr->zone, zonetext, sizeof(zonetext));
va_start(ap, fmt);
xfrin_logv(level, zonetext, &xfr->primaryaddr, fmt, ap);
xfrin_logv(xfr, level, zonetext, &xfr->primaryaddr, fmt, ap);
va_end(ap);
}

View File

@ -323,7 +323,7 @@ struct dns_zone {
isc_sockaddr_t xfrsource4;
isc_sockaddr_t xfrsource6;
isc_sockaddr_t sourceaddr;
dns_xfrin_ctx_t *xfr; /* loop locked */
dns_xfrin_t *xfr; /* loop locked */
dns_tsigkey_t *tsigkey; /* key used for xfr */
dns_transport_t *transport; /* transport used for xfr */
/* Access Control Lists */
@ -17537,7 +17537,7 @@ got_transfer_quota(void *arg) {
CHECK(dns_xfrin_create(zone, xfrtype, &primaryaddr, &sourceaddr,
zone->tsigkey, zone->transport,
zone->zmgr->tlsctx_cache, zone->mctx,
zone->zmgr->netmgr, zone_xfrdone, &zone->xfr));
zone_xfrdone, &zone->xfr));
LOCK_ZONE(zone);
if (xfrtype == dns_rdatatype_axfr) {
if (isc_sockaddr_pf(&primaryaddr) == PF_INET) {

View File

@ -52,6 +52,8 @@ setup_test(void **state) {
result = dns_test_makeview("view", false, &view);
assert_int_equal(result, ISC_R_SUCCESS);
dns_view_setdispatchmgr(view, dispatchmgr);
isc_sockaddr_any(&local);
result = dns_dispatch_createudp(dispatchmgr, &local, &dispatch);
assert_int_equal(result, ISC_R_SUCCESS);
@ -75,7 +77,7 @@ mkres(dns_resolver_t **resolverp) {
isc_tlsctx_cache_create(mctx, &tlsctx_cache);
result = dns_resolver_create(view, loopmgr, 1, netmgr, 0, tlsctx_cache,
dispatchmgr, dispatch, NULL, resolverp);
dispatch, NULL, resolverp);
assert_int_equal(result, ISC_R_SUCCESS);
}