From 8781aef52e6d5498d6007df3ca466d7e23641836 Mon Sep 17 00:00:00 2001 From: Diego Fronza Date: Mon, 21 Sep 2020 16:16:15 -0300 Subject: [PATCH] Refactored dns_message_t for using attach/detach semantics This commit will be used as a base for the next code updates in order to have a better control of dns_message_t objects' lifetime. Conflict: NA Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/8781aef52e6d5498d6007df3ca466d7e23641836 --- bin/dig/dighost.c | 28 ++++++++--------- bin/dig/nslookup.c | 2 +- bin/named/client.c | 4 +-- bin/named/update.c | 2 +- bin/named/xfrout.c | 2 +- bin/nsupdate/nsupdate.c | 32 +++++++++---------- bin/tests/optional/gsstest.c | 10 +++--- bin/tests/optional/sig0_test.c | 4 +-- bin/tests/system/pipelined/pipequeries.c | 4 +-- bin/tests/system/tkey/keycreate.c | 4 +-- bin/tests/system/tkey/keydelete.c | 4 +-- bin/tests/wire_test.c | 4 +-- bin/tools/dnstap-read.c | 2 +- bin/tools/mdig.c | 4 +-- lib/dns/client.c | 14 ++++----- lib/dns/dnstap.c | 4 +-- lib/dns/include/dns/message.h | 25 ++++++++++----- lib/dns/message.c | 40 ++++++++++++++++++------ lib/dns/resolver.c | 8 ++--- lib/dns/tests/tsig_test.c | 8 ++--- lib/dns/win32/libdns.def.in | 3 +- lib/dns/xfrin.c | 8 ++--- lib/dns/zone.c | 32 +++++++++---------- lib/samples/nsprobe.c | 4 +-- lib/samples/sample-request.c | 6 ++-- 25 files changed, 144 insertions(+), 114 deletions(-) diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c index 4ec6c13a4e..4043aa3bf1 100644 --- a/bin/dig/dighost.c +++ b/bin/dig/dighost.c @@ -1907,7 +1907,7 @@ destroy_lookup(dig_lookup_t *lookup) { isc_mem_free(mctx, ptr); } if (lookup->sendmsg != NULL) - dns_message_destroy(&lookup->sendmsg); + dns_message_detach(&lookup->sendmsg); if (lookup->querysig != NULL) { debug("freeing buffer %p", lookup->querysig); isc_buffer_free(&lookup->querysig); @@ -4013,7 +4013,7 @@ recv_done(isc_task_t *task, isc_event_t *event) { printf(";; Got bad packet: %s\n", isc_result_totext(result)); hex_dump(b); query->waiting_connect = false; - dns_message_destroy(&msg); + dns_message_detach(&msg); isc_event_free(&event); clear_query(query); cancel_lookup(l); @@ -4036,7 +4036,7 @@ recv_done(isc_task_t *task, isc_event_t *event) { printf(";; Warning: Opcode mismatch: expected %s, got %s", expect, got); - dns_message_destroy(&msg); + dns_message_detach(&msg); if (l->tcp_mode) { isc_event_free(&event); clear_query(query); @@ -4083,7 +4083,7 @@ recv_done(isc_task_t *task, isc_event_t *event) { } } if (!match) { - dns_message_destroy(&msg); + dns_message_detach(&msg); if (l->tcp_mode) { isc_event_free(&event); clear_query(query); @@ -4107,7 +4107,7 @@ recv_done(isc_task_t *task, isc_event_t *event) { n = requeue_lookup(l, true); if (l->trace && l->trace_root) n->rdtype = l->qrdtype; - dns_message_destroy(&msg); + dns_message_detach(&msg); isc_event_free(&event); clear_query(query); cancel_lookup(l); @@ -4125,7 +4125,7 @@ recv_done(isc_task_t *task, isc_event_t *event) { n->tcp_mode = true; if (l->trace && l->trace_root) n->rdtype = l->qrdtype; - dns_message_destroy(&msg); + dns_message_detach(&msg); isc_event_free(&event); clear_query(query); cancel_lookup(l); @@ -4146,7 +4146,7 @@ recv_done(isc_task_t *task, isc_event_t *event) { n->seenbadcookie = true; if (l->trace && l->trace_root) n->rdtype = l->qrdtype; - dns_message_destroy(&msg); + dns_message_detach(&msg); isc_event_free(&event); clear_query(query); cancel_lookup(l); @@ -4185,7 +4185,7 @@ recv_done(isc_task_t *task, isc_event_t *event) { query->servname); clear_query(query); check_next_lookup(l); - dns_message_destroy(&msg); + dns_message_detach(&msg); isc_event_free(&event); UNLOCK_LOOKUP; return; @@ -4360,7 +4360,7 @@ recv_done(isc_task_t *task, isc_event_t *event) { debug("still pending."); if (l->doing_xfr) { if (query != l->xfr_q) { - dns_message_destroy(&msg); + dns_message_detach(&msg); isc_event_free(&event); query->waiting_connect = false; UNLOCK_LOOKUP; @@ -4369,7 +4369,7 @@ recv_done(isc_task_t *task, isc_event_t *event) { if (!docancel) docancel = check_for_more_data(query, msg, sevent); if (docancel) { - dns_message_destroy(&msg); + dns_message_detach(&msg); clear_query(query); cancel_lookup(l); check_next_lookup(l); @@ -4391,7 +4391,7 @@ recv_done(isc_task_t *task, isc_event_t *event) { #ifdef DIG_SIGCHASE if (!do_sigchase) #endif - dns_message_destroy(&msg); + dns_message_detach(&msg); cancel_lookup(l); } @@ -4404,7 +4404,7 @@ recv_done(isc_task_t *task, isc_event_t *event) { msg = NULL; else #endif - dns_message_destroy(&msg); + dns_message_detach(&msg); } isc_event_free(&event); UNLOCK_LOOKUP; @@ -4658,7 +4658,7 @@ destroy_libs(void) { while (chase_msg != NULL) { INSIST(chase_msg->msg != NULL); - dns_message_destroy(&(chase_msg->msg)); + dns_message_detach(&(chase_msg->msg)); ptr = chase_msg; chase_msg = ISC_LIST_NEXT(chase_msg, link); isc_mem_free(mctx, ptr); @@ -4668,7 +4668,7 @@ destroy_libs(void) { while (chase_msg != NULL) { INSIST(chase_msg->msg != NULL); - dns_message_destroy(&(chase_msg->msg)); + dns_message_detach(&(chase_msg->msg)); ptr = chase_msg; chase_msg = ISC_LIST_NEXT(chase_msg, link); isc_mem_free(mctx, ptr); diff --git a/bin/dig/nslookup.c b/bin/dig/nslookup.c index 647ed8ce50..c35283177d 100644 --- a/bin/dig/nslookup.c +++ b/bin/dig/nslookup.c @@ -983,7 +983,7 @@ flush_lookup_list(void) { } if (l->sendmsg != NULL) - dns_message_destroy(&l->sendmsg); + dns_message_detach(&l->sendmsg); lp = l; l = ISC_LIST_NEXT(l, link); ISC_LIST_DEQUEUE(lookup_list, lp, link); diff --git a/bin/named/client.c b/bin/named/client.c index 95dabbf53b..4a50ad9bae 100644 --- a/bin/named/client.c +++ b/bin/named/client.c @@ -758,7 +758,7 @@ exit_check(ns_client_t *client) { client->keytag_len = 0; } - dns_message_destroy(&client->message); + dns_message_detach(&client->message); /* * Detaching the task must be done after unlinking from @@ -3375,7 +3375,7 @@ client_create(ns_clientmgr_t *manager, ns_client_t **clientp) { client->magic = 0; cleanup_message: - dns_message_destroy(&client->message); + dns_message_detach(&client->message); cleanup_timer: isc_timer_detach(&client->timer); diff --git a/bin/named/update.c b/bin/named/update.c index 82f9d4a13d..ffd2caf7e4 100644 --- a/bin/named/update.c +++ b/bin/named/update.c @@ -3440,7 +3440,7 @@ forward_done(isc_task_t *task, isc_event_t *event) { INSIST(client->nupdates > 0); client->nupdates--; ns_client_sendraw(client, uev->answer); - dns_message_destroy(&uev->answer); + dns_message_detach(&uev->answer); isc_event_free(&event); ns_client_detach(&client); } diff --git a/bin/named/xfrout.c b/bin/named/xfrout.c index 1e139f7a34..7149825a3c 100644 --- a/bin/named/xfrout.c +++ b/bin/named/xfrout.c @@ -1580,7 +1580,7 @@ sendstream(xfrout_ctx_t *xfr) { } if (tcpmsg != NULL) - dns_message_destroy(&tcpmsg); + dns_message_detach(&tcpmsg); if (cleanup_cctx) dns_compress_invalidate(&cctx); diff --git a/bin/nsupdate/nsupdate.c b/bin/nsupdate/nsupdate.c index bf5ec8fe6b..4993265f58 100644 --- a/bin/nsupdate/nsupdate.c +++ b/bin/nsupdate/nsupdate.c @@ -807,7 +807,7 @@ doshutdown(void) { } if (updatemsg != NULL) - dns_message_destroy(&updatemsg); + dns_message_detach(&updatemsg); if (is_dst_up) { ddebug("Destroy DST lib"); @@ -2556,7 +2556,7 @@ recvsoa(isc_task_t *task, isc_event_t *event) { if (shuttingdown) { dns_request_destroy(&request); - dns_message_destroy(&soaquery); + dns_message_detach(&soaquery); isc_mem_put(gmctx, reqinfo, sizeof(nsu_requestinfo_t)); isc_event_free(&event); maybeshutdown(); @@ -2587,7 +2587,7 @@ recvsoa(isc_task_t *task, isc_event_t *event) { result = dns_request_getresponse(request, rcvmsg, DNS_MESSAGEPARSE_PRESERVEORDER); if (result == DNS_R_TSIGERRORSET && servers != NULL) { - dns_message_destroy(&rcvmsg); + dns_message_detach(&rcvmsg); ddebug("Destroying request [%p]", request); dns_request_destroy(&request); reqinfo = isc_mem_get(gmctx, sizeof(nsu_requestinfo_t)); @@ -2628,9 +2628,9 @@ recvsoa(isc_task_t *task, isc_event_t *event) { dns_name_format(userzone, namebuf, sizeof(namebuf)); error("specified zone '%s' does not exist (NXDOMAIN)", namebuf); - dns_message_destroy(&rcvmsg); + dns_message_detach(&rcvmsg); dns_request_destroy(&request); - dns_message_destroy(&soaquery); + dns_message_detach(&soaquery); ddebug("Out of recvsoa"); done_update(); seenerror = true; @@ -2760,11 +2760,11 @@ recvsoa(isc_task_t *task, isc_event_t *event) { setzoneclass(dns_rdataclass_none); #endif - dns_message_destroy(&soaquery); + dns_message_detach(&soaquery); dns_request_destroy(&request); out: - dns_message_destroy(&rcvmsg); + dns_message_detach(&rcvmsg); ddebug("Out of recvsoa"); return; @@ -2973,7 +2973,7 @@ start_gssrequest(dns_name_t *master) { failure: if (rmsg != NULL) - dns_message_destroy(&rmsg); + dns_message_detach(&rmsg); if (err_message != NULL) isc_mem_free(gmctx, err_message); failed_gssrequest(); @@ -3047,7 +3047,7 @@ recvgss(isc_task_t *task, isc_event_t *event) { if (shuttingdown) { dns_request_destroy(&request); - dns_message_destroy(&tsigquery); + dns_message_detach(&tsigquery); isc_mem_put(gmctx, reqinfo, sizeof(nsu_gssinfo_t)); isc_event_free(&event); maybeshutdown(); @@ -3058,7 +3058,7 @@ recvgss(isc_task_t *task, isc_event_t *event) { ddebug("Destroying request [%p]", request); dns_request_destroy(&request); if (!next_master("recvgss", addr, eresult)) { - dns_message_destroy(&tsigquery); + dns_message_detach(&tsigquery); failed_gssrequest(); } else { dns_message_renderreset(tsigquery); @@ -3117,7 +3117,7 @@ recvgss(isc_task_t *task, isc_event_t *event) { switch (result) { case DNS_R_CONTINUE: - dns_message_destroy(&rcvmsg); + dns_message_detach(&rcvmsg); dns_request_destroy(&request); send_gssrequest(kserver, tsigquery, &request, context); ddebug("Out of recvgss"); @@ -3165,9 +3165,9 @@ recvgss(isc_task_t *task, isc_event_t *event) { done: dns_request_destroy(&request); - dns_message_destroy(&tsigquery); + dns_message_detach(&tsigquery); - dns_message_destroy(&rcvmsg); + dns_message_detach(&rcvmsg); ddebug("Out of recvgss"); } #endif @@ -3186,7 +3186,7 @@ start_update(void) { LOCK(&answer_lock); if (answer != NULL) { - dns_message_destroy(&answer); + dns_message_detach(&answer); } UNLOCK(&answer_lock); @@ -3231,7 +3231,7 @@ start_update(void) { dns_message_puttempname(soaquery, &name); dns_rdataset_disassociate(rdataset); dns_message_puttemprdataset(soaquery, &rdataset); - dns_message_destroy(&soaquery); + dns_message_detach(&soaquery); done_update(); return; } @@ -3268,7 +3268,7 @@ cleanup(void) { LOCK(&answer_lock); if (answer != NULL) { - dns_message_destroy(&answer); + dns_message_detach(&answer); } UNLOCK(&answer_lock); diff --git a/bin/tests/optional/gsstest.c b/bin/tests/optional/gsstest.c index 9692c6f42e..901c2bbb91 100644 --- a/bin/tests/optional/gsstest.c +++ b/bin/tests/optional/gsstest.c @@ -157,11 +157,11 @@ recvresponse(isc_task_t *task, isc_event_t *event) { CHECK("dns_request_getresponse", result2); if (response != NULL) - dns_message_destroy(&response); + dns_message_detach(&response); end: if (query != NULL) - dns_message_destroy(&query); + dns_message_detach(&query); if (reqev->request != NULL) dns_request_destroy(&reqev->request); @@ -248,7 +248,7 @@ sendquery(isc_task_t *task, isc_event_t *event) if (qrdataset != NULL) dns_message_puttemprdataset(message, &qrdataset); if (message != NULL) - dns_message_destroy(&message); + dns_message_detach(&message); } static void @@ -314,11 +314,11 @@ initctx2(isc_task_t *task, isc_event_t *event) { tsigkey = NULL; } - dns_message_destroy(&response); + dns_message_detach(&response); end: if (query != NULL) - dns_message_destroy(&query); + dns_message_detach(&query); if (reqev->request != NULL) dns_request_destroy(&reqev->request); diff --git a/bin/tests/optional/sig0_test.c b/bin/tests/optional/sig0_test.c index 4084f226e5..a74bea1ba2 100644 --- a/bin/tests/optional/sig0_test.c +++ b/bin/tests/optional/sig0_test.c @@ -114,7 +114,7 @@ recvdone(isc_task_t *task, isc_event_t *event) { printf("%.*s\n", (int)isc_buffer_usedlength(&outbuf), (char *)isc_buffer_base(&outbuf)); - dns_message_destroy(&response); + dns_message_detach(&response); isc_event_free(&event); isc_app_shutdown(); @@ -190,7 +190,7 @@ buildquery(void) { inr.length = sizeof(rdata); result = isc_socket_recv(s, &inr, 1, task1, recvdone, NULL); CHECK("isc_socket_recv", result); - dns_message_destroy(&query); + dns_message_detach(&query); } int diff --git a/bin/tests/system/pipelined/pipequeries.c b/bin/tests/system/pipelined/pipequeries.c index 63ee7e9d2f..e16ec11681 100644 --- a/bin/tests/system/pipelined/pipequeries.c +++ b/bin/tests/system/pipelined/pipequeries.c @@ -117,8 +117,8 @@ recvresponse(isc_task_t *task, isc_event_t *event) { (char *)isc_buffer_base(&outbuf)); fflush(stdout); - dns_message_destroy(&query); - dns_message_destroy(&response); + dns_message_detach(&query); + dns_message_detach(&response); dns_request_destroy(&reqev->request); isc_event_free(&event); diff --git a/bin/tests/system/tkey/keycreate.c b/bin/tests/system/tkey/keycreate.c index 0c0b08a90b..85b497f280 100644 --- a/bin/tests/system/tkey/keycreate.c +++ b/bin/tests/system/tkey/keycreate.c @@ -117,8 +117,8 @@ recvquery(isc_task_t *task, isc_event_t *event) { result = dst_key_tofile(tsigkey->key, type, ""); CHECK("dst_key_tofile", result); - dns_message_destroy(&query); - dns_message_destroy(&response); + dns_message_detach(&query); + dns_message_detach(&response); dns_request_destroy(&reqev->request); isc_event_free(&event); isc_app_shutdown(); diff --git a/bin/tests/system/tkey/keydelete.c b/bin/tests/system/tkey/keydelete.c index ae26675755..ea7a09b014 100644 --- a/bin/tests/system/tkey/keydelete.c +++ b/bin/tests/system/tkey/keydelete.c @@ -96,8 +96,8 @@ recvquery(isc_task_t *task, isc_event_t *event) { result = dns_tkey_processdeleteresponse(query, response, ring); CHECK("dns_tkey_processdhresponse", result); - dns_message_destroy(&query); - dns_message_destroy(&response); + dns_message_detach(&query); + dns_message_detach(&response); dns_request_destroy(&reqev->request); isc_event_free(&event); isc_app_shutdown(); diff --git a/bin/tests/wire_test.c b/bin/tests/wire_test.c index 0d001a2f77..7fb8446375 100644 --- a/bin/tests/wire_test.c +++ b/bin/tests/wire_test.c @@ -328,7 +328,7 @@ process_message(isc_buffer_t *source) { dns_compress_invalidate(&cctx); message->from_to_wire = DNS_MESSAGE_INTENTPARSE; - dns_message_destroy(&message); + dns_message_detach(&message); printf("Message rendered.\n"); if (printmemstats) @@ -344,5 +344,5 @@ process_message(isc_buffer_t *source) { result = printmessage(message); CHECKRESULT(result, "printmessage() failed"); } - dns_message_destroy(&message); + dns_message_detach(&message); } diff --git a/bin/tools/dnstap-read.c b/bin/tools/dnstap-read.c index 97c2f71346..cf0c884c02 100644 --- a/bin/tools/dnstap-read.c +++ b/bin/tools/dnstap-read.c @@ -362,7 +362,7 @@ main(int argc, char *argv[]) { if (handle != NULL) dns_dt_close(&handle); if (message != NULL) - dns_message_destroy(&message); + dns_message_detach(&message); if (b != NULL) isc_buffer_free(&b); isc_mem_destroy(&mctx); diff --git a/bin/tools/mdig.c b/bin/tools/mdig.c index 9a105cbd83..4dd12ee6f4 100644 --- a/bin/tools/mdig.c +++ b/bin/tools/mdig.c @@ -478,9 +478,9 @@ cleanup: if (style != NULL) dns_master_styledestroy(&style, mctx); if (query != NULL) - dns_message_destroy(&query); + dns_message_detach(&query); if (response != NULL) - dns_message_destroy(&response); + dns_message_detach(&response); dns_request_destroy(&reqev->request); isc_event_free(&event); diff --git a/lib/dns/client.c b/lib/dns/client.c index 6e2b1fe348..c2dca94bad 100644 --- a/lib/dns/client.c +++ b/lib/dns/client.c @@ -1961,7 +1961,7 @@ static void update_sendevent(updatectx_t *uctx, isc_result_t result) { isc_task_t *task; - dns_message_destroy(&uctx->updatemsg); + dns_message_detach(&uctx->updatemsg); if (uctx->tsigkey != NULL) dns_tsigkey_detach(&uctx->tsigkey); if (uctx->sig0key != NULL) @@ -2012,7 +2012,7 @@ update_done(isc_task_t *task, isc_event_t *event) { out: if (answer != NULL) - dns_message_destroy(&answer); + dns_message_detach(&answer); isc_event_free(&event); LOCK(&uctx->lock); @@ -2354,7 +2354,7 @@ receive_soa(isc_task_t *task, isc_event_t *event) { dns_request_t *newrequest = NULL; /* Retry SOA request without TSIG */ - dns_message_destroy(&rcvmsg); + dns_message_detach(&rcvmsg); dns_message_renderreset(uctx->soaquery); reqoptions = 0; if (uctx->want_tcp) @@ -2477,14 +2477,14 @@ receive_soa(isc_task_t *task, isc_event_t *event) { } if (!droplabel || result != ISC_R_SUCCESS) { - dns_message_destroy(&uctx->soaquery); + dns_message_detach(&uctx->soaquery); LOCK(&uctx->lock); dns_request_destroy(&uctx->soareq); UNLOCK(&uctx->lock); } if (rcvmsg != NULL) - dns_message_destroy(&rcvmsg); + dns_message_detach(&rcvmsg); if (result != ISC_R_SUCCESS) update_sendevent(uctx, result); @@ -2541,7 +2541,7 @@ request_soa(updatectx_t *uctx) { } if (name != NULL) dns_message_puttempname(soaquery, &name); - dns_message_destroy(&soaquery); + dns_message_detach(&soaquery); return (result); } @@ -3040,7 +3040,7 @@ dns_client_startupdate(dns_client_t *client, dns_rdataclass_t rdclass, UNLOCK(&client->lock); } if (uctx->updatemsg != NULL) - dns_message_destroy(&uctx->updatemsg); + dns_message_detach(&uctx->updatemsg); while ((sa = ISC_LIST_HEAD(uctx->servers)) != NULL) { ISC_LIST_UNLINK(uctx->servers, sa, link); isc_mem_put(client->mctx, sa, sizeof(*sa)); diff --git a/lib/dns/dnstap.c b/lib/dns/dnstap.c index 4b289a9ea7..fad1e3b040 100644 --- a/lib/dns/dnstap.c +++ b/lib/dns/dnstap.c @@ -1041,7 +1041,7 @@ dns_dt_parse(isc_mem_t *mctx, isc_region_t *src, dns_dtdata_t **destp) { result = dns_message_parse(d->msg, &b, 0); if (result != ISC_R_SUCCESS) { if (result != DNS_R_RECOVERABLE) - dns_message_destroy(&d->msg); + dns_message_detach(&d->msg); result = ISC_R_SUCCESS; } @@ -1248,7 +1248,7 @@ dns_dtdata_free(dns_dtdata_t **dp) { d = *dp; if (d->msg != NULL) - dns_message_destroy(&d->msg); + dns_message_detach(&d->msg); if (d->frame != NULL) dnstap__dnstap__free_unpacked(d->frame, NULL); diff --git a/lib/dns/include/dns/message.h b/lib/dns/include/dns/message.h index 58de67a8af..f64522b43a 100644 --- a/lib/dns/include/dns/message.h +++ b/lib/dns/include/dns/message.h @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -194,6 +195,7 @@ typedef struct dns_msgblock dns_msgblock_t; struct dns_message { /* public from here down */ unsigned int magic; + isc_refcount_t refcount; dns_messageid_t id; unsigned int flags; @@ -310,8 +312,8 @@ dns_message_reset(dns_message_t *msg, unsigned int intent); /*%< * Reset a message structure to default state. All internal lists are freed * or reset to a default state as well. This is simply a more efficient - * way to call dns_message_destroy() followed by dns_message_allocate(), - * since it avoid many memory allocations. + * way to call dns_message_detach() (assuming last reference is hold), + * followed by dns_message_create(), since it avoid many memory allocations. * * If any data loanouts (buffers, names, rdatas, etc) were requested, * the caller must no longer use them after this call. @@ -326,16 +328,23 @@ dns_message_reset(dns_message_t *msg, unsigned int intent); */ void -dns_message_destroy(dns_message_t **msgp); +dns_message_attach(dns_message_t *source, dns_message_t **target); /*%< - * Destroy all state in the message. + * Attach to message 'source'. * * Requires: + *\li 'source' to be a valid message. + *\li 'target' to be non NULL and '*target' to be NULL. + */ + +void +dns_message_detach(dns_message_t **messagep); +/*%< + * Detach *messagep from its message. + * list. * - *\li 'msgp' be valid. - * - * Ensures: - *\li '*msgp' == NULL + * Requires: + *\li '*messagep' to be a valid message. */ isc_result_t diff --git a/lib/dns/message.c b/lib/dns/message.c index 6a6d09e219..2812ab5a37 100644 --- a/lib/dns/message.c +++ b/lib/dns/message.c @@ -23,6 +23,7 @@ #include #include #include +#include #include /* Required for HP/UX (and others?) */ #include #include @@ -554,7 +555,7 @@ msgresetsigs(dns_message_t *msg, bool replying) { /* * Free all but one (or everything) for this message. This is used by - * both dns_message_reset() and dns_message_destroy(). + * both dns_message_reset() and dns__message_destroy(). */ static void msgreset(dns_message_t *msg, bool everything) { @@ -794,6 +795,8 @@ dns_message_create(isc_mem_t *mctx, unsigned int intent, dns_message_t **msgp) m->cctx = NULL; + isc_refcount_init(&m->refcount, 1); + *msgp = m; return (ISC_R_SUCCESS); @@ -826,23 +829,40 @@ dns_message_reset(dns_message_t *msg, unsigned int intent) { msg->from_to_wire = intent; } -void -dns_message_destroy(dns_message_t **msgp) { - dns_message_t *msg; - - REQUIRE(msgp != NULL); - REQUIRE(DNS_MESSAGE_VALID(*msgp)); - - msg = *msgp; - *msgp = NULL; +static void +dns__message_destroy(dns_message_t *msg) { + REQUIRE(msg != NULL); + REQUIRE(DNS_MESSAGE_VALID(msg)); msgreset(msg, true); isc_mempool_destroy(&msg->namepool); isc_mempool_destroy(&msg->rdspool); + isc_refcount_destroy(&msg->refcount); msg->magic = 0; isc_mem_putanddetach(&msg->mctx, msg, sizeof(dns_message_t)); } +void +dns_message_attach(dns_message_t *source, dns_message_t **target) { + REQUIRE(DNS_MESSAGE_VALID(source)); + + isc_refcount_increment(&source->refcount, NULL); + *target = source; +} + +void +dns_message_detach(dns_message_t **messagep) { + REQUIRE(messagep != NULL && DNS_MESSAGE_VALID(*messagep)); + dns_message_t *msg = *messagep; + *messagep = NULL; + int32_t refs; + + isc_refcount_decrement(&msg->refcount, &refs); + if (refs == 0) { + dns__message_destroy(msg); + } +} + static isc_result_t findname(dns_name_t **foundname, dns_name_t *target, dns_namelist_t *section) diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index e67393aba9..daf9a277ec 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -3966,8 +3966,8 @@ fctx_destroy(fetchctx_t *fctx) { isc_counter_detach(&fctx->qc); fcount_decr(fctx); isc_timer_detach(&fctx->timer); - dns_message_destroy(&fctx->rmessage); - dns_message_destroy(&fctx->qmessage); + dns_message_detach(&fctx->rmessage); + dns_message_detach(&fctx->qmessage); if (dns_name_countlabels(&fctx->domain) > 0) dns_name_free(&fctx->domain, fctx->mctx); if (dns_rdataset_isassociated(&fctx->nameservers)) @@ -4578,10 +4578,10 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type, return (ISC_R_SUCCESS); cleanup_rmessage: - dns_message_destroy(&fctx->rmessage); + dns_message_detach(&fctx->rmessage); cleanup_qmessage: - dns_message_destroy(&fctx->qmessage); + dns_message_detach(&fctx->qmessage); cleanup_fcount: fcount_decr(fctx); diff --git a/lib/dns/tests/tsig_test.c b/lib/dns/tests/tsig_test.c index 112a0467f8..ff0c99f7f6 100644 --- a/lib/dns/tests/tsig_test.c +++ b/lib/dns/tests/tsig_test.c @@ -261,7 +261,7 @@ render(isc_buffer_t *buf, unsigned flags, dns_tsigkey_t *key, } dns_compress_invalidate(&cctx); - dns_message_destroy(&msg); + dns_message_detach(&msg); } /* @@ -354,7 +354,7 @@ tsig_tcp_test(void **state) { tsigctx = msg->tsigctx; msg->tsigctx = NULL; isc_buffer_free(&buf); - dns_message_destroy(&msg); + dns_message_detach(&msg); result = dst_context_create3(key->key, mctx, DNS_LOGCATEGORY_DNSSEC, false, &outctx); @@ -412,7 +412,7 @@ tsig_tcp_test(void **state) { tsigctx = msg->tsigctx; msg->tsigctx = NULL; isc_buffer_free(&buf); - dns_message_destroy(&msg); + dns_message_detach(&msg); /* * Create response message 3. @@ -464,7 +464,7 @@ tsig_tcp_test(void **state) { assert_int_equal(result, ISC_R_SUCCESS); isc_buffer_free(&buf); - dns_message_destroy(&msg); + dns_message_detach(&msg); if (outctx != NULL) { dst_context_destroy(&outctx); diff --git a/lib/dns/win32/libdns.def.in b/lib/dns/win32/libdns.def.in index b426f150dd..9c2ef79479 100644 --- a/lib/dns/win32/libdns.def.in +++ b/lib/dns/win32/libdns.def.in @@ -514,11 +514,12 @@ dns_master_stylecreate2 dns_master_styledestroy dns_master_styleflags dns_message_addname +dns_message_attach dns_message_buildopt dns_message_checksig dns_message_create dns_message_currentname -dns_message_destroy +dns_message_detach dns_message_find dns_message_findname dns_message_findtype diff --git a/lib/dns/xfrin.c b/lib/dns/xfrin.c index 1419d523b0..3a3f407289 100644 --- a/lib/dns/xfrin.c +++ b/lib/dns/xfrin.c @@ -1198,7 +1198,7 @@ xfrin_send_request(dns_xfrin_ctx_t *xfr) { if (qrdataset != NULL) dns_message_puttemprdataset(msg, &qrdataset); if (msg != NULL) - dns_message_destroy(&msg); + dns_message_detach(&msg); if (soatuple != NULL) dns_difftuple_free(&soatuple); if (ver != NULL) @@ -1307,7 +1307,7 @@ xfrin_recv_done(isc_task_t *task, isc_event_t *ev) { xfrin_log(xfr, ISC_LOG_DEBUG(3), "got %s, retrying with AXFR", isc_result_totext(result)); try_axfr: - dns_message_destroy(&msg); + dns_message_detach(&msg); xfrin_reset(xfr); xfr->reqtype = dns_rdatatype_soa; xfr->state = XFRST_SOAQUERY; @@ -1419,7 +1419,7 @@ xfrin_recv_done(isc_task_t *task, isc_event_t *ev) { xfr->tsigctx = msg->tsigctx; msg->tsigctx = NULL; - dns_message_destroy(&msg); + dns_message_detach(&msg); switch (xfr->state) { case XFRST_GOTSOA: @@ -1464,7 +1464,7 @@ xfrin_recv_done(isc_task_t *task, isc_event_t *ev) { failure: if (msg != NULL) - dns_message_destroy(&msg); + dns_message_detach(&msg); if (result != ISC_R_SUCCESS) xfrin_fail(xfr, result, "failed while receiving responses"); } diff --git a/lib/dns/zone.c b/lib/dns/zone.c index fd634af65f..6f40ebd636 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -11338,7 +11338,7 @@ notify_send_toaddr(isc_task_t *task, isc_event_t *event) { if (key != NULL) dns_tsigkey_detach(&key); cleanup_message: - dns_message_destroy(&message); + dns_message_detach(&message); cleanup: UNLOCK_ZONE(notify->zone); isc_event_free(&event); @@ -11887,7 +11887,7 @@ stub_callback(isc_task_t *task, isc_event_t *event) { ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write); dns_db_detach(&stub->db); - dns_message_destroy(&msg); + dns_message_detach(&msg); isc_event_free(&event); dns_request_destroy(&zone->request); @@ -11909,7 +11909,7 @@ stub_callback(isc_task_t *task, isc_event_t *event) { if (stub->db != NULL) dns_db_detach(&stub->db); if (msg != NULL) - dns_message_destroy(&msg); + dns_message_detach(&msg); isc_event_free(&event); dns_request_destroy(&zone->request); /* @@ -11956,7 +11956,7 @@ stub_callback(isc_task_t *task, isc_event_t *event) { same_master: if (msg != NULL) - dns_message_destroy(&msg); + dns_message_detach(&msg); isc_event_free(&event); dns_request_destroy(&zone->request); ns_query(zone, NULL, stub); @@ -12352,7 +12352,7 @@ refresh_callback(isc_task_t *task, isc_event_t *event) { ns_query(zone, rdataset, NULL); } if (msg != NULL) - dns_message_destroy(&msg); + dns_message_detach(&msg); } else if (isc_serial_eq(soa.serial, oldserial)) { isc_time_t expiretime; uint32_t expire; @@ -12387,12 +12387,12 @@ refresh_callback(isc_task_t *task, isc_event_t *event) { goto next_master; } if (msg != NULL) - dns_message_destroy(&msg); + dns_message_detach(&msg); goto detach; next_master: if (msg != NULL) - dns_message_destroy(&msg); + dns_message_detach(&msg); isc_event_free(&event); dns_request_destroy(&zone->request); /* @@ -12444,7 +12444,7 @@ refresh_callback(isc_task_t *task, isc_event_t *event) { same_master: if (msg != NULL) - dns_message_destroy(&msg); + dns_message_detach(&msg); isc_event_free(&event); dns_request_destroy(&zone->request); queue_soa_query(zone); @@ -12541,7 +12541,7 @@ create_query(dns_zone_t *zone, dns_rdatatype_t rdtype, if (qrdataset != NULL) dns_message_puttemprdataset(message, &qrdataset); if (message != NULL) - dns_message_destroy(&message); + dns_message_detach(&message); return (result); } @@ -12751,7 +12751,7 @@ soa_query(isc_task_t *task, isc_event_t *event) { if (result != ISC_R_SUCCESS) DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH); if (message != NULL) - dns_message_destroy(&message); + dns_message_detach(&message); if (cancel) cancel_refresh(zone); isc_event_free(&event); @@ -12762,7 +12762,7 @@ soa_query(isc_task_t *task, isc_event_t *event) { skip_master: if (key != NULL) dns_tsigkey_detach(&key); - dns_message_destroy(&message); + dns_message_detach(&message); /* * Skip to next failed / untried master. */ @@ -12983,7 +12983,7 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) { dns_result_totext(result)); goto cleanup; } - dns_message_destroy(&message); + dns_message_detach(&message); goto unlock; cleanup: @@ -13000,7 +13000,7 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) { isc_mem_put(stub->mctx, stub, sizeof(*stub)); } if (message != NULL) - dns_message_destroy(&message); + dns_message_detach(&message); unlock: if (key != NULL) dns_tsigkey_detach(&key); @@ -13436,7 +13436,7 @@ notify_createmessage(dns_zone_t *zone, unsigned int flags, dns_message_puttempname(message, &tempname); if (temprdataset != NULL) dns_message_puttemprdataset(message, &temprdataset); - dns_message_destroy(&message); + dns_message_detach(&message); return (result); } @@ -14251,7 +14251,7 @@ notify_done(isc_task_t *task, isc_event_t *event) { notify_destroy(notify, false); } if (message != NULL) - dns_message_destroy(&message); + dns_message_detach(&message); } struct secure_event { @@ -16247,7 +16247,7 @@ forward_callback(isc_task_t *task, isc_event_t *event) { next_master: if (msg != NULL) - dns_message_destroy(&msg); + dns_message_detach(&msg); isc_event_free(&event); forward->which++; dns_request_destroy(&forward->request); diff --git a/lib/samples/nsprobe.c b/lib/samples/nsprobe.c index f5cc6d6feb..9bf0e65e01 100644 --- a/lib/samples/nsprobe.c +++ b/lib/samples/nsprobe.c @@ -1203,8 +1203,8 @@ main(int argc, char *argv[]) { /* Cleanup */ for (i = 0; i < MAX_PROBES; i++) { - dns_message_destroy(&probes[i].qmessage); - dns_message_destroy(&probes[i].rmessage); + dns_message_detach(&probes[i].qmessage); + dns_message_detach(&probes[i].rmessage); } isc_task_detach(&probe_task); dns_client_destroy(&client); diff --git a/lib/samples/sample-request.c b/lib/samples/sample-request.c index bfd806d28e..3a4123e244 100644 --- a/lib/samples/sample-request.c +++ b/lib/samples/sample-request.c @@ -115,7 +115,7 @@ make_querymessage(dns_message_t *message, const char *namestr, dns_message_puttempname(message, &qname); if (qrdataset != NULL) dns_message_puttemprdataset(message, &qrdataset); - dns_message_destroy(&message); + dns_message_detach(&message); return (result); } @@ -255,8 +255,8 @@ main(int argc, char *argv[]) { isc_buffer_free(&outputbuf); /* Cleanup */ - dns_message_destroy(&qmessage); - dns_message_destroy(&rmessage); + dns_message_detach(&qmessage); + dns_message_detach(&rmessage); isc_mem_destroy(&mctx); dns_client_destroy(&client); dns_lib_shutdown(); -- 2.23.0