mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-23 18:47:40 -04:00
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.
This commit is contained in:
parent
090a451e66
commit
680becfb33
3 changed files with 811 additions and 700 deletions
|
|
@ -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
|
||||
*/
|
||||
|
|
|
|||
727
lib/dns/notify.c
727
lib/dns/notify.c
|
|
@ -13,9 +13,31 @@
|
|||
|
||||
/*! \file */
|
||||
|
||||
#include <isc/netmgr.h>
|
||||
#include <isc/ratelimiter.h>
|
||||
#include <isc/result.h>
|
||||
|
||||
#include <dns/adb.h>
|
||||
#include <dns/notify.h>
|
||||
#include <dns/peer.h>
|
||||
#include <dns/rcode.h>
|
||||
#include <dns/rdatalist.h>
|
||||
#include <dns/request.h>
|
||||
#include <dns/stats.h>
|
||||
#include <dns/tsig.h>
|
||||
#include <dns/zone.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
718
lib/dns/zone.c
718
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;
|
||||
|
|
|
|||
Loading…
Reference in a new issue