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

5c1076
From 771908d313ee9c255adfb5e4fdba4d6797c18409 Mon Sep 17 00:00:00 2001
5c1076
From: Amos Jeffries <yadij@users.noreply.github.com>
5c1076
Date: Thu, 7 Mar 2019 13:50:38 +0000
5c1076
Subject: [PATCH] Bug 4928: Cannot convert non-IPv4 to IPv4 (#379)
5c1076
5c1076
... when reaching client_ip_max_connections
5c1076
5c1076
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
5c1076
details later on (they do not exist for [::]).
5c1076
5c1076
Move client_ip_max_connections test later in the TCP accept process to ensure dst-IP is known when the error is produced.
5c1076
---
5c1076
 src/comm/TcpAcceptor.cc | 82 ++++++++++++++++++++---------------------
5c1076
 1 file changed, 39 insertions(+), 43 deletions(-)
5c1076
5c1076
diff --git a/src/comm/TcpAcceptor.cc b/src/comm/TcpAcceptor.cc
9234f8
index d4b576d..936aa30 100644
5c1076
--- a/src/comm/TcpAcceptor.cc
5c1076
+++ b/src/comm/TcpAcceptor.cc
9234f8
@@ -282,7 +282,16 @@ Comm::TcpAcceptor::acceptOne()
5c1076
     ConnectionPointer newConnDetails = new Connection();
5c1076
     const Comm::Flag flag = oldAccept(newConnDetails);
5c1076
 
9234f8
-    if (flag == Comm::COMM_ERROR) {
9234f8
+    /* Check for errors */
9234f8
+    if (!newConnDetails->isOpen()) {
9234f8
+
9234f8
+        if (flag == Comm::NOMESSAGE) {
9234f8
+            /* register interest again */
9234f8
+            debugs(5, 5, HERE << "try later: " << conn << " handler Subscription: " << theCallSub);
9234f8
+            SetSelect(conn->fd, COMM_SELECT_READ, doAccept, this, 0);
9234f8
+            return;
9234f8
+        }
9234f8
+
5c1076
         // A non-recoverable error; notify the caller */
5c1076
         debugs(5, 5, HERE << "non-recoverable error:" << status() << " handler Subscription: " << theCallSub);
5c1076
         if (intendedForUserConnections())
9234f8
@@ -292,16 +301,12 @@ Comm::TcpAcceptor::acceptOne()
5c1076
         return;
5c1076
     }
5c1076
 
9234f8
-    if (flag == Comm::NOMESSAGE) {
9234f8
-        /* register interest again */
9234f8
-        debugs(5, 5, "try later: " << conn << " handler Subscription: " << theCallSub);
9234f8
-    } else {
9234f8
-        debugs(5, 5, "Listener: " << conn <<
9234f8
-               " accepted new connection " << newConnDetails <<
9234f8
-               " handler Subscription: " << theCallSub);
9234f8
-        notify(flag, newConnDetails);
9234f8
-    }
9234f8
+    newConnDetails->nfmark = Ip::Qos::getNfmarkFromConnection(newConnDetails, Ip::Qos::dirAccepted);
5c1076
 
9234f8
+    debugs(5, 5, HERE << "Listener: " << conn <<
9234f8
+           " accepted new connection " << newConnDetails <<
9234f8
+           " handler Subscription: " << theCallSub);
9234f8
+    notify(flag, newConnDetails);
5c1076
     SetSelect(conn->fd, COMM_SELECT_READ, doAccept, this, 0);
5c1076
 }
5c1076
 
9234f8
@@ -341,8 +346,8 @@ Comm::TcpAcceptor::notify(const Comm::Flag flag, const Comm::ConnectionPointer &
5c1076
  *
5c1076
  * \retval Comm::OK          success. details parameter filled.
5c1076
  * \retval Comm::NOMESSAGE   attempted accept() but nothing useful came in.
9234f8
- *                           Or this client has too many connections already.
9234f8
  * \retval Comm::COMM_ERROR  an outright failure occurred.
9234f8
+ *                           Or this client has too many connections already.
5c1076
  */
5c1076
 Comm::Flag
5c1076
 Comm::TcpAcceptor::oldAccept(Comm::ConnectionPointer &details)
9234f8
@@ -383,6 +388,15 @@ Comm::TcpAcceptor::oldAccept(Comm::ConnectionPointer &details)
9234f8
 
5c1076
     details->remote = *gai;
5c1076
 
9234f8
+    if ( Config.client_ip_max_connections >= 0) {
9234f8
+        if (clientdbEstablished(details->remote, 0) > Config.client_ip_max_connections) {
9234f8
+            debugs(50, DBG_IMPORTANT, "WARNING: " << details->remote << " attempting more than " << Config.client_ip_max_connections << " connections.");
9234f8
+            Ip::Address::FreeAddr(gai);
9234f8
+            PROF_stop(comm_accept);
9234f8
+            return Comm::COMM_ERROR;
9234f8
+        }
9234f8
+    }
9234f8
+
5c1076
     // lookup the local-end details of this new connection
5c1076
     Ip::Address::InitAddr(gai);
5c1076
     details->local.setEmpty();
9234f8
@@ -396,6 +410,23 @@ Comm::TcpAcceptor::oldAccept(Comm::ConnectionPointer &details)
5c1076
     details->local = *gai;
5c1076
     Ip::Address::FreeAddr(gai);
5c1076
 
9234f8
+    /* fdstat update */
9234f8
+    fdd_table[sock].close_file = NULL;
9234f8
+    fdd_table[sock].close_line = 0;
5c1076
+
9234f8
+    fde *F = &fd_table[sock];
9234f8
+    details->remote.toStr(F->ipaddr,MAX_IPSTRLEN);
9234f8
+    F->remote_port = details->remote.port();
9234f8
+    F->local_addr = details->local;
9234f8
+    F->sock_family = details->local.isIPv6()?AF_INET6:AF_INET;
5c1076
+
9234f8
+    // set socket flags
9234f8
+    commSetCloseOnExec(sock);
9234f8
+    commSetNonBlocking(sock);
5c1076
+
9234f8
+    /* IFF the socket is (tproxy) transparent, pass the flag down to allow spoofing */
9234f8
+    F->flags.transparent = fd_table[conn->fd].flags.transparent; // XXX: can we remove this line yet?
5c1076
+
9234f8
     // Perform NAT or TPROXY operations to retrieve the real client/dest IP addresses
9234f8
     if (conn->flags&(COMM_TRANSPARENT|COMM_INTERCEPTION) && !Ip::Interceptor.Lookup(details, conn)) {
9234f8
         debugs(50, DBG_IMPORTANT, "ERROR: NAT/TPROXY lookup failed to locate original IPs on " << details);
9234f8
@@ -414,33 +445,6 @@ Comm::TcpAcceptor::oldAccept(Comm::ConnectionPointer &details)
9234f8
     }
9234f8
 #endif
5c1076
 
9234f8
-    details->nfmark = Ip::Qos::getNfmarkFromConnection(details, Ip::Qos::dirAccepted);
5c1076
-
9234f8
-    if (Config.client_ip_max_connections >= 0) {
9234f8
-        if (clientdbEstablished(details->remote, 0) > Config.client_ip_max_connections) {
9234f8
-            debugs(50, DBG_IMPORTANT, "WARNING: " << details->remote << " attempting more than " << Config.client_ip_max_connections << " connections.");
9234f8
-            PROF_stop(comm_accept);
9234f8
-            return Comm::NOMESSAGE;
5c1076
-        }
5c1076
-    }
9234f8
-
9234f8
-    /* fdstat update */
9234f8
-    fdd_table[sock].close_file = NULL;
9234f8
-    fdd_table[sock].close_line = 0;
9234f8
-
9234f8
-    fde *F = &fd_table[sock];
9234f8
-    details->remote.toStr(F->ipaddr,MAX_IPSTRLEN);
9234f8
-    F->remote_port = details->remote.port();
9234f8
-    F->local_addr = details->local;
9234f8
-    F->sock_family = details->local.isIPv6()?AF_INET6:AF_INET;
9234f8
-
9234f8
-    // set socket flags
9234f8
-    commSetCloseOnExec(sock);
9234f8
-    commSetNonBlocking(sock);
9234f8
-
9234f8
-    /* IFF the socket is (tproxy) transparent, pass the flag down to allow spoofing */
9234f8
-    F->flags.transparent = fd_table[conn->fd].flags.transparent; // XXX: can we remove this line yet?
5c1076
-
5c1076
     PROF_stop(comm_accept);
5c1076
     return Comm::OK;
5c1076
 }