diff options
Diffstat (limited to '')
-rwxr-xr-x | configure | 20 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | dnsdist-doh-common.cc | 4 | ||||
-rw-r--r-- | dnsdist-nghttp2-in.cc | 46 | ||||
-rw-r--r-- | dnsdist-nghttp2-in.hh | 4 | ||||
-rw-r--r-- | dnsdist-tcp-downstream.cc | 1 | ||||
-rw-r--r-- | dnsdist.1 | 2 | ||||
-rw-r--r-- | dnsdist.cc | 11 | ||||
-rw-r--r-- | xsk.cc | 24 |
9 files changed, 83 insertions, 31 deletions
@@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.71 for dnsdist 1.9.3. +# Generated by GNU Autoconf 2.71 for dnsdist 1.9.4. # # # Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation, @@ -618,8 +618,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='dnsdist' PACKAGE_TARNAME='dnsdist' -PACKAGE_VERSION='1.9.3' -PACKAGE_STRING='dnsdist 1.9.3' +PACKAGE_VERSION='1.9.4' +PACKAGE_STRING='dnsdist 1.9.4' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -1645,7 +1645,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures dnsdist 1.9.3 to adapt to many kinds of systems. +\`configure' configures dnsdist 1.9.4 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1716,7 +1716,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of dnsdist 1.9.3:";; + short | recursive ) echo "Configuration of dnsdist 1.9.4:";; esac cat <<\_ACEOF @@ -1951,7 +1951,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -dnsdist configure 1.9.3 +dnsdist configure 1.9.4 generated by GNU Autoconf 2.71 Copyright (C) 2021 Free Software Foundation, Inc. @@ -2440,7 +2440,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by dnsdist $as_me 1.9.3, which was +It was created by dnsdist $as_me 1.9.4, which was generated by GNU Autoconf 2.71. Invocation command line was $ $0$ac_configure_args_raw @@ -3932,7 +3932,7 @@ fi # Define the identity of the package. PACKAGE='dnsdist' - VERSION='1.9.3' + VERSION='1.9.4' printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h @@ -28149,7 +28149,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by dnsdist $as_me 1.9.3, which was +This file was extended by dnsdist $as_me 1.9.4, which was generated by GNU Autoconf 2.71. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -28217,7 +28217,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ -dnsdist config.status 1.9.3 +dnsdist config.status 1.9.4 configured by $0, generated by GNU Autoconf 2.71, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index 5502b83..a8bc16c 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ AC_PREREQ([2.69]) -AC_INIT([dnsdist], [1.9.3]) +AC_INIT([dnsdist], [1.9.4]) AM_INIT_AUTOMAKE([foreign tar-ustar dist-bzip2 no-dist-gzip parallel-tests 1.11 subdir-objects]) AM_SILENT_RULES([yes]) AC_CONFIG_MACRO_DIR([m4]) diff --git a/dnsdist-doh-common.cc b/dnsdist-doh-common.cc index 71cd87c..dcbd183 100644 --- a/dnsdist-doh-common.cc +++ b/dnsdist-doh-common.cc @@ -115,7 +115,9 @@ size_t DOHFrontend::getTicketsKeysCount() void DOHFrontend::reloadCertificates() { - d_tlsContext.setupTLS(); + if (isHTTPS()) { + d_tlsContext.setupTLS(); + } } void DOHFrontend::setup() diff --git a/dnsdist-nghttp2-in.cc b/dnsdist-nghttp2-in.cc index 32dc254..e40f5e6 100644 --- a/dnsdist-nghttp2-in.cc +++ b/dnsdist-nghttp2-in.cc @@ -222,8 +222,9 @@ void IncomingHTTP2Connection::handleResponse(const struct timeval& now, TCPRespo std::unique_ptr<DOHUnitInterface> IncomingHTTP2Connection::getDOHUnit(uint32_t streamID) { - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay): clang-tidy is getting confused by assert() - assert(streamID <= std::numeric_limits<IncomingHTTP2Connection::StreamID>::max()); + if (streamID > std::numeric_limits<IncomingHTTP2Connection::StreamID>::max()) { + throw std::runtime_error("Invalid stream ID while retrieving DoH unit"); + } // NOLINTNEXTLINE(*-narrowing-conversions): generic interface between DNS and DoH with different types auto query = std::move(d_currentStreams.at(static_cast<IncomingHTTP2Connection::StreamID>(streamID))); return std::make_unique<IncomingDoHCrossProtocolContext>(std::move(query), std::dynamic_pointer_cast<IncomingHTTP2Connection>(shared_from_this()), streamID); @@ -330,6 +331,27 @@ IOState IncomingHTTP2Connection::handleHandshake(const struct timeval& now) return iostate; } +class ReadFunctionGuard +{ +public: + ReadFunctionGuard(bool& inReadFunction) : + d_inReadFunctionRef(inReadFunction) + { + d_inReadFunctionRef = true; + } + ReadFunctionGuard(ReadFunctionGuard&&) = delete; + ReadFunctionGuard(const ReadFunctionGuard&) = delete; + ReadFunctionGuard& operator=(ReadFunctionGuard&&) = delete; + ReadFunctionGuard& operator=(const ReadFunctionGuard&) = delete; + ~ReadFunctionGuard() + { + d_inReadFunctionRef = false; + } + +private: + bool& d_inReadFunctionRef; +}; + void IncomingHTTP2Connection::handleIO() { IOState iostate = IOState::Done; @@ -392,10 +414,10 @@ void IncomingHTTP2Connection::handleIO() } } - if (active() && !d_connectionClosing && (d_state == State::waitingForQuery || d_state == State::idle)) { + if (!d_inReadFunction && active() && !d_connectionClosing && (d_state == State::waitingForQuery || d_state == State::idle)) { do { iostate = readHTTPData(); - } while (active() && !d_connectionClosing && iostate == IOState::Done); + } while (!d_inReadFunction && active() && !d_connectionClosing && iostate == IOState::Done); } if (!active()) { @@ -530,8 +552,9 @@ void NGHTTP2Headers::addDynamicHeader(std::vector<nghttp2_nv>& headers, NGHTTP2H IOState IncomingHTTP2Connection::sendResponse(const struct timeval& now, TCPResponse&& response) { - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay): clang-tidy is getting confused by assert() - assert(response.d_idstate.d_streamID != -1); + if (response.d_idstate.d_streamID == -1) { + throw std::runtime_error("Invalid DoH stream ID while sending response"); + } auto& context = d_currentStreams.at(response.d_idstate.d_streamID); uint32_t statusCode = 200U; @@ -562,8 +585,10 @@ void IncomingHTTP2Connection::notifyIOError(const struct timeval& now, TCPRespon return; } - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay): clang-tidy is getting confused by assert() - assert(response.d_idstate.d_streamID != -1); + if (response.d_idstate.d_streamID == -1) { + throw std::runtime_error("Invalid DoH stream ID while handling I/O error notification"); + } + auto& context = d_currentStreams.at(response.d_idstate.d_streamID); context.d_buffer = std::move(response.d_buffer); sendResponse(response.d_idstate.d_streamID, context, 502, d_ci.cs->dohFrontend->d_customResponseHeaders); @@ -1064,6 +1089,11 @@ int IncomingHTTP2Connection::on_error_callback(nghttp2_session* session, int lib IOState IncomingHTTP2Connection::readHTTPData() { + if (d_inReadFunction) { + return IOState::Done; + } + ReadFunctionGuard readGuard(d_inReadFunction); + IOState newState = IOState::Done; size_t got = 0; if (d_in.size() < s_initialReceiveBufferSize) { diff --git a/dnsdist-nghttp2-in.hh b/dnsdist-nghttp2-in.hh index a2e58a4..e630778 100644 --- a/dnsdist-nghttp2-in.hh +++ b/dnsdist-nghttp2-in.hh @@ -116,6 +116,10 @@ private: /* Whether we have data that we want to write to the socket, but the socket is full. */ bool d_pendingWrite{false}; + /* Whether we are currently inside the readHTTPData function, + which is not reentrant and could be called from itself via + the nghttp2 callbacks */ + bool d_inReadFunction{false}; }; class NGHTTP2Headers diff --git a/dnsdist-tcp-downstream.cc b/dnsdist-tcp-downstream.cc index 904913e..dd50c1b 100644 --- a/dnsdist-tcp-downstream.cc +++ b/dnsdist-tcp-downstream.cc @@ -678,6 +678,7 @@ IOState TCPConnectionToBackend::handleResponse(std::shared_ptr<TCPConnectionToBa /* we don't move the whole IDS because we will need for the responses to come */ response.d_idstate.qtype = it->second.d_query.d_idstate.qtype; response.d_idstate.qname = it->second.d_query.d_idstate.qname; + response.d_idstate.d_streamID = it->second.d_query.d_idstate.d_streamID; DEBUGLOG("passing XFRresponse to client connection for "<<response.d_idstate.qname); it->second.d_query.d_xfrStarted = true; @@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "DNSDIST" "1" "Apr 05, 2024" "" "dnsdist" +.TH "DNSDIST" "1" "May 13, 2024" "" "dnsdist" .SH NAME dnsdist \- A DNS and DoS aware, scriptable loadbalancer .SH SYNOPSIS @@ -1670,9 +1670,18 @@ ProcessQueryResult processQuery(DNSQuestion& dq, LocalHolders& holders, std::sha /* we need an accurate ("real") value for the response and to store into the IDS, but not for insertion into the rings for example */ - struct timespec now; + timespec now{}; gettime(&now); + if ((dq.ids.qtype == QType::AXFR || dq.ids.qtype == QType::IXFR) && (dq.getProtocol() == dnsdist::Protocol::DoH || dq.getProtocol() == dnsdist::Protocol::DoQ || dq.getProtocol() == dnsdist::Protocol::DoH3)) { + dq.editHeader([](dnsheader& header) { + header.rcode = RCode::NotImp; + header.qr = true; + return true; + }); + return processQueryAfterRules(dq, holders, selectedBackend); + } + if (!applyRulesToQuery(holders, dq, now)) { return ProcessQueryResult::Drop; } @@ -29,15 +29,6 @@ #include <cstring> #include <fcntl.h> #include <iterator> -#include <linux/bpf.h> -#include <linux/if_ether.h> -#include <linux/if_link.h> -#include <linux/if_xdp.h> -#include <linux/ip.h> -#include <linux/ipv6.h> -#include <linux/tcp.h> -#include <linux/types.h> -#include <linux/udp.h> #include <net/if.h> #include <net/if_arp.h> #include <netinet/in.h> @@ -61,6 +52,21 @@ extern "C" #include "gettime.hh" #include "xsk.hh" +/* we need to include the linux specific headers AFTER the regular + ones, because it then detects that some types have already been + defined (sockaddr_in6 for example) and does not attempt to + re-define them, which otherwise breaks the C++ One Definition Rule +*/ +#include <linux/bpf.h> +#include <linux/if_ether.h> +#include <linux/if_link.h> +#include <linux/if_xdp.h> +#include <linux/ip.h> +#include <linux/ipv6.h> +#include <linux/tcp.h> +#include <linux/types.h> +#include <linux/udp.h> + #ifdef DEBUG_UMEM namespace { |