icp_v2.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2018 The Squid Software Foundation and contributors
3  *
4  * Squid software is distributed under GPLv2+ license and includes
5  * contributions from numerous individuals and organizations.
6  * Please see the COPYING and CONTRIBUTORS files for details.
7  */
8 
9 /* DEBUG: section 12 Internet Cache Protocol (ICP) */
10 
16 #include "squid.h"
17 #include "AccessLogEntry.h"
18 #include "acl/Acl.h"
19 #include "acl/FilledChecklist.h"
20 #include "client_db.h"
21 #include "comm.h"
22 #include "comm/Connection.h"
23 #include "comm/Loops.h"
24 #include "comm/UdpOpenDialer.h"
25 #include "fd.h"
26 #include "HttpRequest.h"
27 #include "icmp/net_db.h"
28 #include "ICP.h"
29 #include "ip/Address.h"
30 #include "ip/tools.h"
31 #include "ipcache.h"
32 #include "md5.h"
33 #include "multicast.h"
34 #include "neighbors.h"
35 #include "refresh.h"
36 #include "rfc1738.h"
37 #include "SquidConfig.h"
38 #include "SquidTime.h"
39 #include "StatCounters.h"
40 #include "Store.h"
41 #include "store_key_md5.h"
42 #include "tools.h"
43 #include "wordlist.h"
44 
45 // for tvSubUsec() which should be in SquidTime.h
46 #include "util.h"
47 
48 #include <cerrno>
49 
52 public:
54  icp_common_t *msg = nullptr;
55  DelayedUdpSend *next = nullptr;
57  struct timeval queue_time = {0, 0};
58 };
59 
60 static void icpIncomingConnectionOpened(const Comm::ConnectionPointer &conn, int errNo);
61 
63 static void icpLogIcp(const Ip::Address &, const LogTags_ot, int, const char *, const int, AccessLogEntryPointer &);
64 
66 static void icpHandleIcpV2(int, Ip::Address &, char *, int);
67 
69 static void icpCount(void *, int, size_t, int);
70 
72 
73 static int icpUdpSend(int fd, const Ip::Address &to, icp_common_t * msg, int delay, AccessLogEntryPointer al);
74 
75 static void
76 icpSyncAle(AccessLogEntryPointer &al, const Ip::Address &caddr, const char *url, int len, int delay)
77 {
78  if (!al)
79  al = new AccessLogEntry();
80  al->icp.opcode = ICP_QUERY;
81  al->cache.caddr = caddr;
82  al->url = url;
83  // XXX: move to use icp.clientReply instead
84  al->http.clientReplySz.payloadData = len;
85  al->cache.start_time = current_time;
86  al->cache.start_time.tv_sec -= delay;
87  al->cache.trTime.tv_sec = delay;
88  al->cache.trTime.tv_usec = 0;
89 }
90 
96 static DelayedUdpSend *IcpQueueHead = NULL;
98 static DelayedUdpSend *IcpQueueTail = NULL;
99 
101 Comm::ConnectionPointer icpIncomingConn = NULL;
103 Comm::ConnectionPointer icpOutgoingConn = NULL;
104 
105 /* icp_common_t */
107  opcode(ICP_INVALID), version(0), length(0), reqnum(0),
108  flags(0), pad(0), shostid(0)
109 {}
110 
111 icp_common_t::icp_common_t(char *buf, unsigned int len) :
112  opcode(ICP_INVALID), version(0), reqnum(0), flags(0), pad(0), shostid(0)
113 {
114  if (len < sizeof(icp_common_t)) {
115  /* mark as invalid */
116  length = len + 1;
117  return;
118  }
119 
120  memcpy(this, buf, sizeof(icp_common_t));
121  /*
122  * Convert network order sensitive fields
123  */
124  length = ntohs(length);
125  reqnum = ntohl(reqnum);
126  flags = ntohl(flags);
127  pad = ntohl(pad);
128 }
129 
132 {
133  if (opcode > static_cast<char>(icp_opcode::ICP_END))
134  return ICP_INVALID;
135 
136  return static_cast<icp_opcode>(opcode);
137 }
138 
139 /* ICPState */
140 
142  header(aHeader),
143  request(aRequest),
144  fd(-1),
145  url(NULL)
146 {
148 }
149 
151 {
152  safe_free(url);
154 }
155 
156 bool
158 {
159  if (e.isNull())
160  return false;
161 
162  if (!e.validToSend())
163  return false;
164 
166  return false;
167 
168  if (e.hittingRequiresCollapsing() && !startCollapsingOn(e, false))
169  return false;
170 
171  return true;
172 }
173 
174 LogTags *
176 {
177  // calling icpSyncAle(LOG_TAG_NONE) here would not change cache.code
178  if (!al)
179  al = new AccessLogEntry();
180  return &al->cache.code;
181 }
182 
183 void
185 {
186  checklist.setRequest(request);
187  icpSyncAle(al, from, url, 0, 0);
188  checklist.al = al;
189 }
190 
191 /* End ICPState */
192 
193 /* ICP2State */
194 
196 class ICP2State: public ICPState
197 {
198 
199 public:
200  ICP2State(icp_common_t & aHeader, HttpRequest *aRequest):
201  ICPState(aHeader, aRequest),rtt(0),src_rtt(0),flags(0) {}
202 
203  ~ICP2State();
204  virtual void created(StoreEntry * newEntry) override;
205 
206  int rtt;
207  int src_rtt;
208  uint32_t flags;
209 };
210 
212 {}
213 
214 void
216 {
217  debugs(12, 5, "icpHandleIcpV2: OPCODE " << icp_opcode_str[header.opcode]);
218  icp_opcode codeToSend;
219 
220  if (confirmAndPrepHit(*e)) {
221  codeToSend = ICP_HIT;
222  } else {
223 #if USE_ICMP
224  if (Config.onoff.test_reachability && rtt == 0) {
225  if ((rtt = netdbHostRtt(request->url.host())) == 0)
227  }
228 #endif /* USE_ICMP */
229 
230  if (icpGetCommonOpcode() != ICP_ERR)
231  codeToSend = icpGetCommonOpcode();
232  else if (Config.onoff.test_reachability && rtt == 0)
233  codeToSend = ICP_MISS_NOFETCH;
234  else
235  codeToSend = ICP_MISS;
236  }
237 
238  icpCreateAndSend(codeToSend, flags, url, header.reqnum, src_rtt, fd, from, al);
239 
240  // TODO: StoreClients must either store/lock or abandon found entries.
241  //if (!e->isNull())
242  // e->abandon();
243 
244  delete this;
245 }
246 
247 /* End ICP2State */
248 
250 static void
251 icpLogIcp(const Ip::Address &caddr, const LogTags_ot logcode, const int len, const char *url, int delay, AccessLogEntry::Pointer &al)
252 {
253  assert(logcode != LOG_TAG_NONE);
254 
255  // Optimization: No premature (ALE creation in) icpSyncAle().
256  if (al) {
257  icpSyncAle(al, caddr, url, len, delay);
258  al->cache.code.update(logcode);
259  }
260 
261  if (logcode == LOG_ICP_QUERY)
262  return; // we never log queries
263 
264  if (!Config.onoff.log_udp) {
265  clientdbUpdate(caddr, al ? al->cache.code : LogTags(logcode), AnyP::PROTO_ICP, len);
266  return;
267  }
268 
269  if (!al) {
270  // The above attempt to optimize ALE creation has failed. We do need it.
271  icpSyncAle(al, caddr, url, len, delay);
272  al->cache.code.update(logcode);
273  }
274  clientdbUpdate(caddr, al->cache.code, AnyP::PROTO_ICP, len);
275  accessLogLog(al, NULL);
276 }
277 
279 void
280 icpUdpSendQueue(int fd, void *)
281 {
282  DelayedUdpSend *q;
283 
284  while ((q = IcpQueueHead) != NULL) {
285  int delay = tvSubUsec(q->queue_time, current_time);
286  /* increment delay to prevent looping */
287  const int x = icpUdpSend(fd, q->address, q->msg, ++delay, q->ale);
288  IcpQueueHead = q->next;
289  delete q;
290 
291  if (x < 0)
292  break;
293  }
294 }
295 
296 icp_common_t *
298  icp_opcode opcode,
299  int flags,
300  const char *url,
301  int reqnum,
302  int pad)
303 {
304  char *buf = NULL;
305  icp_common_t *headerp = NULL;
306  char *urloffset = NULL;
307  int buf_len;
308  buf_len = sizeof(icp_common_t) + strlen(url) + 1;
309 
310  if (opcode == ICP_QUERY)
311  buf_len += sizeof(uint32_t);
312 
313  buf = (char *) xcalloc(buf_len, 1);
314 
315  headerp = (icp_common_t *) (void *) buf;
316 
317  headerp->opcode = (char) opcode;
318 
319  headerp->version = ICP_VERSION_CURRENT;
320 
321  headerp->length = (uint16_t) htons(buf_len);
322 
323  headerp->reqnum = htonl(reqnum);
324 
325  headerp->flags = htonl(flags);
326 
327  headerp->pad = htonl(pad);
328 
329  headerp->shostid = 0;
330 
331  urloffset = buf + sizeof(icp_common_t);
332 
333  if (opcode == ICP_QUERY)
334  urloffset += sizeof(uint32_t);
335 
336  memcpy(urloffset, url, strlen(url));
337 
338  return (icp_common_t *)buf;
339 }
340 
341 // TODO: Move retries to icpCreateAndSend(); the other caller does not retry.
344 static int
345 icpUdpSend(int fd,
346  const Ip::Address &to,
347  icp_common_t * msg,
348  int delay,
350 {
351  int x;
352  int len;
353  len = (int) ntohs(msg->length);
354  debugs(12, 5, "icpUdpSend: FD " << fd << " sending " <<
355  icp_opcode_str[msg->opcode] << ", " << len << " bytes to " << to);
356 
357  x = comm_udp_sendto(fd, to, msg, len);
358 
359  if (x >= 0) {
360  /* successfully written */
361  const auto logcode = icpLogFromICPCode(static_cast<icp_opcode>(msg->opcode));
362  icpLogIcp(to, logcode, len, (char *) (msg + 1), delay, al);
363  icpCount(msg, SENT, (size_t) len, delay);
364  safe_free(msg);
365  } else if (0 == delay) {
366  /* send failed, but queue it */
367  const auto queue = new DelayedUdpSend();
368  queue->address = to;
369  queue->msg = msg;
370  queue->queue_time = current_time;
371  queue->ale = al;
372 
373  if (IcpQueueHead == NULL) {
374  IcpQueueHead = queue;
375  IcpQueueTail = queue;
376  } else if (IcpQueueTail == IcpQueueHead) {
377  IcpQueueTail = queue;
378  IcpQueueHead->next = queue;
379  } else {
380  IcpQueueTail->next = queue;
381  IcpQueueTail = queue;
382  }
383 
386  } else {
387  /* don't queue it */
388  // XXX: safe_free(msg)
390  }
391 
392  return x;
393 }
394 
403 {
404  /* if store is rebuilding, return a UDP_MISS_NOFETCH */
405 
408  return ICP_MISS_NOFETCH;
409  }
410 
411  return ICP_ERR;
412 }
413 
414 static LogTags_ot
416 {
417  if (opcode == ICP_ERR)
418  return LOG_UDP_INVALID;
419 
420  if (opcode == ICP_DENIED)
421  return LOG_UDP_DENIED;
422 
423  if (opcode == ICP_HIT)
424  return LOG_UDP_HIT;
425 
426  if (opcode == ICP_MISS)
427  return LOG_UDP_MISS;
428 
429  if (opcode == ICP_MISS_NOFETCH)
430  return LOG_UDP_MISS_NOFETCH;
431 
432  if (opcode == ICP_DECHO)
433  return LOG_ICP_QUERY;
434 
435  if (opcode == ICP_QUERY)
436  return LOG_ICP_QUERY;
437 
438  fatal("expected ICP opcode\n");
439 
440  return LOG_UDP_INVALID;
441 }
442 
443 void
444 icpCreateAndSend(icp_opcode opcode, int flags, char const *url, int reqnum, int pad, int fd, const Ip::Address &from, AccessLogEntry::Pointer al)
445 {
446  // update potentially shared ALE ASAP; the ICP query itself may be delayed
447  if (al)
448  al->cache.code.update(icpLogFromICPCode(opcode));
449  icp_common_t *reply = icp_common_t::CreateMessage(opcode, flags, url, reqnum, pad);
450  icpUdpSend(fd, from, reply, 0, al);
451 }
452 
453 void
454 icpDenyAccess(Ip::Address &from, char *url, int reqnum, int fd)
455 {
456  debugs(12, 2, "icpDenyAccess: Access Denied for " << from << " by " << AclMatchedName << ".");
457 
458  if (clientdbCutoffDenied(from)) {
459  /*
460  * count this DENIED query in the clientdb, even though
461  * we're not sending an ICP reply...
462  */
464  } else {
465  icpCreateAndSend(ICP_DENIED, 0, url, reqnum, 0, fd, from, nullptr);
466  }
467 }
468 
469 bool
471 {
472  /* absent any explicit rules, we deny all */
473  if (!Config.accessList.icp)
474  return false;
475 
476  ACLFilledChecklist checklist(Config.accessList.icp, icp_request, NULL);
477  checklist.src_addr = from;
478  checklist.my_addr.setNoAddr();
479  return checklist.fastCheck().allowed();
480 }
481 
482 char const *
483 icpGetUrlToSend(char *url)
484 {
485  if (strpbrk(url, w_space))
486  return rfc1738_escape(url);
487  else
488  return url;
489 }
490 
491 HttpRequest *
492 icpGetRequest(char *url, int reqnum, int fd, Ip::Address &from)
493 {
494  if (strpbrk(url, w_space)) {
495  url = rfc1738_escape(url);
496  icpCreateAndSend(ICP_ERR, 0, rfc1738_escape(url), reqnum, 0, fd, from, nullptr);
497  return NULL;
498  }
499 
500  HttpRequest *result;
502  if ((result = HttpRequest::FromUrl(url, mx)) == NULL)
503  icpCreateAndSend(ICP_ERR, 0, url, reqnum, 0, fd, from, nullptr);
504 
505  return result;
506 
507 }
508 
509 static void
510 doV2Query(int fd, Ip::Address &from, char *buf, icp_common_t header)
511 {
512  int rtt = 0;
513  int src_rtt = 0;
514  uint32_t flags = 0;
515  /* We have a valid packet */
516  char *url = buf + sizeof(icp_common_t) + sizeof(uint32_t);
517  HttpRequest *icp_request = icpGetRequest(url, header.reqnum, fd, from);
518 
519  if (!icp_request)
520  return;
521 
522  HTTPMSGLOCK(icp_request);
523 
524  if (!icpAccessAllowed(from, icp_request)) {
525  icpDenyAccess(from, url, header.reqnum, fd);
526  HTTPMSGUNLOCK(icp_request);
527  return;
528  }
529 #if USE_ICMP
530  if (header.flags & ICP_FLAG_SRC_RTT) {
531  rtt = netdbHostRtt(icp_request->url.host());
532  int hops = netdbHostHops(icp_request->url.host());
533  src_rtt = ((hops & 0xFFFF) << 16) | (rtt & 0xFFFF);
534 
535  if (rtt)
536  flags |= ICP_FLAG_SRC_RTT;
537  }
538 #endif /* USE_ICMP */
539 
540  /* The peer is allowed to use this cache */
541  ICP2State *state = new ICP2State(header, icp_request);
542  state->fd = fd;
543  state->from = from;
544  state->url = xstrdup(url);
545  state->flags = flags;
546  state->rtt = rtt;
547  state->src_rtt = src_rtt;
548 
550 
551  HTTPMSGUNLOCK(icp_request);
552 }
553 
554 void
556 {
557  if (neighbors_do_private_keys && reqnum == 0) {
558  debugs(12, DBG_CRITICAL, "icpHandleIcpV2: Neighbor " << from << " returned reqnum = 0");
559  debugs(12, DBG_CRITICAL, "icpHandleIcpV2: Disabling use of private keys");
561  }
562 
563  char *url = buf + sizeof(icp_common_t);
564  debugs(12, 3, "icpHandleIcpV2: " << icp_opcode_str[opcode] << " from " << from << " for '" << url << "'");
565 
566  const cache_key *key = icpGetCacheKey(url, (int) reqnum);
567  /* call neighborsUdpAck even if ping_status != PING_WAITING */
568  neighborsUdpAck(key, this, from);
569 }
570 
571 static void
572 icpHandleIcpV2(int fd, Ip::Address &from, char *buf, int len)
573 {
574  if (len <= 0) {
575  debugs(12, 3, "icpHandleIcpV2: ICP message is too small");
576  return;
577  }
578 
579  icp_common_t header(buf, len);
580  /*
581  * Length field should match the number of bytes read
582  */
583 
584  if (len != header.length) {
585  debugs(12, 3, "icpHandleIcpV2: ICP message is too small");
586  return;
587  }
588 
589  switch (header.opcode) {
590 
591  case ICP_QUERY:
592  /* We have a valid packet */
593  doV2Query(fd, from, buf, header);
594  break;
595 
596  case ICP_HIT:
597 
598  case ICP_DECHO:
599 
600  case ICP_MISS:
601 
602  case ICP_DENIED:
603 
604  case ICP_MISS_NOFETCH:
605  header.handleReply(buf, from);
606  break;
607 
608  case ICP_INVALID:
609 
610  case ICP_ERR:
611  break;
612 
613  default:
614  debugs(12, DBG_CRITICAL, "icpHandleIcpV2: UNKNOWN OPCODE: " << header.opcode << " from " << from);
615 
616  break;
617  }
618 }
619 
620 #ifdef ICP_PKT_DUMP
621 static void
622 icpPktDump(icp_common_t * pkt)
623 {
624  Ip::Address a;
625 
626  debugs(12, 9, "opcode: " << std::setw(3) << pkt->opcode << " " << icp_opcode_str[pkt->opcode]);
627  debugs(12, 9, "version: "<< std::left << std::setw(8) << pkt->version);
628  debugs(12, 9, "length: "<< std::left << std::setw(8) << ntohs(pkt->length));
629  debugs(12, 9, "reqnum: "<< std::left << std::setw(8) << ntohl(pkt->reqnum));
630  debugs(12, 9, "flags: "<< std::left << std::hex << std::setw(8) << ntohl(pkt->flags));
631  a = (struct in_addr)pkt->shostid;
632  debugs(12, 9, "shostid: " << a );
633  debugs(12, 9, "payload: " << (char *) pkt + sizeof(icp_common_t));
634 }
635 
636 #endif
637 
638 void
639 icpHandleUdp(int sock, void *)
640 {
641  int *N = &incoming_sockets_accepted;
642 
643  Ip::Address from;
645  int len;
646  int icp_version;
647  int max = INCOMING_UDP_MAX;
649 
650  while (max) {
651  --max;
652  len = comm_udp_recvfrom(sock,
653  buf,
655  0,
656  from);
657 
658  if (len == 0)
659  break;
660 
661  if (len < 0) {
662  int xerrno = errno;
663  if (ignoreErrno(xerrno))
664  break;
665 
666 #if _SQUID_LINUX_
667  /* Some Linux systems seem to set the FD for reading and then
668  * return ECONNREFUSED when sendto() fails and generates an ICMP
669  * port unreachable message. */
670  /* or maybe an EHOSTUNREACH "No route to host" message */
671  if (xerrno != ECONNREFUSED && xerrno != EHOSTUNREACH)
672 #endif
673  debugs(50, DBG_IMPORTANT, "icpHandleUdp: FD " << sock << " recvfrom: " << xstrerr(xerrno));
674 
675  break;
676  }
677 
678  ++(*N);
679  icpCount(buf, RECV, (size_t) len, 0);
680  buf[len] = '\0';
681  debugs(12, 4, "icpHandleUdp: FD " << sock << ": received " <<
682  (unsigned long int)len << " bytes from " << from);
683 
684 #ifdef ICP_PACKET_DUMP
685 
686  icpPktDump(buf);
687 #endif
688 
689  if ((size_t) len < sizeof(icp_common_t)) {
690  debugs(12, 4, "icpHandleUdp: Ignoring too-small UDP packet");
691  break;
692  }
693 
694  icp_version = (int) buf[1]; /* cheat! */
695 
696  if (icpOutgoingConn->local == from)
697  // ignore ICP packets which loop back (multicast usually)
698  debugs(12, 4, "icpHandleUdp: Ignoring UDP packet sent by myself");
699  else if (icp_version == ICP_VERSION_2)
700  icpHandleIcpV2(sock, from, buf, len);
701  else if (icp_version == ICP_VERSION_3)
702  icpHandleIcpV3(sock, from, buf, len);
703  else
704  debugs(12, DBG_IMPORTANT, "WARNING: Unused ICP version " << icp_version <<
705  " received from " << from);
706  }
707 }
708 
709 void
711 {
712  uint16_t port;
713 
714  if ((port = Config.Port.icp) <= 0)
715  return;
716 
717  icpIncomingConn = new Comm::Connection;
718  icpIncomingConn->local = Config.Addrs.udp_incoming;
719  icpIncomingConn->local.port(port);
720 
721  if (!Ip::EnableIpv6 && !icpIncomingConn->local.setIPv4()) {
722  debugs(12, DBG_CRITICAL, "ERROR: IPv6 is disabled. " << icpIncomingConn->local << " is not an IPv4 address.");
723  fatal("ICP port cannot be opened.");
724  }
725  /* split-stack for now requires default IPv4-only ICP */
726  if (Ip::EnableIpv6&IPV6_SPECIAL_SPLITSTACK && icpIncomingConn->local.isAnyAddr()) {
727  icpIncomingConn->local.setIPv4();
728  }
729 
730  AsyncCall::Pointer call = asyncCall(12, 2,
731  "icpIncomingConnectionOpened",
733 
734  Ipc::StartListening(SOCK_DGRAM,
735  IPPROTO_UDP,
736  icpIncomingConn,
737  Ipc::fdnInIcpSocket, call);
738 
739  if ( !Config.Addrs.udp_outgoing.isNoAddr() ) {
740  icpOutgoingConn = new Comm::Connection;
741  icpOutgoingConn->local = Config.Addrs.udp_outgoing;
742  icpOutgoingConn->local.port(port);
743 
744  if (!Ip::EnableIpv6 && !icpOutgoingConn->local.setIPv4()) {
745  debugs(49, DBG_CRITICAL, "ERROR: IPv6 is disabled. " << icpOutgoingConn->local << " is not an IPv4 address.");
746  fatal("ICP port cannot be opened.");
747  }
748  /* split-stack for now requires default IPv4-only ICP */
749  if (Ip::EnableIpv6&IPV6_SPECIAL_SPLITSTACK && icpOutgoingConn->local.isAnyAddr()) {
750  icpOutgoingConn->local.setIPv4();
751  }
752 
753  enter_suid();
754  comm_open_listener(SOCK_DGRAM, IPPROTO_UDP, icpOutgoingConn, "Outgoing ICP Port");
755  leave_suid();
756 
757  if (!Comm::IsConnOpen(icpOutgoingConn))
758  fatal("Cannot open Outgoing ICP Port");
759 
760  debugs(12, DBG_CRITICAL, "Sending ICP messages from " << icpOutgoingConn->local);
761 
762  Comm::SetSelect(icpOutgoingConn->fd, COMM_SELECT_READ, icpHandleUdp, NULL, 0);
763  fd_note(icpOutgoingConn->fd, "Outgoing ICP socket");
764  }
765 }
766 
767 static void
769 {
770  if (!Comm::IsConnOpen(conn))
771  fatal("Cannot open ICP Port");
772 
774 
775  for (const wordlist *s = Config.mcast_group_list; s; s = s->next)
776  ipcache_nbgethostbyname(s->key, mcastJoinGroups, NULL); // XXX: pass the conn for mcastJoinGroups usage.
777 
778  debugs(12, DBG_IMPORTANT, "Accepting ICP messages on " << conn->local);
779 
780  fd_note(conn->fd, "Incoming ICP port");
781 
783  icpOutgoingConn = conn;
784  debugs(12, DBG_IMPORTANT, "Sending ICP messages from " << icpOutgoingConn->local);
785  }
786 }
787 
792 void
794 {
795  if (!Comm::IsConnOpen(icpIncomingConn))
796  return;
797 
798  debugs(12, DBG_IMPORTANT, "Stop receiving ICP on " << icpIncomingConn->local);
799 
804  icpIncomingConn = NULL;
805 
812  assert(Comm::IsConnOpen(icpOutgoingConn));
813 
814  Comm::SetSelect(icpOutgoingConn->fd, COMM_SELECT_READ, NULL, NULL, 0);
815 }
816 
817 void
819 {
821 
822  if (icpOutgoingConn != NULL) {
823  debugs(12, DBG_IMPORTANT, "Stop sending ICP from " << icpOutgoingConn->local);
824  icpOutgoingConn = NULL;
825  }
826 }
827 
828 static void
829 icpCount(void *buf, int which, size_t len, int delay)
830 {
831  icp_common_t *icp = (icp_common_t *) buf;
832 
833  if (len < sizeof(*icp))
834  return;
835 
836  if (SENT == which) {
839 
840  if (ICP_QUERY == icp->opcode) {
843  } else {
846  /* this is the sent-reply service time */
848  }
849 
850  if (ICP_HIT == icp->opcode)
852  } else if (RECV == which) {
855 
856  if (ICP_QUERY == icp->opcode) {
859  } else {
862  /* statCounter.icp.querySvcTime set in clientUpdateCounters */
863  }
864 
865  if (ICP_HIT == icp->opcode)
867  }
868 }
869 
870 #define N_QUERIED_KEYS 8192
871 #define N_QUERIED_KEYS_MASK 8191
873 
874 int
876 {
877  static int reqnum = 0;
878 
879  if (++reqnum < 0)
880  reqnum = 1;
881 
882  storeKeyCopy(queried_keys[reqnum & N_QUERIED_KEYS_MASK], key);
883 
884  return reqnum;
885 }
886 
887 const cache_key *
888 icpGetCacheKey(const char *url, int reqnum)
889 {
890  if (neighbors_do_private_keys && reqnum)
891  return queried_keys[reqnum & N_QUERIED_KEYS_MASK];
892 
893  return storeKeyPublic(url, Http::METHOD_GET);
894 }
895 
bool setIPv4()
Definition: Address.cc:217
Definition: ICP.h:64
int comm_udp_recvfrom(int fd, void *buf, size_t len, int flags, Ip::Address &from)
Definition: comm.cc:121
int replies_dropped
Definition: StatCounters.h:73
static int store_dirs_rebuilding
the number of cache_dirs being rebuilt; TODO: move to Disks::Rebuilding
Definition: Controller.h:137
void count(double val)
Definition: StatHist.cc:57
bool startCollapsingOn(const StoreEntry &, const bool doingRevalidation)
Definition: store_client.cc:65
#define COMM_SELECT_READ
Definition: defines.h:36
void StartListening(int sock_type, int proto, const Comm::ConnectionPointer &listenConn, FdNoteId fdNote, AsyncCall::Pointer &callback)
StatCounters statCounter
Definition: StatCounters.cc:12
#define assert(EX)
Definition: assert.h:17
Ip::Address udp_outgoing
Definition: SquidConfig.h:232
int src_rtt
Definition: icp_v2.cc:207
icp_common_t()
Definition: icp_v2.cc:106
ByteCounter r_kbytes_recv
Definition: StatCounters.h:79
int neighbors_do_private_keys
ByteCounter kbytes_recv
Definition: StatCounters.h:77
#define ICP_VERSION_3
Definition: defines.h:77
int validToSend() const
Definition: store.cc:1431
struct SquidConfig::@100 Port
void fd_note(int fd, const char *s)
Definition: fd.cc:251
Ip::Address from
Definition: ICP.h:75
icp_opcode icpGetCommonOpcode()
Definition: icp_v2.cc:402
void accessLogLog(AccessLogEntry::Pointer &, ACLChecklist *checklist)
Definition: access_log.cc:144
void icpUdpSendQueue(int fd, void *)
Definition: icp_v2.cc:280
static void icpLogIcp(const Ip::Address &, const LogTags_ot, int, const char *, const int, AccessLogEntryPointer &)
updates ALE (if any) and logs the transaction (if needed)
Definition: icp_v2.cc:251
struct SquidConfig::@113 onoff
const cache_key * icpGetCacheKey(const char *url, int reqnum)
Definition: icp_v2.cc:888
ByteCounter r_kbytes_sent
Definition: StatCounters.h:76
struct timeval queue_time
queuing timestamp
Definition: icp_v2.cc:57
unsigned char cache_key
Store key.
Definition: forward.h:29
int opt_reload_hit_only
#define xcalloc
Definition: membanger.c:57
Ip::Address src_addr
void comm_open_listener(int sock_type, int proto, Comm::ConnectionPointer &conn, const char *note)
Definition: comm.cc:232
bool confirmAndPrepHit(const StoreEntry &)
either confirms and starts processing a cache hit or returns false
Definition: icp_v2.cc:157
bool isNoAddr() const
Definition: Address.cc:277
struct _request * request(char *urlin)
Definition: tcp-banger2.c:291
#define xstrdup
static int version
void icpConnectionShutdown(void)
Definition: icp_v2.cc:793
Ip::Address address
remote peer (which may not be a cache_peer)
Definition: icp_v2.cc:53
unsigned char version
Definition: ICP.h:40
virtual void created(StoreEntry *newEntry) override
Definition: icp_v2.cc:215
IPH mcastJoinGroups
#define safe_free(x)
Definition: xalloc.h:73
wordlist * mcast_group_list
Definition: SquidConfig.h:242
AccessLogEntry::Pointer al
info for the future access.log, and external ACL
#define rfc1738_escape(x)
Definition: rfc1738.h:52
struct SquidConfig::@108 Addrs
ByteCounter kbytes_sent
Definition: StatCounters.h:74
char const * icpGetUrlToSend(char *url)
Definition: icp_v2.cc:483
void HTTPMSGLOCK(Http::Message *a)
Definition: Message.h:154
void clientdbUpdate(const Ip::Address &addr, const LogTags &ltype, AnyP::ProtocolType p, size_t size)
Definition: client_db.cc:139
int netdbHostRtt(const char *host)
Definition: net_db.cc:1052
virtual void fillChecklist(ACLFilledChecklist &) const override
configure the ACL checklist with the current transaction state
Definition: icp_v2.cc:184
int fd
Definition: ICP.h:73
void handleReply(char *buf, Ip::Address &from)
Definition: icp_v2.cc:555
#define DBG_CRITICAL
Definition: Debug.h:45
int conn
the current server connection FD
Definition: Transport.cc:26
unsigned short length
Definition: ICP.h:42
bool icpAccessAllowed(Ip::Address &from, HttpRequest *icp_request)
Definition: icp_v2.cc:470
struct timeval current_time
Definition: stub_time.cc:15
int comm_udp_sendto(int fd, const Ip::Address &to_addr, const void *buf, int len)
Definition: comm.cc:927
DelayedUdpSend * next
invasive FIFO queue of delayed ICP messages
Definition: icp_v2.cc:55
A const & max(A const &lhs, A const &rhs)
time_t squid_curtime
Definition: stub_time.cc:17
int icpSetCacheKey(const cache_key *key)
Definition: icp_v2.cc:875
bool isAnyAddr() const
Definition: Address.cc:163
void neighborsUdpAck(const cache_key *key, icp_common_t *header, const Ip::Address &from)
Definition: neighbors.cc:997
#define w_space
uint32_t reqnum
Definition: ICP.h:44
int refreshCheckICP(const StoreEntry *entry, HttpRequest *request)
Definition: refresh.cc:600
AsyncCall * asyncCall(int aDebugSection, int aDebugLevel, const char *aName, const Dialer &aDialer)
Definition: AsyncCall.h:156
#define ICP_VERSION_2
Definition: defines.h:76
void icpOpenPorts(void)
Definition: icp_v2.cc:710
int replies_queued
Definition: StatCounters.h:72
StatHist replySvcTime
Definition: StatCounters.h:81
static void getPublic(StoreClient *aClient, const char *uri, const HttpRequestMethod &method)
Definition: store.cc:521
void setNoAddr()
Definition: Address.cc:285
const char * xstrerr(int error)
Definition: xstrerror.cc:83
bool IsConnOpen(const Comm::ConnectionPointer &conn)
Definition: Connection.cc:24
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:124
#define DBG_IMPORTANT
Definition: Debug.h:46
void SetSelect(int, unsigned int, PF *, void *, time_t)
Mark an FD to be watched for its IO status.
Definition: ModDevPoll.cc:225
#define ICP_VERSION_CURRENT
Definition: defines.h:78
LogTags_ot
Definition: LogTags.h:22
#define SQUID_MD5_DIGEST_LENGTH
Definition: md5.h:66
~ICP2State()
Definition: icp_v2.cc:211
void icpHandleUdp(int sock, void *)
Definition: icp_v2.cc:639
#define INCOMING_UDP_MAX
Definition: Loops.h:45
void leave_suid(void)
Definition: tools.cc:504
unsigned char opcode
Definition: ICP.h:38
static void doV2Query(int fd, Ip::Address &from, char *buf, icp_common_t header)
Definition: icp_v2.cc:510
#define COMM_SELECT_WRITE
Definition: defines.h:37
unsigned short icp
Definition: SquidConfig.h:131
AnyP::Uri url
the request URI
Definition: HttpRequest.h:103
void icpClosePorts(void)
Definition: icp_v2.cc:818
void fatal(const char *message)
Definition: fatal.cc:28
char * url
Definition: ICP.h:76
int incoming_sockets_accepted
Ip::Address udp_incoming
Definition: SquidConfig.h:231
bool allowed() const
Definition: Acl.h:141
int icp_hit_stale
Definition: SquidConfig.h:279
icp_opcode
Definition: icp_opcode.h:13
icp_common_t * msg
ICP message with network byte order fields.
Definition: icp_v2.cc:54
icp_common_t header
Definition: ICP.h:71
void ipcache_nbgethostbyname(const char *name, IPH *handler, void *handlerData)
Definition: ipcache.cc:600
const char * AclMatchedName
Definition: Acl.cc:30
void host(const char *src)
Definition: Uri.cc:47
static int port
Definition: ldap_backend.cc:69
uint32_t flags
Definition: icp_v2.cc:208
int test_reachability
Definition: SquidConfig.h:286
static LogTags_ot icpLogFromICPCode(icp_opcode)
Definition: icp_v2.cc:415
#define LOCAL_ARRAY(type, name, size)
Definition: leakcheck.h:18
SQUIDCEXTERN int tvSubUsec(struct timeval, struct timeval)
Definition: util.c:39
virtual ~ICPState()
Definition: icp_v2.cc:150
int unsigned int const char *desc STUB void int len
Definition: stub_fd.cc:20
static HttpRequest * FromUrl(const char *url, const MasterXaction::Pointer &, const HttpRequestMethod &method=Http::METHOD_GET)
Definition: HttpRequest.cc:522
HttpRequest * icpGetRequest(char *url, int reqnum, int fd, Ip::Address &from)
Definition: icp_v2.cc:492
void const char * buf
Definition: stub_helper.cc:16
uint32_t flags
Definition: ICP.h:45
class AccessLogEntry::CacheDetails cache
void icpCreateAndSend(icp_opcode opcode, int flags, char const *url, int reqnum, int pad, int fd, const Ip::Address &from, AccessLogEntry::Pointer al)
Definition: icp_v2.cc:444
static void icpSyncAle(AccessLogEntryPointer &al, const Ip::Address &caddr, const char *url, int len, int delay)
Definition: icp_v2.cc:76
unsigned short port() const
Definition: Address.cc:771
uint32_t pad
Definition: ICP.h:46
struct StatCounters::@131 icp
Ip::Address local
Definition: Connection.h:135
bool SIGHDLR int STUB void int
Definition: stub_tools.cc:68
int ignoreErrno(int ierrno)
Definition: comm.cc:1477
int netdbHostHops(const char *host)
Definition: net_db.cc:1037
static void icpIncomingConnectionOpened(const Comm::ConnectionPointer &conn, int errNo)
Definition: icp_v2.cc:768
allow_t const & fastCheck()
Definition: Checklist.cc:336
void enter_suid(void)
Definition: tools.cc:575
AccessLogEntryPointer al
Definition: ICP.h:86
#define N_QUERIED_KEYS
Definition: icp_v2.cc:870
ICP2State(icp_common_t &aHeader, HttpRequest *aRequest)
Definition: icp_v2.cc:200
icp_opcode getOpCode() const
Definition: icp_v2.cc:131
uint32_t shostid
Definition: ICP.h:48
struct SquidConfig::@114 accessList
int clientdbCutoffDenied(const Ip::Address &addr)
Definition: client_db.cc:210
void icpHandleIcpV3(int, Ip::Address &, char *, int)
Definition: icp_v3.cc:88
virtual bool isNull() const
Definition: Store.h:230
cache_key * storeKeyCopy(cache_key *dst, const cache_key *src)
bool hittingRequiresCollapsing() const
whether this entry can feed collapsed requests and only them
Definition: Store.h:192
#define N_QUERIED_KEYS_MASK
Definition: icp_v2.cc:871
void icpDenyAccess(Ip::Address &from, char *url, int reqnum, int fd)
Definition: icp_v2.cc:454
int EnableIpv6
Whether IPv6 is supported and type of support.
Definition: tools.h:25
static void icpHandleIcpV2(int, Ip::Address &, char *, int)
Definition: icp_v2.cc:572
int a
Definition: membanger.c:50
#define ICP_FLAG_SRC_RTT
Definition: defines.h:73
HttpRequest * request
Definition: ICP.h:72
#define SQUID_UDP_SO_RCVBUF
Definition: squid.h:60
a delayed icpUdpSend() call
Definition: icp_v2.cc:51
void setRequest(HttpRequest *)
configure client request-related fields for the first time
int rtt
Definition: icp_v2.cc:206
time_t hit_only_mode_until
the ICP/neighbors subsystem
Definition: enums.h:167
virtual LogTags * loggingTags() override
Definition: icp_v2.cc:175
ByteCounter q_kbytes_recv
Definition: StatCounters.h:78
ICPState(icp_common_t &aHeader, HttpRequest *aRequest)
Definition: icp_v2.cc:141
void netdbPingSite(const char *hostname)
Definition: net_db.cc:909
#define IPV6_SPECIAL_SPLITSTACK
Definition: tools.h:22
ByteCounter q_kbytes_sent
Definition: StatCounters.h:75
dials a UDP port-opened call
Definition: UdpOpenDialer.h:18
const cache_key * storeKeyPublic(const char *url, const HttpRequestMethod &method, const KeyScope keyScope)
AccessLogEntryPointer ale
sender's master transaction summary
Definition: icp_v2.cc:56
static icp_common_t * CreateMessage(icp_opcode opcode, int flags, const char *url, int reqnum, int pad)
Definition: icp_v2.cc:297
class SquidConfig Config
Definition: SquidConfig.cc:12
static int icpUdpSend(int fd, const Ip::Address &to, icp_common_t *msg, int delay, AccessLogEntryPointer al)
Definition: icp_v2.cc:345
#define NULL
Definition: types.h:166
void HTTPMSGUNLOCK(Http::Message *a)
Definition: Message.h:144
static void icpCount(void *, int, size_t, int)
Definition: icp_v2.cc:829
Definition: enums.h:168
const char * icp_opcode_str[]
wordlist * next
Definition: wordlist.h:34

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors