diff --git a/bin/tools/dnstap-read.c b/bin/tools/dnstap-read.c index 1df44dad6f..cbc82c33c5 100644 --- a/bin/tools/dnstap-read.c +++ b/bin/tools/dnstap-read.c @@ -269,7 +269,8 @@ print_yaml(dns_dtdata_t *dt) { } } - printf(" socket_protocol: %s\n", dt->tcp ? "TCP" : "UDP"); + printf(" socket_protocol: %s\n", + dt->transport == DNS_TRANSPORT_UDP ? "UDP" : "TCP"); if (m->has_query_address) { ProtobufCBinaryData *ip = &m->query_address; diff --git a/lib/dns/dnstap.c b/lib/dns/dnstap.c index 887c017996..bc0be5fe6a 100644 --- a/lib/dns/dnstap.c +++ b/lib/dns/dnstap.c @@ -643,7 +643,7 @@ cpbuf(isc_buffer_t *buf, ProtobufCBinaryData *p, protobuf_c_boolean *has) { } static void -setaddr(dns_dtmsg_t *dm, isc_sockaddr_t *sa, bool tcp, +setaddr(dns_dtmsg_t *dm, isc_sockaddr_t *sa, dns_transport_type_t transport, ProtobufCBinaryData *addr, protobuf_c_boolean *has_addr, uint32_t *port, protobuf_c_boolean *has_port) { int family = isc_sockaddr_pf(sa); @@ -664,10 +664,22 @@ setaddr(dns_dtmsg_t *dm, isc_sockaddr_t *sa, bool tcp, *port = ntohs(sa->type.sin.sin_port); } - if (tcp) { + switch (transport) { + case DNS_TRANSPORT_TCP: dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__TCP; - } else { + break; + case DNS_TRANSPORT_UDP: dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__UDP; + break; + case DNS_TRANSPORT_TLS: + dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__DOT; + break; + case DNS_TRANSPORT_HTTP: + dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__DOH; + break; + case DNS_TRANSPORT_NONE: + case DNS_TRANSPORT_COUNT: + UNREACHABLE(); } dm->m.has_socket_protocol = 1; @@ -732,8 +744,9 @@ unlock_and_return: void dns_dt_send(dns_view_t *view, dns_dtmsgtype_t msgtype, isc_sockaddr_t *qaddr, - isc_sockaddr_t *raddr, bool tcp, isc_region_t *zone, - isc_time_t *qtime, isc_time_t *rtime, isc_buffer_t *buf) { + isc_sockaddr_t *raddr, dns_transport_type_t transport, + isc_region_t *zone, isc_time_t *qtime, isc_time_t *rtime, + isc_buffer_t *buf) { isc_time_t now, *t; dns_dtmsg_t dm; @@ -833,12 +846,12 @@ dns_dt_send(dns_view_t *view, dns_dtmsgtype_t msgtype, isc_sockaddr_t *qaddr, } if (qaddr != NULL) { - setaddr(&dm, qaddr, tcp, &dm.m.query_address, + setaddr(&dm, qaddr, transport, &dm.m.query_address, &dm.m.has_query_address, &dm.m.query_port, &dm.m.has_query_port); } if (raddr != NULL) { - setaddr(&dm, raddr, tcp, &dm.m.response_address, + setaddr(&dm, raddr, transport, &dm.m.response_address, &dm.m.has_response_address, &dm.m.response_port, &dm.m.has_response_port); } @@ -1162,11 +1175,27 @@ dns_dt_parse(isc_mem_t *mctx, isc_region_t *src, dns_dtdata_t **destp) { protobuf_c_enum_descriptor_get_value( &dnstap__socket_protocol__descriptor, m->socket_protocol); - if (type != NULL && type->value == DNSTAP__SOCKET_PROTOCOL__TCP) - { - d->tcp = true; + + if (type != NULL) { + switch (type->value) { + case DNSTAP__SOCKET_PROTOCOL__DNSCryptUDP: + case DNSTAP__SOCKET_PROTOCOL__DOQ: + case DNSTAP__SOCKET_PROTOCOL__UDP: + d->transport = DNS_TRANSPORT_UDP; + break; + case DNSTAP__SOCKET_PROTOCOL__DNSCryptTCP: + case DNSTAP__SOCKET_PROTOCOL__TCP: + d->transport = DNS_TRANSPORT_TCP; + break; + case DNSTAP__SOCKET_PROTOCOL__DOT: + d->transport = DNS_TRANSPORT_TLS; + break; + case DNSTAP__SOCKET_PROTOCOL__DOH: + d->transport = DNS_TRANSPORT_HTTP; + break; + } } else { - d->tcp = false; + d->transport = DNS_TRANSPORT_UDP; } } @@ -1292,10 +1321,24 @@ dns_dt_datatotext(dns_dtdata_t *d, isc_buffer_t **dest) { CHECK(putstr(dest, " ")); /* Protocol */ - if (d->tcp) { - CHECK(putstr(dest, "TCP ")); - } else { + switch (d->transport) { + case DNS_TRANSPORT_NONE: + CHECK(putstr(dest, "NUL ")); + break; + case DNS_TRANSPORT_UDP: CHECK(putstr(dest, "UDP ")); + break; + case DNS_TRANSPORT_TCP: + CHECK(putstr(dest, "TCP ")); + break; + case DNS_TRANSPORT_TLS: + CHECK(putstr(dest, "DOT ")); + break; + case DNS_TRANSPORT_HTTP: + CHECK(putstr(dest, "DOH ")); + break; + case DNS_TRANSPORT_COUNT: + UNREACHABLE(); } /* Message size */ diff --git a/lib/dns/include/dns/dnstap.h b/lib/dns/include/dns/dnstap.h index 0d937c4e00..aa80cbba78 100644 --- a/lib/dns/include/dns/dnstap.h +++ b/lib/dns/include/dns/dnstap.h @@ -39,6 +39,7 @@ struct fstrm_iothr_options; #include #include #include +#include #include /*% @@ -93,9 +94,9 @@ struct dns_dtdata { void *frame; - bool query; - bool tcp; - dns_dtmsgtype_t type; + bool query; + dns_dtmsgtype_t type; + dns_transport_type_t transport; isc_time_t qtime; isc_time_t rtime; @@ -262,8 +263,9 @@ dns_dt_getstats(dns_dtenv_t *env, isc_stats_t **statsp); void dns_dt_send(dns_view_t *view, dns_dtmsgtype_t msgtype, isc_sockaddr_t *qaddr, - isc_sockaddr_t *dstaddr, bool tcp, isc_region_t *zone, - isc_time_t *qtime, isc_time_t *rtime, isc_buffer_t *buf); + isc_sockaddr_t *dstaddr, dns_transport_type_t transport, + isc_region_t *zone, isc_time_t *qtime, isc_time_t *rtime, + isc_buffer_t *buf); /*%< * Sends a dnstap message to the log, if 'msgtype' is one of the message * types represented in 'view->dttypes'. diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 6fe8ba448b..fd5cc04be1 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -2319,6 +2319,7 @@ resquery_send(resquery_t *query) { #ifdef HAVE_DNSTAP isc_sockaddr_t localaddr, *la = NULL; unsigned char zone[DNS_NAME_MAXWIRE]; + dns_transport_type_t transport_type; dns_dtmsgtype_t dtmsgtype; isc_region_t zr; isc_buffer_t zb; @@ -2717,8 +2718,17 @@ resquery_send(resquery_t *query) { la = &localaddr; } + if (query->addrinfo->transport != NULL) { + transport_type = + dns_transport_get_type(query->addrinfo->transport); + } else if ((query->options & DNS_FETCHOPT_TCP) != 0) { + transport_type = DNS_TRANSPORT_TCP; + } else { + transport_type = DNS_TRANSPORT_UDP; + } + dns_dt_send(fctx->res->view, dtmsgtype, la, &query->addrinfo->sockaddr, - tcp, &zr, &query->start, NULL, &buffer); + transport_type, &zr, &query->start, NULL, &buffer); #endif /* HAVE_DNSTAP */ return (ISC_R_SUCCESS); @@ -9556,6 +9566,7 @@ rctx_logpacket(respctx_t *rctx) { isc_result_t result; isc_sockaddr_t localaddr, *la = NULL; unsigned char zone[DNS_NAME_MAXWIRE]; + dns_transport_type_t transport_type; dns_dtmsgtype_t dtmsgtype; dns_compress_t cctx; isc_region_t zr; @@ -9594,9 +9605,17 @@ rctx_logpacket(respctx_t *rctx) { la = &localaddr; } + if (rctx->query->addrinfo->transport != NULL) { + transport_type = dns_transport_get_type( + rctx->query->addrinfo->transport); + } else if ((rctx->query->options & DNS_FETCHOPT_TCP) != 0) { + transport_type = DNS_TRANSPORT_TCP; + } else { + transport_type = DNS_TRANSPORT_UDP; + } + dns_dt_send(fctx->res->view, dtmsgtype, la, - &rctx->query->addrinfo->sockaddr, - ((rctx->query->options & DNS_FETCHOPT_TCP) != 0), &zr, + &rctx->query->addrinfo->sockaddr, transport_type, &zr, &rctx->query->start, NULL, &rctx->buffer); #endif /* HAVE_DNSTAP */ } diff --git a/lib/ns/client.c b/lib/ns/client.c index 34ab13caa3..b129db00c3 100644 --- a/lib/ns/client.c +++ b/lib/ns/client.c @@ -123,6 +123,40 @@ static void compute_cookie(ns_client_t *client, uint32_t when, const unsigned char *secret, isc_buffer_t *buf); +static dns_transport_type_t +ns_client_transport_type(const ns_client_t *client) { + REQUIRE(client->handle != NULL); + + switch (isc_nm_socket_type(client->handle)) { + case isc_nm_udpsocket: + case isc_nm_udplistener: + case isc_nm_proxyudpsocket: + case isc_nm_proxyudplistener: + return DNS_TRANSPORT_UDP; + case isc_nm_tlssocket: + case isc_nm_tlslistener: + return DNS_TRANSPORT_TLS; + case isc_nm_httpsocket: + case isc_nm_httplistener: + return DNS_TRANSPORT_HTTP; + case isc_nm_streamdnslistener: + case isc_nm_streamdnssocket: + case isc_nm_proxystreamlistener: + case isc_nm_proxystreamsocket: + /* If it isn't DoT, it is DNS-over-TCP */ + if (isc_nm_has_encryption(client->handle)) { + return DNS_TRANSPORT_TLS; + } + FALLTHROUGH; + case isc_nm_tcpsocket: + case isc_nm_tcplistener: + return DNS_TRANSPORT_TCP; + case isc_nm_maxsocket: + case isc_nm_nonesocket: + UNREACHABLE(); + } +} + void ns_client_recursing(ns_client_t *client) { REQUIRE(NS_CLIENT_VALID(client)); @@ -396,6 +430,10 @@ ns_client_sendraw(ns_client_t *client, dns_message_t *message) { isc_buffer_t buffer; isc_region_t r; isc_region_t *mr = NULL; +#ifdef HAVE_DNSTAP + dns_transport_type_t transport_type; + dns_dtmsgtype_t dtmsgtype; +#endif REQUIRE(NS_CLIENT_VALID(client)); @@ -427,8 +465,8 @@ ns_client_sendraw(ns_client_t *client, dns_message_t *message) { #ifdef HAVE_DNSTAP if (client->view != NULL) { - bool tcp = TCP_CLIENT(client); - dns_dtmsgtype_t dtmsgtype; + transport_type = ns_client_transport_type(client); + if (client->message->opcode == dns_opcode_update) { dtmsgtype = DNS_DTTYPE_UR; } else if ((client->message->flags & DNS_MESSAGEFLAG_RD) != 0) { @@ -437,7 +475,7 @@ ns_client_sendraw(ns_client_t *client, dns_message_t *message) { dtmsgtype = DNS_DTTYPE_AR; } dns_dt_send(client->view, dtmsgtype, &client->peeraddr, - &client->destsockaddr, tcp, NULL, + &client->destsockaddr, transport_type, NULL, &client->requesttime, NULL, &buffer); } #endif @@ -470,6 +508,7 @@ ns_client_send(ns_client_t *client) { dns_aclenv_t *env = NULL; #ifdef HAVE_DNSTAP unsigned char zone[DNS_NAME_MAXWIRE]; + dns_transport_type_t transport_type; dns_dtmsgtype_t dtmsgtype; isc_region_t zr; #endif /* HAVE_DNSTAP */ @@ -637,6 +676,8 @@ renderend: } else { dtmsgtype = DNS_DTTYPE_AR; } + + transport_type = ns_client_transport_type(client); #endif /* HAVE_DNSTAP */ if (cleanup_cctx) { @@ -650,7 +691,7 @@ renderend: #ifdef HAVE_DNSTAP if (client->view != NULL) { dns_dt_send(client->view, dtmsgtype, &client->peeraddr, - &client->destsockaddr, true, &zr, + &client->destsockaddr, transport_type, &zr, &client->requesttime, NULL, &buffer); } #endif /* HAVE_DNSTAP */ @@ -679,7 +720,7 @@ renderend: */ if (client->view != NULL) { dns_dt_send(client->view, dtmsgtype, &client->peeraddr, - &client->destsockaddr, false, &zr, + &client->destsockaddr, transport_type, &zr, &client->requesttime, NULL, &buffer); } #endif /* HAVE_DNSTAP */ @@ -1652,6 +1693,7 @@ ns_client_request(isc_nmhandle_t *handle, isc_result_t eresult, size_t reqsize; dns_aclenv_t *env = NULL; #ifdef HAVE_DNSTAP + dns_transport_type_t transport_type; dns_dtmsgtype_t dtmsgtype; #endif /* ifdef HAVE_DNSTAP */ static const char *ra_reasons[] = { @@ -2210,6 +2252,10 @@ ns_client_request(isc_nmhandle_t *handle, isc_result_t eresult, } } +#ifdef HAVE_DNSTAP + transport_type = ns_client_transport_type(client); +#endif /* HAVE_DNSTAP */ + /* * Dispatch the request. */ @@ -2224,7 +2270,7 @@ ns_client_request(isc_nmhandle_t *handle, isc_result_t eresult, } dns_dt_send(client->view, dtmsgtype, &client->peeraddr, - &client->destsockaddr, TCP_CLIENT(client), NULL, + &client->destsockaddr, transport_type, NULL, &client->requesttime, NULL, buffer); #endif /* HAVE_DNSTAP */ @@ -2234,7 +2280,7 @@ ns_client_request(isc_nmhandle_t *handle, isc_result_t eresult, CTRACE("update"); #ifdef HAVE_DNSTAP dns_dt_send(client->view, DNS_DTTYPE_UQ, &client->peeraddr, - &client->destsockaddr, TCP_CLIENT(client), NULL, + &client->destsockaddr, transport_type, NULL, &client->requesttime, NULL, buffer); #endif /* HAVE_DNSTAP */ ns_client_settimeout(client, 60); diff --git a/tests/dns/dnstap_test.c b/tests/dns/dnstap_test.c index 8c82461b28..6d37979c3d 100644 --- a/tests/dns/dnstap_test.c +++ b/tests/dns/dnstap_test.c @@ -230,14 +230,20 @@ ISC_RUN_TEST_IMPL(dns_dt_send) { break; } - dns_dt_send(view, dt, q, r, false, &zr, &p, &f, m); - dns_dt_send(view, dt, q, r, false, &zr, NULL, &f, m); - dns_dt_send(view, dt, q, r, false, &zr, &p, NULL, m); - dns_dt_send(view, dt, q, r, false, &zr, NULL, NULL, m); - dns_dt_send(view, dt, q, r, true, &zr, &p, &f, m); - dns_dt_send(view, dt, q, r, true, &zr, NULL, &f, m); - dns_dt_send(view, dt, q, r, true, &zr, &p, NULL, m); - dns_dt_send(view, dt, q, r, true, &zr, NULL, NULL, m); + dns_dt_send(view, dt, q, r, DNS_TRANSPORT_UDP, &zr, &p, &f, m); + dns_dt_send(view, dt, q, r, DNS_TRANSPORT_UDP, &zr, NULL, &f, + m); + dns_dt_send(view, dt, q, r, DNS_TRANSPORT_UDP, &zr, &p, NULL, + m); + dns_dt_send(view, dt, q, r, DNS_TRANSPORT_UDP, &zr, NULL, NULL, + m); + dns_dt_send(view, dt, q, r, DNS_TRANSPORT_TCP, &zr, &p, &f, m); + dns_dt_send(view, dt, q, r, DNS_TRANSPORT_TCP, &zr, NULL, &f, + m); + dns_dt_send(view, dt, q, r, DNS_TRANSPORT_TCP, &zr, &p, NULL, + m); + dns_dt_send(view, dt, q, r, DNS_TRANSPORT_TCP, &zr, NULL, NULL, + m); } dns_dt_detach(&view->dtenv);