From 87c453850c716fb8ac283b10668aa95a9cef421e Mon Sep 17 00:00:00 2001 From: Aram Sargsyan Date: Fri, 20 Dec 2024 08:41:03 +0000 Subject: [PATCH] Fix rtt calculation bug for TCP in the resolver When TCP is used, 'fctx_query()' adds one second to the rtt (round-trip time) value, but there's a bug when the decision about using TCP is made already after the calculation. Move the block of the code which looks up the peers list to decide whether to use TCP into a place that's before the rtt calculation is performed. This commit doesn't add or remove any code, it just moves the code and adds a comment block. --- lib/dns/resolver.c | 115 +++++++++++++++++++++++---------------------- 1 file changed, 60 insertions(+), 55 deletions(-) diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 746fe6d947..2aa4ca381a 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -1911,6 +1911,66 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, } } + /* + * Maybe apply DNS64 mappings to IPv4 addresses. + */ + sockaddr = addrinfo->sockaddr; + dns64 = ISC_LIST_HEAD(fctx->res->view->dns64); + if (isc_sockaddr_pf(&sockaddr) == AF_INET && + fctx->res->view->usedns64 && dns64 != NULL) + { + struct in6_addr aaaa; + + result = dns_dns64_aaaafroma( + dns64, NULL, NULL, fctx->res->view->aclenv, 0, + (unsigned char *)&sockaddr.type.sin.sin_addr.s_addr, + aaaa.s6_addr); + if (result == ISC_R_SUCCESS) { + char sockaddrbuf1[ISC_SOCKADDR_FORMATSIZE]; + char sockaddrbuf2[ISC_SOCKADDR_FORMATSIZE]; + + /* format old address */ + isc_sockaddr_format(&sockaddr, sockaddrbuf1, + sizeof(sockaddrbuf1)); + + /* replace address */ + isc_sockaddr_fromin6(&sockaddr, &aaaa, + ntohs(sockaddr.type.sin.sin_port)); + addrinfo->sockaddr = sockaddr; + + /* format new address */ + isc_sockaddr_format(&sockaddr, sockaddrbuf2, + sizeof(sockaddrbuf2)); + isc_log_write(DNS_LOGCATEGORY_RESOLVER, + DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3), + "Using DNS64 address %s to talk to %s\n", + sockaddrbuf2, sockaddrbuf1); + } + } + + /* + * Check if the address is in the peers list and has a special + * confguration. + */ + if (res->view->peers != NULL) { + dns_peer_t *peer = NULL; + isc_netaddr_t dstip; + bool usetcp = false; + isc_netaddr_fromsockaddr(&dstip, &sockaddr); + result = dns_peerlist_peerbyaddr(res->view->peers, &dstip, + &peer); + if (result == ISC_R_SUCCESS) { + result = dns_peer_getquerysource(peer, &addr); + if (result == ISC_R_SUCCESS) { + have_addr = true; + } + result = dns_peer_getforcetcp(peer, &usetcp); + if (result == ISC_R_SUCCESS && usetcp) { + options |= DNS_FETCHOPT_TCP; + } + } + } + /* * Allow an additional second for the kernel to resend the SYN * (or SYN without ECN in the case of stupid firewalls blocking @@ -1960,61 +2020,6 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, DNS_MESSAGE_INTENTPARSE, &query->rmessage); query->start = isc_time_now(); - /* - * Maybe apply DNS64 mappings to IPv4 addresses. - */ - sockaddr = addrinfo->sockaddr; - dns64 = ISC_LIST_HEAD(fctx->res->view->dns64); - if (isc_sockaddr_pf(&sockaddr) == AF_INET && - fctx->res->view->usedns64 && dns64 != NULL) - { - struct in6_addr aaaa; - - result = dns_dns64_aaaafroma( - dns64, NULL, NULL, fctx->res->view->aclenv, 0, - (unsigned char *)&sockaddr.type.sin.sin_addr.s_addr, - aaaa.s6_addr); - if (result == ISC_R_SUCCESS) { - char sockaddrbuf1[ISC_SOCKADDR_FORMATSIZE]; - char sockaddrbuf2[ISC_SOCKADDR_FORMATSIZE]; - - /* format old address */ - isc_sockaddr_format(&sockaddr, sockaddrbuf1, - sizeof(sockaddrbuf1)); - - /* replace address */ - isc_sockaddr_fromin6(&sockaddr, &aaaa, - ntohs(sockaddr.type.sin.sin_port)); - addrinfo->sockaddr = sockaddr; - - /* format new address */ - isc_sockaddr_format(&sockaddr, sockaddrbuf2, - sizeof(sockaddrbuf2)); - isc_log_write(DNS_LOGCATEGORY_RESOLVER, - DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3), - "Using DNS64 address %s to talk to %s\n", - sockaddrbuf2, sockaddrbuf1); - } - } - if (res->view->peers != NULL) { - dns_peer_t *peer = NULL; - isc_netaddr_t dstip; - bool usetcp = false; - isc_netaddr_fromsockaddr(&dstip, &sockaddr); - result = dns_peerlist_peerbyaddr(res->view->peers, &dstip, - &peer); - if (result == ISC_R_SUCCESS) { - result = dns_peer_getquerysource(peer, &addr); - if (result == ISC_R_SUCCESS) { - have_addr = true; - } - result = dns_peer_getforcetcp(peer, &usetcp); - if (result == ISC_R_SUCCESS && usetcp) { - query->options |= DNS_FETCHOPT_TCP; - } - } - } - /* * If this is a TCP query, then we need to make a socket and * a dispatch for it here. Otherwise we use the resolver's