]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: Use the correct source IP for outgoing QUIC datagrams
authorRemi Gacogne <remi.gacogne@powerdns.com>
Fri, 19 Apr 2024 13:58:25 +0000 (15:58 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Fri, 19 Apr 2024 14:41:31 +0000 (16:41 +0200)
And expose the correct destination IP to Lua.

pdns/dnsdistdist/dnsdist.cc
pdns/dnsdistdist/doh3.cc
pdns/dnsdistdist/doq-common.cc
pdns/dnsdistdist/doq-common.hh
pdns/dnsdistdist/doq.cc
pdns/iputils.cc
pdns/iputils.hh

index 4de6f6eae5cbb6465ef6032d531c7066b7aed5f5..2cc044f54c48d9d27f0452d09f164f902c1aba3c 100644 (file)
@@ -157,34 +157,14 @@ static constexpr size_t s_maxUDPResponsePacketSize{4096U};
 static size_t const s_initialUDPPacketBufferSize = s_maxUDPResponsePacketSize + DNSCRYPT_MAX_RESPONSE_PADDING_AND_MAC_SIZE;
 static_assert(s_initialUDPPacketBufferSize <= UINT16_MAX, "Packet size should fit in a uint16_t");
 
-static ssize_t sendfromto(int sock, const void* data, size_t len, int flags, const ComboAddress& from, const ComboAddress& dest)
+static ssize_t sendfromto(int sock, const PacketBuffer& buffer, const ComboAddress& from, const ComboAddress& dest)
 {
+  const int flags = 0;
   if (from.sin4.sin_family == 0) {
     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
-    return sendto(sock, data, len, flags, reinterpret_cast<const struct sockaddr*>(&dest), dest.getSocklen());
-  }
-  msghdr msgh{};
-  iovec iov{};
-  cmsgbuf_aligned cbuf;
-
-  /* Set up iov and msgh structures. */
-  memset(&msgh, 0, sizeof(struct msghdr));
-  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast): it's the API
-  iov.iov_base = const_cast<void*>(data);
-  iov.iov_len = len;
-  msgh.msg_iov = &iov;
-  msgh.msg_iovlen = 1;
-  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-pro-type-const-cast)
-  msgh.msg_name = const_cast<sockaddr*>(reinterpret_cast<const sockaddr*>(&dest));
-  msgh.msg_namelen = dest.getSocklen();
-
-  if (from.sin4.sin_family != 0) {
-    addCMsgSrcAddr(&msgh, &cbuf, &from, 0);
+    return sendto(sock, buffer.data(), buffer.size(), flags, reinterpret_cast<const struct sockaddr*>(&dest), dest.getSocklen());
   }
-  else {
-    msgh.msg_control = nullptr;
-  }
-  return sendmsg(sock, &msgh, flags);
+  return sendMsgWithOptions(sock, buffer.data(), buffer.size(), &dest, &from, 0, 0);
 }
 
 static void truncateTC(PacketBuffer& packet, size_t maximumSize, unsigned int qnameWireLength)
@@ -225,7 +205,7 @@ struct DelayedPacket
   ComboAddress origDest;
   void operator()()
   {
-    ssize_t res = sendfromto(fd, packet.data(), packet.size(), 0, origDest, destination);
+    ssize_t res = sendfromto(fd, packet, origDest, destination);
     if (res == -1) {
       int err = errno;
       vinfolog("Error sending delayed response to %s: %s", destination.toStringWithPort(), stringerror(err));
@@ -666,8 +646,7 @@ bool sendUDPResponse(int origFD, const PacketBuffer& response, const int delayMs
     return true;
   }
 #endif /* DISABLE_DELAY_PIPE */
-  // NOLINTNEXTLINE(readability-suspicious-call-argument)
-  ssize_t res = sendfromto(origFD, response.data(), response.size(), 0, origDest, origRemote);
+  ssize_t res = sendfromto(origFD, response, origDest, origRemote);
   if (res == -1) {
     int err = errno;
     vinfolog("Error sending response to %s: %s", origRemote.toStringWithPort(), stringerror(err));
index 26b3cf5686ae25faef783713f82105fccbf96169..7ff4748f1551521e65daa445cbec8d17d0b9932a 100644 (file)
@@ -54,8 +54,8 @@ using h3_headers_t = std::map<std::string, std::string>;
 class H3Connection
 {
 public:
-  H3Connection(const ComboAddress& peer, QuicheConfig config, QuicheConnection&& conn) :
-    d_peer(peer), d_conn(std::move(conn)), d_config(std::move(config))
+  H3Connection(const ComboAddress& peer, const ComboAddress& localAddr, QuicheConfig config, QuicheConnection&& conn) :
+    d_peer(peer), d_localAddr(localAddr), d_conn(std::move(conn)), d_config(std::move(config))
   {
   }
   H3Connection(const H3Connection&) = delete;
@@ -65,6 +65,7 @@ public:
   ~H3Connection() = default;
 
   ComboAddress d_peer;
+  ComboAddress d_localAddr;
   QuicheConnection d_conn;
   QuicheConfig d_config;
   QuicheHTTP3Connection d_http3{nullptr, quiche_h3_conn_free};
@@ -421,14 +422,14 @@ static void sendBackDOH3Unit(DOH3UnitUniquePtr&& unit, const char* description)
   }
 }
 
-static std::optional<std::reference_wrapper<H3Connection>> createConnection(DOH3ServerConfig& config, const PacketBuffer& serverSideID, const PacketBuffer& originalDestinationID, const ComboAddress& local, const ComboAddress& peer)
+static std::optional<std::reference_wrapper<H3Connection>> createConnection(DOH3ServerConfig& config, const PacketBuffer& serverSideID, const PacketBuffer& originalDestinationID, const ComboAddress& localAddr, const ComboAddress& peer)
 {
   auto quicheConfig = std::atomic_load_explicit(&config.config, std::memory_order_acquire);
   auto quicheConn = QuicheConnection(quiche_accept(serverSideID.data(), serverSideID.size(),
                                                    originalDestinationID.data(), originalDestinationID.size(),
                                                    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
-                                                   reinterpret_cast<const struct sockaddr*>(&local),
-                                                   local.getSocklen(),
+                                                   reinterpret_cast<const struct sockaddr*>(&localAddr),
+                                                   localAddr.getSocklen(),
                                                    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
                                                    reinterpret_cast<const struct sockaddr*>(&peer),
                                                    peer.getSocklen(),
@@ -439,7 +440,7 @@ static std::optional<std::reference_wrapper<H3Connection>> createConnection(DOH3
     quiche_conn_set_keylog_path(quicheConn.get(), config.df->d_quicheParams.d_keyLogFile.c_str());
   }
 
-  auto conn = H3Connection(peer, std::move(quicheConfig), std::move(quicheConn));
+  auto conn = H3Connection(peer, localAddr, std::move(quicheConfig), std::move(quicheConn));
   auto pair = config.d_connections.emplace(serverSideID, std::move(conn));
   return pair.first->second;
 }
@@ -743,7 +744,7 @@ static void processH3HeaderEvent(ClientState& clientState, DOH3Frontend& fronten
       return;
     }
     DEBUGLOG("Dispatching GET query");
-    doh3_dispatch_query(*(frontend.d_server_config), std::move(*payload), clientState.local, client, serverConnID, streamID);
+    doh3_dispatch_query(*(frontend.d_server_config), std::move(*payload), conn.d_localAddr, client, serverConnID, streamID);
     conn.d_streamBuffers.erase(streamID);
     conn.d_headersBuffers.erase(streamID);
     return;
@@ -808,7 +809,7 @@ static void processH3DataEvent(ClientState& clientState, DOH3Frontend& frontend,
   }
 
   DEBUGLOG("Dispatching POST query");
-  doh3_dispatch_query(*(frontend.d_server_config), std::move(streamBuffer), clientState.local, client, serverConnID, streamID);
+  doh3_dispatch_query(*(frontend.d_server_config), std::move(streamBuffer), conn.d_localAddr, client, serverConnID, streamID);
   conn.d_headersBuffers.erase(streamID);
   conn.d_streamBuffers.erase(streamID);
 }
@@ -856,10 +857,21 @@ static void handleSocketReadable(DOH3Frontend& frontend, ClientState& clientStat
   PacketBuffer tokenBuf;
   while (true) {
     ComboAddress client;
+    ComboAddress localAddr;
+    client.sin4.sin_family = clientState.local.sin4.sin_family;
+    localAddr.sin4.sin_family = clientState.local.sin4.sin_family;
     buffer.resize(4096);
-    if (!sock.recvFromAsync(buffer, client) || buffer.empty()) {
+    if (!dnsdist::doq::recvAsync(sock, buffer, client, localAddr)) {
       return;
     }
+    if (localAddr.sin4.sin_family == 0) {
+      localAddr = clientState.local;
+    }
+    else {
+      /* we don't get the port, only the address */
+      localAddr.sin4.sin_port = clientState.local.sin4.sin_port;
+    }
+
     DEBUGLOG("Received DoH3 datagram of size " << buffer.size() << " from " << client.toStringWithPort());
 
     uint32_t version{0};
@@ -896,14 +908,14 @@ static void handleSocketReadable(DOH3Frontend& frontend, ClientState& clientStat
       if (!quiche_version_is_supported(version)) {
         DEBUGLOG("Unsupported version");
         ++frontend.d_doh3UnsupportedVersionErrors;
-        handleVersionNegociation(sock, clientConnID, serverConnID, client, buffer);
+        handleVersionNegociation(sock, clientConnID, serverConnID, client, localAddr, buffer);
         continue;
       }
 
       if (token_len == 0) {
         /* stateless retry */
         DEBUGLOG("No token received");
-        handleStatelessRetry(sock, clientConnID, serverConnID, client, version, buffer);
+        handleStatelessRetry(sock, clientConnID, serverConnID, client, localAddr, version, buffer);
         continue;
       }
 
@@ -916,7 +928,7 @@ static void handleSocketReadable(DOH3Frontend& frontend, ClientState& clientStat
       }
 
       DEBUGLOG("Creating a new connection");
-      conn = createConnection(*frontend.d_server_config, serverConnID, *originalDestinationID, clientState.local, client);
+      conn = createConnection(*frontend.d_server_config, serverConnID, *originalDestinationID, localAddr, client);
       if (!conn) {
         continue;
       }
@@ -927,8 +939,8 @@ static void handleSocketReadable(DOH3Frontend& frontend, ClientState& clientStat
       reinterpret_cast<struct sockaddr*>(&client),
       client.getSocklen(),
       // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
-      reinterpret_cast<struct sockaddr*>(&clientState.local),
-      clientState.local.getSocklen(),
+      reinterpret_cast<struct sockaddr*>(&localAddr),
+      localAddr.getSocklen(),
     };
 
     auto done = quiche_conn_recv(conn->get().d_conn.get(), buffer.data(), buffer.size(), &recv_info);
@@ -950,7 +962,7 @@ static void handleSocketReadable(DOH3Frontend& frontend, ClientState& clientStat
 
       processH3Events(clientState, frontend, conn->get(), client, serverConnID, buffer);
 
-      flushEgress(sock, conn->get().d_conn, client, buffer);
+      flushEgress(sock, conn->get().d_conn, client, localAddr, buffer);
     }
     else {
       DEBUGLOG("Connection not established");
@@ -995,7 +1007,7 @@ void doh3Thread(ClientState* clientState)
         for (auto conn = frontend->d_server_config->d_connections.begin(); conn != frontend->d_server_config->d_connections.end();) {
           quiche_conn_on_timeout(conn->second.d_conn.get());
 
-          flushEgress(sock, conn->second.d_conn, conn->second.d_peer, buffer);
+          flushEgress(sock, conn->second.d_conn, conn->second.d_peer, conn->second.d_localAddr, buffer);
 
           if (quiche_conn_is_closed(conn->second.d_conn.get())) {
 #ifdef DEBUGLOG_ENABLED
index e92ccffdea4ee61354f8fa5b565e6f5113c39799..f8ac8d871b2aed5879194780e66be2de6a07b87f 100644 (file)
@@ -126,7 +126,18 @@ std::optional<PacketBuffer> validateToken(const PacketBuffer& token, const Combo
   }
 }
 
-void handleStatelessRetry(Socket& sock, const PacketBuffer& clientConnID, const PacketBuffer& serverConnID, const ComboAddress& peer, uint32_t version, PacketBuffer& buffer)
+static ssize_t sendFromTo(Socket& sock, const ComboAddress& peer, const ComboAddress& local, PacketBuffer& buffer)
+{
+  const int flags = 0;
+  if (local.sin4.sin_family == 0) {
+    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
+    return sendto(sock.getHandle(), buffer.data(), buffer.size(), flags, reinterpret_cast<const struct sockaddr*>(&peer), peer.getSocklen());
+  }
+
+  return sendMsgWithOptions(sock.getHandle(), buffer.data(), buffer.size(), &peer, &local, 0, 0);
+}
+
+void handleStatelessRetry(Socket& sock, const PacketBuffer& clientConnID, const PacketBuffer& serverConnID, const ComboAddress& peer, const ComboAddress& localAddr, uint32_t version, PacketBuffer& buffer)
 {
   auto newServerConnID = getCID();
   if (!newServerConnID) {
@@ -148,11 +159,11 @@ void handleStatelessRetry(Socket& sock, const PacketBuffer& clientConnID, const
     return;
   }
 
-  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
-  sock.sendTo(reinterpret_cast<const char*>(buffer.data()), static_cast<size_t>(written), peer);
+  buffer.resize(static_cast<size_t>(written));
+  sendFromTo(sock, peer, localAddr, buffer);
 }
 
-void handleVersionNegociation(Socket& sock, const PacketBuffer& clientConnID, const PacketBuffer& serverConnID, const ComboAddress& peer, PacketBuffer& buffer)
+void handleVersionNegociation(Socket& sock, const PacketBuffer& clientConnID, const PacketBuffer& serverConnID, const ComboAddress& peer, const ComboAddress& localAddr, PacketBuffer& buffer)
 {
   buffer.resize(MAX_DATAGRAM_SIZE);
 
@@ -164,11 +175,12 @@ void handleVersionNegociation(Socket& sock, const PacketBuffer& clientConnID, co
     DEBUGLOG("failed to create vneg packet " << written);
     return;
   }
-  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
-  sock.sendTo(reinterpret_cast<const char*>(buffer.data()), static_cast<size_t>(written), peer);
+
+  buffer.resize(static_cast<size_t>(written));
+  sendFromTo(sock, peer, localAddr, buffer);
 }
 
-void flushEgress(Socket& sock, QuicheConnection& conn, const ComboAddress& peer, PacketBuffer& buffer)
+void flushEgress(Socket& sock, QuicheConnection& conn, const ComboAddress& peer, const ComboAddress& localAddr, PacketBuffer& buffer)
 {
   buffer.resize(MAX_DATAGRAM_SIZE);
   quiche_send_info send_info;
@@ -183,8 +195,8 @@ void flushEgress(Socket& sock, QuicheConnection& conn, const ComboAddress& peer,
       return;
     }
     // FIXME pacing (as send_info.at should tell us when to send the packet) ?
-    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
-    sock.sendTo(reinterpret_cast<const char*>(buffer.data()), static_cast<size_t>(written), peer);
+    buffer.resize(static_cast<size_t>(written));
+    sendFromTo(sock, peer, localAddr, buffer);
   }
 }
 
@@ -258,6 +270,51 @@ void configureQuiche(QuicheConfig& config, const QuicheParams& params, bool isHT
   }
 }
 
+bool recvAsync(Socket& socket, PacketBuffer& buffer, ComboAddress& clientAddr, ComboAddress& localAddr)
+{
+  msghdr msgh{};
+  iovec iov{};
+  /* used by HarvestDestinationAddress */
+  cmsgbuf_aligned cbuf;
+  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
+  fillMSGHdr(&msgh, &iov, &cbuf, sizeof(cbuf), reinterpret_cast<char*>(&buffer.at(0)), buffer.size(), &clientAddr);
+
+  ssize_t got = recvmsg(socket.getHandle(), &msgh, 0);
+  if (got < 0) {
+    int error = errno;
+    if (error != EAGAIN) {
+      throw NetworkError("Error in recvmsg: " + stringerror(error));
+    }
+    return false;
+  }
+
+  if ((msgh.msg_flags & MSG_TRUNC) != 0) {
+    return false;
+  }
+
+  buffer.resize(static_cast<size_t>(got));
+
+  if (HarvestDestinationAddress(&msgh, &localAddr)) {
+    /* so it turns out that sometimes the kernel lies to us:
+       the address is set to 0.0.0.0:0 which makes our sendfromto() use
+       the wrong address. In that case it's better to let the kernel
+       do the work by itself and use sendto() instead.
+       This is indicated by setting the family to 0 which is acted upon
+       in sendUDPResponse() and DelayedPacket::().
+    */
+    const ComboAddress bogusV4("0.0.0.0:0");
+    const ComboAddress bogusV6("[::]:0");
+    if ((localAddr.sin4.sin_family == AF_INET && localAddr == bogusV4) || (localAddr.sin4.sin_family == AF_INET6 && localAddr == bogusV6)) {
+      localAddr.sin4.sin_family = 0;
+    }
+  }
+  else {
+    localAddr.sin4.sin_family = 0;
+  }
+
+  return !buffer.empty();
+}
+
 };
 
 #endif
index d2222c68338262470185dcca8ddfbb261212dbbe..9b04e4c83581460e5842aadaa32720e257cb4751 100644 (file)
@@ -92,10 +92,11 @@ void fillRandom(PacketBuffer& buffer, size_t size);
 std::optional<PacketBuffer> getCID();
 PacketBuffer mintToken(const PacketBuffer& dcid, const ComboAddress& peer);
 std::optional<PacketBuffer> validateToken(const PacketBuffer& token, const ComboAddress& peer);
-void handleStatelessRetry(Socket& sock, const PacketBuffer& clientConnID, const PacketBuffer& serverConnID, const ComboAddress& peer, uint32_t version, PacketBuffer& buffer);
-void handleVersionNegociation(Socket& sock, const PacketBuffer& clientConnID, const PacketBuffer& serverConnID, const ComboAddress& peer, PacketBuffer& buffer);
-void flushEgress(Socket& sock, QuicheConnection& conn, const ComboAddress& peer, PacketBuffer& buffer);
+void handleStatelessRetry(Socket& sock, const PacketBuffer& clientConnID, const PacketBuffer& serverConnID, const ComboAddress& peer, const ComboAddress& localAddr, uint32_t version, PacketBuffer& buffer);
+void handleVersionNegociation(Socket& sock, const PacketBuffer& clientConnID, const PacketBuffer& serverConnID, const ComboAddress& peer, const ComboAddress& localAddr, PacketBuffer& buffer);
+void flushEgress(Socket& sock, QuicheConnection& conn, const ComboAddress& peer, const ComboAddress& localAddr, PacketBuffer& buffer);
 void configureQuiche(QuicheConfig& config, const QuicheParams& params, bool isHTTP);
+bool recvAsync(Socket& socket, PacketBuffer& buffer, ComboAddress& clientAddr, ComboAddress& localAddr);
 
 };
 
index b6a3da6cb7a05368dec80a8efb403dc6f89ddb0e..e757b1a96883474b5954e7315c32b54e2379459d 100644 (file)
@@ -51,8 +51,8 @@ using namespace dnsdist::doq;
 class Connection
 {
 public:
-  Connection(const ComboAddress& peer, QuicheConfig config, QuicheConnection conn) :
-    d_peer(peer), d_conn(std::move(conn)), d_config(std::move(config))
+  Connection(const ComboAddress& peer, const ComboAddress& localAddr, QuicheConfig config, QuicheConnection conn) :
+    d_peer(peer), d_localAddr(localAddr), d_conn(std::move(conn)), d_config(std::move(config))
   {
   }
   Connection(const Connection&) = delete;
@@ -62,6 +62,7 @@ public:
   ~Connection() = default;
 
   ComboAddress d_peer;
+  ComboAddress d_localAddr;
   QuicheConnection d_conn;
   QuicheConfig d_config;
 
@@ -338,14 +339,14 @@ static void sendBackDOQUnit(DOQUnitUniquePtr&& unit, const char* description)
   }
 }
 
-static std::optional<std::reference_wrapper<Connection>> createConnection(DOQServerConfig& config, const PacketBuffer& serverSideID, const PacketBuffer& originalDestinationID, const ComboAddress& local, const ComboAddress& peer)
+static std::optional<std::reference_wrapper<Connection>> createConnection(DOQServerConfig& config, const PacketBuffer& serverSideID, const PacketBuffer& originalDestinationID, const ComboAddress& peer, const ComboAddress& localAddr)
 {
   auto quicheConfig = std::atomic_load_explicit(&config.config, std::memory_order_acquire);
   auto quicheConn = QuicheConnection(quiche_accept(serverSideID.data(), serverSideID.size(),
                                                    originalDestinationID.data(), originalDestinationID.size(),
                                                    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
-                                                   reinterpret_cast<const struct sockaddr*>(&local),
-                                                   local.getSocklen(),
+                                                   reinterpret_cast<const struct sockaddr*>(&localAddr),
+                                                   localAddr.getSocklen(),
                                                    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
                                                    reinterpret_cast<const struct sockaddr*>(&peer),
                                                    peer.getSocklen(),
@@ -356,7 +357,7 @@ static std::optional<std::reference_wrapper<Connection>> createConnection(DOQSer
     quiche_conn_set_keylog_path(quicheConn.get(), config.df->d_quicheParams.d_keyLogFile.c_str());
   }
 
-  auto conn = Connection(peer, std::move(quicheConfig), std::move(quicheConn));
+  auto conn = Connection(peer, localAddr, std::move(quicheConfig), std::move(quicheConn));
   auto pair = config.d_connections.emplace(serverSideID, std::move(conn));
   return pair.first->second;
 }
@@ -641,7 +642,7 @@ static void handleReadableStream(DOQFrontend& frontend, ClientState& clientState
     return;
   }
   DEBUGLOG("Dispatching query");
-  doq_dispatch_query(*(frontend.d_server_config), std::move(streamBuffer), clientState.local, client, serverConnID, streamID);
+  doq_dispatch_query(*(frontend.d_server_config), std::move(streamBuffer), conn.d_localAddr, client, serverConnID, streamID);
   conn.d_streamBuffers.erase(streamID);
 }
 
@@ -654,10 +655,21 @@ static void handleSocketReadable(DOQFrontend& frontend, ClientState& clientState
   PacketBuffer tokenBuf;
   while (true) {
     ComboAddress client;
+    ComboAddress localAddr;
+    client.sin4.sin_family = clientState.local.sin4.sin_family;
+    localAddr.sin4.sin_family = clientState.local.sin4.sin_family;
     buffer.resize(4096);
-    if (!sock.recvFromAsync(buffer, client) || buffer.empty()) {
+    if (!dnsdist::doq::recvAsync(sock, buffer, client, localAddr)) {
       return;
     }
+    if (localAddr.sin4.sin_family == 0) {
+      localAddr = clientState.local;
+    }
+    else {
+      /* we don't get the port, only the address */
+      localAddr.sin4.sin_port = clientState.local.sin4.sin_port;
+    }
+
     DEBUGLOG("Received DoQ datagram of size " << buffer.size() << " from " << client.toStringWithPort());
 
     uint32_t version{0};
@@ -693,14 +705,14 @@ static void handleSocketReadable(DOQFrontend& frontend, ClientState& clientState
       if (!quiche_version_is_supported(version)) {
         DEBUGLOG("Unsupported version");
         ++frontend.d_doqUnsupportedVersionErrors;
-        handleVersionNegociation(sock, clientConnID, serverConnID, client, buffer);
+        handleVersionNegociation(sock, clientConnID, serverConnID, client, localAddr, buffer);
         continue;
       }
 
       if (token_len == 0) {
         /* stateless retry */
         DEBUGLOG("No token received");
-        handleStatelessRetry(sock, clientConnID, serverConnID, client, version, buffer);
+        handleStatelessRetry(sock, clientConnID, serverConnID, client, localAddr, version, buffer);
         continue;
       }
 
@@ -713,7 +725,7 @@ static void handleSocketReadable(DOQFrontend& frontend, ClientState& clientState
       }
 
       DEBUGLOG("Creating a new connection");
-      conn = createConnection(*frontend.d_server_config, serverConnID, *originalDestinationID, clientState.local, client);
+      conn = createConnection(*frontend.d_server_config, serverConnID, *originalDestinationID, client, localAddr);
       if (!conn) {
         continue;
       }
@@ -724,8 +736,8 @@ static void handleSocketReadable(DOQFrontend& frontend, ClientState& clientState
       reinterpret_cast<struct sockaddr*>(&client),
       client.getSocklen(),
       // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
-      reinterpret_cast<struct sockaddr*>(&clientState.local),
-      clientState.local.getSocklen(),
+      reinterpret_cast<struct sockaddr*>(&localAddr),
+      localAddr.getSocklen(),
     };
 
     auto done = quiche_conn_recv(conn->get().d_conn.get(), buffer.data(), buffer.size(), &recv_info);
@@ -741,7 +753,7 @@ static void handleSocketReadable(DOQFrontend& frontend, ClientState& clientState
         handleReadableStream(frontend, clientState, *conn, streamID, client, serverConnID);
       }
 
-      flushEgress(sock, conn->get().d_conn, client, buffer);
+      flushEgress(sock, conn->get().d_conn, client, localAddr, buffer);
     }
     else {
       DEBUGLOG("Connection not established");
@@ -786,7 +798,7 @@ void doqThread(ClientState* clientState)
         for (auto conn = frontend->d_server_config->d_connections.begin(); conn != frontend->d_server_config->d_connections.end();) {
           quiche_conn_on_timeout(conn->second.d_conn.get());
 
-          flushEgress(sock, conn->second.d_conn, conn->second.d_peer, buffer);
+          flushEgress(sock, conn->second.d_conn, conn->second.d_peer, conn->second.d_localAddr, buffer);
 
           if (quiche_conn_is_closed(conn->second.d_conn.get())) {
 #ifdef DEBUGLOG_ENABLED
index 4409997bded10dd85f8400e7aa7aaa320db8e60c..955b9392c642a116552e38f1a451634c163d32d0 100644 (file)
@@ -366,17 +366,18 @@ void ComboAddress::truncate(unsigned int bits) noexcept
   *place &= (~((1<<bitsleft)-1));
 }
 
-size_t sendMsgWithOptions(int fd, const char* buffer, size_t len, const ComboAddress* dest, const ComboAddress* local, unsigned int localItf, int flags)
+size_t sendMsgWithOptions(int fd, const void* buffer, size_t len, const ComboAddress* dest, const ComboAddress* local, unsigned int localItf, int flags)
 {
-  struct msghdr msgh;
-  struct iovec iov;
+  msghdr msgh{};
+  iovec iov{};
   cmsgbuf_aligned cbuf;
 
   /* Set up iov and msgh structures. */
-  memset(&msgh, 0, sizeof(struct msghdr));
+  memset(&msgh, 0, sizeof(msgh));
   msgh.msg_control = nullptr;
   msgh.msg_controllen = 0;
   if (dest) {
+    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-pro-type-const-cast): it's the API
     msgh.msg_name = reinterpret_cast<void*>(const_cast<ComboAddress*>(dest));
     msgh.msg_namelen = dest->getSocklen();
   }
@@ -387,11 +388,12 @@ size_t sendMsgWithOptions(int fd, const char* buffer, size_t len, const ComboAdd
 
   msgh.msg_flags = 0;
 
-  if (localItf != 0 && local) {
+  if (local && local->sin4.sin_family != 0) {
     addCMsgSrcAddr(&msgh, &cbuf, local, localItf);
   }
 
-  iov.iov_base = reinterpret_cast<void*>(const_cast<char*>(buffer));
+  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast): it's the API
+  iov.iov_base = const_cast<void*>(buffer);
   iov.iov_len = len;
   msgh.msg_iov = &iov;
   msgh.msg_iovlen = 1;
@@ -425,6 +427,7 @@ size_t sendMsgWithOptions(int fd, const char* buffer, size_t len, const ComboAdd
       firstTry = false;
  #endif
       iov.iov_len -= written;
+      // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast): it's the API
       iov.iov_base = reinterpret_cast<void*>(reinterpret_cast<char*>(iov.iov_base) + written);
     }
     else if (res == 0) {
@@ -441,7 +444,7 @@ size_t sendMsgWithOptions(int fd, const char* buffer, size_t len, const ComboAdd
         return sent;
       }
       else {
-        unixDie("failed in sendMsgWithTimeout");
+        unixDie("failed in sendMsgWithOptions");
       }
     }
   }
index e5943c8e7dcf07149b41460664927569c720ebae..8a3bd502a7370bea7b307249d433a1838ed45a78 100644 (file)
@@ -1736,7 +1736,7 @@ bool HarvestDestinationAddress(const struct msghdr* msgh, ComboAddress* destinat
 bool HarvestTimestamp(struct msghdr* msgh, struct timeval* tv);
 void fillMSGHdr(struct msghdr* msgh, struct iovec* iov, cmsgbuf_aligned* cbuf, size_t cbufsize, char* data, size_t datalen, ComboAddress* addr);
 int sendOnNBSocket(int fd, const struct msghdr *msgh);
-size_t sendMsgWithOptions(int fd, const char* buffer, size_t len, const ComboAddress* dest, const ComboAddress* local, unsigned int localItf, int flags);
+size_t sendMsgWithOptions(int fd, const void* buffer, size_t len, const ComboAddress* dest, const ComboAddress* local, unsigned int localItf, int flags);
 
 /* requires a non-blocking, connected TCP socket */
 bool isTCPSocketUsable(int sock);