Blame SOURCES/squid-4.11-convert-ipv4.patch

5871b5
From 771908d313ee9c255adfb5e4fdba4d6797c18409 Mon Sep 17 00:00:00 2001
5871b5
From: Amos Jeffries <yadij@users.noreply.github.com>
5871b5
Date: Thu, 7 Mar 2019 13:50:38 +0000
5871b5
Subject: [PATCH] Bug 4928: Cannot convert non-IPv4 to IPv4 (#379)
5871b5
5871b5
... when reaching client_ip_max_connections
5871b5
5871b5
The client_ip_max_connections limit is checked before the TCP dst-IP is located for the newly received TCP connection. This leaves Squid unable to fetch the NFMARK or similar
5871b5
details later on (they do not exist for [::]).
5871b5
5871b5
Move client_ip_max_connections test later in the TCP accept process to ensure dst-IP is known when the error is produced.
5871b5
---
5871b5
 src/comm/TcpAcceptor.cc | 82 ++++++++++++++++++++---------------------
5871b5
 1 file changed, 39 insertions(+), 43 deletions(-)
5871b5
5871b5
diff --git a/src/comm/TcpAcceptor.cc b/src/comm/TcpAcceptor.cc
5871b5
index cae92a7b1e..2109913008 100644
5871b5
--- a/src/comm/TcpAcceptor.cc
5871b5
+++ b/src/comm/TcpAcceptor.cc
5871b5
@@ -282,16 +282,7 @@ Comm::TcpAcceptor::acceptOne()
5871b5
     ConnectionPointer newConnDetails = new Connection();
5871b5
     const Comm::Flag flag = oldAccept(newConnDetails);
5871b5
 
5871b5
-    /* Check for errors */
5871b5
-    if (!newConnDetails->isOpen()) {
5871b5
-
5871b5
-        if (flag == Comm::NOMESSAGE) {
5871b5
-            /* register interest again */
5871b5
-            debugs(5, 5, HERE << "try later: " << conn << " handler Subscription: " << theCallSub);
5871b5
-            SetSelect(conn->fd, COMM_SELECT_READ, doAccept, this, 0);
5871b5
-            return;
5871b5
-        }
5871b5
-
5871b5
+    if (flag == Comm::COMM_ERROR) {
5871b5
         // A non-recoverable error; notify the caller */
5871b5
         debugs(5, 5, HERE << "non-recoverable error:" << status() << " handler Subscription: " << theCallSub);
5871b5
         if (intendedForUserConnections())
5871b5
@@ -301,12 +292,16 @@ Comm::TcpAcceptor::acceptOne()
5871b5
         return;
5871b5
     }
5871b5
 
5871b5
-    newConnDetails->nfmark = Ip::Qos::getNfmarkFromConnection(newConnDetails, Ip::Qos::dirAccepted);
5871b5
+    if (flag == Comm::NOMESSAGE) {
5871b5
+        /* register interest again */
5871b5
+        debugs(5, 5, "try later: " << conn << " handler Subscription: " << theCallSub);
5871b5
+    } else {
5871b5
+        debugs(5, 5, "Listener: " << conn <<
5871b5
+               " accepted new connection " << newConnDetails <<
5871b5
+               " handler Subscription: " << theCallSub);
5871b5
+        notify(flag, newConnDetails);
5871b5
+    }
5871b5
 
5871b5
-    debugs(5, 5, HERE << "Listener: " << conn <<
5871b5
-           " accepted new connection " << newConnDetails <<
5871b5
-           " handler Subscription: " << theCallSub);
5871b5
-    notify(flag, newConnDetails);
5871b5
     SetSelect(conn->fd, COMM_SELECT_READ, doAccept, this, 0);
5871b5
 }
5871b5
 
5871b5
@@ -346,8 +341,8 @@ Comm::TcpAcceptor::notify(const Comm::Flag flag, const Comm::ConnectionPointer &
5871b5
  *
5871b5
  * \retval Comm::OK          success. details parameter filled.
5871b5
  * \retval Comm::NOMESSAGE   attempted accept() but nothing useful came in.
5871b5
- * \retval Comm::COMM_ERROR  an outright failure occurred.
5871b5
  *                           Or this client has too many connections already.
5871b5
+ * \retval Comm::COMM_ERROR  an outright failure occurred.
5871b5
  */
5871b5
 Comm::Flag
5871b5
 Comm::TcpAcceptor::oldAccept(Comm::ConnectionPointer &details)
5871b5
@@ -382,15 +377,6 @@ Comm::TcpAcceptor::oldAccept(Comm::ConnectionPointer &details)
5871b5
     details->fd = sock;
5871b5
     details->remote = *gai;
5871b5
 
5871b5
-    if ( Config.client_ip_max_connections >= 0) {
5871b5
-        if (clientdbEstablished(details->remote, 0) > Config.client_ip_max_connections) {
5871b5
-            debugs(50, DBG_IMPORTANT, "WARNING: " << details->remote << " attempting more than " << Config.client_ip_max_connections << " connections.");
5871b5
-            Ip::Address::FreeAddr(gai);
5871b5
-            PROF_stop(comm_accept);
5871b5
-            return Comm::COMM_ERROR;
5871b5
-        }
5871b5
-    }
5871b5
-
5871b5
     // lookup the local-end details of this new connection
5871b5
     Ip::Address::InitAddr(gai);
5871b5
     details->local.setEmpty();
5871b5
@@ -404,6 +390,34 @@ Comm::TcpAcceptor::oldAccept(Comm::ConnectionPointer &details)
5871b5
     details->local = *gai;
5871b5
     Ip::Address::FreeAddr(gai);
5871b5
 
5871b5
+    // Perform NAT or TPROXY operations to retrieve the real client/dest IP addresses
5871b5
+    if (conn->flags&(COMM_TRANSPARENT|COMM_INTERCEPTION) && !Ip::Interceptor.Lookup(details, conn)) {
5871b5
+        debugs(50, DBG_IMPORTANT, "ERROR: NAT/TPROXY lookup failed to locate original IPs on " << details);
5871b5
+        // Failed.
5871b5
+        PROF_stop(comm_accept);
5871b5
+        return Comm::COMM_ERROR;
5871b5
+    }
5871b5
+
5871b5
+#if USE_SQUID_EUI
5871b5
+    if (Eui::TheConfig.euiLookup) {
5871b5
+        if (details->remote.isIPv4()) {
5871b5
+            details->remoteEui48.lookup(details->remote);
5871b5
+        } else if (details->remote.isIPv6()) {
5871b5
+            details->remoteEui64.lookup(details->remote);
5871b5
+        }
5871b5
+    }
5871b5
+#endif
5871b5
+
5871b5
+    details->nfmark = Ip::Qos::getNfmarkFromConnection(details, Ip::Qos::dirAccepted);
5871b5
+
5871b5
+    if (Config.client_ip_max_connections >= 0) {
5871b5
+        if (clientdbEstablished(details->remote, 0) > Config.client_ip_max_connections) {
5871b5
+            debugs(50, DBG_IMPORTANT, "WARNING: " << details->remote << " attempting more than " << Config.client_ip_max_connections << " connections.");
5871b5
+            PROF_stop(comm_accept);
5871b5
+            return Comm::NOMESSAGE;
5871b5
+        }
5871b5
+    }
5871b5
+
5871b5
     /* fdstat update */
5871b5
     // XXX : these are not all HTTP requests. use a note about type and ip:port details->
5871b5
     // so we end up with a uniform "(HTTP|FTP-data|HTTPS|...) remote-ip:remote-port"
5871b5
@@ -425,24 +439,6 @@ Comm::TcpAcceptor::oldAccept(Comm::ConnectionPointer &details)
5871b5
     /* IFF the socket is (tproxy) transparent, pass the flag down to allow spoofing */
5871b5
     F->flags.transparent = fd_table[conn->fd].flags.transparent; // XXX: can we remove this line yet?
5871b5
 
5871b5
-    // Perform NAT or TPROXY operations to retrieve the real client/dest IP addresses
5871b5
-    if (conn->flags&(COMM_TRANSPARENT|COMM_INTERCEPTION) && !Ip::Interceptor.Lookup(details, conn)) {
5871b5
-        debugs(50, DBG_IMPORTANT, "ERROR: NAT/TPROXY lookup failed to locate original IPs on " << details);
5871b5
-        // Failed.
5871b5
-        PROF_stop(comm_accept);
5871b5
-        return Comm::COMM_ERROR;
5871b5
-    }
5871b5
-
5871b5
-#if USE_SQUID_EUI
5871b5
-    if (Eui::TheConfig.euiLookup) {
5871b5
-        if (details->remote.isIPv4()) {
5871b5
-            details->remoteEui48.lookup(details->remote);
5871b5
-        } else if (details->remote.isIPv6()) {
5871b5
-            details->remoteEui64.lookup(details->remote);
5871b5
-        }
5871b5
-    }
5871b5
-#endif
5871b5
-
5871b5
     PROF_stop(comm_accept);
5871b5
     return Comm::OK;
5871b5
 }