]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Support ICP and HTCP _servers_ sharing listening sockets.
authorAlex Rousskov <rousskov@measurement-factory.com>
Mon, 14 Jun 2010 21:22:01 +0000 (15:22 -0600)
committerAlex Rousskov <rousskov@measurement-factory.com>
Mon, 14 Jun 2010 21:22:01 +0000 (15:22 -0600)
Without a shared cache, the servers will report many false misses.

ICP and HTCP _clients_ cannot be supported in SMP environment unless each
process has its own address (i.e., unique IP address and/or unique [ICP] port)
because we cannot match outgoing queries and incoming responses across
processes. If ICP/HTCP support in SMP is needed, the easiest change would
be to use random source ports for sending ICP/HTCP queries. This may also
improve security by avoiding well-known source ports for UDP queries.

src/htcp.cc
src/icp_v2.cc
src/ipc/FdNotes.cc
src/ipc/FdNotes.h

index b3c269d91519fe40636b75c687990de0dc0dda0a..ab76d6678d61d1093fab165be3d1713fe556a35a 100644 (file)
 #include "http.h"
 #include "icmp/net_db.h"
 #include "AccessLogEntry.h"
+#include "ipc/StartListening.h"
+
+/// dials htcpIncomingConnectionOpened call
+class HtcpListeningStartedDialer: public CallDialer,
+    public Ipc::StartListeningCb
+{
+public:
+    typedef void (*Handler)(int fd, int errNo);
+    HtcpListeningStartedDialer(Handler aHandler): handler(aHandler) {}
+
+    virtual void print(std::ostream &os) const { startPrint(os) << ')'; }
+
+    virtual bool canDial(AsyncCall &) const { return true; }
+    virtual void dial(AsyncCall &) { (handler)(fd, errNo); }
+
+public:
+    Handler handler;
+};
 
 typedef struct _Countstr Countstr;
 
@@ -225,6 +243,8 @@ enum {
     RR_RESPONSE
 };
 
+static void htcpIncomingConnectionOpened(int fd, int errNo);
+
 static u_int32_t msg_id_counter = 0;
 static int htcpInSocket = -1;
 static int htcpOutSocket = -1;
@@ -1483,20 +1503,15 @@ htcpInit(void)
     IpAddress incomingAddr = Config.Addrs.udp_incoming;
     incomingAddr.SetPort(Config.Port.htcp);
 
-    enter_suid();
-    htcpInSocket = comm_open_listener(SOCK_DGRAM,
+    AsyncCall::Pointer call = asyncCall(31, 2,
+        "htcpIncomingConnectionOpened",
+        HtcpListeningStartedDialer(&htcpIncomingConnectionOpened));
+
+    Ipc::StartListening(SOCK_DGRAM,
                                       IPPROTO_UDP,
                                       incomingAddr,
                                       COMM_NONBLOCKING,
-                                      "HTCP Socket");
-    leave_suid();
-
-    if (htcpInSocket < 0)
-        fatal("Cannot open HTCP Socket");
-
-    commSetSelect(htcpInSocket, COMM_SELECT_READ, htcpRecv, NULL, 0);
-
-    debugs(31, 1, "Accepting HTCP messages on port " << Config.Port.htcp << ", FD " << htcpInSocket << ".");
+                                      Ipc::fdnInHtcpSocket, call);
 
     if (!Config.Addrs.udp_outgoing.IsNoAddr()) {
         IpAddress outgoingAddr = Config.Addrs.udp_outgoing;
@@ -1518,8 +1533,6 @@ htcpInit(void)
         debugs(31, 1, "Outgoing HTCP messages on port " << Config.Port.htcp << ", FD " << htcpOutSocket << ".");
 
         fd_note(htcpInSocket, "Incoming HTCP socket");
-    } else {
-        htcpOutSocket = htcpInSocket;
     }
 
     if (!htcpDetailPool) {
@@ -1527,6 +1540,22 @@ htcpInit(void)
     }
 }
 
+static void
+htcpIncomingConnectionOpened(int fd, int errNo)
+{
+    htcpInSocket = fd;
+
+    if (htcpInSocket < 0)
+        fatal("Cannot open HTCP Socket");
+
+    commSetSelect(htcpInSocket, COMM_SELECT_READ, htcpRecv, NULL, 0);
+
+    debugs(31, 1, "Accepting HTCP messages on port " << Config.Port.htcp << ", FD " << htcpInSocket << ".");
+
+    if (Config.Addrs.udp_outgoing.IsNoAddr())
+        htcpOutSocket = htcpInSocket;
+}
+
 int
 htcpQuery(StoreEntry * e, HttpRequest * req, peer * p)
 {
index cbfed7a3597e09aefb9cecd58949e6d3a5f2d2cd..fbd600b20e30512b58f00253303c3b311c2f7ea4 100644 (file)
 #include "SwapDir.h"
 #include "icmp/net_db.h"
 #include "ip/IpAddress.h"
+#include "ipc/StartListening.h"
 #include "rfc1738.h"
 
+/// dials icpIncomingConnectionOpened call
+class IcpListeningStartedDialer: public CallDialer,
+    public Ipc::StartListeningCb
+{
+public:
+    typedef void (*Handler)(int fd, int errNo, IpAddress& addr);
+    IcpListeningStartedDialer(Handler aHandler, IpAddress& anAddr):
+        handler(aHandler), addr(anAddr) {}
+
+    virtual void print(std::ostream &os) const { startPrint(os) <<
+        ", address=" << addr << ')'; }
+
+    virtual bool canDial(AsyncCall &) const { return true; }
+    virtual void dial(AsyncCall &) { (handler)(fd, errNo, addr); }
+
+public:
+    Handler handler;
+    IpAddress addr;
+};
+
+static void icpIncomingConnectionOpened(int fd, int errNo, IpAddress& addr);
+
 /// \ingroup ServerProtocolICPInternal2
 static void icpLogIcp(const IpAddress &, log_type, int, const char *, int);
 
@@ -656,35 +679,22 @@ icpConnectionsOpen(void)
 
     struct addrinfo *xai = NULL;
     int x;
-    wordlist *s;
 
     if ((port = Config.Port.icp) <= 0)
         return;
 
-    enter_suid();
-
     addr = Config.Addrs.udp_incoming;
     addr.SetPort(port);
-    theInIcpConnection = comm_open_listener(SOCK_DGRAM,
+
+    AsyncCall::Pointer call = asyncCall(12, 2,
+        "icpIncomingConnectionOpened",
+        IcpListeningStartedDialer(&icpIncomingConnectionOpened, addr));
+
+    Ipc::StartListening(SOCK_DGRAM,
                                             IPPROTO_UDP,
                                             addr,
                                             COMM_NONBLOCKING,
-                                            "ICP Socket");
-    leave_suid();
-
-    if (theInIcpConnection < 0)
-        fatal("Cannot open ICP Port");
-
-    commSetSelect(theInIcpConnection,
-                  COMM_SELECT_READ,
-                  icpHandleUdp,
-                  NULL,
-                  0);
-
-    for (s = Config.mcast_group_list; s; s = s->next)
-        ipcache_nbgethostbyname(s->key, mcastJoinGroups, NULL);
-
-    debugs(12, 1, "Accepting ICP messages at " << addr << ", FD " << theInIcpConnection << ".");
+                                            Ipc::fdnInIcpSocket, call);
 
     addr.SetEmpty(); // clear for next use.
     addr = Config.Addrs.udp_outgoing;
@@ -710,10 +720,6 @@ icpConnectionsOpen(void)
         debugs(12, 1, "Outgoing ICP messages on port " << addr.GetPort() << ", FD " << theOutIcpConnection << ".");
 
         fd_note(theOutIcpConnection, "Outgoing ICP socket");
-
-        fd_note(theInIcpConnection, "Incoming ICP socket");
-    } else {
-        theOutIcpConnection = theInIcpConnection;
     }
 
     theOutICPAddr.SetEmpty();
@@ -730,6 +736,31 @@ icpConnectionsOpen(void)
     theOutICPAddr.FreeAddrInfo(xai);
 }
 
+static void
+icpIncomingConnectionOpened(int fd, int errNo, IpAddress& addr)
+{
+    theInIcpConnection = fd;
+
+    if (theInIcpConnection < 0)
+        fatal("Cannot open ICP Port");
+
+    commSetSelect(theInIcpConnection,
+                  COMM_SELECT_READ,
+                  icpHandleUdp,
+                  NULL,
+                  0);
+
+    for (const wordlist *s = Config.mcast_group_list; s; s = s->next)
+        ipcache_nbgethostbyname(s->key, mcastJoinGroups, NULL);
+
+    debugs(12, 1, "Accepting ICP messages at " << addr << ", FD " << theInIcpConnection << ".");
+
+        fd_note(theInIcpConnection, "Incoming ICP socket");
+
+    if (Config.Addrs.udp_outgoing.IsNoAddr())
+        theOutIcpConnection = theInIcpConnection;
+}
+
 /**
  * icpConnectionShutdown only closes the 'in' socket if it is
  * different than the 'out' socket.
index 6c2a992011bc7c950ba2bbd0972f40af7be45c55..9eb3328f33e1e85c83e551defd9182d20bdaa8ff 100644 (file)
@@ -18,7 +18,9 @@ Ipc::FdNote(int fdNoteId)
         "HTTP Socket", // fdnHttpSocket
         "HTTPS Socket", // fdnHttpsSocket
         "Incoming SNMP Socket", // fdnInSnmpSocket
-        "Outgoing SNMP Socket" // fdnOutSnmpSocket
+        "Outgoing SNMP Socket", // fdnOutSnmpSocket
+        "Incoming ICP Socket", // fdnInIcpSocket
+        "Incoming HTCP Socket" // fdnInHtcpSocket
     };
 
     if (fdnNone < fdNoteId && fdNoteId < fdnEnd)
index 74deca3456f337808cf41ba84615c6a44544b926..87219d09bc6d1741244897a45a9ecc7665d34d05 100644 (file)
@@ -15,7 +15,8 @@ namespace Ipc
 
 /// fd_note() label ID
 typedef enum { fdnNone, fdnHttpSocket, fdnHttpsSocket,
-               fdnInSnmpSocket, fdnOutSnmpSocket, fdnEnd } FdNoteId;
+               fdnInSnmpSocket, fdnOutSnmpSocket, 
+               fdnInIcpSocket, fdnInHtcpSocket, fdnEnd } FdNoteId;
 
 extern const char *FdNote(int fdNodeId); ///< converts FdNoteId into a string