2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-29 05:28:00 +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 6109. [func] Infrastructure for QSBR, asynchronous safe memory
reclamation for lock-free data structures. [GL !7471] 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); ndisp = 4 * ISC_MIN(named_g_udpdisp, MAX_UDP_DISPATCH);
CHECK(dns_view_createresolver( CHECK(dns_view_createresolver(
view, named_g_loopmgr, ndisp, named_g_netmgr, resopts, view, named_g_loopmgr, ndisp, named_g_netmgr, resopts,
named_g_server->tlsctx_client_cache, named_g_dispatchmgr, named_g_server->tlsctx_client_cache, dispatch4, dispatch6));
dispatch4, dispatch6));
if (resstats == NULL) { if (resstats == NULL) {
CHECK(isc_stats_create(mctx, &resstats, CHECK(isc_stats_create(mctx, &resstats,
@ -6467,6 +6466,8 @@ create_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist,
return (result); return (result);
} }
dns_view_setdispatchmgr(view, named_g_dispatchmgr);
isc_nonce_buf(view->secret, sizeof(view->secret)); isc_nonce_buf(view->secret, sizeof(view->secret));
ISC_LIST_APPEND(*viewlist, view, link); ISC_LIST_APPEND(*viewlist, view, link);

View File

@ -37,7 +37,6 @@
#include <dns/name.h> #include <dns/name.h>
#include <dns/rdataset.h> #include <dns/rdataset.h>
#include <dns/request.h> #include <dns/request.h>
#include <dns/resolver.h>
#include <dns/result.h> #include <dns/result.h>
#include <dns/types.h> #include <dns/types.h>
#include <dns/view.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 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" echo_i "failed: expected status was not logged"
status=$((status+1)) status=$((status+1))
} }

View File

@ -48,7 +48,6 @@
#include <dns/rdataset.h> #include <dns/rdataset.h>
#include <dns/rdatatype.h> #include <dns/rdatatype.h>
#include <dns/request.h> #include <dns/request.h>
#include <dns/resolver.h>
#include <dns/types.h> #include <dns/types.h>
#include <dns/view.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); return (result);
} }
dns_view_setdispatchmgr(view, dispatchmgr);
/* Initialize view security roots */ /* Initialize view security roots */
result = dns_view_initsecroots(view, mctx); result = dns_view_initsecroots(view, mctx);
if (result != ISC_R_SUCCESS) { 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, result = dns_view_createresolver(view, loopmgr, 1, nm, 0,
tlsctx_client_cache, dispatchmgr, tlsctx_client_cache, dispatchv4,
dispatchv4, dispatchv6); dispatchv6);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
goto cleanup_view; 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 static void
tcp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region, tcp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
void *arg); void *arg);
static void
tcp_recv_done(dns_dispentry_t *resp, isc_result_t eresult,
isc_region_t *region);
static uint32_t static uint32_t
dns_hash(dns_qid_t *, const isc_sockaddr_t *, dns_messageid_t, in_port_t); dns_hash(dns_qid_t *, const isc_sockaddr_t *, dns_messageid_t, in_port_t);
static void static void
@ -210,8 +207,7 @@ qid_destroy(isc_mem_t *mctx, dns_qid_t **qidp);
static void static void
udp_startrecv(isc_nmhandle_t *handle, dns_dispentry_t *resp); udp_startrecv(isc_nmhandle_t *handle, dns_dispentry_t *resp);
static void static void
tcp_startrecv(isc_nmhandle_t *handle, dns_dispatch_t *disp, tcp_startrecv(dns_dispatch_t *disp, dns_dispentry_t *resp);
dns_dispentry_t *resp);
static void static void
tcp_dispatch_getnext(dns_dispatch_t *disp, dns_dispentry_t *resp, tcp_dispatch_getnext(dns_dispatch_t *disp, dns_dispentry_t *resp,
int32_t timeout); 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_sockaddr_t peer;
isc_netaddr_t netaddr; isc_netaddr_t netaddr;
int match, timeout = 0; int match, timeout = 0;
dispatch_cb_t response = NULL; bool respond = true;
REQUIRE(VALID_RESPONSE(resp)); REQUIRE(VALID_RESPONSE(resp));
REQUIRE(VALID_DISPATCH(resp->disp)); 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); INSIST(resp->reading);
resp->reading = false; resp->reading = false;
response = resp->response;
if (resp->state == DNS_DISPATCHSTATE_CANCELED) { if (resp->state == DNS_DISPATCHSTATE_CANCELED) {
/* /*
* Nobody is interested in the callback if the response * Nobody is interested in the callback if the response
* has been canceled already. Detach from the response * has been canceled already. Detach from the response
* and the handle. * and the handle.
*/ */
response = NULL; respond = false;
eresult = ISC_R_CANCELED; eresult = ISC_R_CANCELED;
} }
@ -652,16 +646,16 @@ next:
* Do not invoke the read callback just yet and instead wait for the * Do not invoke the read callback just yet and instead wait for the
* proper response to arrive until the original timeout fires. * proper response to arrive until the original timeout fires.
*/ */
response = NULL; respond = false;
udp_dispatch_getnext(resp, timeout); udp_dispatch_getnext(resp, timeout);
done: done:
UNLOCK(&disp->lock); UNLOCK(&disp->lock);
if (response != NULL) { if (respond) {
dispentry_log(resp, LVL(90), "UDP read callback on %p: %s", dispentry_log(resp, LVL(90), "UDP read callback on %p: %s",
handle, isc_result_totext(eresult)); handle, isc_result_totext(eresult));
response(eresult, region, resp->arg); resp->response(eresult, region, resp->arg);
} }
dns_dispentry_detach(&resp); /* DISPENTRY003 */ 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) { if (resp->reading) {
*respp = resp; *respp = resp;
} else { } 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; result = ISC_R_UNEXPECTED;
} }
} else { } else {
@ -769,16 +766,6 @@ tcp_recv_shutdown(dns_dispatch_t *disp, dns_displist_t *resps,
disp->state = DNS_DISPATCHSTATE_CANCELED; 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 static void
tcp_recv_processall(dns_displist_t *resps, isc_region_t *region) { tcp_recv_processall(dns_displist_t *resps, isc_region_t *region) {
dns_dispentry_t *resp = NULL, *next = NULL; 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) { for (resp = ISC_LIST_HEAD(*resps); resp != NULL; resp = next) {
next = ISC_LIST_NEXT(resp, rlink); next = ISC_LIST_NEXT(resp, rlink);
ISC_LIST_UNLINK(*resps, 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 * 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. * prevented this.
*/ */
dns_dispentry_t *next = NULL; 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 * Phase 5: Resume reading if there are still active responses
*/ */
if (!ISC_LIST_EMPTY(disp->active)) { 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); UNLOCK(&disp->lock);
@ -1586,6 +1577,8 @@ dns_dispatch_getnext(dns_dispentry_t *resp) {
isc_result_t result = ISC_R_SUCCESS; isc_result_t result = ISC_R_SUCCESS;
int32_t timeout = -1; int32_t timeout = -1;
dispentry_log(resp, LVL(90), "getnext for QID %d", resp->id);
LOCK(&disp->lock); LOCK(&disp->lock);
switch (disp->socktype) { switch (disp->socktype) {
case isc_socktype_udp: { 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_dispatch_t *disp = resp->disp;
dns_dispatchmgr_t *mgr = disp->mgr; dns_dispatchmgr_t *mgr = disp->mgr;
dns_qid_t *qid = mgr->qid; dns_qid_t *qid = mgr->qid;
dispatch_cb_t response = NULL; bool respond = false;
LOCK(&disp->lock); LOCK(&disp->lock);
dispentry_log(resp, LVL(90), dispentry_log(resp, LVL(90),
@ -1643,9 +1636,7 @@ udp_dispentry_cancel(dns_dispentry_t *resp, isc_result_t result) {
case DNS_DISPATCHSTATE_CONNECTED: case DNS_DISPATCHSTATE_CONNECTED:
if (resp->reading) { if (resp->reading) {
dns_dispentry_ref(resp); /* DISPENTRY003 */ respond = true;
response = resp->response;
dispentry_log(resp, LVL(90), "canceling read on %p", dispentry_log(resp, LVL(90), "canceling read on %p",
resp->handle); resp->handle);
isc_nm_cancelread(resp->handle); isc_nm_cancelread(resp->handle);
@ -1669,11 +1660,10 @@ udp_dispentry_cancel(dns_dispentry_t *resp, isc_result_t result) {
unlock: unlock:
UNLOCK(&disp->lock); UNLOCK(&disp->lock);
if (response) { if (respond) {
dispentry_log(resp, LVL(90), "read callback: %s", dispentry_log(resp, LVL(90), "read callback: %s",
isc_result_totext(result)); isc_result_totext(result));
response(result, NULL, resp->arg); resp->response(result, NULL, resp->arg);
dns_dispentry_detach(&resp); /* DISPENTRY003 */
} }
} }
@ -1739,7 +1729,7 @@ tcp_dispentry_cancel(dns_dispentry_t *resp, isc_result_t result) {
dispentry_log(resp, LVL(90), dispentry_log(resp, LVL(90),
"final 1 second timeout on %p", "final 1 second timeout on %p",
disp->handle); disp->handle);
tcp_startrecv(NULL, disp, NULL); tcp_startrecv(disp, NULL);
} }
#else #else
if (disp->reading) { if (disp->reading) {
@ -1825,14 +1815,10 @@ udp_startrecv(isc_nmhandle_t *handle, dns_dispentry_t *resp) {
} }
static void static void
tcp_startrecv(isc_nmhandle_t *handle, dns_dispatch_t *disp, tcp_startrecv(dns_dispatch_t *disp, dns_dispentry_t *resp) {
dns_dispentry_t *resp) {
REQUIRE(VALID_DISPATCH(disp)); REQUIRE(VALID_DISPATCH(disp));
REQUIRE(disp->socktype == isc_socktype_tcp); REQUIRE(disp->socktype == isc_socktype_tcp);
if (handle != NULL) {
isc_nmhandle_attach(handle, &disp->handle);
}
dns_dispatch_ref(disp); /* DISPATCH002 */ dns_dispatch_ref(disp); /* DISPATCH002 */
if (resp != NULL) { if (resp != NULL) {
dispentry_log(resp, LVL(90), "reading from %p", disp->handle); 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; disp->state = DNS_DISPATCHSTATE_CANCELED;
} else if (eresult == ISC_R_SUCCESS) { } else if (eresult == ISC_R_SUCCESS) {
disp->state = DNS_DISPATCHSTATE_CONNECTED; disp->state = DNS_DISPATCHSTATE_CONNECTED;
tcp_startrecv(handle, disp, resp); isc_nmhandle_attach(handle, &disp->handle);
tcp_startrecv(disp, resp);
} else { } else {
disp->state = DNS_DISPATCHSTATE_NONE; 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, "connecting from %s to %s, timeout %u", localbuf,
peerbuf, resp->timeout); peerbuf, resp->timeout);
if (transport_type == DNS_TRANSPORT_TLS) { isc_nm_streamdnsconnect(disp->mgr->nm, &disp->local,
isc_nm_streamdnsconnect(disp->mgr->nm, &disp->local, &disp->peer, tcp_connected, disp,
&disp->peer, tcp_connected, resp->timeout, tlsctx, sess_cache);
disp, resp->timeout, tlsctx,
sess_cache);
} else {
isc_nm_streamdnsconnect(
disp->mgr->nm, &disp->local, &disp->peer,
tcp_connected, disp, resp->timeout, NULL, NULL);
}
break; break;
case DNS_DISPATCHSTATE_CONNECTING: case DNS_DISPATCHSTATE_CONNECTING:
@ -2073,7 +2053,7 @@ tcp_dispatch_connect(dns_dispatch_t *disp, dns_dispentry_t *resp) {
if (!disp->reading) { if (!disp->reading) {
/* Restart the reading */ /* Restart the reading */
tcp_startrecv(NULL, disp, resp); tcp_startrecv(disp, resp);
} }
UNLOCK(&disp->lock); UNLOCK(&disp->lock);
@ -2137,6 +2117,13 @@ tcp_dispatch_getnext(dns_dispatch_t *disp, dns_dispentry_t *resp,
int32_t timeout) { int32_t timeout) {
REQUIRE(timeout <= INT16_MAX); 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) { if (disp->reading) {
return; return;
} }
@ -2145,14 +2132,9 @@ tcp_dispatch_getnext(dns_dispatch_t *disp, dns_dispentry_t *resp,
isc_nmhandle_settimeout(disp->handle, timeout); isc_nmhandle_settimeout(disp->handle, timeout);
} }
dispentry_log(resp, LVL(90), "continue reading");
dns_dispatch_ref(disp); /* DISPATCH002 */ dns_dispatch_ref(disp); /* DISPATCH002 */
isc_nm_read(disp->handle, tcp_recv, disp); isc_nm_read(disp->handle, tcp_recv, disp);
disp->reading = true; disp->reading = true;
ISC_LIST_APPEND(disp->active, resp, alink);
resp->reading = true;
} }
static void static void
@ -2181,6 +2163,8 @@ dns_dispatch_resume(dns_dispentry_t *resp, uint16_t timeout) {
dns_dispatch_t *disp = resp->disp; dns_dispatch_t *disp = resp->disp;
dispentry_log(resp, LVL(90), "resume");
LOCK(&disp->lock); LOCK(&disp->lock);
switch (disp->socktype) { switch (disp->socktype) {
case isc_socktype_udp: { case isc_socktype_udp: {
@ -2348,3 +2332,14 @@ dns_dispatchset_destroy(dns_dispatchset_t **dsetp) {
isc_mutex_destroy(&dset->lock); isc_mutex_destroy(&dset->lock);
isc_mem_putanddetach(&dset->mctx, dset, sizeof(dns_dispatchset_t)); 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 *\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 ISC_LANG_ENDDECLS

View File

@ -183,8 +183,8 @@ isc_result_t
dns_resolver_create(dns_view_t *view, isc_loopmgr_t *loopmgr, dns_resolver_create(dns_view_t *view, isc_loopmgr_t *loopmgr,
unsigned int ndisp, isc_nm_t *nm, unsigned int options, unsigned int ndisp, isc_nm_t *nm, unsigned int options,
isc_tlsctx_cache_t *tlsctx_cache, isc_tlsctx_cache_t *tlsctx_cache,
dns_dispatchmgr_t *dispatchmgr, dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6,
dns_dispatch_t *dispatchv6, dns_resolver_t **resp); dns_resolver_t **resp);
/*%< /*%<
* Create a resolver. * Create a resolver.
@ -204,8 +204,6 @@ dns_resolver_create(dns_view_t *view, isc_loopmgr_t *loopmgr,
* *
*\li 'tlsctx_cache' != NULL. *\li 'tlsctx_cache' != NULL.
* *
*\li 'dispatchmgr' != NULL.
*
*\li 'dispatchv4' is a dispatch with an IPv4 UDP socket, or is 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. * 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. *\li 'fetch' is a valid fetch, and has completed.
*/ */
dns_dispatchmgr_t *
dns_resolver_dispatchmgr(dns_resolver_t *resolver);
dns_dispatch_t * dns_dispatch_t *
dns_resolver_dispatchv4(dns_resolver_t *resolver); dns_resolver_dispatchv4(dns_resolver_t *resolver);

View File

@ -82,17 +82,18 @@ ISC_LANG_BEGINDECLS
struct dns_view { struct dns_view {
/* Unlocked. */ /* Unlocked. */
unsigned int magic; unsigned int magic;
isc_mem_t *mctx; isc_mem_t *mctx;
dns_rdataclass_t rdclass; dns_rdataclass_t rdclass;
char *name; char *name;
dns_zt_t *zonetable; dns_zt_t *zonetable;
dns_resolver_t *resolver; dns_resolver_t *resolver;
dns_adb_t *adb; dns_adb_t *adb;
dns_requestmgr_t *requestmgr; dns_requestmgr_t *requestmgr;
dns_cache_t *cache; dns_dispatchmgr_t *dispatchmgr;
dns_db_t *cachedb; dns_cache_t *cache;
dns_db_t *hints; dns_db_t *cachedb;
dns_db_t *hints;
/* /*
* security roots and negative trust anchors. * security roots and negative trust anchors.
@ -389,7 +390,6 @@ isc_result_t
dns_view_createresolver(dns_view_t *view, isc_loopmgr_t *loopmgr, dns_view_createresolver(dns_view_t *view, isc_loopmgr_t *loopmgr,
unsigned int ndisp, isc_nm_t *netmgr, unsigned int ndisp, isc_nm_t *netmgr,
unsigned int options, isc_tlsctx_cache_t *tlsctx_cache, unsigned int options, isc_tlsctx_cache_t *tlsctx_cache,
dns_dispatchmgr_t *dispatchmgr,
dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6); dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6);
/*%< /*%<
* Create a resolver and address database for the view. * 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 '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', *\li The requirements of dns_resolver_create() apply to 'ndisp',
* 'netmgr', 'options', 'tlsctx_cache', 'dispatchv4', and 'dispatchv6'. * '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. * 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 ISC_LANG_ENDDECLS

View File

@ -32,6 +32,9 @@
#include <dns/transport.h> #include <dns/transport.h>
#include <dns/types.h> #include <dns/types.h>
/* Define to 1 for detailed reference tracing */
#undef DNS_XFRIN_TRACE
/*** /***
*** Types *** Types
***/ ***/
@ -39,7 +42,7 @@
/*% /*%
* A transfer in progress. This is an opaque type. * 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 *** 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 *primaryaddr,
const isc_sockaddr_t *sourceaddr, dns_tsigkey_t *tsigkey, const isc_sockaddr_t *sourceaddr, dns_tsigkey_t *tsigkey,
dns_transport_t *transport, isc_tlsctx_cache_t *tlsctx_cache, dns_transport_t *transport, isc_tlsctx_cache_t *tlsctx_cache,
isc_mem_t *mctx, isc_nm_t *netmgr, dns_xfrindone_t done, isc_mem_t *mctx, dns_xfrindone_t done, dns_xfrin_t **xfrp);
dns_xfrin_ctx_t **xfrp);
/*%< /*%<
* Attempt to start an incoming zone transfer of 'zone' * 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. * manage it. Attach '*xfrp' to the newly created object.
* *
* Iff ISC_R_SUCCESS is returned, '*done' is called with * Iff ISC_R_SUCCESS is returned, '*done' is called with
* 'zone' and a result code as arguments when the transfer finishes. * 'zone' and a result code as arguments when the transfer finishes.
* *
* Requires: * 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 *\li 'xfrtype' is dns_rdatatype_axfr, dns_rdatatype_ixfr
* or dns_rdatatype_soa (soa query followed by axfr if * or dns_rdatatype_soa (soa query followed by axfr if
* serial is greater than current serial). * serial is greater than current serial).
@ -72,24 +82,22 @@ dns_xfrin_create(dns_zone_t *zone, dns_rdatatype_t xfrtype,
*/ */
void void
dns_xfrin_shutdown(dns_xfrin_ctx_t *xfr); dns_xfrin_shutdown(dns_xfrin_t *xfr);
/*%< /*%<
* If the zone transfer 'xfr' has already finished, * If the zone transfer 'xfr' has already finished,
* do nothing. Otherwise, abort it and cause it to call * do nothing. Otherwise, abort it and cause it to call
* its done callback with a status of ISC_R_CANCELED. * its done callback with a status of ISC_R_CANCELED.
*/ */
void #if DNS_XFRIN_TRACE
dns_xfrin_detach(dns_xfrin_ctx_t **xfrp); #define dns_xfrin_ref(ptr) dns_xfrin__ref(ptr, __func__, __FILE__, __LINE__)
/*%< #define dns_xfrin_unref(ptr) dns_xfrin__unref(ptr, __func__, __FILE__, __LINE__)
* Detach a reference to a zone transfer object. #define dns_xfrin_attach(ptr, ptrp) \
* Caller to maintain external locking if required. dns_xfrin__attach(ptr, ptrp, __func__, __FILE__, __LINE__)
*/ #define dns_xfrin_detach(ptrp) \
dns_xfrin__detach(ptrp, __func__, __FILE__, __LINE__)
void ISC_REFCOUNT_TRACE_DECL(dns_xfrin);
dns_xfrin_attach(dns_xfrin_ctx_t *source, dns_xfrin_ctx_t **target); #else
/*%< ISC_REFCOUNT_DECL(dns_xfrin);
* Caller to maintain external locking if required. #endif
*/
ISC_LANG_ENDDECLS 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; isc_mem_t *mctx = NULL;
dns_messageid_t id; dns_messageid_t id;
bool tcp = false; bool tcp = false;
bool connected = false;
REQUIRE(VALID_REQUESTMGR(requestmgr)); REQUIRE(VALID_REQUESTMGR(requestmgr));
REQUIRE(message != NULL); REQUIRE(message != NULL);
@ -672,21 +671,14 @@ again:
UNLOCK(&requestmgr->lock); UNLOCK(&requestmgr->lock);
request->destaddr = *destaddr; request->destaddr = *destaddr;
if (tcp && connected) { request->flags |= DNS_REQUEST_F_CONNECTING;
req_send(request); if (tcp) {
request->flags |= DNS_REQUEST_F_TCP;
}
/* no need to call req_connected(), unref here */ result = dns_dispatch_connect(request->dispentry);
dns_request_unref(request); if (result != ISC_R_SUCCESS) {
} else { goto unlink;
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;
}
} }
req_log(ISC_LOG_DEBUG(3), "dns_request_create: request %p", request); req_log(ISC_LOG_DEBUG(3), "dns_request_create: request %p", request);

View File

@ -549,7 +549,6 @@ struct dns_resolver {
bool frozen; bool frozen;
unsigned int options; unsigned int options;
isc_tlsctx_cache_t *tlsctx_cache; isc_tlsctx_cache_t *tlsctx_cache;
dns_dispatchmgr_t *dispatchmgr;
dns_dispatchset_t *dispatches4; dns_dispatchset_t *dispatches4;
dns_dispatchset_t *dispatches6; 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 = isc_mem_get(fctx->mctx, sizeof(*query));
*query = (resquery_t){ .options = options, *query = (resquery_t){ .options = options,
.addrinfo = addrinfo, .addrinfo = addrinfo,
.dispatchmgr = res->dispatchmgr }; .dispatchmgr = res->view->dispatchmgr };
#if DNS_RESOLVER_TRACE #if DNS_RESOLVER_TRACE
fprintf(stderr, "rctx_init:%s:%s:%d:%p->references = 1\n", __func__, 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); isc_sockaddr_setport(&addr, 0);
result = dns_dispatch_createtcp(res->dispatchmgr, &addr, result = dns_dispatch_createtcp(res->view->dispatchmgr, &addr,
&addrinfo->sockaddr, &addrinfo->sockaddr,
&query->dispatch); &query->dispatch);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
@ -2266,7 +2265,8 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
FCTXTRACE("connecting via TCP"); FCTXTRACE("connecting via TCP");
} else { } else {
if (have_addr) { if (have_addr) {
result = dns_dispatch_createudp(res->dispatchmgr, &addr, result = dns_dispatch_createudp(res->view->dispatchmgr,
&addr,
&query->dispatch); &query->dispatch);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
goto cleanup_query; goto cleanup_query;
@ -3914,20 +3914,17 @@ out:
static void static void
possibly_mark(fetchctx_t *fctx, dns_adbaddrinfo_t *addr) { possibly_mark(fetchctx_t *fctx, dns_adbaddrinfo_t *addr) {
isc_netaddr_t na; isc_netaddr_t na;
isc_sockaddr_t *sa; isc_sockaddr_t *sa = &addr->sockaddr;
bool aborted = false; bool aborted = false;
bool bogus; bool bogus;
dns_acl_t *blackhole; dns_acl_t *blackhole;
isc_netaddr_t ipaddr; isc_netaddr_t ipaddr;
dns_peer_t *peer = NULL; dns_peer_t *peer = NULL;
dns_resolver_t *res; dns_resolver_t *res = fctx->res;
const char *msg = NULL; const char *msg = NULL;
sa = &addr->sockaddr;
res = fctx->res;
isc_netaddr_fromsockaddr(&ipaddr, sa); 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); (void)dns_peerlist_peerbyaddr(res->view->peers, &ipaddr, &peer);
if (blackhole != NULL) { if (blackhole != NULL) {
@ -10116,8 +10113,8 @@ isc_result_t
dns_resolver_create(dns_view_t *view, isc_loopmgr_t *loopmgr, dns_resolver_create(dns_view_t *view, isc_loopmgr_t *loopmgr,
unsigned int ndisp, isc_nm_t *nm, unsigned int options, unsigned int ndisp, isc_nm_t *nm, unsigned int options,
isc_tlsctx_cache_t *tlsctx_cache, isc_tlsctx_cache_t *tlsctx_cache,
dns_dispatchmgr_t *dispatchmgr, dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6,
dns_dispatch_t *dispatchv6, dns_resolver_t **resp) { dns_resolver_t **resp) {
isc_result_t result = ISC_R_SUCCESS; isc_result_t result = ISC_R_SUCCESS;
dns_resolver_t *res = NULL; dns_resolver_t *res = NULL;
@ -10129,7 +10126,6 @@ dns_resolver_create(dns_view_t *view, isc_loopmgr_t *loopmgr,
REQUIRE(ndisp > 0); REQUIRE(ndisp > 0);
REQUIRE(resp != NULL && *resp == NULL); REQUIRE(resp != NULL && *resp == NULL);
REQUIRE(tlsctx_cache != NULL); REQUIRE(tlsctx_cache != NULL);
REQUIRE(dispatchmgr != NULL);
REQUIRE(dispatchv4 != NULL || dispatchv6 != NULL); REQUIRE(dispatchv4 != NULL || dispatchv6 != NULL);
RTRACE("create"); RTRACE("create");
@ -10139,7 +10135,6 @@ dns_resolver_create(dns_view_t *view, isc_loopmgr_t *loopmgr,
.loopmgr = loopmgr, .loopmgr = loopmgr,
.rdclass = view->rdclass, .rdclass = view->rdclass,
.nm = nm, .nm = nm,
.dispatchmgr = dispatchmgr,
.options = options, .options = options,
.tlsctx_cache = tlsctx_cache, .tlsctx_cache = tlsctx_cache,
.spillatmin = 10, .spillatmin = 10,
@ -10848,12 +10843,6 @@ dns_resolver_logfetch(dns_fetch_t *fetch, isc_log_t *lctx,
UNLOCK(&fctx->lock); UNLOCK(&fctx->lock);
} }
dns_dispatchmgr_t *
dns_resolver_dispatchmgr(dns_resolver_t *resolver) {
REQUIRE(VALID_RESOLVER(resolver));
return (resolver->dispatchmgr);
}
dns_dispatch_t * dns_dispatch_t *
dns_resolver_dispatchv4(dns_resolver_t *resolver) { dns_resolver_dispatchv4(dns_resolver_t *resolver) {
REQUIRE(VALID_RESOLVER(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, dns_view_createresolver(dns_view_t *view, isc_loopmgr_t *loopmgr,
unsigned int ndisp, isc_nm_t *netmgr, unsigned int ndisp, isc_nm_t *netmgr,
unsigned int options, isc_tlsctx_cache_t *tlsctx_cache, unsigned int options, isc_tlsctx_cache_t *tlsctx_cache,
dns_dispatchmgr_t *dispatchmgr,
dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv4,
dns_dispatch_t *dispatchv6) { dns_dispatch_t *dispatchv6) {
isc_result_t result; 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(DNS_VIEW_VALID(view));
REQUIRE(!view->frozen); REQUIRE(!view->frozen);
REQUIRE(view->resolver == NULL); REQUIRE(view->resolver == NULL);
REQUIRE(view->dispatchmgr != NULL);
view->loop = isc_loop_current(loopmgr); view->loop = isc_loop_current(loopmgr);
result = dns_resolver_create(view, loopmgr, ndisp, netmgr, options, result = dns_resolver_create(view, loopmgr, ndisp, netmgr, options,
tlsctx_cache, dispatchmgr, dispatchv4, tlsctx_cache, dispatchv4, dispatchv6,
dispatchv6, &view->resolver); &view->resolver);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
return (result); return (result);
} }
@ -664,9 +664,9 @@ dns_view_createresolver(dns_view_t *view, isc_loopmgr_t *loopmgr,
goto cleanup_resolver; goto cleanup_resolver;
} }
result = dns_requestmgr_create( result = dns_requestmgr_create(view->mctx, view->dispatchmgr,
view->mctx, dns_resolver_dispatchmgr(view->resolver), dispatchv4, dispatchv6,
dispatchv4, dispatchv6, &view->requestmgr); &view->requestmgr);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
goto cleanup_adb; goto cleanup_adb;
} }
@ -2445,3 +2445,15 @@ dns_view_getudpsize(dns_view_t *view) {
REQUIRE(DNS_VIEW_VALID(view)); REQUIRE(DNS_VIEW_VALID(view));
return (view->udpsize); 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 <stdbool.h>
#include <isc/mem.h> #include <isc/mem.h>
#include <isc/netmgr.h>
#include <isc/random.h> #include <isc/random.h>
#include <isc/result.h> #include <isc/result.h>
#include <isc/string.h> #include <isc/string.h>
@ -27,6 +26,7 @@
#include <dns/catz.h> #include <dns/catz.h>
#include <dns/db.h> #include <dns/db.h>
#include <dns/diff.h> #include <dns/diff.h>
#include <dns/dispatch.h>
#include <dns/journal.h> #include <dns/journal.h>
#include <dns/log.h> #include <dns/log.h>
#include <dns/message.h> #include <dns/message.h>
@ -90,19 +90,14 @@ typedef enum {
* Incoming zone transfer context. * Incoming zone transfer context.
*/ */
struct dns_xfrin_ctx { struct dns_xfrin {
unsigned int magic; unsigned int magic;
isc_mem_t *mctx; isc_mem_t *mctx;
dns_zone_t *zone; dns_zone_t *zone;
dns_view_t *view;
isc_refcount_t references; 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; atomic_bool shuttingdown;
isc_result_t shutdown_result; isc_result_t shutdown_result;
@ -122,9 +117,8 @@ struct dns_xfrin_ctx {
isc_sockaddr_t primaryaddr; isc_sockaddr_t primaryaddr;
isc_sockaddr_t sourceaddr; isc_sockaddr_t sourceaddr;
isc_nmhandle_t *handle; dns_dispatch_t *disp;
isc_nmhandle_t *readhandle; dns_dispentry_t *dispentry;
isc_nmhandle_t *sendhandle;
/*% Buffer for IXFR/AXFR request message */ /*% Buffer for IXFR/AXFR request message */
isc_buffer_t qbuffer; isc_buffer_t qbuffer;
@ -194,72 +188,67 @@ struct dns_xfrin_ctx {
*/ */
static void 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_name_t *zonename, dns_rdataclass_t rdclass,
dns_rdatatype_t reqtype, const isc_sockaddr_t *primaryaddr, dns_rdatatype_t reqtype, const isc_sockaddr_t *primaryaddr,
const isc_sockaddr_t *sourceaddr, dns_tsigkey_t *tsigkey, const isc_sockaddr_t *sourceaddr, dns_tsigkey_t *tsigkey,
dns_transport_t *transport, isc_tlsctx_cache_t *tlsctx_cache, dns_transport_t *transport, isc_tlsctx_cache_t *tlsctx_cache,
dns_xfrin_ctx_t **xfrp); dns_xfrin_t **xfrp);
static isc_result_t static isc_result_t
axfr_init(dns_xfrin_ctx_t *xfr); axfr_init(dns_xfrin_t *xfr);
static isc_result_t 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 static isc_result_t
axfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op, dns_name_t *name, axfr_putdata(dns_xfrin_t *xfr, dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
dns_ttl_t ttl, dns_rdata_t *rdata); dns_rdata_t *rdata);
static isc_result_t static isc_result_t
axfr_apply(dns_xfrin_ctx_t *xfr); axfr_apply(dns_xfrin_t *xfr);
static isc_result_t static isc_result_t
axfr_commit(dns_xfrin_ctx_t *xfr); axfr_commit(dns_xfrin_t *xfr);
static isc_result_t static isc_result_t
axfr_finalize(dns_xfrin_ctx_t *xfr); axfr_finalize(dns_xfrin_t *xfr);
static isc_result_t static isc_result_t
ixfr_init(dns_xfrin_ctx_t *xfr); ixfr_init(dns_xfrin_t *xfr);
static isc_result_t static isc_result_t
ixfr_apply(dns_xfrin_ctx_t *xfr); ixfr_apply(dns_xfrin_t *xfr);
static isc_result_t static isc_result_t
ixfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op, dns_name_t *name, ixfr_putdata(dns_xfrin_t *xfr, dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
dns_ttl_t ttl, dns_rdata_t *rdata); dns_rdata_t *rdata);
static isc_result_t static isc_result_t
ixfr_commit(dns_xfrin_ctx_t *xfr); ixfr_commit(dns_xfrin_t *xfr);
static isc_result_t static isc_result_t
xfr_rr(dns_xfrin_ctx_t *xfr, dns_name_t *name, uint32_t ttl, xfr_rr(dns_xfrin_t *xfr, dns_name_t *name, uint32_t ttl, dns_rdata_t *rdata);
dns_rdata_t *rdata);
static isc_result_t static isc_result_t
xfrin_start(dns_xfrin_ctx_t *xfr); xfrin_start(dns_xfrin_t *xfr);
static void 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 static isc_result_t
xfrin_send_request(dns_xfrin_ctx_t *xfr); xfrin_send_request(dns_xfrin_t *xfr);
static void 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 static void
xfrin_recv_done(isc_nmhandle_t *handle, isc_result_t result, xfrin_recv_done(isc_result_t result, isc_region_t *region, void *arg);
isc_region_t *region, void *cbarg);
static void static void
xfrin_destroy(dns_xfrin_ctx_t *xfr); xfrin_destroy(dns_xfrin_t *xfr);
static void 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 static isc_result_t
render(dns_message_t *msg, isc_mem_t *mctx, isc_buffer_t *buf); render(dns_message_t *msg, isc_mem_t *mctx, isc_buffer_t *buf);
static void static void
xfrin_logv(int level, const char *zonetext, const isc_sockaddr_t *primaryaddr, xfrin_logv(dns_xfrin_t *xff, int level, const char *zonetext,
const char *fmt, va_list ap) ISC_FORMAT_PRINTF(4, 0); const isc_sockaddr_t *primaryaddr, const char *fmt, va_list ap)
ISC_FORMAT_PRINTF(5, 0);
static void static void
xfrin_log1(int level, const char *zonetext, const isc_sockaddr_t *primaryaddr, xfrin_log(dns_xfrin_t *xfr, int level, const char *fmt, ...)
const char *fmt, ...) ISC_FORMAT_PRINTF(4, 5);
static void
xfrin_log(dns_xfrin_ctx_t *xfr, int level, const char *fmt, ...)
ISC_FORMAT_PRINTF(3, 4); 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 static isc_result_t
axfr_init(dns_xfrin_ctx_t *xfr) { axfr_init(dns_xfrin_t *xfr) {
isc_result_t result; isc_result_t result;
xfr->is_ixfr = false; xfr->is_ixfr = false;
@ -286,7 +275,7 @@ failure:
} }
static isc_result_t 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; isc_result_t result;
result = dns_db_create(xfr->mctx, /* XXX */ 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 static isc_result_t
axfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op, dns_name_t *name, axfr_putdata(dns_xfrin_t *xfr, dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
dns_ttl_t ttl, dns_rdata_t *rdata) { dns_rdata_t *rdata) {
isc_result_t result; isc_result_t result;
dns_difftuple_t *tuple = NULL; dns_difftuple_t *tuple = NULL;
@ -328,7 +317,7 @@ failure:
* Store a set of AXFR RRs in the database. * Store a set of AXFR RRs in the database.
*/ */
static isc_result_t static isc_result_t
axfr_apply(dns_xfrin_ctx_t *xfr) { axfr_apply(dns_xfrin_t *xfr) {
isc_result_t result; isc_result_t result;
uint64_t records; uint64_t records;
@ -348,7 +337,7 @@ failure:
} }
static isc_result_t static isc_result_t
axfr_commit(dns_xfrin_ctx_t *xfr) { axfr_commit(dns_xfrin_t *xfr) {
isc_result_t result; isc_result_t result;
CHECK(axfr_apply(xfr)); CHECK(axfr_apply(xfr));
@ -361,7 +350,7 @@ failure:
} }
static isc_result_t static isc_result_t
axfr_finalize(dns_xfrin_ctx_t *xfr) { axfr_finalize(dns_xfrin_t *xfr) {
isc_result_t result; isc_result_t result;
CHECK(dns_zone_replacedb(xfr->zone, xfr->db, true)); CHECK(dns_zone_replacedb(xfr->zone, xfr->db, true));
@ -377,7 +366,7 @@ failure:
*/ */
static isc_result_t static isc_result_t
ixfr_init(dns_xfrin_ctx_t *xfr) { ixfr_init(dns_xfrin_t *xfr) {
isc_result_t result; isc_result_t result;
char *journalfile = NULL; char *journalfile = NULL;
@ -403,8 +392,8 @@ failure:
} }
static isc_result_t static isc_result_t
ixfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op, dns_name_t *name, ixfr_putdata(dns_xfrin_t *xfr, dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
dns_ttl_t ttl, dns_rdata_t *rdata) { dns_rdata_t *rdata) {
isc_result_t result; isc_result_t result;
dns_difftuple_t *tuple = NULL; dns_difftuple_t *tuple = NULL;
@ -430,7 +419,7 @@ failure:
* Apply a set of IXFR changes to the database. * Apply a set of IXFR changes to the database.
*/ */
static isc_result_t static isc_result_t
ixfr_apply(dns_xfrin_ctx_t *xfr) { ixfr_apply(dns_xfrin_t *xfr) {
isc_result_t result; isc_result_t result;
uint64_t records; uint64_t records;
@ -462,7 +451,7 @@ failure:
} }
static isc_result_t static isc_result_t
ixfr_commit(dns_xfrin_ctx_t *xfr) { ixfr_commit(dns_xfrin_t *xfr) {
isc_result_t result; isc_result_t result;
CHECK(ixfr_apply(xfr)); CHECK(ixfr_apply(xfr));
@ -490,8 +479,7 @@ failure:
* state. * state.
*/ */
static isc_result_t static isc_result_t
xfr_rr(dns_xfrin_ctx_t *xfr, dns_name_t *name, uint32_t ttl, xfr_rr(dns_xfrin_t *xfr, dns_name_t *name, uint32_t ttl, dns_rdata_t *rdata) {
dns_rdata_t *rdata) {
isc_result_t result; isc_result_t result;
xfr->nrecs++; 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 *primaryaddr,
const isc_sockaddr_t *sourceaddr, dns_tsigkey_t *tsigkey, const isc_sockaddr_t *sourceaddr, dns_tsigkey_t *tsigkey,
dns_transport_t *transport, isc_tlsctx_cache_t *tlsctx_cache, dns_transport_t *transport, isc_tlsctx_cache_t *tlsctx_cache,
isc_mem_t *mctx, isc_nm_t *netmgr, dns_xfrindone_t done, isc_mem_t *mctx, dns_xfrindone_t done, dns_xfrin_t **xfrp) {
dns_xfrin_ctx_t **xfrp) {
dns_name_t *zonename = dns_zone_getorigin(zone); dns_name_t *zonename = dns_zone_getorigin(zone);
dns_xfrin_ctx_t *xfr = NULL; dns_xfrin_t *xfr = NULL;
isc_result_t result; isc_result_t result;
dns_db_t *db = NULL; dns_db_t *db = NULL;
REQUIRE(xfrp != NULL && *xfrp == NULL); REQUIRE(xfrp != NULL && *xfrp == NULL);
REQUIRE(done != NULL); REQUIRE(done != NULL);
REQUIRE(isc_sockaddr_getport(primaryaddr) != 0); REQUIRE(isc_sockaddr_getport(primaryaddr) != 0);
REQUIRE(zone != NULL);
REQUIRE(dns_zone_getview(zone) != NULL);
(void)dns_zone_getdb(zone, &db); (void)dns_zone_getdb(zone, &db);
@ -711,9 +700,9 @@ dns_xfrin_create(dns_zone_t *zone, dns_rdatatype_t xfrtype,
REQUIRE(db != NULL); REQUIRE(db != NULL);
} }
xfrin_create(mctx, zone, db, netmgr, zonename, dns_zone_getclass(zone), xfrin_create(mctx, zone, db, zonename, dns_zone_getclass(zone), xfrtype,
xfrtype, primaryaddr, sourceaddr, tsigkey, transport, primaryaddr, sourceaddr, tsigkey, transport, tlsctx_cache,
tlsctx_cache, &xfr); &xfr);
if (db != NULL) { if (db != NULL) {
xfr->zone_had_db = true; 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); isc_refcount_init(&xfr->references, 1);
/* /*
* Set *xfrp now, before calling xfrin_start(). Asynchronous * Set *xfrp now, before calling xfrin_start(), otherwise it's
* netmgr processing could cause the 'done' callback to run in * possible the 'done' callback could be run before *xfrp
* another thread before we reached the end of the present * was attached.
* function. In that case, if *xfrp hadn't already been
* attached, the 'done' function would be unable to detach it.
*/ */
*xfrp = xfr; *xfrp = xfr;
@ -744,67 +731,40 @@ dns_xfrin_create(dns_zone_t *zone, dns_rdatatype_t xfrtype,
} }
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
char zonetext[DNS_NAME_MAXTEXT + 32]; xfrin_log(xfr, ISC_LOG_ERROR, "zone transfer setup failed");
dns_zone_name(zone, zonetext, sizeof(zonetext));
xfrin_log1(ISC_LOG_ERROR, zonetext, primaryaddr,
"zone transfer setup failed");
} }
return (result); return (result);
} }
static void
xfrin_cancelio(dns_xfrin_ctx_t *xfr);
void void
dns_xfrin_shutdown(dns_xfrin_ctx_t *xfr) { dns_xfrin_shutdown(dns_xfrin_t *xfr) {
REQUIRE(VALID_XFRIN(xfr)); REQUIRE(VALID_XFRIN(xfr));
xfrin_fail(xfr, ISC_R_CANCELED, "shut down"); xfrin_fail(xfr, ISC_R_CANCELED, "shut down");
/* we won't reach xfrin_recv_done(), so dereference xfr here */
dns_xfrin_unref(xfr);
} }
void #if DNS_XFRIN_TRACE
dns_xfrin_attach(dns_xfrin_ctx_t *source, dns_xfrin_ctx_t **target) { ISC_REFCOUNT_TRACE_IMPL(dns_xfrin, xfrin_destroy);
REQUIRE(VALID_XFRIN(source)); #else
REQUIRE(target != NULL && *target == NULL); ISC_REFCOUNT_IMPL(dns_xfrin, xfrin_destroy);
(void)isc_refcount_increment(&source->references); #endif
*target = source; static void
} xfrin_cancelio(dns_xfrin_t *xfr) {
dns_dispatch_done(&xfr->dispentry);
void dns_dispatch_detach(&xfr->disp);
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 static void
xfrin_cancelio(dns_xfrin_ctx_t *xfr) { xfrin_reset(dns_xfrin_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) {
REQUIRE(VALID_XFRIN(xfr)); REQUIRE(VALID_XFRIN(xfr));
xfrin_log(xfr, ISC_LOG_INFO, "resetting"); xfrin_log(xfr, ISC_LOG_INFO, "resetting");
REQUIRE(xfr->readhandle == NULL);
REQUIRE(xfr->sendhandle == NULL);
if (xfr->lasttsig != NULL) { if (xfr->lasttsig != NULL) {
isc_buffer_free(&xfr->lasttsig); isc_buffer_free(&xfr->lasttsig);
} }
@ -826,7 +786,9 @@ xfrin_reset(dns_xfrin_ctx_t *xfr) {
} }
static void 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 */ /* Make sure only the first xfrin_fail() trumps */
if (atomic_compare_exchange_strong(&xfr->shuttingdown, &(bool){ false }, if (atomic_compare_exchange_strong(&xfr->shuttingdown, &(bool){ false },
true)) 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, xfrin_log(xfr, ISC_LOG_ERROR, "%s: %s", msg,
isc_result_totext(result)); isc_result_totext(result));
if (xfr->is_ixfr) { if (xfr->is_ixfr) {
/* Pass special result code to force AXFR retry /*
* Pass special result code to force AXFR retry
*/ */
result = DNS_R_BADIXFR; result = DNS_R_BADIXFR;
} }
} }
xfrin_cancelio(xfr); xfrin_cancelio(xfr);
/* /*
* Close the journal. * 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; xfr->shutdown_result = result;
} }
dns_xfrin_detach(&xfr);
} }
static void 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_name_t *zonename, dns_rdataclass_t rdclass,
dns_rdatatype_t reqtype, const isc_sockaddr_t *primaryaddr, dns_rdatatype_t reqtype, const isc_sockaddr_t *primaryaddr,
const isc_sockaddr_t *sourceaddr, dns_tsigkey_t *tsigkey, const isc_sockaddr_t *sourceaddr, dns_tsigkey_t *tsigkey,
dns_transport_t *transport, isc_tlsctx_cache_t *tlsctx_cache, dns_transport_t *transport, isc_tlsctx_cache_t *tlsctx_cache,
dns_xfrin_ctx_t **xfrp) { dns_xfrin_t **xfrp) {
dns_xfrin_ctx_t *xfr = NULL; dns_xfrin_t *xfr = NULL;
xfr = isc_mem_get(mctx, sizeof(*xfr)); xfr = isc_mem_get(mctx, sizeof(*xfr));
*xfr = (dns_xfrin_ctx_t){ .netmgr = netmgr, *xfr = (dns_xfrin_t){ .shutdown_result = ISC_R_UNSET,
.shutdown_result = ISC_R_UNSET, .rdclass = rdclass,
.rdclass = rdclass, .reqtype = reqtype,
.reqtype = reqtype, .maxrecords = dns_zone_getmaxrecords(zone),
.id = (dns_messageid_t)isc_random16(), .primaryaddr = *primaryaddr,
.maxrecords = dns_zone_getmaxrecords(zone), .sourceaddr = *sourceaddr,
.primaryaddr = *primaryaddr, .firstsoa = DNS_RDATA_INIT };
.sourceaddr = *sourceaddr,
.firstsoa = DNS_RDATA_INIT };
isc_mem_attach(mctx, &xfr->mctx); isc_mem_attach(mctx, &xfr->mctx);
dns_zone_iattach(zone, &xfr->zone); dns_zone_iattach(zone, &xfr->zone);
dns_view_weakattach(dns_zone_getview(zone), &xfr->view);
dns_name_init(&xfr->name, NULL); 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); atomic_init(&xfr->shuttingdown, false);
if (db != NULL) { 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 static isc_result_t
xfrin_start(dns_xfrin_ctx_t *xfr) { xfrin_start(dns_xfrin_t *xfr) {
isc_result_t result; isc_result_t result = ISC_R_FAILURE;
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;
(void)isc_refcount_increment0(&xfr->connects); dns_xfrin_ref(xfr);
dns_xfrin_attach(xfr, &connect_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 * XXX: timeouts are hard-coded to 30 seconds; this needs to be
* configurable. * configurable.
*/ */
switch (transport_type) { CHECK(dns_dispatch_add(
case DNS_TRANSPORT_TCP: xfr->disp, 0, 30000, &xfr->primaryaddr, xfr->transport,
isc_nm_streamdnsconnect(xfr->netmgr, &xfr->sourceaddr, xfr->tlsctx_cache, xfrin_connect_done, xfrin_send_done,
&xfr->primaryaddr, xfrin_connect_done, xfrin_recv_done, xfr, &xfr->id, &xfr->dispentry));
connect_xfr, 30000, NULL, NULL); CHECK(dns_dispatch_connect(xfr->dispentry));
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();
}
return (ISC_R_SUCCESS); return (ISC_R_SUCCESS);
failure: failure:
isc_refcount_decrement0(&xfr->connects); if (xfr->dispentry != NULL) {
dns_xfrin_detach(&connect_xfr); dns_dispatch_done(&xfr->dispentry);
}
if (xfr->disp != NULL) {
dns_dispatch_detach(&xfr->disp);
}
dns_xfrin_detach(&xfr);
return (result); return (result);
} }
@ -999,26 +963,29 @@ failure:
* A connection has been established. * A connection has been established.
*/ */
static void 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) {
dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *)cbarg; dns_xfrin_t *xfr = (dns_xfrin_t *)arg;
char sourcetext[ISC_SOCKADDR_FORMATSIZE]; char addrtext[ISC_SOCKADDR_FORMATSIZE];
char signerbuf[DNS_NAME_FORMATSIZE]; char signerbuf[DNS_NAME_FORMATSIZE];
const char *signer = "", *sep = ""; const char *signer = "", *sep = "";
isc_sockaddr_t sockaddr;
dns_zonemgr_t *zmgr = NULL; dns_zonemgr_t *zmgr = NULL;
isc_time_t now; isc_time_t now;
REQUIRE(VALID_XFRIN(xfr)); UNUSED(region);
isc_refcount_decrement0(&xfr->connects); REQUIRE(VALID_XFRIN(xfr));
if (atomic_load(&xfr->shuttingdown)) { if (atomic_load(&xfr->shuttingdown)) {
result = ISC_R_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); zmgr = dns_zone_getmgr(xfr->zone);
if (zmgr != NULL) { 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) { if (xfr->tsigkey != NULL && xfr->tsigkey->key != NULL) {
dns_name_format(dst_key_name(xfr->tsigkey->key), signerbuf, dns_name_format(dst_key_name(xfr->tsigkey->key), signerbuf,
sizeof(signerbuf)); sizeof(signerbuf));
@ -1044,17 +1007,16 @@ xfrin_connect_done(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
signer = signerbuf; 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); signer);
CHECK(xfrin_send_request(xfr)); CHECK(xfrin_send_request(xfr));
failure: failure:
if (result != ISC_R_SUCCESS) { 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; *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. * Build an *XFR request and send its length prefix.
*/ */
static isc_result_t static isc_result_t
xfrin_send_request(dns_xfrin_ctx_t *xfr) { xfrin_send_request(dns_xfrin_t *xfr) {
isc_result_t result; isc_result_t result;
isc_region_t region; isc_region_t region;
dns_rdataset_t *qrdataset = NULL; dns_rdataset_t *qrdataset = NULL;
@ -1104,7 +1080,6 @@ xfrin_send_request(dns_xfrin_ctx_t *xfr) {
dns_name_t *qname = NULL; dns_name_t *qname = NULL;
dns_dbversion_t *ver = NULL; dns_dbversion_t *ver = NULL;
dns_name_t *msgsoaname = NULL; dns_name_t *msgsoaname = NULL;
dns_xfrin_ctx_t *send_xfr = NULL;
/* Create the request message */ /* Create the request message */
dns_message_create(xfr->mctx, DNS_MESSAGE_INTENTRENDER, &msg); 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) { if (xfr->reqtype == dns_rdatatype_ixfr) {
/* Get the SOA and add it to the authority section. */ /* 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); dns_db_currentversion(xfr->db, &ver);
CHECK(dns_db_createsoatuple(xfr->db, ver, xfr->mctx, CHECK(dns_db_createsoatuple(xfr->db, ver, xfr->mctx,
DNS_DIFFOP_EXISTS, &soatuple)); DNS_DIFFOP_EXISTS, &soatuple));
@ -1142,7 +1116,6 @@ xfrin_send_request(dns_xfrin_ctx_t *xfr) {
&xfr->ixfr.request_serial)); &xfr->ixfr.request_serial));
} }
xfr->id++;
xfr->nmsg = 0; xfr->nmsg = 0;
xfr->nrecs = 0; xfr->nrecs = 0;
xfr->nbytes = 0; xfr->nbytes = 0;
@ -1169,10 +1142,10 @@ xfrin_send_request(dns_xfrin_ctx_t *xfr) {
isc_buffer_usedregion(&xfr->qbuffer, &region); isc_buffer_usedregion(&xfr->qbuffer, &region);
INSIST(region.length <= 65535); INSIST(region.length <= 65535);
dns_xfrin_attach(xfr, &send_xfr); dns_xfrin_ref(xfr);
isc_nmhandle_attach(send_xfr->handle, &xfr->sendhandle); dns_dispatch_send(xfr->dispentry, &region);
isc_refcount_increment0(&send_xfr->sends); xfrin_log(xfr, ISC_LOG_DEBUG(3), "sending %s request, QID %d",
isc_nm_send(xfr->handle, &region, xfrin_send_done, send_xfr); request_type(xfr), xfr->id);
failure: failure:
dns_message_detach(&msg); dns_message_detach(&msg);
@ -1187,13 +1160,13 @@ failure:
} }
static void static void
xfrin_send_done(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) { xfrin_send_done(isc_result_t result, isc_region_t *region, void *arg) {
dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *)cbarg; dns_xfrin_t *xfr = (dns_xfrin_t *)arg;
dns_xfrin_ctx_t *recv_xfr = NULL;
UNUSED(region);
REQUIRE(VALID_XFRIN(xfr)); REQUIRE(VALID_XFRIN(xfr));
isc_refcount_decrement0(&xfr->sends);
if (atomic_load(&xfr->shuttingdown)) { if (atomic_load(&xfr->shuttingdown)) {
result = ISC_R_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"); 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: failure:
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
xfrin_fail(xfr, result, "failed sending request data"); xfrin_fail(xfr, result, "failed sending request data");
} }
isc_nmhandle_detach(&xfr->sendhandle); dns_xfrin_detach(&xfr);
dns_xfrin_detach(&xfr); /* send_xfr */
} }
static void static void
xfrin_recv_done(isc_nmhandle_t *handle, isc_result_t result, xfrin_recv_done(isc_result_t result, isc_region_t *region, void *arg) {
isc_region_t *region, void *cbarg) { dns_xfrin_t *xfr = (dns_xfrin_t *)arg;
dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *)cbarg;
dns_message_t *msg = NULL; dns_message_t *msg = NULL;
dns_name_t *name = NULL; dns_name_t *name = NULL;
const dns_name_t *tsigowner = NULL; const dns_name_t *tsigowner = NULL;
isc_buffer_t buffer; isc_buffer_t buffer;
isc_sockaddr_t peer;
REQUIRE(VALID_XFRIN(xfr)); REQUIRE(VALID_XFRIN(xfr));
isc_refcount_decrement0(&xfr->recvs);
if (atomic_load(&xfr->shuttingdown)) { if (atomic_load(&xfr->shuttingdown)) {
result = ISC_R_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_init(&buffer, region->base, region->length);
isc_buffer_add(&buffer, region->length); isc_buffer_add(&buffer, region->length);
peer = isc_nmhandle_peeraddr(handle);
result = dns_message_parse(msg, &buffer, result = dns_message_parse(msg, &buffer,
DNS_MESSAGEPARSE_PRESERVEORDER); DNS_MESSAGEPARSE_PRESERVEORDER);
if (result == ISC_R_SUCCESS) { if (result == ISC_R_SUCCESS) {
dns_message_logpacket(msg, "received message from", &peer, dns_message_logpacket(
DNS_LOGCATEGORY_XFER_IN, msg, "received message from", &xfr->primaryaddr,
DNS_LOGMODULE_XFER_IN, ISC_LOG_DEBUG(10), DNS_LOGCATEGORY_XFER_IN, DNS_LOGMODULE_XFER_IN,
xfr->mctx); ISC_LOG_DEBUG(10), xfr->mctx);
} else { } else {
xfrin_log(xfr, ISC_LOG_DEBUG(10), "dns_message_parse: %s", xfrin_log(xfr, ISC_LOG_DEBUG(10), "dns_message_parse: %s",
isc_result_totext(result)); isc_result_totext(result));
} }
if (result != ISC_R_SUCCESS || msg->rcode != dns_rcode_noerror || if (result != ISC_R_SUCCESS || msg->rcode != dns_rcode_noerror ||
msg->opcode != dns_opcode_query || msg->rdclass != xfr->rdclass || msg->opcode != dns_opcode_query || msg->rdclass != xfr->rdclass)
msg->id != xfr->id)
{ {
if (result == ISC_R_SUCCESS && msg->rcode != dns_rcode_noerror) 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", xfrin_log(xfr, ISC_LOG_DEBUG(3), "got %s, retrying with AXFR",
isc_result_totext(result)); isc_result_totext(result));
try_axfr: try_axfr:
isc_nmhandle_detach(&xfr->readhandle);
dns_message_detach(&msg); dns_message_detach(&msg);
xfrin_reset(xfr); xfrin_reset(xfr);
xfr->reqtype = dns_rdatatype_soa; 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) { if (result != ISC_R_SUCCESS) {
xfrin_fail(xfr, result, "failed setting up socket"); xfrin_fail(xfr, result, "failed setting up socket");
} }
dns_xfrin_detach(&xfr); /* recv_xfr */ dns_xfrin_detach(&xfr);
return; return;
} }
@ -1385,7 +1345,7 @@ xfrin_recv_done(isc_nmhandle_t *handle, isc_result_t result,
FAIL(DNS_R_NOTAUTHORITATIVE); 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) { if (result != ISC_R_SUCCESS) {
xfrin_log(xfr, ISC_LOG_DEBUG(3), "TSIG check failed: %s", xfrin_log(xfr, ISC_LOG_DEBUG(3), "TSIG check failed: %s",
isc_result_totext(result)); isc_result_totext(result));
@ -1494,11 +1454,8 @@ xfrin_recv_done(isc_nmhandle_t *handle, isc_result_t result,
/* /*
* Read the next message. * Read the next message.
*/ */
/* The readhandle is still attached */
/* The recv_xfr is still attached */
dns_message_detach(&msg); dns_message_detach(&msg);
isc_refcount_increment0(&xfr->recvs); dns_dispatch_getnext(xfr->dispentry);
isc_nm_read(xfr->handle, xfrin_recv_done, xfr);
return; return;
} }
@ -1510,24 +1467,18 @@ failure:
if (msg != NULL) { if (msg != NULL) {
dns_message_detach(&msg); dns_message_detach(&msg);
} }
isc_nmhandle_detach(&xfr->readhandle); dns_xfrin_detach(&xfr);
dns_xfrin_detach(&xfr); /* recv_xfr */
} }
static void static void
xfrin_destroy(dns_xfrin_ctx_t *xfr) { xfrin_destroy(dns_xfrin_t *xfr) {
uint64_t msecs; uint64_t msecs, persec;
uint64_t persec;
const char *result_str;
REQUIRE(VALID_XFRIN(xfr)); REQUIRE(VALID_XFRIN(xfr));
/* Safe-guards */ /* Safe-guards */
REQUIRE(atomic_load(&xfr->shuttingdown)); REQUIRE(atomic_load(&xfr->shuttingdown));
isc_refcount_destroy(&xfr->references); 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); 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 * shutting down, we can't know what the transfer status is as
* we are only called when the last reference is lost. * 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",
xfrin_log(xfr, ISC_LOG_INFO, "Transfer status: %s", result_str); isc_result_totext(xfr->shutdown_result));
/* /*
* Calculate the length of time the transfer took, * 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)(msecs / 1000), (unsigned int)(msecs % 1000),
(unsigned int)persec, xfr->end_serial); (unsigned int)persec, xfr->end_serial);
if (xfr->readhandle != NULL) { if (xfr->dispentry != NULL) {
isc_nmhandle_detach(&xfr->readhandle); dns_dispatch_done(&xfr->dispentry);
} }
if (xfr->sendhandle != NULL) { if (xfr->disp != NULL) {
isc_nmhandle_detach(&xfr->sendhandle); dns_dispatch_detach(&xfr->disp);
} }
if (xfr->transport != NULL) { if (xfr->transport != NULL) {
@ -1617,6 +1568,10 @@ xfrin_destroy(dns_xfrin_ctx_t *xfr) {
dns_zone_idetach(&xfr->zone); dns_zone_idetach(&xfr->zone);
} }
if (xfr->view != NULL) {
dns_view_weakdetach(&xfr->view);
}
if (xfr->firstsoa_data != NULL) { if (xfr->firstsoa_data != NULL) {
isc_mem_free(xfr->mctx, xfr->firstsoa_data); 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> * transfer of <zone> from <address>: <message>
*/ */
static void static void
xfrin_logv(int level, const char *zonetext, const isc_sockaddr_t *primaryaddr, xfrin_logv(dns_xfrin_t *xfr, int level, const char *zonetext,
const char *fmt, va_list ap) { const isc_sockaddr_t *primaryaddr, const char *fmt, va_list ap) {
char primarytext[ISC_SOCKADDR_FORMATSIZE]; char primarytext[ISC_SOCKADDR_FORMATSIZE];
char msgtext[2048]; 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); vsnprintf(msgtext, sizeof(msgtext), fmt, ap);
isc_log_write(dns_lctx, DNS_LOGCATEGORY_XFER_IN, DNS_LOGMODULE_XFER_IN, 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); 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. * Logging function for use when there is a xfrin_ctx_t.
*/ */
static void 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; va_list ap;
char zonetext[DNS_NAME_MAXTEXT + 32]; 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)); dns_zone_name(xfr->zone, zonetext, sizeof(zonetext));
va_start(ap, fmt); va_start(ap, fmt);
xfrin_logv(level, zonetext, &xfr->primaryaddr, fmt, ap); xfrin_logv(xfr, level, zonetext, &xfr->primaryaddr, fmt, ap);
va_end(ap); va_end(ap);
} }

View File

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

View File

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