]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Enable extraction of exact local socket addresses
authorMichał Kępień <michal@isc.org>
Sun, 29 Dec 2024 11:32:05 +0000 (12:32 +0100)
committerMichał Kępień <michal@isc.org>
Sun, 29 Dec 2024 11:32:05 +0000 (12:32 +0100)
Extracting the exact address that each wildcard/TCP socket is bound to
locally requires issuing the getsockname() system call, which libuv
exposes via its uv_*_getsockname() functions.  This is only required for
detailed logging and comes at a noticeable performance cost, so it
should not happen by default.  However, it is useful for debugging
certain problems (e.g. cryptic system test failures), so a convenient
way of enabling that behavior should exist.

Update isc_nmhandle_localaddr() so that it calls uv_*_getsockname() when
the ISC_SOCKET_DETAILS preprocessor macro is set at compile time.
Ensure proper handling of sockets that wrap other sockets.

Set the new ISC_SOCKET_DETAILS macro by default when --enable-developer
is passed to ./configure.  This enables detailed logging in the system
tests run in GitLab CI without affecting performance in non-development
BIND 9 builds.

Note that setting the ISC_SOCKET_DETAILS preprocessor macro at compile
time enables all callers of isc_nmhandle_localaddr() to extract the
exact address of a given local socket, which results e.g. in dnstap
captures containing more accurate information.

Mention the new preprocessor macro in the section of the ARM that
discusses why exact socket addresses may not be logged by default.

configure.ac
doc/arm/reference.rst
lib/dns/dispatch.c
lib/isc/netmgr/netmgr.c

index 53f67d50f8733b83d2091307a036ec8c35ebf82d..71f14127eeb044b5fbb1563c381134d876b5d25b 100644 (file)
@@ -178,7 +178,7 @@ AC_ARG_ENABLE([developer],
 
 AS_IF([test "$enable_developer" = "yes"],
       [DEVELOPER_MODE=yes
-       STD_CPPFLAGS="$STD_CPPFLAGS -DISC_MEM_DEFAULTFILL=1 -DISC_MEM_TRACKLINES=1 -DISC_LIST_CHECKINIT=1 -DISC_STATS_CHECKUNDERFLOW=1 -DISC_MUTEX_ERROR_CHECK=1"
+       STD_CPPFLAGS="$STD_CPPFLAGS -DISC_MEM_DEFAULTFILL=1 -DISC_MEM_TRACKLINES=1 -DISC_LIST_CHECKINIT=1 -DISC_STATS_CHECKUNDERFLOW=1 -DISC_MUTEX_ERROR_CHECK=1 -DISC_SOCKET_DETAILS=1"
        test "${enable_querytrace+set}" = set || enable_querytrace=yes
        test "${with_cmocka+set}" = set || with_cmocka=yes
        test "${with_zlib+set}" = set || with_zlib=yes
index 66b3ffc30d260510a20d36d2bf97a2f7e0a847f1..4f83936ba84ce424744fb3297a2779c91c9f37f1 100644 (file)
@@ -1214,7 +1214,11 @@ default is used.
       :ref:`query source address <query_address>` is explicitly set,
       these sockets are bound to wildcard IP addresses and determining
       the specific IP address used by each of them requires issuing a
-      system call (i.e. incurring a performance penalty).
+      system call (i.e. incurring a performance penalty). If the highest
+      possible logging accuracy is required, BIND 9 can be built with
+      ``-DISC_SOCKET_DETAILS=1`` added to ``CFLAGS`` at compile-time;
+      this enables exact socket addresses to be logged, although at the
+      cost of lowering the server's performance.
 
    Logged :any:`dnstap` messages can be parsed using the :iscman:`dnstap-read`
    utility (see :ref:`man_dnstap-read` for details).
index 6e71c5c6455996c6ac2a7d47590452397bc94c7c..6c9227fd844b02a37232c2eb50b278c5868f21d2 100644 (file)
@@ -2200,7 +2200,7 @@ dns_dispentry_getlocaladdress(dns_dispentry_t *resp, isc_sockaddr_t *addrp) {
 
        switch (disp->socktype) {
        case isc_socktype_tcp:
-               *addrp = disp->local;
+               *addrp = isc_nmhandle_localaddr(disp->handle);
                return ISC_R_SUCCESS;
        case isc_socktype_udp:
                *addrp = isc_nmhandle_localaddr(resp->handle);
index c8e67fafda90c7e47583855e52fed54be7468d8f..b88f2d9fb7047d6acd0ad689c039ed64b48c19eb 100644 (file)
@@ -1539,9 +1539,45 @@ isc_nmhandle_peeraddr(isc_nmhandle_t *handle) {
 
 isc_sockaddr_t
 isc_nmhandle_localaddr(isc_nmhandle_t *handle) {
+       isc_sockaddr_t addr;
+
        REQUIRE(VALID_NMHANDLE(handle));
 
-       return handle->local;
+       addr = handle->local;
+
+#ifdef ISC_SOCKET_DETAILS
+       switch (handle->sock->type) {
+       case isc_nm_tcpsocket:
+               uv_tcp_getsockname(&handle->sock->uv_handle.tcp,
+                                  (struct sockaddr *)&addr.type,
+                                  &(int){ sizeof(addr.type) });
+               break;
+
+       case isc_nm_udpsocket:
+               uv_udp_getsockname(&handle->sock->uv_handle.udp,
+                                  (struct sockaddr *)&addr.type,
+                                  &(int){ sizeof(addr.type) });
+               break;
+
+       case isc_nm_tlssocket:
+       case isc_nm_httpsocket:
+       case isc_nm_streamdnssocket:
+               if (handle->sock->outerhandle) {
+                       addr = isc_nmhandle_localaddr(
+                               handle->sock->outerhandle);
+               }
+               break;
+
+       case isc_nm_proxystreamsocket:
+       case isc_nm_proxyudpsocket:
+               break;
+
+       default:
+               UNREACHABLE();
+       }
+#endif /* ISC_SOCKET_DETAILS */
+
+       return addr;
 }
 
 isc_nm_t *