}
typedef struct {
- isc_mem_t *mctx;
- isc_task_t *task;
- dns_rdataset_t rdataset;
- dns_rdataset_t sigrdataset;
- dns_fetch_t *fetch;
+ isc_mem_t *mctx;
+ isc_task_t *task;
+ dns_fetch_t *fetch;
+ dns_view_t *view;
+ dns_fixedname_t tatname;
+ dns_fixedname_t keyname;
+ dns_rdataset_t rdataset;
+ dns_rdataset_t sigrdataset;
} ns_tat_t;
static int
dns_fetchevent_t *devent;
ns_tat_t *tat;
- UNUSED(task);
INSIST(event != NULL && event->ev_type == DNS_EVENT_FETCHDONE);
INSIST(event->ev_arg != NULL);
+ UNUSED(task);
+
tat = event->ev_arg;
devent = (dns_fetchevent_t *) event;
dns_rdataset_disassociate(&tat->rdataset);
if (dns_rdataset_isassociated(&tat->sigrdataset))
dns_rdataset_disassociate(&tat->sigrdataset);
+ dns_view_detach(&tat->view);
isc_task_detach(&tat->task);
isc_mem_putanddetach(&tat->mctx, tat, sizeof(*tat));
}
/*%
* Prepare the QNAME for the TAT query to be sent by processing the trust
* anchors present at 'keynode' of 'keytable'. Store the result in 'dst' and
- * the domain name which 'keynode' is associated with in 'origin'.
+ * the domain name which 'keynode' is associated with in 'keyname'.
*
* A maximum of 12 key IDs can be reported in a single TAT query due to the
* 63-octet length limit for any single label in a domain name. If there are
* reported in the TAT query.
*/
static isc_result_t
-get_tat_qname(dns_name_t *dst, dns_name_t **origin, dns_keytable_t *keytable,
+get_tat_qname(dns_name_t *dst, dns_name_t **keyname, dns_keytable_t *keytable,
dns_keynode_t *keynode)
{
dns_keynode_t *firstnode = keynode;
char label[64];
int m;
- REQUIRE(origin != NULL && *origin == NULL);
+ REQUIRE(keyname != NULL && *keyname == NULL);
do {
dst_key_t *key = dns_keynode_key(keynode);
if (key != NULL) {
- *origin = dst_key_name(key);
+ *keyname = dst_key_name(key);
if (n < (sizeof(ids)/sizeof(ids[0]))) {
ids[n] = dst_key_id(key);
n++;
isc_textregion_consume(&r, m);
}
- return (dns_name_fromstring2(dst, label, *origin, 0, NULL));
+ return (dns_name_fromstring2(dst, label, *keyname, 0, NULL));
}
static void
-dotat(dns_keytable_t *keytable, dns_keynode_t *keynode, void *arg) {
- struct dotat_arg *dotat_arg = arg;
+tat_send(isc_task_t *task, isc_event_t *event) {
+ ns_tat_t *tat;
char namebuf[DNS_NAME_FORMATSIZE];
- dns_fixedname_t fixed, fdomain;
- dns_name_t *tatname, *domain;
+ dns_fixedname_t fdomain;
+ dns_name_t *domain;
dns_rdataset_t nameservers;
- dns_name_t *origin = NULL;
isc_result_t result;
- dns_view_t *view;
- isc_task_t *task;
- ns_tat_t *tat;
+ dns_name_t *keyname;
+ dns_name_t *tatname;
- REQUIRE(keytable != NULL);
- REQUIRE(keynode != NULL);
- REQUIRE(dotat_arg != NULL);
+ INSIST(event != NULL && event->ev_type == NS_EVENT_TATSEND);
+ INSIST(event->ev_arg != NULL);
- view = dotat_arg->view;
- task = dotat_arg->task;
+ UNUSED(task);
- tatname = dns_fixedname_initname(&fixed);
- result = get_tat_qname(tatname, &origin, keytable, keynode);
- if (result != ISC_R_SUCCESS) {
- return;
- }
+ tat = event->ev_arg;
+
+ tatname = dns_fixedname_name(&tat->tatname);
+ keyname = dns_fixedname_name(&tat->keyname);
dns_name_format(tatname, namebuf, sizeof(namebuf));
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
ISC_LOG_INFO,
- "%s: sending trust-anchor-telemetry query '%s/NULL'",
- view->name, namebuf);
-
- tat = isc_mem_get(dotat_arg->view->mctx, sizeof(*tat));
- if (tat == NULL)
- return;
-
- tat->mctx = NULL;
- tat->task = NULL;
- tat->fetch = NULL;
- dns_rdataset_init(&tat->rdataset);
- dns_rdataset_init(&tat->sigrdataset);
- isc_mem_attach(dotat_arg->view->mctx, &tat->mctx);
- isc_task_attach(task, &tat->task);
+ "%s: sending trust-anchor-telemetry query '%s/NULL'",
+ tat->view->name, namebuf);
/*
* TAT queries should be sent to the authoritative servers for a given
* order to eventually find the destination host to send the TAT query
* to.
*
- * 'origin' holds the domain name at 'keynode', i.e. the domain name
+ * 'keyname' holds the domain name at 'keynode', i.e. the domain name
* for which the trust anchors to be reported by this TAT query are
* defined.
*
* After the dns_view_findzonecut() call, 'domain' will hold the
- * deepest zone cut we can find for 'origin' while 'nameservers' will
+ * deepest zone cut we can find for 'keyname' while 'nameservers' will
* hold the NS RRset at that zone cut.
*/
domain = dns_fixedname_initname(&fdomain);
dns_rdataset_init(&nameservers);
- result = dns_view_findzonecut(view, origin, domain, 0, 0, true,
+ result = dns_view_findzonecut(tat->view, keyname, domain, 0, 0, true,
&nameservers, NULL);
if (result == ISC_R_SUCCESS) {
- result = dns_resolver_createfetch(view->resolver, tatname,
+ result = dns_resolver_createfetch(tat->view->resolver, tatname,
dns_rdatatype_null, domain,
&nameservers, NULL, 0,
tat->task, tat_done, tat,
}
if (result != ISC_R_SUCCESS) {
+ dns_view_detach(&tat->view);
isc_task_detach(&tat->task);
isc_mem_putanddetach(&tat->mctx, tat, sizeof(*tat));
}
+ isc_event_free(&event);
+}
+
+static void
+dotat(dns_keytable_t *keytable, dns_keynode_t *keynode, void *arg) {
+ struct dotat_arg *dotat_arg = arg;
+ dns_name_t *keyname = NULL;
+ isc_result_t result;
+ dns_view_t *view;
+ isc_task_t *task;
+ ns_tat_t *tat;
+ isc_event_t *event;
+
+ REQUIRE(keytable != NULL);
+ REQUIRE(keynode != NULL);
+ REQUIRE(dotat_arg != NULL);
+
+ view = dotat_arg->view;
+ task = dotat_arg->task;
+
+ tat = isc_mem_get(dotat_arg->view->mctx, sizeof(*tat));
+
+ tat->fetch = NULL;
+ tat->mctx = NULL;
+ tat->task = NULL;
+ tat->view = NULL;
+ dns_rdataset_init(&tat->rdataset);
+ dns_rdataset_init(&tat->sigrdataset);
+ result = get_tat_qname(dns_fixedname_initname(&tat->tatname), &keyname,
+ keytable, keynode);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(dotat_arg->view->mctx, tat, sizeof(*tat));
+ return;
+ }
+ dns_name_copy(keyname, dns_fixedname_initname(&tat->keyname), NULL);
+ isc_mem_attach(dotat_arg->view->mctx, &tat->mctx);
+ isc_task_attach(task, &tat->task);
+ dns_view_attach(view, &tat->view);
+
+ /*
+ * We don't want to be holding the keytable lock when calling
+ * dns_view_findzonecut() as it creates a lock order loop so
+ * call dns_view_findzonecut() in a event handler.
+ *
+ * zone->lock (dns_zone_setviewcommit) while holding view->lock
+ * (dns_view_setviewcommit)
+ *
+ * keytable->lock (dns_keytable_find) while holding zone->lock
+ * (zone_asyncload)
+ *
+ * view->lock (dns_view_findzonecut) while holding keytable->lock
+ * (dns_keytable_forall)
+ */
+ event = isc_event_allocate(tat->mctx, keytable, NS_EVENT_TATSEND,
+ tat_send, tat, sizeof(isc_event_t));
+ isc_task_send(task, &event);
}
static void