From: Matthijs Mekking Date: Fri, 24 Oct 2025 12:21:25 +0000 (+0200) Subject: Move notify functions to notify source files X-Git-Tag: v9.21.15~14^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=680becfb33ea888d08d1e9fa8c1e42c22ecbe343;p=thirdparty%2Fbind9.git Move notify functions to notify source files Move dns_notify_destroy, dns_notify_log, dns_notify_cancel, dns_notify_queue, dns_notify_isqueued, dns_notify_find_address, and notify related static functions over to the notify source files. --- diff --git a/lib/dns/include/dns/notify.h b/lib/dns/include/dns/notify.h index fd62f527fe3..2db6028fada 100644 --- a/lib/dns/include/dns/notify.h +++ b/lib/dns/include/dns/notify.h @@ -72,3 +72,69 @@ dns_notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp); * 'mctx' is not NULL. * 'notifyp' is not NULL and '*notifyp' is NULL. */ + +void +dns_notify_destroy(dns_notify_t *notify, bool zone_locked); +/*%< + * Destroy a notify structure. If 'zone_locked' is true, the attached + * zone is already locked. + * + * Requires: + * 'notify' is a valid notify. + */ + +bool +dns_notify_isqueued(dns_notifyctx_t *nctx, unsigned int flags, dns_name_t *name, + isc_sockaddr_t *addr, dns_tsigkey_t *key, + dns_transport_t *transport); +/*%< + * Check if we already have a notify queued matching name, destination + * address, TSIG key, and transport. Will requeue on the normal notify + * ratelimiter if the notify was enqueued on the startup ratelimiter and + * this is not a startup notify. + * + * Requires: + * 'nctx' is not NULL + * + * Returns: + * true if the notify matching the parameters is already enqueued + * false otherwise + */ + +isc_result_t +dns_notify_queue(dns_notify_t *notify, bool startup); +/*%< + * Queue notify. + * + * Requires: + * 'notify' is a valid notify. + */ + +isc_result_t +dns_notify_dequeue(dns_notify_t *notify, bool startup); +/*%< + * Dequeue notify. + * + * Requires: + * 'notify' is a valid notify. + */ + +void +dns_notify_find_address(dns_notify_t *notify); +/*%< + * Find corresponding addresses for name server to send notify to. + * Does a lookup into the ADB, then sends a notify to the found + * addresses. + * + * Requires: + * 'notify' is a valid notify. + */ + +void +dns_notify_cancel(dns_notifyctx_t *nctx); +/*%< + * Cancel all notifies. The corresponding zone must be locked. + * + * Requires: + * 'nctx' is not NULL + */ diff --git a/lib/dns/notify.c b/lib/dns/notify.c index 53106a0df80..f4d5cfb6703 100644 --- a/lib/dns/notify.c +++ b/lib/dns/notify.c @@ -13,9 +13,31 @@ /*! \file */ +#include +#include #include +#include #include +#include +#include +#include +#include +#include +#include +#include + +#include "zone_p.h" + +static void +notify_log(dns_notify_t *notify, int level, const char *fmt, ...) { + va_list ap; + + va_start(ap, fmt); + dns_zone_logv(notify->zone, DNS_LOGCATEGORY_NOTIFY, level, NULL, fmt, + ap); + va_end(ap); +} void dns_notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) { @@ -36,3 +58,708 @@ dns_notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) { notify->magic = NOTIFY_MAGIC; *notifyp = notify; } + +void +dns_notify_destroy(dns_notify_t *notify, bool locked) { + REQUIRE(DNS_NOTIFY_VALID(notify)); + + isc_mem_t *mctx; + dns_notifyctx_t *nctx; + + if (notify->zone != NULL) { + if (!locked) { + dns__zone_lock(notify->zone); + } + REQUIRE(dns__zone_locked(notify->zone)); + nctx = dns__zone_getnotifyctx(notify->zone); + if (ISC_LINK_LINKED(notify, link)) { + ISC_LIST_UNLINK(nctx->notifies, notify, link); + } + if (!locked) { + dns__zone_unlock(notify->zone); + } + if (locked) { + dns__zone_idetach_locked(¬ify->zone); + } else { + dns_zone_idetach(¬ify->zone); + } + } + if (notify->find != NULL) { + dns_adb_destroyfind(¬ify->find); + } + if (notify->request != NULL) { + dns_request_destroy(¬ify->request); + } + if (dns_name_dynamic(¬ify->ns)) { + dns_name_free(¬ify->ns, notify->mctx); + } + if (notify->key != NULL) { + dns_tsigkey_detach(¬ify->key); + } + if (notify->transport != NULL) { + dns_transport_detach(¬ify->transport); + } + mctx = notify->mctx; + isc_mem_put(notify->mctx, notify, sizeof(*notify)); + isc_mem_detach(&mctx); +} + +static void +notify_done(void *arg) { + dns_request_t *request = (dns_request_t *)arg; + dns_notify_t *notify = dns_request_getarg(request); + isc_result_t result; + dns_message_t *message = NULL; + isc_buffer_t buf; + char rcode[128]; + char addrbuf[ISC_SOCKADDR_FORMATSIZE]; + + REQUIRE(DNS_NOTIFY_VALID(notify)); + + isc_buffer_init(&buf, rcode, sizeof(rcode)); + isc_sockaddr_format(¬ify->dst, addrbuf, sizeof(addrbuf)); + /* WMM: This is changing the mctx from zone to notify. */ + dns_message_create(notify->mctx, NULL, NULL, DNS_MESSAGE_INTENTPARSE, + &message); + + result = dns_request_getresult(request); + if (result != ISC_R_SUCCESS) { + goto fail; + } + + result = dns_request_getresponse(request, message, + DNS_MESSAGEPARSE_PRESERVEORDER); + if (result != ISC_R_SUCCESS) { + goto fail; + } + + result = dns_rcode_totext(message->rcode, &buf); + if (result == ISC_R_SUCCESS) { + notify_log(notify, ISC_LOG_DEBUG(3), + "notify response from %s: %.*s", addrbuf, + (int)buf.used, rcode); + } +fail: + dns_message_detach(&message); + + if (result == ISC_R_SUCCESS) { + notify_log(notify, ISC_LOG_DEBUG(1), "notify to %s successful", + addrbuf); + } else if (result == ISC_R_SHUTTINGDOWN || result == ISC_R_CANCELED) { + /* just destroy the notify */ + } else if ((notify->flags & DNS_NOTIFY_TCP) == 0) { + notify_log(notify, ISC_LOG_NOTICE, + "notify to %s failed: %s: retrying over TCP", + addrbuf, isc_result_totext(result)); + notify->flags |= DNS_NOTIFY_TCP; + dns_request_destroy(¬ify->request); + dns_notify_queue(notify, notify->flags & DNS_NOTIFY_STARTUP); + return; + } else if (result == ISC_R_TIMEDOUT) { + notify_log(notify, ISC_LOG_WARNING, + "notify to %s failed: %s: retries exceeded", addrbuf, + isc_result_totext(result)); + } else { + notify_log(notify, ISC_LOG_WARNING, "notify to %s failed: %s", + addrbuf, isc_result_totext(result)); + } + dns_notify_destroy(notify, false); +} + +static isc_result_t +notify_createmessage(dns_notify_t *notify, dns_message_t **messagep) { + dns_db_t *zonedb = NULL; + dns_dbnode_t *node = NULL; + dns_dbversion_t *version = NULL; + dns_message_t *message = NULL; + dns_rdataset_t rdataset; + dns_rdata_t rdata = DNS_RDATA_INIT; + + dns_name_t *tempname = NULL; + dns_rdata_t *temprdata = NULL; + dns_rdatalist_t *temprdatalist = NULL; + dns_rdataset_t *temprdataset = NULL; + + isc_result_t result; + isc_region_t r; + isc_buffer_t *b = NULL; + + REQUIRE(DNS_NOTIFY_VALID(notify)); + REQUIRE(messagep != NULL && *messagep == NULL); + + /* WMM: This is changing the mctx from zone to notify. */ + dns_message_create(notify->mctx, NULL, NULL, DNS_MESSAGE_INTENTRENDER, + &message); + + message->opcode = dns_opcode_notify; + message->flags |= DNS_MESSAGEFLAG_AA; + message->rdclass = dns_zone_getrdclass(notify->zone); + + dns_message_gettempname(message, &tempname); + dns_message_gettemprdataset(message, &temprdataset); + + /* + * Make question. + */ + dns_name_clone(dns_zone_getorigin(notify->zone), tempname); + dns_rdataset_makequestion(temprdataset, + dns_zone_getrdclass(notify->zone), + dns_rdatatype_soa); + ISC_LIST_APPEND(tempname->list, temprdataset, link); + dns_message_addname(message, tempname, DNS_SECTION_QUESTION); + tempname = NULL; + temprdataset = NULL; + + if ((notify->flags & DNS_NOTIFY_NOSOA) != 0) { + goto done; + } + + dns_message_gettempname(message, &tempname); + dns_message_gettemprdata(message, &temprdata); + dns_message_gettemprdataset(message, &temprdataset); + dns_message_gettemprdatalist(message, &temprdatalist); + + result = dns_zone_getdb(notify->zone, &zonedb); + INSIST(result == ISC_R_SUCCESS); + INSIST(zonedb != NULL); /* XXXJT: is this assumption correct? */ + + dns_name_clone(dns_zone_getorigin(notify->zone), tempname); + dns_db_currentversion(zonedb, &version); + result = dns_db_findnode(zonedb, tempname, false, &node); + if (result != ISC_R_SUCCESS) { + goto soa_cleanup; + } + + dns_rdataset_init(&rdataset); + result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa, + dns_rdatatype_none, 0, &rdataset, NULL); + if (result != ISC_R_SUCCESS) { + goto soa_cleanup; + } + result = dns_rdataset_first(&rdataset); + if (result != ISC_R_SUCCESS) { + goto soa_cleanup; + } + dns_rdataset_current(&rdataset, &rdata); + dns_rdata_toregion(&rdata, &r); + /* WMM: This is changing the mctx from zone to notify. */ + isc_buffer_allocate(notify->mctx, &b, r.length); + isc_buffer_putmem(b, r.base, r.length); + isc_buffer_usedregion(b, &r); + dns_rdata_fromregion(temprdata, rdata.rdclass, rdata.type, &r); + dns_message_takebuffer(message, &b); + result = dns_rdataset_next(&rdataset); + dns_rdataset_disassociate(&rdataset); + if (result != ISC_R_NOMORE) { + goto soa_cleanup; + } + temprdatalist->rdclass = rdata.rdclass; + temprdatalist->type = rdata.type; + temprdatalist->ttl = rdataset.ttl; + ISC_LIST_APPEND(temprdatalist->rdata, temprdata, link); + + dns_rdatalist_tordataset(temprdatalist, temprdataset); + + ISC_LIST_APPEND(tempname->list, temprdataset, link); + dns_message_addname(message, tempname, DNS_SECTION_ANSWER); + temprdatalist = NULL; + temprdataset = NULL; + temprdata = NULL; + tempname = NULL; + +soa_cleanup: + if (node != NULL) { + dns_db_detachnode(&node); + } + if (version != NULL) { + dns_db_closeversion(zonedb, &version, false); + } + if (zonedb != NULL) { + dns_db_detach(&zonedb); + } + if (tempname != NULL) { + dns_message_puttempname(message, &tempname); + } + if (temprdata != NULL) { + dns_message_puttemprdata(message, &temprdata); + } + if (temprdataset != NULL) { + dns_message_puttemprdataset(message, &temprdataset); + } + if (temprdatalist != NULL) { + dns_message_puttemprdatalist(message, &temprdatalist); + } + +done: + *messagep = message; + return ISC_R_SUCCESS; +} + +static void +notify_send_toaddr(void *arg) { + dns_notify_t *notify = (dns_notify_t *)arg; + dns_notifyctx_t *notifyctx = NULL; + isc_result_t result; + dns_db_t *zonedb = NULL; + dns_view_t *view = NULL; + isc_loop_t *loop = NULL; + dns_zonemgr_t *zmgr = NULL; + dns_message_t *message = NULL; + isc_netaddr_t dstip; + dns_tsigkey_t *key = NULL; + char addrbuf[ISC_SOCKADDR_FORMATSIZE]; + isc_sockaddr_t src; + unsigned int options; + bool have_notifysource = false; + isc_tlsctx_cache_t *zmgr_tlsctx_cache = NULL; + + REQUIRE(DNS_NOTIFY_VALID(notify)); + + dns__zone_lock(notify->zone); + + notifyctx = dns__zone_getnotifyctx(notify->zone); + zmgr = dns_zone_getmgr(notify->zone); + view = dns_zone_getview(notify->zone); + loop = dns_zone_getloop(notify->zone); + result = dns_zone_getdb(notify->zone, &zonedb); + isc_sockaddr_format(¬ify->dst, addrbuf, sizeof(addrbuf)); + + if (!dns__zone_loaded(notify->zone) || notify->rlevent->canceled || + dns__zone_exiting(notify->zone) || zmgr == NULL || view == NULL || + view->requestmgr == NULL || loop == NULL || zonedb == NULL || + result != ISC_R_SUCCESS) + { + result = ISC_R_CANCELED; + goto cleanup; + } + + /* + * The raw IPv4 address should also exist. Don't send to the + * mapped form. + */ + if (isc_sockaddr_pf(¬ify->dst) == PF_INET6 && + IN6_IS_ADDR_V4MAPPED(¬ify->dst.type.sin6.sin6_addr)) + { + notify_log(notify, ISC_LOG_DEBUG(3), + "notify: ignoring IPv6 mapped IPV4 address: %s", + addrbuf); + result = ISC_R_CANCELED; + goto cleanup; + } + + result = notify_createmessage(notify, &message); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + + if (notify->key != NULL) { + /* Transfer ownership of key */ + key = notify->key; + notify->key = NULL; + } else { + isc_netaddr_fromsockaddr(&dstip, ¬ify->dst); + result = dns_view_getpeertsig(view, &dstip, &key); + if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) { + notify_log(notify, ISC_LOG_ERROR, + "NOTIFY to %s not sent. " + "Peer TSIG key lookup failure.", + addrbuf); + goto cleanup_message; + } + } + + if (key != NULL) { + char namebuf[DNS_NAME_FORMATSIZE]; + + dns_name_format(key->name, namebuf, sizeof(namebuf)); + notify_log(notify, ISC_LOG_INFO, + "sending notify to %s : TSIG (%s)", addrbuf, + namebuf); + } else { + notify_log(notify, ISC_LOG_INFO, "sending notify to %s", + addrbuf); + } + options = 0; + if (view->peers != NULL) { + dns_peer_t *peer = NULL; + bool usetcp = false; + result = dns_peerlist_peerbyaddr(view->peers, &dstip, &peer); + if (result == ISC_R_SUCCESS) { + result = dns_peer_getnotifysource(peer, &src); + if (result == ISC_R_SUCCESS) { + have_notifysource = true; + } + result = dns_peer_getforcetcp(peer, &usetcp); + if (result == ISC_R_SUCCESS && usetcp) { + options |= DNS_FETCHOPT_TCP; + } + } + } + switch (isc_sockaddr_pf(¬ify->dst)) { + case PF_INET: + if (!have_notifysource) { + isc_sockaddr_t any; + isc_sockaddr_any(&any); + + src = notify->src; + if (isc_sockaddr_equal(&src, &any)) { + src = notifyctx->notifysrc4; + } + } + break; + case PF_INET6: + if (!have_notifysource) { + isc_sockaddr_t any; + isc_sockaddr_any6(&any); + + src = notify->src; + if (isc_sockaddr_equal(&src, &any)) { + src = notifyctx->notifysrc6; + } + } + break; + default: + result = ISC_R_NOTIMPLEMENTED; + goto cleanup_key; + } + +again: + if ((notify->flags & DNS_NOTIFY_TCP) != 0) { + options |= DNS_REQUESTOPT_TCP; + } + + dns__zonemgr_tlsctx_attach(zmgr, &zmgr_tlsctx_cache); + + const unsigned int connect_timeout = isc_nm_getinitialtimeout() / + MS_PER_SEC; + result = dns_request_create( + view->requestmgr, message, &src, ¬ify->dst, + notify->transport, zmgr_tlsctx_cache, options, key, + connect_timeout, TCP_REQUEST_TIMEOUT, UDP_REQUEST_TIMEOUT, + UDP_REQUEST_RETRIES, loop, notify_done, notify, + ¬ify->request); + + isc_tlsctx_cache_detach(&zmgr_tlsctx_cache); + + if (result == ISC_R_SUCCESS) { + if (isc_sockaddr_pf(¬ify->dst) == AF_INET) { + dns__zone_stats_increment( + notify->zone, dns_zonestatscounter_notifyoutv4); + } else { + dns__zone_stats_increment( + notify->zone, dns_zonestatscounter_notifyoutv6); + } + } else if (result == ISC_R_SHUTTINGDOWN || result == ISC_R_CANCELED) { + goto cleanup_key; + } else if ((notify->flags & DNS_NOTIFY_TCP) == 0) { + notify_log(notify, ISC_LOG_NOTICE, + "notify to %s failed: %s: retrying over TCP", + addrbuf, isc_result_totext(result)); + notify->flags |= DNS_NOTIFY_TCP; + goto again; + } + +cleanup_key: + if (key != NULL) { + dns_tsigkey_detach(&key); + } +cleanup_message: + dns_message_detach(&message); +cleanup: + dns__zone_unlock(notify->zone); + + if (zonedb != NULL) { + dns_db_detach(&zonedb); + } + + if (notify->rlevent != NULL) { + isc_rlevent_free(¬ify->rlevent); + } + + if (result != ISC_R_SUCCESS) { + isc_sockaddr_format(¬ify->dst, addrbuf, sizeof(addrbuf)); + notify_log(notify, ISC_LOG_WARNING, "notify to %s failed: %s", + addrbuf, isc_result_totext(result)); + dns_notify_destroy(notify, false); + } +} + +static isc_result_t +notify_queue(dns_notify_t *notify, bool startup, bool dequeue) { + REQUIRE(DNS_NOTIFY_VALID(notify)); + + isc_loop_t *loop = dns_zone_getloop(notify->zone); + dns_zonemgr_t *zmgr = dns_zone_getmgr(notify->zone); + isc_ratelimiter_t *notifyrl = NULL; + isc_ratelimiter_t *startupnotifyrl = NULL; + + INSIST(loop != NULL); + INSIST(zmgr != NULL); + + dns__zonemgr_getnotifyrl(zmgr, ¬ifyrl); + dns__zonemgr_getstartupnotifyrl(zmgr, &startupnotifyrl); + + if (dequeue) { + return isc_ratelimiter_dequeue( + startup ? startupnotifyrl : notifyrl, ¬ify->rlevent); + } + + return isc_ratelimiter_enqueue(startup ? startupnotifyrl : notifyrl, + loop, notify_send_toaddr, notify, + ¬ify->rlevent); +} + +isc_result_t +dns_notify_dequeue(dns_notify_t *notify, bool startup) { + return notify_queue(notify, startup, true); +} + +isc_result_t +dns_notify_queue(dns_notify_t *notify, bool startup) { + return notify_queue(notify, startup, false); +} + +bool +dns_notify_isqueued(dns_notifyctx_t *nctx, unsigned int flags, dns_name_t *name, + isc_sockaddr_t *addr, dns_tsigkey_t *key, + dns_transport_t *transport) { + dns_notify_t *notify = NULL; + isc_result_t result; + + REQUIRE(nctx != NULL); + + ISC_LIST_FOREACH(nctx->notifies, n, link) { + if (n->request != NULL) { + continue; + } + if ((name != NULL && dns_name_dynamic(&n->ns) && + dns_name_equal(name, &n->ns)) || + (addr != NULL && isc_sockaddr_equal(addr, &n->dst) && + n->key == key && n->transport == transport)) + { + notify = n; + goto requeue; + } + } + return false; +requeue: + /* + * If we are enqueued on the startup ratelimiter and this is + * not a startup notify, re-enqueue on the normal notify + * ratelimiter. + */ + if (notify->rlevent != NULL && (flags & DNS_NOTIFY_STARTUP) == 0 && + (notify->flags & DNS_NOTIFY_STARTUP) != 0) + { + result = notify_queue(notify, true, true); + if (result != ISC_R_SUCCESS) { + return true; + } + + notify->flags &= ~DNS_NOTIFY_STARTUP; + result = notify_queue(notify, false, false); + if (result != ISC_R_SUCCESS) { + return false; + } + } + + return true; +} + +static bool +notify_isself(dns_notify_t *notify, isc_sockaddr_t *dst) { + dns_tsigkey_t *key = NULL; + isc_sockaddr_t src; + isc_sockaddr_t any; + bool isself; + isc_netaddr_t dstaddr; + isc_result_t result; + dns_notifyctx_t *notifyctx = NULL; + dns_view_t *view = NULL; + dns_isselffunc_t isselffunc; + void *isselfarg = NULL; + + notifyctx = dns__zone_getnotifyctx(notify->zone); + view = dns_zone_getview(notify->zone); + dns__zone_getisself(notify->zone, &isselffunc, &isselfarg); + if (view == NULL || isselffunc == NULL) { + return false; + } + + switch (isc_sockaddr_pf(dst)) { + case PF_INET: + src = notifyctx->notifysrc4; + isc_sockaddr_any(&any); + break; + case PF_INET6: + src = notifyctx->notifysrc6; + isc_sockaddr_any6(&any); + break; + default: + return false; + } + + /* + * When sending from any the kernel will assign a source address + * that matches the destination address. + */ + if (isc_sockaddr_eqaddr(&any, &src)) { + src = *dst; + } + + isc_netaddr_fromsockaddr(&dstaddr, dst); + result = dns_view_getpeertsig(view, &dstaddr, &key); + if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) { + return false; + } + isself = (isselffunc)(view, key, &src, dst, + dns_zone_getrdclass(notify->zone), isselfarg); + if (key != NULL) { + dns_tsigkey_detach(&key); + } + return isself; +} + +static void +notify_send(dns_notify_t *notify) { + isc_sockaddr_t dst; + isc_result_t result; + dns_notify_t *newnotify = NULL; + dns_notifyctx_t *notifyctx = NULL; + unsigned int flags; + bool startup; + + /* + * Zone lock held by caller. + */ + REQUIRE(DNS_NOTIFY_VALID(notify)); + REQUIRE(dns__zone_locked(notify->zone)); + if (dns__zone_exiting(notify->zone)) { + return; + } + notifyctx = dns__zone_getnotifyctx(notify->zone); + + ISC_LIST_FOREACH(notify->find->list, ai, publink) { + dst = ai->sockaddr; + if (dns_notify_isqueued(notifyctx, notify->flags, NULL, &dst, + NULL, NULL)) + { + continue; + } + if (notify_isself(notify, &dst)) { + continue; + } + newnotify = NULL; + flags = notify->flags & DNS_NOTIFY_NOSOA; + dns_notify_create(notify->mctx, flags, &newnotify); + dns__zone_iattach_locked(notify->zone, &newnotify->zone); + ISC_LIST_APPEND(notifyctx->notifies, newnotify, link); + newnotify->dst = dst; + if (isc_sockaddr_pf(&dst) == AF_INET6) { + isc_sockaddr_any6(&newnotify->src); + } + startup = ((notify->flags & DNS_NOTIFY_STARTUP) != 0); + result = dns_notify_queue(newnotify, startup); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + newnotify = NULL; + } + +cleanup: + if (newnotify != NULL) { + dns_notify_destroy(newnotify, true); + } +} + +/* + * XXXAG should check for DNS_ZONEFLG_EXITING + */ +static void +process_notify_adb_event(void *arg) { + dns_adbfind_t *find = (dns_adbfind_t *)arg; + dns_notify_t *notify = (dns_notify_t *)find->cbarg; + dns_adbstatus_t astat = find->status; + + REQUIRE(DNS_NOTIFY_VALID(notify)); + REQUIRE(find == notify->find); + + switch (astat) { + case DNS_ADB_MOREADDRESSES: + dns_adb_destroyfind(¬ify->find); + dns_notify_find_address(notify); + return; + + case DNS_ADB_NOMOREADDRESSES: + dns__zone_lock(notify->zone); + notify_send(notify); + dns__zone_unlock(notify->zone); + break; + + default: + break; + } + + dns_notify_destroy(notify, false); +} + +void +dns_notify_find_address(dns_notify_t *notify) { + isc_result_t result; + unsigned int options; + dns_adb_t *adb = NULL; + dns_view_t *view = NULL; + isc_loop_t *loop = NULL; + + REQUIRE(DNS_NOTIFY_VALID(notify)); + + options = DNS_ADBFIND_WANTEVENT; + if (isc_net_probeipv4() != ISC_R_DISABLED) { + options |= DNS_ADBFIND_INET; + } + if (isc_net_probeipv6() != ISC_R_DISABLED) { + options |= DNS_ADBFIND_INET6; + } + + loop = dns_zone_getloop(notify->zone); + view = dns_zone_getview(notify->zone); + dns_view_getadb(view, &adb); + if (loop == NULL || view == NULL || adb == NULL) { + goto destroy; + } + + result = dns_adb_createfind(adb, loop, process_notify_adb_event, notify, + ¬ify->ns, options, 0, view->dstport, 0, + NULL, NULL, ¬ify->find); + dns_adb_detach(&adb); + + /* Something failed? */ + if (result != ISC_R_SUCCESS) { + goto destroy; + } + + /* More addresses pending? */ + if ((notify->find->options & DNS_ADBFIND_WANTEVENT) != 0) { + return; + } + + /* We have as many addresses as we can get. */ + dns__zone_lock(notify->zone); + notify_send(notify); + dns__zone_unlock(notify->zone); +destroy: + dns_notify_destroy(notify, false); +} + +void +dns_notify_cancel(dns_notifyctx_t *nctx) { + ISC_LIST_FOREACH(nctx->notifies, notify, link) { + INSIST(dns__zone_locked(notify->zone)); + if (notify->find != NULL) { + dns_adb_cancelfind(notify->find); + } + if (notify->request != NULL) { + dns_request_cancel(notify->request); + } + } +} diff --git a/lib/dns/zone.c b/lib/dns/zone.c index e7ea558681b..280cf2b79f7 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -833,9 +833,6 @@ static void zone_debuglog(dns_zone_t *zone, const char *, int debuglevel, const char *msg, ...) ISC_FORMAT_PRINTF(4, 5); static void -notify_log(dns_zone_t *zone, int level, const char *fmt, ...) - ISC_FORMAT_PRINTF(3, 4); -static void dnssec_log(dns_zone_t *zone, int level, const char *fmt, ...) ISC_FORMAT_PRINTF(3, 4); static void @@ -917,19 +914,6 @@ static void checkds_send_toaddr(void *arg); static void nsfetch_levelup(dns_nsfetch_t *nsfetch); -static void -notify_cancel(dns_zone_t *zone); -static void -notify_find_address(dns_notify_t *notify); -static void -notify_send(dns_notify_t *notify); -static isc_result_t -notify_createmessage(dns_zone_t *zone, unsigned int flags, - dns_message_t **messagep); -static void -notify_done(void *arg); -static void -notify_send_toaddr(void *arg); static isc_result_t zone_dump(dns_zone_t *, bool); static void @@ -12501,24 +12485,6 @@ dns_zone_unload(dns_zone_t *zone) { UNLOCK_ZONE(zone); } -static void -notify_cancel(dns_zone_t *zone) { - /* - * 'zone' locked by caller. - */ - - REQUIRE(LOCKED_ZONE(zone)); - - ISC_LIST_FOREACH(zone->notifyctx.notifies, notify, link) { - if (notify->find != NULL) { - dns_adb_cancelfind(notify->find); - } - if (notify->request != NULL) { - dns_request_cancel(notify->request); - } - } -} - static void checkds_cancel(dns_zone_t *zone) { /* @@ -12646,458 +12612,6 @@ dns_zone_setmaxtypepername(dns_zone_t *zone, uint32_t val) { } } -static bool -notify_isqueued(dns_zone_t *zone, unsigned int flags, dns_name_t *name, - isc_sockaddr_t *addr, dns_tsigkey_t *key, - dns_transport_t *transport) { - dns_notify_t *notify = NULL; - dns_zonemgr_t *zmgr = NULL; - isc_result_t result; - - ISC_LIST_FOREACH(zone->notifyctx.notifies, n, link) { - if (n->request != NULL) { - continue; - } - if ((name != NULL && dns_name_dynamic(&n->ns) && - dns_name_equal(name, &n->ns)) || - (addr != NULL && isc_sockaddr_equal(addr, &n->dst) && - n->key == key && n->transport == transport)) - { - notify = n; - goto requeue; - } - } - return false; - -requeue: - /* - * If we are enqueued on the startup ratelimiter and this is - * not a startup notify, re-enqueue on the normal notify - * ratelimiter. - */ - if (notify->rlevent != NULL && (flags & DNS_NOTIFY_STARTUP) == 0 && - (notify->flags & DNS_NOTIFY_STARTUP) != 0) - { - zmgr = notify->zone->zmgr; - result = isc_ratelimiter_dequeue(zmgr->startupnotifyrl, - ¬ify->rlevent); - if (result != ISC_R_SUCCESS) { - return true; - } - - notify->flags &= ~DNS_NOTIFY_STARTUP; - result = isc_ratelimiter_enqueue( - notify->zone->zmgr->notifyrl, notify->zone->loop, - notify_send_toaddr, notify, ¬ify->rlevent); - if (result != ISC_R_SUCCESS) { - return false; - } - } - - return true; -} - -static bool -notify_isself(dns_zone_t *zone, isc_sockaddr_t *dst) { - dns_tsigkey_t *key = NULL; - isc_sockaddr_t src; - isc_sockaddr_t any; - bool isself; - isc_netaddr_t dstaddr; - isc_result_t result; - - if (zone->view == NULL || zone->isself == NULL) { - return false; - } - - switch (isc_sockaddr_pf(dst)) { - case PF_INET: - src = zone->notifyctx.notifysrc4; - isc_sockaddr_any(&any); - break; - case PF_INET6: - src = zone->notifyctx.notifysrc6; - isc_sockaddr_any6(&any); - break; - default: - return false; - } - - /* - * When sending from any the kernel will assign a source address - * that matches the destination address. - */ - if (isc_sockaddr_eqaddr(&any, &src)) { - src = *dst; - } - - isc_netaddr_fromsockaddr(&dstaddr, dst); - result = dns_view_getpeertsig(zone->view, &dstaddr, &key); - if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) { - return false; - } - isself = (zone->isself)(zone->view, key, &src, dst, zone->rdclass, - zone->isselfarg); - if (key != NULL) { - dns_tsigkey_detach(&key); - } - return isself; -} - -static void -notify_destroy(dns_notify_t *notify, bool locked) { - isc_mem_t *mctx; - - REQUIRE(DNS_NOTIFY_VALID(notify)); - - if (notify->zone != NULL) { - if (!locked) { - LOCK_ZONE(notify->zone); - } - REQUIRE(LOCKED_ZONE(notify->zone)); - if (ISC_LINK_LINKED(notify, link)) { - ISC_LIST_UNLINK(notify->zone->notifyctx.notifies, - notify, link); - } - if (!locked) { - UNLOCK_ZONE(notify->zone); - } - dns_zone_idetach(¬ify->zone, locked); - } - if (notify->find != NULL) { - dns_adb_destroyfind(¬ify->find); - } - if (notify->request != NULL) { - dns_request_destroy(¬ify->request); - } - if (dns_name_dynamic(¬ify->ns)) { - dns_name_free(¬ify->ns, notify->mctx); - } - if (notify->key != NULL) { - dns_tsigkey_detach(¬ify->key); - } - if (notify->transport != NULL) { - dns_transport_detach(¬ify->transport); - } - mctx = notify->mctx; - isc_mem_put(notify->mctx, notify, sizeof(*notify)); - isc_mem_detach(&mctx); -} - -/* - * XXXAG should check for DNS_ZONEFLG_EXITING - */ -static void -process_notify_adb_event(void *arg) { - dns_adbfind_t *find = (dns_adbfind_t *)arg; - dns_notify_t *notify = (dns_notify_t *)find->cbarg; - dns_adbstatus_t astat = find->status; - - REQUIRE(DNS_NOTIFY_VALID(notify)); - REQUIRE(find == notify->find); - - switch (astat) { - case DNS_ADB_MOREADDRESSES: - dns_adb_destroyfind(¬ify->find); - notify_find_address(notify); - return; - - case DNS_ADB_NOMOREADDRESSES: - LOCK_ZONE(notify->zone); - notify_send(notify); - UNLOCK_ZONE(notify->zone); - break; - - default: - break; - } - - notify_destroy(notify, false); -} - -static void -notify_find_address(dns_notify_t *notify) { - isc_result_t result; - unsigned int options; - dns_adb_t *adb = NULL; - - REQUIRE(DNS_NOTIFY_VALID(notify)); - - options = DNS_ADBFIND_WANTEVENT; - if (isc_net_probeipv4() != ISC_R_DISABLED) { - options |= DNS_ADBFIND_INET; - } - if (isc_net_probeipv6() != ISC_R_DISABLED) { - options |= DNS_ADBFIND_INET6; - } - - dns_view_getadb(notify->zone->view, &adb); - if (adb == NULL) { - goto destroy; - } - - result = dns_adb_createfind( - adb, notify->zone->loop, process_notify_adb_event, notify, - ¬ify->ns, options, 0, notify->zone->view->dstport, 0, NULL, - NULL, ¬ify->find); - dns_adb_detach(&adb); - - /* Something failed? */ - if (result != ISC_R_SUCCESS) { - goto destroy; - } - - /* More addresses pending? */ - if ((notify->find->options & DNS_ADBFIND_WANTEVENT) != 0) { - return; - } - - /* We have as many addresses as we can get. */ - LOCK_ZONE(notify->zone); - notify_send(notify); - UNLOCK_ZONE(notify->zone); - -destroy: - notify_destroy(notify, false); -} - -static isc_result_t -notify_send_queue(dns_notify_t *notify, bool startup) { - return isc_ratelimiter_enqueue( - startup ? notify->zone->zmgr->startupnotifyrl - : notify->zone->zmgr->notifyrl, - notify->zone->loop, notify_send_toaddr, notify, - ¬ify->rlevent); -} - -static void -notify_send_toaddr(void *arg) { - dns_notify_t *notify = (dns_notify_t *)arg; - isc_result_t result; - dns_message_t *message = NULL; - isc_netaddr_t dstip; - dns_tsigkey_t *key = NULL; - char addrbuf[ISC_SOCKADDR_FORMATSIZE]; - isc_sockaddr_t src; - unsigned int options; - bool have_notifysource = false; - isc_tlsctx_cache_t *zmgr_tlsctx_cache = NULL; - - REQUIRE(DNS_NOTIFY_VALID(notify)); - - LOCK_ZONE(notify->zone); - - isc_sockaddr_format(¬ify->dst, addrbuf, sizeof(addrbuf)); - - if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0 || - notify->rlevent->canceled || - DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING) || - notify->zone->view->requestmgr == NULL || notify->zone->db == NULL) - { - result = ISC_R_CANCELED; - goto cleanup; - } - - /* - * The raw IPv4 address should also exist. Don't send to the - * mapped form. - */ - if (isc_sockaddr_pf(¬ify->dst) == PF_INET6 && - IN6_IS_ADDR_V4MAPPED(¬ify->dst.type.sin6.sin6_addr)) - { - notify_log(notify->zone, ISC_LOG_DEBUG(3), - "notify: ignoring IPv6 mapped IPV4 address: %s", - addrbuf); - result = ISC_R_CANCELED; - goto cleanup; - } - - result = notify_createmessage(notify->zone, notify->flags, &message); - if (result != ISC_R_SUCCESS) { - goto cleanup; - } - - if (notify->key != NULL) { - /* Transfer ownership of key */ - key = notify->key; - notify->key = NULL; - } else { - isc_netaddr_fromsockaddr(&dstip, ¬ify->dst); - result = dns_view_getpeertsig(notify->zone->view, &dstip, &key); - if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) { - notify_log(notify->zone, ISC_LOG_ERROR, - "NOTIFY to %s not sent. " - "Peer TSIG key lookup failure.", - addrbuf); - goto cleanup_message; - } - } - - if (key != NULL) { - char namebuf[DNS_NAME_FORMATSIZE]; - - dns_name_format(key->name, namebuf, sizeof(namebuf)); - notify_log(notify->zone, ISC_LOG_INFO, - "sending notify to %s : TSIG (%s)", addrbuf, - namebuf); - } else { - notify_log(notify->zone, ISC_LOG_INFO, "sending notify to %s", - addrbuf); - } - options = 0; - if (notify->zone->view->peers != NULL) { - dns_peer_t *peer = NULL; - bool usetcp = false; - result = dns_peerlist_peerbyaddr(notify->zone->view->peers, - &dstip, &peer); - if (result == ISC_R_SUCCESS) { - result = dns_peer_getnotifysource(peer, &src); - if (result == ISC_R_SUCCESS) { - have_notifysource = true; - } - result = dns_peer_getforcetcp(peer, &usetcp); - if (result == ISC_R_SUCCESS && usetcp) { - options |= DNS_FETCHOPT_TCP; - } - } - } - switch (isc_sockaddr_pf(¬ify->dst)) { - case PF_INET: - if (!have_notifysource) { - isc_sockaddr_t any; - isc_sockaddr_any(&any); - - src = notify->src; - if (isc_sockaddr_equal(&src, &any)) { - src = notify->zone->notifyctx.notifysrc4; - } - } - break; - case PF_INET6: - if (!have_notifysource) { - isc_sockaddr_t any; - isc_sockaddr_any6(&any); - - src = notify->src; - if (isc_sockaddr_equal(&src, &any)) { - src = notify->zone->notifyctx.notifysrc6; - } - } - break; - default: - result = ISC_R_NOTIMPLEMENTED; - goto cleanup_key; - } - -again: - if ((notify->flags & DNS_NOTIFY_TCP) != 0) { - options |= DNS_REQUESTOPT_TCP; - } - - dns_zonemgr_tlsctx_attach(notify->zone->zmgr, &zmgr_tlsctx_cache); - - const unsigned int connect_timeout = isc_nm_getinitialtimeout() / - MS_PER_SEC; - result = dns_request_create( - notify->zone->view->requestmgr, message, &src, ¬ify->dst, - notify->transport, zmgr_tlsctx_cache, options, key, - connect_timeout, TCP_REQUEST_TIMEOUT, UDP_REQUEST_TIMEOUT, - UDP_REQUEST_RETRIES, notify->zone->loop, notify_done, notify, - ¬ify->request); - - isc_tlsctx_cache_detach(&zmgr_tlsctx_cache); - - if (result == ISC_R_SUCCESS) { - if (isc_sockaddr_pf(¬ify->dst) == AF_INET) { - inc_stats(notify->zone, - dns_zonestatscounter_notifyoutv4); - } else { - inc_stats(notify->zone, - dns_zonestatscounter_notifyoutv6); - } - } else if (result == ISC_R_SHUTTINGDOWN || result == ISC_R_CANCELED) { - goto cleanup_key; - } else if ((notify->flags & DNS_NOTIFY_TCP) == 0) { - notify_log(notify->zone, ISC_LOG_NOTICE, - "notify to %s failed: %s: retrying over TCP", - addrbuf, isc_result_totext(result)); - notify->flags |= DNS_NOTIFY_TCP; - goto again; - } - -cleanup_key: - if (key != NULL) { - dns_tsigkey_detach(&key); - } -cleanup_message: - dns_message_detach(&message); -cleanup: - UNLOCK_ZONE(notify->zone); - if (notify->rlevent != NULL) { - isc_rlevent_free(¬ify->rlevent); - } - - if (result != ISC_R_SUCCESS) { - isc_sockaddr_format(¬ify->dst, addrbuf, sizeof(addrbuf)); - notify_log(notify->zone, ISC_LOG_WARNING, - "notify to %s failed: %s", addrbuf, - isc_result_totext(result)); - notify_destroy(notify, false); - } -} - -static void -notify_send(dns_notify_t *notify) { - isc_sockaddr_t dst; - isc_result_t result; - dns_notify_t *newnotify = NULL; - unsigned int flags; - bool startup; - - /* - * Zone lock held by caller. - */ - REQUIRE(DNS_NOTIFY_VALID(notify)); - REQUIRE(LOCKED_ZONE(notify->zone)); - - if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING)) { - return; - } - - ISC_LIST_FOREACH(notify->find->list, ai, publink) { - dst = ai->sockaddr; - if (notify_isqueued(notify->zone, notify->flags, NULL, &dst, - NULL, NULL)) - { - continue; - } - if (notify_isself(notify->zone, &dst)) { - continue; - } - newnotify = NULL; - flags = notify->flags & DNS_NOTIFY_NOSOA; - dns_notify_create(notify->mctx, flags, &newnotify); - zone_iattach(notify->zone, &newnotify->zone); - ISC_LIST_APPEND(newnotify->zone->notifyctx.notifies, newnotify, - link); - newnotify->dst = dst; - if (isc_sockaddr_pf(&dst) == AF_INET6) { - isc_sockaddr_any6(&newnotify->src); - } - startup = ((notify->flags & DNS_NOTIFY_STARTUP) != 0); - result = notify_send_queue(newnotify, startup); - if (result != ISC_R_SUCCESS) { - goto cleanup; - } - newnotify = NULL; - } - -cleanup: - if (newnotify != NULL) { - notify_destroy(newnotify, true); - } -} - void dns_zone_notify(dns_zone_t *zone, bool nodefer) { isc_time_t now; @@ -13248,8 +12762,9 @@ zone_notify(dns_zone_t *zone, isc_time_t *now) { tlsname, &transport); if (result == ISC_R_SUCCESS) { - notify_log( - zone, ISC_LOG_INFO, + dns_zone_logc( + zone, DNS_LOGCATEGORY_NOTIFY, + ISC_LOG_INFO, "got TLS configuration for a notify"); } else { dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, @@ -13273,7 +12788,9 @@ zone_notify(dns_zone_t *zone, isc_time_t *now) { goto next; } - if (notify_isqueued(zone, flags, NULL, &dst, key, transport)) { + if (dns_notify_isqueued(&zone->notifyctx, flags, NULL, &dst, + key, transport)) + { if (key != NULL) { dns_tsigkey_detach(&key); } @@ -13302,13 +12819,14 @@ zone_notify(dns_zone_t *zone, isc_time_t *now) { } ISC_LIST_APPEND(zone->notifyctx.notifies, notify, link); - result = notify_send_queue(notify, startup); + result = dns_notify_queue(notify, startup); if (result != ISC_R_SUCCESS) { - notify_destroy(notify, true); + dns_notify_destroy(notify, true); } if (!loggednotify) { - notify_log(zone, ISC_LOG_INFO, - "sending notifies (serial %u)", serial); + dns_zone_logc(zone, DNS_LOGCATEGORY_NOTIFY, + ISC_LOG_INFO, + "sending notifies (serial %u)", serial); loggednotify = true; } next: @@ -13352,14 +12870,15 @@ zone_notify(dns_zone_t *zone, isc_time_t *now) { } if (!loggednotify) { - notify_log(zone, ISC_LOG_INFO, - "sending notifies (serial %u)", serial); + dns_zone_logc(zone, DNS_LOGCATEGORY_NOTIFY, + ISC_LOG_INFO, + "sending notifies (serial %u)", serial); loggednotify = true; } LOCK_ZONE(zone); - isqueued = notify_isqueued(zone, flags, &ns.name, NULL, NULL, - NULL); + isqueued = dns_notify_isqueued(&zone->notifyctx, flags, + &ns.name, NULL, NULL, NULL); UNLOCK_ZONE(zone); if (isqueued) { continue; @@ -13370,7 +12889,7 @@ zone_notify(dns_zone_t *zone, isc_time_t *now) { LOCK_ZONE(zone); ISC_LIST_APPEND(zone->notifyctx.notifies, notify, link); UNLOCK_ZONE(zone); - notify_find_address(notify); + dns_notify_find_address(notify); } dns_rdataset_disassociate(&nsrdset); @@ -15311,7 +14830,7 @@ zone_shutdown(void *arg) { checkds_cancel(zone); - notify_cancel(zone); + dns_notify_cancel(&zone->notifyctx); forward_cancel(zone); @@ -15596,135 +15115,6 @@ cancel_refresh(dns_zone_t *zone) { zone_settimer(zone, &now); } -static isc_result_t -notify_createmessage(dns_zone_t *zone, unsigned int flags, - dns_message_t **messagep) { - dns_db_t *zonedb = NULL; - dns_dbnode_t *node = NULL; - dns_dbversion_t *version = NULL; - dns_message_t *message = NULL; - dns_rdataset_t rdataset; - dns_rdata_t rdata = DNS_RDATA_INIT; - - dns_name_t *tempname = NULL; - dns_rdata_t *temprdata = NULL; - dns_rdatalist_t *temprdatalist = NULL; - dns_rdataset_t *temprdataset = NULL; - - isc_result_t result; - isc_region_t r; - isc_buffer_t *b = NULL; - - REQUIRE(DNS_ZONE_VALID(zone)); - REQUIRE(messagep != NULL && *messagep == NULL); - - dns_message_create(zone->mctx, NULL, NULL, DNS_MESSAGE_INTENTRENDER, - &message); - - message->opcode = dns_opcode_notify; - message->flags |= DNS_MESSAGEFLAG_AA; - message->rdclass = zone->rdclass; - - dns_message_gettempname(message, &tempname); - - dns_message_gettemprdataset(message, &temprdataset); - - /* - * Make question. - */ - dns_name_clone(&zone->origin, tempname); - dns_rdataset_makequestion(temprdataset, zone->rdclass, - dns_rdatatype_soa); - ISC_LIST_APPEND(tempname->list, temprdataset, link); - dns_message_addname(message, tempname, DNS_SECTION_QUESTION); - tempname = NULL; - temprdataset = NULL; - - if ((flags & DNS_NOTIFY_NOSOA) != 0) { - goto done; - } - - dns_message_gettempname(message, &tempname); - dns_message_gettemprdata(message, &temprdata); - dns_message_gettemprdataset(message, &temprdataset); - dns_message_gettemprdatalist(message, &temprdatalist); - - ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read); - INSIST(zone->db != NULL); /* XXXJT: is this assumption correct? */ - dns_db_attach(zone->db, &zonedb); - ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read); - - dns_name_clone(&zone->origin, tempname); - dns_db_currentversion(zonedb, &version); - result = dns_db_findnode(zonedb, tempname, false, &node); - if (result != ISC_R_SUCCESS) { - goto soa_cleanup; - } - - dns_rdataset_init(&rdataset); - result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa, - dns_rdatatype_none, 0, &rdataset, NULL); - if (result != ISC_R_SUCCESS) { - goto soa_cleanup; - } - result = dns_rdataset_first(&rdataset); - if (result != ISC_R_SUCCESS) { - goto soa_cleanup; - } - dns_rdataset_current(&rdataset, &rdata); - dns_rdata_toregion(&rdata, &r); - isc_buffer_allocate(zone->mctx, &b, r.length); - isc_buffer_putmem(b, r.base, r.length); - isc_buffer_usedregion(b, &r); - dns_rdata_fromregion(temprdata, rdata.rdclass, rdata.type, &r); - dns_message_takebuffer(message, &b); - result = dns_rdataset_next(&rdataset); - dns_rdataset_disassociate(&rdataset); - if (result != ISC_R_NOMORE) { - goto soa_cleanup; - } - temprdatalist->rdclass = rdata.rdclass; - temprdatalist->type = rdata.type; - temprdatalist->ttl = rdataset.ttl; - ISC_LIST_APPEND(temprdatalist->rdata, temprdata, link); - - dns_rdatalist_tordataset(temprdatalist, temprdataset); - - ISC_LIST_APPEND(tempname->list, temprdataset, link); - dns_message_addname(message, tempname, DNS_SECTION_ANSWER); - temprdatalist = NULL; - temprdataset = NULL; - temprdata = NULL; - tempname = NULL; - -soa_cleanup: - if (node != NULL) { - dns_db_detachnode(&node); - } - if (version != NULL) { - dns_db_closeversion(zonedb, &version, false); - } - if (zonedb != NULL) { - dns_db_detach(&zonedb); - } - if (tempname != NULL) { - dns_message_puttempname(message, &tempname); - } - if (temprdata != NULL) { - dns_message_puttemprdata(message, &temprdata); - } - if (temprdataset != NULL) { - dns_message_puttemprdataset(message, &temprdataset); - } - if (temprdatalist != NULL) { - dns_message_puttemprdatalist(message, &temprdatalist); - } - -done: - *messagep = message; - return ISC_R_SUCCESS; -} - isc_result_t dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from, isc_sockaddr_t *to, dns_message_t *msg) { @@ -16329,15 +15719,6 @@ dns_zone_logv(dns_zone_t *zone, isc_logcategory_t category, int level, zstr, zone->strnamerd, message); } -static void -notify_log(dns_zone_t *zone, int level, const char *fmt, ...) { - va_list ap; - - va_start(ap, fmt); - dns_zone_logv(zone, DNS_LOGCATEGORY_NOTIFY, level, NULL, fmt, ap); - va_end(ap); -} - void dns_zone_logc(dns_zone_t *zone, isc_logcategory_t category, int level, const char *fmt, ...) { @@ -16584,69 +15965,6 @@ dns__zone_exiting(dns_zone_t *zone) { return DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) != 0; } -static void -notify_done(void *arg) { - dns_request_t *request = (dns_request_t *)arg; - dns_notify_t *notify = dns_request_getarg(request); - isc_result_t result; - dns_message_t *message = NULL; - isc_buffer_t buf; - char rcode[128]; - char addrbuf[ISC_SOCKADDR_FORMATSIZE]; - - REQUIRE(DNS_NOTIFY_VALID(notify)); - - isc_buffer_init(&buf, rcode, sizeof(rcode)); - isc_sockaddr_format(¬ify->dst, addrbuf, sizeof(addrbuf)); - dns_message_create(notify->zone->mctx, NULL, NULL, - DNS_MESSAGE_INTENTPARSE, &message); - - result = dns_request_getresult(request); - if (result != ISC_R_SUCCESS) { - goto fail; - } - - result = dns_request_getresponse(request, message, - DNS_MESSAGEPARSE_PRESERVEORDER); - if (result != ISC_R_SUCCESS) { - goto fail; - } - - result = dns_rcode_totext(message->rcode, &buf); - if (result == ISC_R_SUCCESS) { - notify_log(notify->zone, ISC_LOG_DEBUG(3), - "notify response from %s: %.*s", addrbuf, - (int)buf.used, rcode); - } - -fail: - dns_message_detach(&message); - - if (result == ISC_R_SUCCESS) { - notify_log(notify->zone, ISC_LOG_DEBUG(1), - "notify to %s successful", addrbuf); - } else if (result == ISC_R_SHUTTINGDOWN || result == ISC_R_CANCELED) { - /* just destroy the notify */ - } else if ((notify->flags & DNS_NOTIFY_TCP) == 0) { - notify_log(notify->zone, ISC_LOG_NOTICE, - "notify to %s failed: %s: retrying over TCP", - addrbuf, isc_result_totext(result)); - notify->flags |= DNS_NOTIFY_TCP; - dns_request_destroy(¬ify->request); - notify_send_queue(notify, notify->flags & DNS_NOTIFY_STARTUP); - return; - } else if (result == ISC_R_TIMEDOUT) { - notify_log(notify->zone, ISC_LOG_WARNING, - "notify to %s failed: %s: retries exceeded", addrbuf, - isc_result_totext(result)); - } else { - notify_log(notify->zone, ISC_LOG_WARNING, - "notify to %s failed: %s", addrbuf, - isc_result_totext(result)); - } - notify_destroy(notify, false); -} - struct rss { dns_zone_t *zone; dns_db_t *db;