From fbfaa3e731ec73b6ae35de36725e0f870759f8a8 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Tue, 30 May 2017 09:47:41 +1000 Subject: [PATCH] 4629. [bug] dns_client_startupdate could not be called with a running client. [RT #45277] (cherry picked from commit e51d62ecaee0b0171ca47cbf63cc082d2ad98ce5) --- CHANGES | 3 +++ bin/tests/system/nsupdate/tests.sh | 3 ++- lib/dns/client.c | 11 +++++++++++ lib/dns/include/dns/events.h | 1 + lib/export/samples/sample-update.c | 28 ++++++++++++++++++++++++---- lib/isc/unix/app.c | 1 + 6 files changed, 42 insertions(+), 5 deletions(-) diff --git a/CHANGES b/CHANGES index d7301ba99a..ac78f31463 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +4629. [bug] dns_client_startupdate could not be called with a + running client. [RT #45277] + 4628. [bug] Fixed a potential reference leak in query_getdb(). [RT #45247] diff --git a/bin/tests/system/nsupdate/tests.sh b/bin/tests/system/nsupdate/tests.sh index ea2aa7e98d..0bb14ad792 100644 --- a/bin/tests/system/nsupdate/tests.sh +++ b/bin/tests/system/nsupdate/tests.sh @@ -642,7 +642,7 @@ then n=`expr $n + 1` echo "I:check that dns_client_update handles prerequisite YXRRSET failure ($n)" - $SAMPLEUPDATE -P 5300 -a 10.53.0.1 -a 10.53.0.2 -p "yxrrset no-txt.sample TXT" \ + $SAMPLEUPDATE -s -P 5300 -a 10.53.0.1 -a 10.53.0.2 -p "yxrrset no-txt.sample TXT" \ add "yxrrset-nxrrset.sample 0 in a 1.2.3.4" > update.out.test$n 2>&1 $SAMPLEUPDATE -P 5300 -a 10.53.0.2 -p "yxrrset no-txt.sample TXT" \ add "check-yxrrset-nxrrset.sample 0 in a 1.2.3.4" > update.out.check$n 2>&1 @@ -654,6 +654,7 @@ then grep "status: NXDOMAIN" dig.out.ns1.test$n > /dev/null || ret=1 grep "status: NXDOMAIN" dig.out.ns2.test$n > /dev/null || ret=1 grep "status: NOERROR" check.out.ns2.test$n > /dev/null || ret=1 + grep "2nd update failed: NXRRSET" update.out.test$n > /dev/null || ret=1 [ $ret = 0 ] || { echo I:failed; status=1; } fi # diff --git a/lib/dns/client.c b/lib/dns/client.c index eefe66c4ec..854d5d901e 100644 --- a/lib/dns/client.c +++ b/lib/dns/client.c @@ -2883,6 +2883,17 @@ dns_client_startupdate(dns_client_t *client, dns_rdataclass_t rdclass, *transp = (dns_clientupdatetrans_t *)uctx; result = isc_app_ctxonrun(client->actx, client->mctx, client->task, startupdate, uctx); + if (result == ISC_R_ALREADYRUNNING) { + isc_event_t *event; + event = isc_event_allocate(client->mctx, dns_client_startupdate, + DNS_EVENT_STARTUPDATE, startupdate, + uctx, sizeof(*event)); + if (event != NULL) { + result = ISC_R_SUCCESS; + isc_task_send(task, &event); + } else + result = ISC_R_NOMEMORY; + } if (result == ISC_R_SUCCESS) return (result); *transp = NULL; diff --git a/lib/dns/include/dns/events.h b/lib/dns/include/dns/events.h index fecf5f5b57..87447dff94 100644 --- a/lib/dns/include/dns/events.h +++ b/lib/dns/include/dns/events.h @@ -80,6 +80,7 @@ #define DNS_EVENT_KEYDONE (ISC_EVENTCLASS_DNS + 50) #define DNS_EVENT_SETNSEC3PARAM (ISC_EVENTCLASS_DNS + 51) #define DNS_EVENT_SETSERIAL (ISC_EVENTCLASS_DNS + 52) +#define DNS_EVENT_STARTUPDATE (ISC_EVENTCLASS_DNS + 58) #define DNS_EVENT_FIRSTEVENT (ISC_EVENTCLASS_DNS + 0) #define DNS_EVENT_LASTEVENT (ISC_EVENTCLASS_DNS + 65535) diff --git a/lib/export/samples/sample-update.c b/lib/export/samples/sample-update.c index c78658e431..08ad33e329 100644 --- a/lib/export/samples/sample-update.c +++ b/lib/export/samples/sample-update.c @@ -77,6 +77,7 @@ usage(void) ISC_PLATFORM_NORETURN_POST; static void usage(void) { fprintf(stderr, "sample-update " + "-s " "[-a auth_server] " "[-k keyfile] " "[-p prerequisite] " @@ -128,7 +129,7 @@ main(int argc, char *argv[]) { isc_sockaddr_t sa_auth[10], sa_recursive[10]; unsigned int nsa_auth = 0, nsa_recursive = 0; isc_sockaddrlist_t rec_servers; - isc_sockaddrlist_t auth_servers; + isc_sockaddrlist_t auth_servers, *auth_serversp = &auth_servers; isc_result_t result; isc_boolean_t isdelete; isc_buffer_t b, *buf; @@ -140,11 +141,12 @@ main(int argc, char *argv[]) { dns_rdata_t *rdata; dns_namelist_t updatelist, prereqlist, *prereqlistp = NULL; isc_mem_t *umctx = NULL; + isc_boolean_t sendtwice; ISC_LIST_INIT(auth_servers); ISC_LIST_INIT(rec_servers); - while ((ch = getopt(argc, argv, "a:k:p:P:r:z:")) != -1) { + while ((ch = getopt(argc, argv, "a:k:p:P:r:sz:")) != -1) { switch (ch) { case 'k': keyfilename = optarg; @@ -168,6 +170,9 @@ main(int argc, char *argv[]) { &sa_recursive[nsa_recursive])) nsa_recursive++; break; + case 's': + sendtwice = ISC_TRUE; + break; case 'z': zonenamestr = optarg; break; @@ -254,18 +259,33 @@ main(int argc, char *argv[]) { if (keyfilename != NULL) setup_tsec(keyfilename, umctx); + if (ISC_LIST_HEAD(auth_servers) == NULL) + auth_serversp = NULL; + /* Perform update */ result = dns_client_update(client, default_rdataclass, /* XXX: fixed */ zname, prereqlistp, &updatelist, - (ISC_LIST_HEAD(auth_servers) == NULL) ? - NULL : &auth_servers, tsec, 0); + auth_serversp, tsec, 0); if (result != ISC_R_SUCCESS) { fprintf(stderr, "update failed: %s\n", dns_result_totext(result)); } else fprintf(stderr, "update succeeded\n"); + if (sendtwice) { + /* Perform 2nd update */ + result = dns_client_update(client, + default_rdataclass, /* XXX: fixed */ + zname, prereqlistp, &updatelist, + auth_serversp, tsec, 0); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "2nd update failed: %s\n", + dns_result_totext(result)); + } else + fprintf(stderr, "2nd update succeeded\n"); + } + /* Cleanup */ while ((pname = ISC_LIST_HEAD(prereqlist)) != NULL) { while ((rdataset = ISC_LIST_HEAD(pname->list)) != NULL) { diff --git a/lib/isc/unix/app.c b/lib/isc/unix/app.c index 141e9c21a9..16fdeedc39 100644 --- a/lib/isc/unix/app.c +++ b/lib/isc/unix/app.c @@ -424,6 +424,7 @@ isc__app_ctxonrun(isc_appctx_t *ctx0, isc_mem_t *mctx, isc_task_t *task, event = isc_event_allocate(mctx, cloned_task, ISC_APPEVENT_SHUTDOWN, action, arg, sizeof(*event)); if (event == NULL) { + isc_task_detach(&cloned_task); result = ISC_R_NOMEMORY; goto unlock; }