]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Expose the SOA query transport type used before/during XFR
authorAram Sargsyan <aram@isc.org>
Wed, 23 Aug 2023 10:46:44 +0000 (10:46 +0000)
committerAram Sargsyan <aram@isc.org>
Fri, 22 Sep 2023 09:56:33 +0000 (09:56 +0000)
Add a new field in the incoming zone transfers section of the
statistics channel to show the transport used for the SOA request.

When the transfer is started beginning from the XFRST_SOAQUERY state,
it means that the SOA query will be performed by xfrin itself, using
the same transport. Otherwise, it means that the SOA query was already
performed by other means (e.g. by zone.c:soa_query()), and, in that
case, we use the SOA query transport type information passed by the
'soa_transport_type' argument, when the xfrin object was created.

bin/named/bind9.xsl
bin/named/statschannel.c
doc/arm/reference.rst
lib/dns/include/dns/xfrin.h
lib/dns/xfrin.c
lib/dns/zone.c

index badb3a1e9a6ddcdbd463b97bbfd6075f9203d496..2c5f2eb1e06214fc402563c99a3d01d621a4069f 100644 (file)
                   <th>Additional Refresh Queued</th>
                   <th>Local Address</th>
                   <th>Remote Address</th>
+                  <th>SOA Transport</th>
                   <th>Transport</th>
                   <th>TSIG Key Name</th>
                   <th>Duration (s)</th>
                     <td><xsl:value-of select="refreshqueued"/></td>
                     <td><xsl:value-of select="localaddr"/></td>
                     <td><xsl:value-of select="remoteaddr"/></td>
+                    <td><xsl:value-of select="soatransport"/></td>
                     <td><xsl:value-of select="transport"/></td>
                     <td><xsl:value-of select="tsigkeyname"/></td>
                     <td><xsl:value-of select="duration"/></td>
index 191006ede0e3a241a8c83bf5855f75228ec513cd..36fbe9cde81cff04edabd05346c89001fd00b9c3 100644 (file)
@@ -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 "soatransport"));
+       if (is_running) {
+               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 (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 = dns_xfrin_gettransport(xfr);
-               if (transport == NULL ||
-                   dns_transport_get_type(transport) == DNS_TRANSPORT_TCP)
-               {
+               transport_type = dns_xfrin_gettransporttype(xfr);
+               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 {
+                       /* 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("-"));
                }
index 332c189bb67abe703165d38a68ba092e688b5108..29467716faddcb9543eead47dbabb46eacb3b2e3 100644 (file)
@@ -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``.
index 3d10bb42fe1fd879d80bd8b44cea85384bb1b311..7fa72f42ed6fe5aa5c3dd21b33848d3afcd3758f 100644 (file)
@@ -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 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 trnasport of the xfrin object.
+ * Get the SOA request's trnasport type of the xfrin object.
  *
  * Requires:
  *\li  'xfr' is a valid dns_xfrin_t.
index c830533a27dae08eb5d21ff01c8e3e2a885d79ce..7dd634eb12ff52f379f9a4abe56dc13ef799a3df 100644 (file)
@@ -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);
index 8e9c4ca5d664b0d14679f74d60c124eb852edaee..1847f4ee990f316667856b4fc1614d9c908bae8a 100644 (file)
@@ -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);