From aceabacdb8de37c84dd18a12f40a09c1daa04b62 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Tue, 27 Dec 2016 07:02:33 +1100 Subject: [PATCH] 4538. [bug] Call dns_client_startresolve from client->task. [RT #43896] --- CHANGES | 3 ++ lib/dns/client.c | 91 +++++++++++++++++++++++++----------- lib/dns/include/dns/events.h | 1 + 3 files changed, 69 insertions(+), 26 deletions(-) diff --git a/CHANGES b/CHANGES index f824b03532..8656e1c55f 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +4538. [bug] Call dns_client_startresolve from client->task. + [RT #43896] + 4537. [bug] Handle timouts better in dig/host/nslookup. [RT #43576] 4536. [bug] ISC_SOCKEVENTATTR_USEMINMTU was not being cleared diff --git a/lib/dns/client.c b/lib/dns/client.c index 0ec1953eb1..d91862c43c 100644 --- a/lib/dns/client.c +++ b/lib/dns/client.c @@ -2772,6 +2772,48 @@ dns_client_update(dns_client_t *client, dns_rdataclass_t rdclass, return (result); } +static void +runintask(isc_task_t *task, isc_event_t *event) { + updatectx_t *uctx; + isc_result_t result; + unsigned int resoptions; + + REQUIRE(event != NULL); + + UNUSED(task); + + uctx = event->ev_arg; + + if (uctx->zonename != NULL && uctx->currentserver != NULL) { + result = send_update(uctx); + if (result != ISC_R_SUCCESS) + goto fail; + } else if (uctx->currentserver != NULL) { + result = request_soa(uctx); + if (result != ISC_R_SUCCESS) + goto fail; + } else { + resoptions = 0; + if (uctx->want_tcp) + resoptions |= DNS_CLIENTRESOPT_TCP; + dns_name_clone(uctx->firstname, &uctx->soaqname); + result = dns_client_startresolve(uctx->client, &uctx->soaqname, + uctx->rdclass, + dns_rdatatype_soa, resoptions, + uctx->client->task, + resolvesoa_done, uctx, + &uctx->restrans); + if (result != ISC_R_SUCCESS) + goto fail; + } + + isc_event_free(&event); + +fail: + if (result != ISC_R_SUCCESS) + update_sendevent(uctx, result); +} + isc_result_t dns_client_startupdate(dns_client_t *client, dns_rdataclass_t rdclass, dns_name_t *zonename, dns_namelist_t *prerequisites, @@ -2789,7 +2831,7 @@ dns_client_startupdate(dns_client_t *client, dns_rdataclass_t rdclass, isc_sockaddr_t *server, *sa = NULL; dns_tsectype_t tsectype = dns_tsectype_none; isc_boolean_t want_tcp; - unsigned int resoptions; + isc_event_t *runinevent; UNUSED(options); @@ -2810,20 +2852,36 @@ dns_client_startupdate(dns_client_t *client, dns_rdataclass_t rdclass, UNLOCK(&client->lock); if (result != ISC_R_SUCCESS) return (result); + want_tcp = ISC_TF((options & DNS_CLIENTUPDOPT_TCP) != 0); - /* Create a context and prepare some resources */ + /* + * Create a context and prepare some resources. + */ + uctx = isc_mem_get(client->mctx, sizeof(*uctx)); if (uctx == NULL) { dns_view_detach(&view); return (ISC_R_NOMEMORY); } - result = isc_mutex_init(&uctx->lock); - if (result != ISC_R_SUCCESS) { + + runinevent = isc_event_allocate(client->mctx, client->task, + DNS_EVENT_RUNIN, runintask, + uctx, sizeof(*runinevent)); + if (runinevent == NULL) { dns_view_detach(&view); isc_mem_put(client->mctx, uctx, sizeof(*uctx)); return (ISC_R_NOMEMORY); } + + result = isc_mutex_init(&uctx->lock); + if (result != ISC_R_SUCCESS) { + dns_view_detach(&view); + isc_event_free(&runinevent); + isc_mem_put(client->mctx, uctx, sizeof(*uctx)); + return (ISC_R_NOMEMORY); + } + tclone = NULL; isc_task_attach(task, &tclone); uctx->client = client; @@ -2925,33 +2983,14 @@ dns_client_startupdate(dns_client_t *client, dns_rdataclass_t rdclass, ISC_LIST_APPEND(client->updatectxs, uctx, link); UNLOCK(&client->lock); - if (uctx->zonename != NULL && uctx->currentserver != NULL) { - result = send_update(uctx); - if (result != ISC_R_SUCCESS) - goto fail; - } else if (uctx->currentserver != NULL) { - result = request_soa(uctx); - if (result != ISC_R_SUCCESS) - goto fail; - } else { - resoptions = 0; - if (want_tcp) - resoptions |= DNS_CLIENTRESOPT_TCP; - dns_name_clone(uctx->firstname, &uctx->soaqname); - result = dns_client_startresolve(uctx->client, &uctx->soaqname, - uctx->rdclass, - dns_rdatatype_soa, resoptions, - client->task, resolvesoa_done, - uctx, &uctx->restrans); - if (result != ISC_R_SUCCESS) - goto fail; - } - *transp = (dns_clientupdatetrans_t *)uctx; + isc_task_send(client->task, &runinevent); return (ISC_R_SUCCESS); fail: + if (runinevent != NULL) + isc_event_free(&runinevent); if (ISC_LINK_LINKED(uctx, link)) { LOCK(&client->lock); ISC_LIST_UNLINK(client->updatectxs, uctx, link); diff --git a/lib/dns/include/dns/events.h b/lib/dns/include/dns/events.h index 2023f01e98..41cee1028f 100644 --- a/lib/dns/include/dns/events.h +++ b/lib/dns/include/dns/events.h @@ -75,6 +75,7 @@ #define DNS_EVENT_CATZADDZONE (ISC_EVENTCLASS_DNS + 54) #define DNS_EVENT_CATZMODZONE (ISC_EVENTCLASS_DNS + 55) #define DNS_EVENT_CATZDELZONE (ISC_EVENTCLASS_DNS + 56) +#define DNS_EVENT_RUNIN (ISC_EVENTCLASS_DNS + 57) #define DNS_EVENT_FIRSTEVENT (ISC_EVENTCLASS_DNS + 0) #define DNS_EVENT_LASTEVENT (ISC_EVENTCLASS_DNS + 65535)