2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-22 18:19:42 +00:00

refactor dns_xfrin to use dns_dispatch

the dns_xfrin module was still using the network manager directly to
manage TCP connections and send and receive messages.  this commit
changes it to use the dispatch manager instead.
This commit is contained in:
Evan Hunt 2023-02-21 20:14:30 -08:00
parent a4c8decc6a
commit f0c766abec
6 changed files with 150 additions and 148 deletions

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

@ -2328,3 +2328,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

@ -387,4 +387,15 @@ dns_dispatch_getnext(dns_dispentry_t *resp);
* Requires: * Requires:
*\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

@ -55,8 +55,7 @@ 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_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_t object to * from 'primaryaddr', creating a dns_xfrin_t object to

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>
@ -94,15 +94,10 @@ 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 {
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,7 +188,7 @@ struct dns_xfrin {
*/ */
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,
@ -232,14 +226,13 @@ static isc_result_t
xfrin_start(dns_xfrin_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_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_t *xfr); xfrin_destroy(dns_xfrin_t *xfr);
@ -689,8 +682,7 @@ 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_t **xfrp) {
dns_name_t *zonename = dns_zone_getorigin(zone); dns_name_t *zonename = dns_zone_getorigin(zone);
dns_xfrin_t *xfr = NULL; dns_xfrin_t *xfr = NULL;
isc_result_t result; isc_result_t result;
@ -708,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;
@ -721,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;
@ -752,6 +742,9 @@ 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);
} }
#if DNS_XFRIN_TRACE #if DNS_XFRIN_TRACE
@ -762,12 +755,8 @@ ISC_REFCOUNT_IMPL(dns_xfrin, xfrin_destroy);
static void static void
xfrin_cancelio(dns_xfrin_t *xfr) { xfrin_cancelio(dns_xfrin_t *xfr) {
if (xfr->readhandle == NULL) { dns_dispatch_done(&xfr->dispentry);
return; dns_dispatch_detach(&xfr->disp);
}
isc_nm_cancelread(xfr->readhandle);
/* The xfr->readhandle detach will happen in xfrin_recv_done callback */
} }
static void static void
@ -776,9 +765,6 @@ xfrin_reset(dns_xfrin_t *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);
} }
@ -801,6 +787,8 @@ xfrin_reset(dns_xfrin_t *xfr) {
static void static void
xfrin_fail(dns_xfrin_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))
@ -810,12 +798,14 @@ xfrin_fail(dns_xfrin_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.
*/ */
@ -828,10 +818,12 @@ xfrin_fail(dns_xfrin_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,
@ -840,11 +832,9 @@ xfrin_create(isc_mem_t *mctx, dns_zone_t *zone, dns_db_t *db, isc_nm_t *netmgr,
dns_xfrin_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_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,
.id = (dns_messageid_t)isc_random16(),
.maxrecords = dns_zone_getmaxrecords(zone), .maxrecords = dns_zone_getmaxrecords(zone),
.primaryaddr = *primaryaddr, .primaryaddr = *primaryaddr,
.sourceaddr = *sourceaddr, .sourceaddr = *sourceaddr,
@ -852,12 +842,9 @@ xfrin_create(isc_mem_t *mctx, dns_zone_t *zone, dns_db_t *db, isc_nm_t *netmgr,
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) {
@ -902,50 +889,53 @@ 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_t *xfr) { xfrin_start(dns_xfrin_t *xfr) {
isc_result_t result; isc_result_t result = ISC_R_FAILURE;
dns_xfrin_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);
} }
@ -973,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_t *xfr = (dns_xfrin_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) {
@ -1007,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));
@ -1018,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 */
} }
/* /*
@ -1065,6 +1053,20 @@ 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.
*/ */
@ -1078,7 +1080,6 @@ xfrin_send_request(dns_xfrin_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_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);
@ -1099,7 +1100,6 @@ xfrin_send_request(dns_xfrin_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));
@ -1116,7 +1116,6 @@ xfrin_send_request(dns_xfrin_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;
@ -1143,10 +1142,10 @@ xfrin_send_request(dns_xfrin_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);
@ -1161,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_t *xfr = (dns_xfrin_t *)cbarg; dns_xfrin_t *xfr = (dns_xfrin_t *)arg;
dns_xfrin_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;
} }
@ -1176,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_t *xfr = (dns_xfrin_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;
} }
@ -1228,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)
{ {
@ -1270,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;
@ -1279,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;
} }
@ -1359,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));
@ -1468,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;
} }
@ -1484,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_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);
@ -1510,8 +1487,8 @@ xfrin_destroy(dns_xfrin_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,
@ -1531,11 +1508,11 @@ xfrin_destroy(dns_xfrin_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) {
@ -1591,6 +1568,10 @@ xfrin_destroy(dns_xfrin_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);
} }

View File

@ -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) {