#include "AccessLogEntry.h"
#include "acl/Acl.h"
#include "acl/FilledChecklist.h"
+#include "comm.h"
#include "comm/Connection.h"
+#include "comm/Loops.h"
+#include "comm/UdpOpenDialer.h"
#include "HttpRequest.h"
#include "icmp/net_db.h"
#include "ICP.h"
#include "ip/Address.h"
#include "ip/tools.h"
-#include "ipc/StartListening.h"
+#include "ipcache.h"
+#include "md5.h"
+#include "protos.h"
#include "rfc1738.h"
-#include "Store.h"
#include "SquidTime.h"
+#include "StatCounters.h"
+#include "Store.h"
#include "SwapDir.h"
#include "wordlist.h"
-/// dials icpIncomingConnectionOpened call
-class IcpListeningStartedDialer: public CallDialer,
- public Ipc::StartListeningCb
-{
-public:
- typedef void (*Handler)(int errNo);
- IcpListeningStartedDialer(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)(errNo); }
-
-public:
- Handler handler;
-};
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
-static void icpIncomingConnectionOpened(int errNo);
+static void icpIncomingConnectionOpened(const Comm::ConnectionPointer &conn, int errNo);
/// \ingroup ServerProtocolICPInternal2
static void icpLogIcp(const Ip::Address &, log_type, int, const char *, int);
/// \ingroup ServerProtocolICPInternal2
Comm::ConnectionPointer icpOutgoingConn = NULL;
-/** \ingroup ServerProtocolICPInternal2
- * ICP v2 uses the outgoing address as host ID.
- * NP: this *may* be identical to icpOutgoingConn->local
- * but when IN/OUT sockets are shared we can't guarantee that
- * so a separate variable is used for now.
- *
- * We have one for private use (sent only by this local cache)
- * and one for public use (for external caches to contact us)
- */
-Ip::Address theIcpPrivateHostID;
-
-/// \see theIcpPrivateHostID
-Ip::Address theIcpPublicHostID;
-
-
/* icp_common_t */
_icp_common_t::_icp_common_t() : opcode(ICP_INVALID), version(0), length(0), reqnum(0), flags(0), pad(0), shostid(0)
{}
return;
}
- xmemcpy(this, buf, sizeof(icp_common_t));
+ memcpy(this, buf, sizeof(icp_common_t));
/*
* Convert network order sensitive fields
*/
HTTPMSGUNLOCK(request);
}
-
/* End ICPState */
/* ICP2State */
static void
icpLogIcp(const Ip::Address &caddr, log_type logcode, int len, const char *url, int delay)
{
- AccessLogEntry al;
+ AccessLogEntry::Pointer al = new AccessLogEntry();
if (LOG_TAG_NONE == logcode)
return;
if (LOG_ICP_QUERY == logcode)
return;
- clientdbUpdate(caddr, logcode, PROTO_ICP, len);
+ clientdbUpdate(caddr, logcode, AnyP::PROTO_ICP, len);
if (!Config.onoff.log_udp)
return;
- al.icp.opcode = ICP_QUERY;
+ al->icp.opcode = ICP_QUERY;
- al.url = url;
+ al->url = url;
- al.cache.caddr = caddr;
+ al->cache.caddr = caddr;
- al.cache.replySize = len;
+ al->cache.replySize = len;
- al.cache.code = logcode;
+ al->cache.code = logcode;
- al.cache.msec = delay;
+ al->cache.msec = delay;
- accessLogLog(&al, NULL);
+ accessLogLog(al, NULL);
}
/// \ingroup ServerProtocolICPInternal2
headerp->pad = htonl(pad);
- theIcpPrivateHostID.GetInAddr( *((struct in_addr*)&headerp->shostid) );
+ headerp->shostid = 0;
urloffset = buf + sizeof(icp_common_t);
if (opcode == ICP_QUERY)
urloffset += sizeof(uint32_t);
- xmemcpy(urloffset, url, strlen(url));
+ memcpy(urloffset, url, strlen(url));
return (icp_common_t *)buf;
}
IcpQueueTail = queue;
}
- commSetSelect(fd, COMM_SELECT_WRITE, icpUdpSendQueue, NULL, 0);
- statCounter.icp.replies_queued++;
+ Comm::SetSelect(fd, COMM_SELECT_WRITE, icpUdpSendQueue, NULL, 0);
+ ++statCounter.icp.replies_queued;
} else {
/* don't queue it */
- statCounter.icp.replies_dropped++;
+ ++statCounter.icp.replies_dropped;
}
return x;
* count this DENIED query in the clientdb, even though
* we're not sending an ICP reply...
*/
- clientdbUpdate(from, LOG_UDP_DENIED, PROTO_ICP, 0);
+ clientdbUpdate(from, LOG_UDP_DENIED, AnyP::PROTO_ICP, 0);
} else {
icpCreateAndSend(ICP_DENIED, 0, url, reqnum, 0, fd, from);
}
}
-int
+bool
icpAccessAllowed(Ip::Address &from, HttpRequest * icp_request)
{
/* absent an explicit allow, we deny all */
if (!Config.accessList.icp)
- return 0;
+ return true;
ACLFilledChecklist checklist(Config.accessList.icp, icp_request, NULL);
checklist.src_addr = from;
checklist.my_addr.SetNoAddr();
- int result = checklist.fastCheck();
- return result;
+ return (checklist.fastCheck() == ACCESS_ALLOWED);
}
char const *
_icp_common_t::handleReply(char *buf, Ip::Address &from)
{
if (neighbors_do_private_keys && reqnum == 0) {
- debugs(12, 0, "icpHandleIcpV2: Neighbor " << from << " returned reqnum = 0");
- debugs(12, 0, "icpHandleIcpV2: Disabling use of private keys");
+ debugs(12, DBG_CRITICAL, "icpHandleIcpV2: Neighbor " << from << " returned reqnum = 0");
+ debugs(12, DBG_CRITICAL, "icpHandleIcpV2: Disabling use of private keys");
neighbors_do_private_keys = 0;
}
break;
default:
- debugs(12, 0, "icpHandleIcpV2: UNKNOWN OPCODE: " << header.opcode << " from " << from);
+ debugs(12, DBG_CRITICAL, "icpHandleIcpV2: UNKNOWN OPCODE: " << header.opcode << " from " << from);
break;
}
LOCAL_ARRAY(char, buf, SQUID_UDP_SO_RCVBUF);
int len;
int icp_version;
- int max = INCOMING_ICP_MAX;
- commSetSelect(sock, COMM_SELECT_READ, icpHandleUdp, NULL, 0);
+ int max = INCOMING_UDP_MAX;
+ Comm::SetSelect(sock, COMM_SELECT_READ, icpHandleUdp, NULL, 0);
- while (max--) {
+ while (max) {
+ --max;
len = comm_udp_recvfrom(sock,
buf,
SQUID_UDP_SO_RCVBUF - 1,
if (ignoreErrno(errno))
break;
-#ifdef _SQUID_LINUX_
+#if _SQUID_LINUX_
/* Some Linux systems seem to set the FD for reading and then
* return ECONNREFUSED when sendto() fails and generates an ICMP
* port unreachable message. */
if (errno != ECONNREFUSED && errno != EHOSTUNREACH)
#endif
- debugs(50, 1, "icpHandleUdp: FD " << sock << " recvfrom: " << xstrerror());
+ debugs(50, DBG_IMPORTANT, "icpHandleUdp: FD " << sock << " recvfrom: " << xstrerror());
break;
}
- (*N)++;
+ ++(*N);
icpCount(buf, RECV, (size_t) len, 0);
buf[len] = '\0';
debugs(12, 4, "icpHandleUdp: FD " << sock << ": received " <<
icp_version = (int) buf[1]; /* cheat! */
- if (icp_version == ICP_VERSION_2)
+ if (icpOutgoingConn->local == from)
+ // ignore ICP packets which loop back (multicast usually)
+ debugs(12, 4, "icpHandleUdp: Ignoring UDP packet sent by myself");
+ else if (icp_version == ICP_VERSION_2)
icpHandleIcpV2(sock, from, buf, len);
else if (icp_version == ICP_VERSION_3)
icpHandleIcpV3(sock, from, buf, len);
else
- debugs(12, 1, "WARNING: Unused ICP version " << icp_version <<
+ debugs(12, DBG_IMPORTANT, "WARNING: Unused ICP version " << icp_version <<
" received from " << from);
}
}
void
-icpConnectionsOpen(void)
+icpOpenPorts(void)
{
uint16_t port;
-// Ip::Address addr;
if ((port = Config.Port.icp) <= 0)
return;
AsyncCall::Pointer call = asyncCall(12, 2,
"icpIncomingConnectionOpened",
- IcpListeningStartedDialer(&icpIncomingConnectionOpened));
+ Comm::UdpOpenDialer(&icpIncomingConnectionOpened));
Ipc::StartListening(SOCK_DGRAM,
IPPROTO_UDP,
icpIncomingConn,
- Ipc::fdnInIcpSocket, call, Subscription::Pointer());
+ Ipc::fdnInIcpSocket, call);
if ( !Config.Addrs.udp_outgoing.IsNoAddr() ) {
icpOutgoingConn = new Comm::Connection;
debugs(12, DBG_CRITICAL, "Sending ICP messages from " << icpOutgoingConn->local);
- commSetSelect(icpOutgoingConn->fd, COMM_SELECT_READ, icpHandleUdp, NULL, 0);
+ Comm::SetSelect(icpOutgoingConn->fd, COMM_SELECT_READ, icpHandleUdp, NULL, 0);
+ fd_note(icpOutgoingConn->fd, "Outgoing ICP socket");
}
-
- // Ensure that we have the IP address(es) to use for Host ID.
- // The outgoing address is used as 'private' host ID used only on packets we send
- struct addrinfo *xai = NULL;
- theIcpPrivateHostID.InitAddrInfo(xai);
- if (getsockname(icpOutgoingConn->fd, xai->ai_addr, &xai->ai_addrlen) < 0)
- debugs(50, DBG_IMPORTANT, "ERROR: Unable to identify ICP host ID to use for " << icpOutgoingConn
- << ": getsockname: " << xstrerror());
- else
- theIcpPrivateHostID = *xai;
- theIcpPrivateHostID.FreeAddrInfo(xai);
}
static void
-icpIncomingConnectionOpened(int errNo)
+icpIncomingConnectionOpened(const Comm::ConnectionPointer &conn, int errNo)
{
- if (!Comm::IsConnOpen(icpIncomingConn))
+ if (!Comm::IsConnOpen(conn))
fatal("Cannot open ICP Port");
- commSetSelect(icpIncomingConn->fd, COMM_SELECT_READ, icpHandleUdp, NULL, 0);
+ Comm::SetSelect(conn->fd, COMM_SELECT_READ, icpHandleUdp, NULL, 0);
for (const wordlist *s = Config.mcast_group_list; s; s = s->next)
- ipcache_nbgethostbyname(s->key, mcastJoinGroups, NULL); // XXX: pass the icpIncomingConn for mcastJoinGroups usage.
+ ipcache_nbgethostbyname(s->key, mcastJoinGroups, NULL); // XXX: pass the conn for mcastJoinGroups usage.
- debugs(12, DBG_IMPORTANT, "Accepting ICP messages on " << icpIncomingConn->local);
+ debugs(12, DBG_IMPORTANT, "Accepting ICP messages on " << conn->local);
- fd_note(icpIncomingConn->fd, "Incoming ICP port");
+ fd_note(conn->fd, "Incoming ICP port");
if (Config.Addrs.udp_outgoing.IsNoAddr()) {
- icpOutgoingConn = icpIncomingConn;
+ icpOutgoingConn = conn;
debugs(12, DBG_IMPORTANT, "Sending ICP messages from " << icpOutgoingConn->local);
}
-
- // Ensure that we have the IP address(es) to use for Host ID.
- // The listening address is used as 'public' host ID which can be used to contact us
- struct addrinfo *xai = NULL;
- theIcpPublicHostID.InitAddrInfo(xai); // reset xai
- if (getsockname(icpIncomingConn->fd, xai->ai_addr, &xai->ai_addrlen) < 0)
- debugs(50, DBG_IMPORTANT, "ERROR: Unable to identify ICP host ID to use for " << icpIncomingConn
- << ": getsockname: " << xstrerror());
- else
- theIcpPublicHostID = *xai;
- theIcpPublicHostID.FreeAddrInfo(xai);
}
/**
*/
assert(Comm::IsConnOpen(icpOutgoingConn));
- commSetSelect(icpOutgoingConn->fd, COMM_SELECT_READ, NULL, NULL, 0);
+ Comm::SetSelect(icpOutgoingConn->fd, COMM_SELECT_READ, NULL, NULL, 0);
}
void
-icpConnectionClose(void)
+icpClosePorts(void)
{
icpConnectionShutdown();
return;
if (SENT == which) {
- statCounter.icp.pkts_sent++;
+ ++statCounter.icp.pkts_sent;
kb_incr(&statCounter.icp.kbytes_sent, len);
if (ICP_QUERY == icp->opcode) {
- statCounter.icp.queries_sent++;
+ ++statCounter.icp.queries_sent;
kb_incr(&statCounter.icp.q_kbytes_sent, len);
} else {
- statCounter.icp.replies_sent++;
+ ++statCounter.icp.replies_sent;
kb_incr(&statCounter.icp.r_kbytes_sent, len);
/* this is the sent-reply service time */
- statHistCount(&statCounter.icp.reply_svc_time, delay);
+ statCounter.icp.replySvcTime.count(delay);
}
if (ICP_HIT == icp->opcode)
- statCounter.icp.hits_sent++;
+ ++statCounter.icp.hits_sent;
} else if (RECV == which) {
- statCounter.icp.pkts_recv++;
+ ++statCounter.icp.pkts_recv;
kb_incr(&statCounter.icp.kbytes_recv, len);
if (ICP_QUERY == icp->opcode) {
- statCounter.icp.queries_recv++;
+ ++statCounter.icp.queries_recv;
kb_incr(&statCounter.icp.q_kbytes_recv, len);
} else {
- statCounter.icp.replies_recv++;
+ ++statCounter.icp.replies_recv;
kb_incr(&statCounter.icp.r_kbytes_recv, len);
- /* statCounter.icp.query_svc_time set in clientUpdateCounters */
+ /* statCounter.icp.querySvcTime set in clientUpdateCounters */
}
if (ICP_HIT == icp->opcode)
- statCounter.icp.hits_recv++;
+ ++statCounter.icp.hits_recv;
}
}