]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/icp_v2.cc
transaction_initiator ACL for detecting various unusual transactions
[thirdparty/squid.git] / src / icp_v2.cc
index 5de16354fe7893816403b881be3c2541d7251b3f..d9ed9f0df27647d3571ca62e84d8fe7af1bffdac 100644 (file)
@@ -1,35 +1,13 @@
 /*
- * DEBUG: section 12    Internet Cache Protocol (ICP)
- * AUTHOR: Duane Wessels
- *
- * SQUID Web Proxy Cache          http://www.squid-cache.org/
- * ----------------------------------------------------------
- *
- *  Squid is the result of efforts by numerous individuals from
- *  the Internet community; see the CONTRIBUTORS file for full
- *  details.   Many organizations have provided support for Squid's
- *  development; see the SPONSORS file for full details.  Squid is
- *  Copyrighted (C) 2001 by the Regents of the University of
- *  California; see the COPYRIGHT file for full details.  Squid
- *  incorporates software developed and/or copyrighted by other
- *  sources; see the CREDITS file for full details.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
+ * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
  *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
+/* DEBUG: section 12    Internet Cache Protocol (ICP) */
+
 /**
  \defgroup ServerProtocolICPInternal2 ICPv2 Internals
  \ingroup ServerProtocolICPAPI
 #include "StatCounters.h"
 #include "Store.h"
 #include "store_key_md5.h"
-#include "SwapDir.h"
 #include "tools.h"
 #include "wordlist.h"
 
-#if HAVE_ERRNO_H
-#include <errno.h>
-#endif
+// for tvSubUsec() which should be in SquidTime.h
+#include "util.h"
+
+#include <cerrno>
 
 static void icpIncomingConnectionOpened(const Comm::ConnectionPointer &conn, int errNo);
 
 /// \ingroup ServerProtocolICPInternal2
-static void icpLogIcp(const Ip::Address &, log_type, int, const char *, int);
+static void icpLogIcp(const Ip::Address &, const LogTags &, int, const char *, int);
 
 /// \ingroup ServerProtocolICPInternal2
 static void icpHandleIcpV2(int, Ip::Address &, char *, int);
@@ -95,10 +73,13 @@ Comm::ConnectionPointer icpIncomingConn = NULL;
 Comm::ConnectionPointer icpOutgoingConn = NULL;
 
 /* icp_common_t */
-_icp_common_t::_icp_common_t() : opcode(ICP_INVALID), version(0), length(0), reqnum(0), flags(0), pad(0), shostid(0)
+_icp_common_t::_icp_common_t() :
+    opcode(ICP_INVALID), version(0), length(0), reqnum(0),
+    flags(0), pad(0), shostid(0)
 {}
 
-_icp_common_t::_icp_common_t(char *buf, unsigned int len)
+_icp_common_t::_icp_common_t(char *buf, unsigned int len) :
+    opcode(ICP_INVALID), version(0), reqnum(0), flags(0), pad(0), shostid(0)
 {
     if (len < sizeof(_icp_common_t)) {
         /* mark as invalid */
@@ -119,20 +100,22 @@ _icp_common_t::_icp_common_t(char *buf, unsigned int len)
 icp_opcode
 _icp_common_t::getOpCode() const
 {
-    if (opcode > (char)ICP_END)
+    if (opcode > static_cast<char>(icp_opcode::ICP_END))
         return ICP_INVALID;
 
-    return (icp_opcode)opcode;
+    return static_cast<icp_opcode>(opcode);
 }
 
 /* ICPState */
 
 ICPState::ICPState(icp_common_t &aHeader, HttpRequest *aRequest):
-        header(aHeader),
-        request(HTTPMSGLOCK(aRequest)),
-        fd(-1),
-        url(NULL)
-{}
+    header(aHeader),
+    request(aRequest),
+    fd(-1),
+    url(NULL)
+{
+    HTTPMSGLOCK(request);
+}
 
 ICPState::~ICPState()
 {
@@ -150,7 +133,7 @@ class ICP2State : public ICPState, public StoreClient
 
 public:
     ICP2State(icp_common_t & aHeader, HttpRequest *aRequest):
-            ICPState(aHeader, aRequest),rtt(0),src_rtt(0),flags(0) {}
+        ICPState(aHeader, aRequest),rtt(0),src_rtt(0),flags(0) {}
 
     ~ICP2State();
     void created(StoreEntry * newEntry);
@@ -175,8 +158,8 @@ ICP2State::created(StoreEntry *newEntry)
     } else {
 #if USE_ICMP
         if (Config.onoff.test_reachability && rtt == 0) {
-            if ((rtt = netdbHostRtt(request->GetHost())) == 0)
-                netdbPingSite(request->GetHost());
+            if ((rtt = netdbHostRtt(request->url.host())) == 0)
+                netdbPingSite(request->url.host());
         }
 #endif /* USE_ICMP */
 
@@ -196,14 +179,14 @@ ICP2State::created(StoreEntry *newEntry)
 
 /// \ingroup ServerProtocolICPInternal2
 static void
-icpLogIcp(const Ip::Address &caddr, log_type logcode, int len, const char *url, int delay)
+icpLogIcp(const Ip::Address &caddr, const LogTags &logcode, int len, const char *url, int delay)
 {
     AccessLogEntry::Pointer al = new AccessLogEntry();
 
-    if (LOG_TAG_NONE == logcode)
+    if (LOG_TAG_NONE == logcode.oldType)
         return;
 
-    if (LOG_ICP_QUERY == logcode)
+    if (LOG_ICP_QUERY == logcode.oldType)
         return;
 
     clientdbUpdate(caddr, logcode, AnyP::PROTO_ICP, len);
@@ -217,18 +200,19 @@ icpLogIcp(const Ip::Address &caddr, log_type logcode, int len, const char *url,
 
     al->cache.caddr = caddr;
 
-    al->cache.replySize = len;
+    // XXX: move to use icp.clientReply instead
+    al->http.clientReplySz.payloadData = len;
 
     al->cache.code = logcode;
 
-    al->cache.msec = delay;
+    al->cache.trTime.tv_sec = delay;
 
     accessLogLog(al, NULL);
 }
 
 /// \ingroup ServerProtocolICPInternal2
 void
-icpUdpSendQueue(int fd, void *unused)
+icpUdpSendQueue(int fd, void *)
 {
     icpUdpData *q;
 
@@ -293,7 +277,7 @@ int
 icpUdpSend(int fd,
            const Ip::Address &to,
            icp_common_t * msg,
-           log_type logcode,
+           const LogTags &logcode,
            int delay)
 {
     icpUdpData *queue;
@@ -377,7 +361,7 @@ icpGetCommonOpcode()
     return ICP_ERR;
 }
 
-log_type
+LogTags
 icpLogFromICPCode(icp_opcode opcode)
 {
     if (opcode == ICP_ERR)
@@ -426,13 +410,13 @@ icpDenyAccess(Ip::Address &from, char *url, int reqnum, int fd)
 bool
 icpAccessAllowed(Ip::Address &from, HttpRequest * icp_request)
 {
-    /* absent an explicit allow, we deny all */
+    /* absent any explicit rules, we deny all */
     if (!Config.accessList.icp)
-        return true;
+        return false;
 
     ACLFilledChecklist checklist(Config.accessList.icp, icp_request, NULL);
     checklist.src_addr = from;
-    checklist.my_addr.SetNoAddr();
+    checklist.my_addr.setNoAddr();
     return (checklist.fastCheck() == ACCESS_ALLOWED);
 }
 
@@ -455,8 +439,8 @@ icpGetRequest(char *url, int reqnum, int fd, Ip::Address &from)
     }
 
     HttpRequest *result;
-
-    if ((result = HttpRequest::CreateFromUrl(url)) == NULL)
+    const MasterXaction::Pointer mx = new MasterXaction(XactionInitiator::initIcp);
+    if ((result = HttpRequest::FromUrl(url, mx)) == NULL)
         icpCreateAndSend(ICP_ERR, 0, url, reqnum, 0, fd, from);
 
     return result;
@@ -485,8 +469,8 @@ doV2Query(int fd, Ip::Address &from, char *buf, icp_common_t header)
     }
 #if USE_ICMP
     if (header.flags & ICP_FLAG_SRC_RTT) {
-        rtt = netdbHostRtt(icp_request->GetHost());
-        int hops = netdbHostHops(icp_request->GetHost());
+        rtt = netdbHostRtt(icp_request->url.host());
+        int hops = netdbHostHops(icp_request->url.host());
         src_rtt = ((hops & 0xFFFF) << 16) | (rtt & 0xFFFF);
 
         if (rtt)
@@ -495,21 +479,15 @@ doV2Query(int fd, Ip::Address &from, char *buf, icp_common_t header)
 #endif /* USE_ICMP */
 
     /* The peer is allowed to use this cache */
-    ICP2State *state = new ICP2State (header, icp_request);
-
+    ICP2State *state = new ICP2State(header, icp_request);
     state->fd = fd;
-
     state->from = from;
-
-    state->url = xstrdup (url);
-
+    state->url = xstrdup(url);
     state->flags = flags;
-
     state->rtt = rtt;
-
     state->src_rtt = src_rtt;
 
-    StoreEntry::getPublic (state, url, Http::METHOD_GET);
+    StoreEntry::getPublic(state, url, Http::METHOD_GET);
 
     HTTPMSGUNLOCK(icp_request);
 }
@@ -599,7 +577,7 @@ icpPktDump(icp_common_t * pkt)
 #endif
 
 void
-icpHandleUdp(int sock, void *data)
+icpHandleUdp(int sock, void *)
 {
     int *N = &incoming_sockets_accepted;
 
@@ -622,7 +600,8 @@ icpHandleUdp(int sock, void *data)
             break;
 
         if (len < 0) {
-            if (ignoreErrno(errno))
+            int xerrno = errno;
+            if (ignoreErrno(xerrno))
                 break;
 
 #if _SQUID_LINUX_
@@ -630,10 +609,9 @@ icpHandleUdp(int sock, void *data)
              * return ECONNREFUSED when sendto() fails and generates an ICMP
              * port unreachable message. */
             /* or maybe an EHOSTUNREACH "No route to host" message */
-            if (errno != ECONNREFUSED && errno != EHOSTUNREACH)
+            if (xerrno != ECONNREFUSED && xerrno != EHOSTUNREACH)
 #endif
-
-                debugs(50, DBG_IMPORTANT, "icpHandleUdp: FD " << sock << " recvfrom: " << xstrerror());
+                debugs(50, DBG_IMPORTANT, "icpHandleUdp: FD " << sock << " recvfrom: " << xstrerr(xerrno));
 
             break;
         }
@@ -654,7 +632,7 @@ icpHandleUdp(int sock, void *data)
             break;
         }
 
-        icp_version = (int) buf[1];    /* cheat! */
+        icp_version = (int) buf[1]; /* cheat! */
 
         if (icpOutgoingConn->local == from)
             // ignore ICP packets which loop back (multicast usually)
@@ -679,15 +657,15 @@ icpOpenPorts(void)
 
     icpIncomingConn = new Comm::Connection;
     icpIncomingConn->local = Config.Addrs.udp_incoming;
-    icpIncomingConn->local.SetPort(port);
+    icpIncomingConn->local.port(port);
 
-    if (!Ip::EnableIpv6 && !icpIncomingConn->local.SetIPv4()) {
+    if (!Ip::EnableIpv6 && !icpIncomingConn->local.setIPv4()) {
         debugs(12, DBG_CRITICAL, "ERROR: IPv6 is disabled. " << icpIncomingConn->local << " is not an IPv4 address.");
         fatal("ICP port cannot be opened.");
     }
     /* split-stack for now requires default IPv4-only ICP */
-    if (Ip::EnableIpv6&IPV6_SPECIAL_SPLITSTACK && icpIncomingConn->local.IsAnyAddr()) {
-        icpIncomingConn->local.SetIPv4();
+    if (Ip::EnableIpv6&IPV6_SPECIAL_SPLITSTACK && icpIncomingConn->local.isAnyAddr()) {
+        icpIncomingConn->local.setIPv4();
     }
 
     AsyncCall::Pointer call = asyncCall(12, 2,
@@ -699,18 +677,18 @@ icpOpenPorts(void)
                         icpIncomingConn,
                         Ipc::fdnInIcpSocket, call);
 
-    if ( !Config.Addrs.udp_outgoing.IsNoAddr() ) {
+    if ( !Config.Addrs.udp_outgoing.isNoAddr() ) {
         icpOutgoingConn = new Comm::Connection;
         icpOutgoingConn->local = Config.Addrs.udp_outgoing;
-        icpOutgoingConn->local.SetPort(port);
+        icpOutgoingConn->local.port(port);
 
-        if (!Ip::EnableIpv6 && !icpOutgoingConn->local.SetIPv4()) {
+        if (!Ip::EnableIpv6 && !icpOutgoingConn->local.setIPv4()) {
             debugs(49, DBG_CRITICAL, "ERROR: IPv6 is disabled. " << icpOutgoingConn->local << " is not an IPv4 address.");
             fatal("ICP port cannot be opened.");
         }
         /* split-stack for now requires default IPv4-only ICP */
-        if (Ip::EnableIpv6&IPV6_SPECIAL_SPLITSTACK && icpOutgoingConn->local.IsAnyAddr()) {
-            icpOutgoingConn->local.SetIPv4();
+        if (Ip::EnableIpv6&IPV6_SPECIAL_SPLITSTACK && icpOutgoingConn->local.isAnyAddr()) {
+            icpOutgoingConn->local.setIPv4();
         }
 
         enter_suid();
@@ -728,7 +706,7 @@ icpOpenPorts(void)
 }
 
 static void
-icpIncomingConnectionOpened(const Comm::ConnectionPointer &conn, int errNo)
+icpIncomingConnectionOpened(const Comm::ConnectionPointer &conn, int)
 {
     if (!Comm::IsConnOpen(conn))
         fatal("Cannot open ICP Port");
@@ -742,7 +720,7 @@ icpIncomingConnectionOpened(const Comm::ConnectionPointer &conn, int errNo)
 
     fd_note(conn->fd, "Incoming ICP port");
 
-    if (Config.Addrs.udp_outgoing.IsNoAddr()) {
+    if (Config.Addrs.udp_outgoing.isNoAddr()) {
         icpOutgoingConn = conn;
         debugs(12, DBG_IMPORTANT, "Sending ICP messages from " << icpOutgoingConn->local);
     }
@@ -798,14 +776,14 @@ icpCount(void *buf, int which, size_t len, int delay)
 
     if (SENT == which) {
         ++statCounter.icp.pkts_sent;
-        kb_incr(&statCounter.icp.kbytes_sent, len);
+        statCounter.icp.kbytes_sent += len;
 
         if (ICP_QUERY == icp->opcode) {
             ++statCounter.icp.queries_sent;
-            kb_incr(&statCounter.icp.q_kbytes_sent, len);
+            statCounter.icp.q_kbytes_sent += len;
         } else {
             ++statCounter.icp.replies_sent;
-            kb_incr(&statCounter.icp.r_kbytes_sent, len);
+            statCounter.icp.r_kbytes_sent += len;
             /* this is the sent-reply service time */
             statCounter.icp.replySvcTime.count(delay);
         }
@@ -814,14 +792,14 @@ icpCount(void *buf, int which, size_t len, int delay)
             ++statCounter.icp.hits_sent;
     } else if (RECV == which) {
         ++statCounter.icp.pkts_recv;
-        kb_incr(&statCounter.icp.kbytes_recv, len);
+        statCounter.icp.kbytes_recv += len;
 
         if (ICP_QUERY == icp->opcode) {
             ++statCounter.icp.queries_recv;
-            kb_incr(&statCounter.icp.q_kbytes_recv, len);
+            statCounter.icp.q_kbytes_recv += len;
         } else {
             ++statCounter.icp.replies_recv;
-            kb_incr(&statCounter.icp.r_kbytes_recv, len);
+            statCounter.icp.r_kbytes_recv += len;
             /* statCounter.icp.querySvcTime set in clientUpdateCounters */
         }
 
@@ -855,3 +833,4 @@ icpGetCacheKey(const char *url, int reqnum)
 
     return storeKeyPublic(url, Http::METHOD_GET);
 }
+