diff --git a/bin/named/server.c b/bin/named/server.c
index 8acdae9a26..9052672e2b 100644
--- a/bin/named/server.c
+++ b/bin/named/server.c
@@ -3412,11 +3412,14 @@ configure_dnstap(const cfg_obj_t **maps, dns_view_t *view) {
dt |= DNS_DTTYPE_RQ|DNS_DTTYPE_RR;
} else if (strcasecmp(str, "forwarder") == 0) {
dt |= DNS_DTTYPE_FQ|DNS_DTTYPE_FR;
+ } else if (strcasecmp(str, "update") == 0) {
+ dt |= DNS_DTTYPE_UQ|DNS_DTTYPE_UR;
} else if (strcasecmp(str, "all") == 0) {
dt |= DNS_DTTYPE_CQ|DNS_DTTYPE_CR|
DNS_DTTYPE_AQ|DNS_DTTYPE_AR|
DNS_DTTYPE_RQ|DNS_DTTYPE_RR|
- DNS_DTTYPE_FQ|DNS_DTTYPE_FR;
+ DNS_DTTYPE_FQ|DNS_DTTYPE_FR|
+ DNS_DTTYPE_UQ|DNS_DTTYPE_UR;
}
obj2 = cfg_tuple_get(obj, "mode");
diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml
index f34ac57b6b..c012ce88c7 100644
--- a/doc/arm/Bv9ARM-book.xml
+++ b/doc/arm/Bv9ARM-book.xml
@@ -4366,10 +4366,11 @@ badresp:1,adberr:0,findfail:0,valfail:0]
The dnstap option is a bracketed list
of message types to be logged. These may be set differently
for each view. Supported types are client,
- auth, resolver, and
- forwarder. Specifying type
- all will cause all dnstap
- messages to be logged, regardless of type.
+ auth, resolver,
+ forwarder, and update.
+ Specifying type all will cause all
+ dnstap messages to be logged, regardless of
+ type.
Each type may take an additional argument to indicate whether
diff --git a/lib/dns/dnstap.c b/lib/dns/dnstap.c
index 077445d005..cd83d45633 100644
--- a/lib/dns/dnstap.c
+++ b/lib/dns/dnstap.c
@@ -694,6 +694,10 @@ dnstap_type(dns_dtmsgtype_t msgtype) {
return (DNSTAP__MESSAGE__TYPE__TOOL_QUERY);
case DNS_DTTYPE_TR:
return (DNSTAP__MESSAGE__TYPE__TOOL_RESPONSE);
+ case DNS_DTTYPE_UQ:
+ return (DNSTAP__MESSAGE__TYPE__UPDATE_QUERY);
+ case DNS_DTTYPE_UR:
+ return (DNSTAP__MESSAGE__TYPE__UPDATE_RESPONSE);
default:
INSIST(0);
}
@@ -860,6 +864,7 @@ dns_dt_send(dns_view_t *view, dns_dtmsgtype_t msgtype,
case DNS_DTTYPE_FR:
case DNS_DTTYPE_SR:
case DNS_DTTYPE_TR:
+ case DNS_DTTYPE_UR:
if (rtime != NULL)
t = rtime;
@@ -881,6 +886,7 @@ dns_dt_send(dns_view_t *view, dns_dtmsgtype_t msgtype,
case DNS_DTTYPE_RQ:
case DNS_DTTYPE_SQ:
case DNS_DTTYPE_TQ:
+ case DNS_DTTYPE_UQ:
if (qtime != NULL)
t = qtime;
@@ -1160,6 +1166,12 @@ dns_dt_parse(isc_mem_t *mctx, isc_region_t *src, dns_dtdata_t **destp) {
case DNSTAP__MESSAGE__TYPE__TOOL_RESPONSE:
d->type = DNS_DTTYPE_TR;
break;
+ case DNSTAP__MESSAGE__TYPE__UPDATE_QUERY:
+ d->type = DNS_DTTYPE_UQ;
+ break;
+ case DNSTAP__MESSAGE__TYPE__UPDATE_RESPONSE:
+ d->type = DNS_DTTYPE_UR;
+ break;
default:
CHECK(DNS_R_BADDNSTAP);
}
@@ -1316,6 +1328,12 @@ dns_dt_datatotext(dns_dtdata_t *d, isc_buffer_t **dest) {
case DNS_DTTYPE_TR:
CHECK(putstr(dest, "TR "));
break;
+ case DNS_DTTYPE_UQ:
+ CHECK(putstr(dest, "UQ "));
+ break;
+ case DNS_DTTYPE_UR:
+ CHECK(putstr(dest, "UR "));
+ break;
default:
return (DNS_R_BADDNSTAP);
}
diff --git a/lib/dns/dnstap.proto b/lib/dns/dnstap.proto
index 1ed1bb00e2..5280c9b650 100644
--- a/lib/dns/dnstap.proto
+++ b/lib/dns/dnstap.proto
@@ -165,6 +165,16 @@ message Message {
// TOOL_RESPONSE is a DNS response message received by a DNS software
// tool from a DNS server, from the perspective of the tool.
TOOL_RESPONSE = 12;
+
+ // UPDATE_QUERY is a DNS update query message received from a resolver
+ // by an authoritative name server, from the perspective of the
+ // authoritative name server.
+ UPDATE_QUERY = 13;
+
+ // UPDATE_RESPONSE is a DNS update response message sent from an
+ // authoritative name server to a resolver, from the perspective of the
+ // authoritative name server.
+ UPDATE_RESPONSE = 14;
}
// One of the Type values described above.
diff --git a/lib/dns/include/dns/dnstap.h b/lib/dns/include/dns/dnstap.h
index bc3b79e9eb..e27c95e8a0 100644
--- a/lib/dns/include/dns/dnstap.h
+++ b/lib/dns/include/dns/dnstap.h
@@ -73,13 +73,17 @@ struct fstrm_iothr_options;
#define DNS_DTTYPE_FR 0x0200
#define DNS_DTTYPE_TQ 0x0400
#define DNS_DTTYPE_TR 0x0800
+#define DNS_DTTYPE_UQ 0x1000
+#define DNS_DTTYPE_UR 0x2000
#define DNS_DTTYPE_QUERY \
(DNS_DTTYPE_SQ|DNS_DTTYPE_CQ|DNS_DTTYPE_AQ|\
- DNS_DTTYPE_RQ|DNS_DTTYPE_FQ|DNS_DTTYPE_TQ)
+ DNS_DTTYPE_RQ|DNS_DTTYPE_FQ|DNS_DTTYPE_TQ|\
+ DNS_DTTYPE_UQ)
#define DNS_DTTYPE_RESPONSE \
(DNS_DTTYPE_SR|DNS_DTTYPE_CR|DNS_DTTYPE_AR|\
- DNS_DTTYPE_RR|DNS_DTTYPE_FR|DNS_DTTYPE_TR)
+ DNS_DTTYPE_RR|DNS_DTTYPE_FR|DNS_DTTYPE_TR|\
+ DNS_DTTYPE_UR)
#define DNS_DTTYPE_ALL \
(DNS_DTTYPE_QUERY|DNS_DTTYPE_RESPONSE)
diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c
index c6b1072d88..d6881de77f 100644
--- a/lib/isccfg/namedconf.c
+++ b/lib/isccfg/namedconf.c
@@ -1276,10 +1276,11 @@ static cfg_type_t cfg_type_resppadding = {
* ...
* }
*
- * ... where message type is one of: client, resolver, auth, forwarder, all
+ * ... where message type is one of: client, resolver, auth, forwarder,
+ * update, all
*/
static const char *dnstap_types[] = {
- "all", "auth", "client", "forwarder", "resolver", NULL
+ "all", "auth", "client", "forwarder", "resolver", "update", NULL
};
static const char *dnstap_modes[] = { "query", "response", NULL };
diff --git a/lib/ns/client.c b/lib/ns/client.c
index bcf022e1ee..b5c3175dc2 100644
--- a/lib/ns/client.c
+++ b/lib/ns/client.c
@@ -1225,10 +1225,13 @@ client_send(ns_client_t *client) {
isc_buffer_usedregion(&b, &zr);
}
- if ((client->message->flags & DNS_MESSAGEFLAG_RD) != 0)
+ if (client->message->opcode == dns_opcode_update) {
+ dtmsgtype = DNS_DTTYPE_UR;
+ } else if ((client->message->flags & DNS_MESSAGEFLAG_RD) != 0) {
dtmsgtype = DNS_DTTYPE_CR;
- else
+ } else {
dtmsgtype = DNS_DTTYPE_AR;
+ }
#endif /* HAVE_DNSTAP */
if (cleanup_cctx) {
@@ -1269,9 +1272,11 @@ client_send(ns_client_t *client) {
break;
}
} else {
- respsize = isc_buffer_usedlength(&buffer);
- result = client_sendpkg(client, &buffer);
#ifdef HAVE_DNSTAP
+ /*
+ * Log dnstap data first, because client_sendpkg() may
+ * leave client->view set to NULL.
+ */
if (client->view != NULL) {
dns_dt_send(client->view, dtmsgtype,
&client->peeraddr,
@@ -1281,6 +1286,9 @@ client_send(ns_client_t *client) {
}
#endif /* HAVE_DNSTAP */
+ respsize = isc_buffer_usedlength(&buffer);
+ result = client_sendpkg(client, &buffer);
+
switch (isc_sockaddr_pf(&client->peeraddr)) {
case AF_INET:
isc_stats_increment(client->sctx->udpoutstats4,
@@ -2847,6 +2855,11 @@ ns__client_request(isc_task_t *task, isc_event_t *event) {
break;
case dns_opcode_update:
CTRACE("update");
+#ifdef HAVE_DNSTAP
+ dns_dt_send(client->view, DNS_DTTYPE_UQ, &client->peeraddr,
+ &client->destsockaddr, TCP_CLIENT(client), NULL,
+ &client->requesttime, NULL, buffer);
+#endif /* HAVE_DNSTAP */
ns_client_settimeout(client, 60);
ns_update_start(client, sigresult);
break;