diff --git a/bin/named/bind9.xsl b/bin/named/bind9.xsl
index badb3a1e9a..2c5f2eb1e0 100644
--- a/bin/named/bind9.xsl
+++ b/bin/named/bind9.xsl
@@ -923,6 +923,7 @@
Additional Refresh Queued |
Local Address |
Remote Address |
+ SOA Transport |
Transport |
TSIG Key Name |
Duration (s) |
@@ -949,6 +950,7 @@
|
|
|
+ |
|
|
|
diff --git a/bin/named/statschannel.c b/bin/named/statschannel.c
index 191006ede0..36fbe9cde8 100644
--- a/bin/named/statschannel.c
+++ b/bin/named/statschannel.c
@@ -1461,7 +1461,7 @@ xfrin_xmlrender(dns_zone_t *zone, void *arg) {
uint32_t serial;
const isc_sockaddr_t *addrp = NULL;
char addr_buf[ISC_SOCKADDR_FORMATSIZE];
- const dns_transport_t *transport = NULL;
+ dns_transport_type_t transport_type;
xmlTextWriterPtr writer = arg;
dns_zonestat_level_t statlevel;
int xmlrc;
@@ -1581,20 +1581,41 @@ xfrin_xmlrender(dns_zone_t *zone, void *arg) {
}
TRY0(xmlTextWriterEndElement(writer));
- TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "transport"));
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "soatransport"));
if (is_running) {
- transport = dns_xfrin_gettransport(xfr);
- if (transport == NULL ||
- dns_transport_get_type(transport) == DNS_TRANSPORT_TCP)
- {
+ transport_type = dns_xfrin_getsoatransporttype(xfr);
+ if (transport_type == DNS_TRANSPORT_UDP) {
+ TRY0(xmlTextWriterWriteString(writer,
+ ISC_XMLCHAR "UDP"));
+ } else if (transport_type == DNS_TRANSPORT_TCP) {
TRY0(xmlTextWriterWriteString(writer,
ISC_XMLCHAR "TCP"));
- } else if (dns_transport_get_type(transport) ==
- DNS_TRANSPORT_TLS)
- {
+ } else if (transport_type == DNS_TRANSPORT_TLS) {
+ TRY0(xmlTextWriterWriteString(writer,
+ ISC_XMLCHAR "TLS"));
+ } else if (transport_type == DNS_TRANSPORT_NONE) {
+ TRY0(xmlTextWriterWriteString(writer,
+ ISC_XMLCHAR "None"));
+ } else {
+ /* We don't expect any other SOA transport type. */
+ TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "-"));
+ }
+ } else {
+ TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "-"));
+ }
+ TRY0(xmlTextWriterEndElement(writer));
+
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "transport"));
+ if (is_running) {
+ transport_type = dns_xfrin_gettransporttype(xfr);
+ if (transport_type == DNS_TRANSPORT_TCP) {
+ TRY0(xmlTextWriterWriteString(writer,
+ ISC_XMLCHAR "TCP"));
+ } else if (transport_type == DNS_TRANSPORT_TLS) {
TRY0(xmlTextWriterWriteString(writer,
ISC_XMLCHAR "TLS"));
} else {
+ /* We don't expect any other transport type. */
TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "-"));
}
} else {
@@ -2477,7 +2498,7 @@ xfrin_jsonrender(dns_zone_t *zone, void *arg) {
json_object *xfrinobj = NULL;
const isc_sockaddr_t *addrp = NULL;
char addr_buf[ISC_SOCKADDR_FORMATSIZE];
- const dns_transport_t *transport = NULL;
+ dns_transport_type_t transport_type;
dns_zonestat_level_t statlevel;
dns_xfrin_t *xfr = NULL;
bool is_running, is_deferred, is_pending;
@@ -2582,18 +2603,39 @@ xfrin_jsonrender(dns_zone_t *zone, void *arg) {
}
if (is_running) {
- transport = dns_xfrin_gettransport(xfr);
- if (transport == NULL ||
- dns_transport_get_type(transport) == DNS_TRANSPORT_TCP)
- {
+ transport_type = dns_xfrin_getsoatransporttype(xfr);
+ if (transport_type == DNS_TRANSPORT_UDP) {
+ json_object_object_add(xfrinobj, "soatransport",
+ json_object_new_string("UDP"));
+ } else if (transport_type == DNS_TRANSPORT_TCP) {
+ json_object_object_add(xfrinobj, "soatransport",
+ json_object_new_string("TCP"));
+ } else if (transport_type == DNS_TRANSPORT_TLS) {
+ json_object_object_add(xfrinobj, "soatransport",
+ json_object_new_string("TLS"));
+ } else if (transport_type == DNS_TRANSPORT_NONE) {
+ json_object_object_add(xfrinobj, "soatransport",
+ json_object_new_string("None"));
+ } else {
+ /* We don't expect any other SOA transport type. */
+ json_object_object_add(xfrinobj, "soatransport",
+ json_object_new_string("-"));
+ }
+ } else {
+ json_object_object_add(xfrinobj, "soatransport",
+ json_object_new_string("-"));
+ }
+
+ if (is_running) {
+ transport_type = dns_xfrin_gettransporttype(xfr);
+ if (transport_type == DNS_TRANSPORT_TCP) {
json_object_object_add(xfrinobj, "transport",
json_object_new_string("TCP"));
- } else if (dns_transport_get_type(transport) ==
- DNS_TRANSPORT_TLS)
- {
+ } else if (transport_type == DNS_TRANSPORT_TLS) {
json_object_object_add(xfrinobj, "transport",
json_object_new_string("TLS"));
} else {
+ /* We don't expect any other transport type. */
json_object_object_add(xfrinobj, "transport",
json_object_new_string("-"));
}
diff --git a/doc/arm/reference.rst b/doc/arm/reference.rst
index 332c189bb6..29467716fa 100644
--- a/doc/arm/reference.rst
+++ b/doc/arm/reference.rst
@@ -7639,6 +7639,10 @@ Incoming Zone Transfers
This shows the destination address used to establish the
connection for the transfer.
+ ``SOA Transport`` (``soatransport``)
+ Text string. This is the transport protocol in use for the
+ SOA request. Possible values are: ``UDP``, ``TCP``, ``TLS``, ``None``.
+
``Transport`` (``transport``)
Text string. This is the transport protocol in use for the
transfer. Possible values are: ``TCP``, ``TLS``.
diff --git a/lib/dns/include/dns/xfrin.h b/lib/dns/include/dns/xfrin.h
index 3d10bb42fe..7fa72f42ed 100644
--- a/lib/dns/include/dns/xfrin.h
+++ b/lib/dns/include/dns/xfrin.h
@@ -56,6 +56,7 @@ isc_result_t
dns_xfrin_create(dns_zone_t *zone, dns_rdatatype_t xfrtype,
const isc_sockaddr_t *primaryaddr,
const isc_sockaddr_t *sourceaddr, dns_tsigkey_t *tsigkey,
+ dns_transport_type_t soa_transport_type,
dns_transport_t *transport, isc_tlsctx_cache_t *tlsctx_cache,
isc_mem_t *mctx, dns_xfrindone_t done, dns_xfrin_t **xfrp);
/*%<
@@ -81,6 +82,13 @@ dns_xfrin_create(dns_zone_t *zone, dns_rdatatype_t xfrtype,
*
*\li If 'xfrtype' is dns_rdatatype_ixfr or dns_rdatatype_soa,
* the zone has a database.
+ *
+ *\li 'soa_transport_type' is DNS_TRANSPORT_NONE if 'xfrtype'
+ * is dns_rdatatype_soa (because in that case the SOA request
+ * will use the same transport as the XFR), or when there is no
+ * preceding SOA request. Otherwise, it should indicate the
+ * transport type used for the SOA request performed by the
+ * caller itself.
*/
isc_time_t
@@ -160,10 +168,23 @@ dns_xfrin_getprimaryaddr(const dns_xfrin_t *xfr);
*\li const pointer to the zone transfer's primary server's socket address
*/
-const dns_transport_t *
-dns_xfrin_gettransport(const dns_xfrin_t *xfr);
+dns_transport_type_t
+dns_xfrin_gettransporttype(const dns_xfrin_t *xfr);
/*%<
- * Get the trnasport of the xfrin object.
+ * Get the zone transfer's trnasport type of the xfrin object.
+ *
+ * Requires:
+ *\li 'xfr' is a valid dns_xfrin_t.
+ *
+ * Returns:
+ *\li const pointer to the zone transfer's transport
+ *
+ */
+
+dns_transport_type_t
+dns_xfrin_getsoatransporttype(const dns_xfrin_t *xfr);
+/*%<
+ * Get the SOA request's trnasport type of the xfrin object.
*
* Requires:
*\li 'xfr' is a valid dns_xfrin_t.
diff --git a/lib/dns/xfrin.c b/lib/dns/xfrin.c
index c830533a27..7dd634eb12 100644
--- a/lib/dns/xfrin.c
+++ b/lib/dns/xfrin.c
@@ -164,6 +164,7 @@ struct dns_xfrin {
dst_context_t *tsigctx; /*%< TSIG verification context */
unsigned int sincetsig; /*%< recvd since the last TSIG */
+ dns_transport_type_t soa_transport_type;
dns_transport_t *transport;
dns_xfrindone_t done;
@@ -206,6 +207,7 @@ xfrin_create(isc_mem_t *mctx, dns_zone_t *zone, dns_db_t *db,
dns_name_t *zonename, dns_rdataclass_t rdclass,
dns_rdatatype_t reqtype, const isc_sockaddr_t *primaryaddr,
const isc_sockaddr_t *sourceaddr, dns_tsigkey_t *tsigkey,
+ dns_transport_type_t soa_transport_type,
dns_transport_t *transport, isc_tlsctx_cache_t *tlsctx_cache,
dns_xfrin_t **xfrp);
@@ -700,6 +702,7 @@ isc_result_t
dns_xfrin_create(dns_zone_t *zone, dns_rdatatype_t xfrtype,
const isc_sockaddr_t *primaryaddr,
const isc_sockaddr_t *sourceaddr, dns_tsigkey_t *tsigkey,
+ dns_transport_type_t soa_transport_type,
dns_transport_t *transport, isc_tlsctx_cache_t *tlsctx_cache,
isc_mem_t *mctx, dns_xfrindone_t done, dns_xfrin_t **xfrp) {
dns_name_t *zonename = dns_zone_getorigin(zone);
@@ -721,8 +724,8 @@ dns_xfrin_create(dns_zone_t *zone, dns_rdatatype_t xfrtype,
}
xfrin_create(mctx, zone, db, zonename, dns_zone_getclass(zone), xfrtype,
- primaryaddr, sourceaddr, tsigkey, transport, tlsctx_cache,
- &xfr);
+ primaryaddr, sourceaddr, tsigkey, soa_transport_type,
+ transport, tlsctx_cache, &xfr);
if (db != NULL) {
xfr->zone_had_db = true;
@@ -854,11 +857,22 @@ dns_xfrin_getprimaryaddr(const dns_xfrin_t *xfr) {
return (&xfr->primaryaddr);
}
-const dns_transport_t *
-dns_xfrin_gettransport(const dns_xfrin_t *xfr) {
+dns_transport_type_t
+dns_xfrin_gettransporttype(const dns_xfrin_t *xfr) {
REQUIRE(VALID_XFRIN(xfr));
- return (xfr->transport);
+ if (xfr->transport != NULL) {
+ return (dns_transport_get_type(xfr->transport));
+ }
+
+ return (DNS_TRANSPORT_TCP);
+}
+
+dns_transport_type_t
+dns_xfrin_getsoatransporttype(const dns_xfrin_t *xfr) {
+ REQUIRE(VALID_XFRIN(xfr));
+
+ return (xfr->soa_transport_type);
}
const dns_name_t *
@@ -965,6 +979,7 @@ xfrin_create(isc_mem_t *mctx, dns_zone_t *zone, dns_db_t *db,
dns_name_t *zonename, dns_rdataclass_t rdclass,
dns_rdatatype_t reqtype, const isc_sockaddr_t *primaryaddr,
const isc_sockaddr_t *sourceaddr, dns_tsigkey_t *tsigkey,
+ dns_transport_type_t soa_transport_type,
dns_transport_t *transport, isc_tlsctx_cache_t *tlsctx_cache,
dns_xfrin_t **xfrp) {
dns_xfrin_t *xfr = NULL;
@@ -977,6 +992,7 @@ xfrin_create(isc_mem_t *mctx, dns_zone_t *zone, dns_db_t *db,
.maxrecords = dns_zone_getmaxrecords(zone),
.primaryaddr = *primaryaddr,
.sourceaddr = *sourceaddr,
+ .soa_transport_type = soa_transport_type,
.firstsoa = DNS_RDATA_INIT,
.edns = true,
.magic = XFRIN_MAGIC,
@@ -1082,6 +1098,23 @@ xfrin_start(dns_xfrin_t *xfr) {
LIBDNS_XFRIN_START(xfr, xfr->info);
+ /*
+ * If the transfer is started when the 'state' is XFRST_SOAQUERY, it
+ * means the SOA query will be performed by xfrin. A transfer could also
+ * be initiated starting from the XFRST_INITIALSOA state, which means
+ * that the SOA query was already performed by other means (e.g. by
+ * zone.c:soa_query()), or that it's a transfer without a preceding
+ * SOA request, and 'soa_transport_type' is already correctly
+ * set by the creator of the xfrin.
+ */
+ if (atomic_load(&xfr->state) == XFRST_SOAQUERY) {
+ /*
+ * The "SOA before" mode is used, where the SOA request is
+ * using the same transport as the XFR.
+ */
+ xfr->soa_transport_type = dns_xfrin_gettransporttype(xfr);
+ }
+
/* Set the maximum timer */
isc_interval_set(&interval, dns_zone_getmaxxfrin(xfr->zone), 0);
isc_timer_start(xfr->max_time_timer, isc_timertype_once, &interval);
diff --git a/lib/dns/zone.c b/lib/dns/zone.c
index 8e9c4ca5d6..1847f4ee99 100644
--- a/lib/dns/zone.c
+++ b/lib/dns/zone.c
@@ -17616,6 +17616,7 @@ got_transfer_quota(void *arg) {
isc_sockaddr_t primaryaddr;
isc_sockaddr_t sourceaddr;
isc_time_t now;
+ dns_transport_type_t soa_transport_type = DNS_TRANSPORT_NONE;
const char *soa_before = "";
bool loaded;
isc_tlsctx_cache_t *zmgr_tlsctx_cache = NULL;
@@ -17742,11 +17743,33 @@ got_transfer_quota(void *arg) {
"zone transfer: %s",
isc_result_totext(result));
}
+
+ if (result == ISC_R_SUCCESS && xfrtype != dns_rdatatype_soa) {
+ soa_transport_type = DNS_TRANSPORT_TLS;
+ }
}
LOCK_ZONE(zone);
+ if (soa_transport_type == DNS_TRANSPORT_NONE &&
+ xfrtype != dns_rdatatype_soa)
+ {
+ soa_transport_type = (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC))
+ ? DNS_TRANSPORT_TCP
+ : DNS_TRANSPORT_UDP;
+
+ /* Check if the peer is forced to always use TCP. */
+ if (soa_transport_type != DNS_TRANSPORT_TCP && peer != NULL) {
+ bool usetcp;
+ result = dns_peer_getforcetcp(peer, &usetcp);
+ if (result == ISC_R_SUCCESS && usetcp) {
+ soa_transport_type = DNS_TRANSPORT_TCP;
+ }
+ }
+ }
+
sourceaddr = zone->sourceaddr;
UNLOCK_ZONE(zone);
+
INSIST(isc_sockaddr_pf(&primaryaddr) == isc_sockaddr_pf(&sourceaddr));
if (zone->xfr != NULL) {
@@ -17756,9 +17779,9 @@ got_transfer_quota(void *arg) {
zmgr_tlsctx_attach(zone->zmgr, &zmgr_tlsctx_cache);
result = dns_xfrin_create(zone, xfrtype, &primaryaddr, &sourceaddr,
- zone->tsigkey, zone->transport,
- zmgr_tlsctx_cache, zone->mctx, zone_xfrdone,
- &zone->xfr);
+ zone->tsigkey, soa_transport_type,
+ zone->transport, zmgr_tlsctx_cache,
+ zone->mctx, zone_xfrdone, &zone->xfr);
isc_tlsctx_cache_detach(&zmgr_tlsctx_cache);