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  al->setVirginUrlForMissingRequest(al->url);
84  // XXX: move to use icp.clientReply instead
85  al->http.clientReplySz.payloadData = len;
86  al->cache.start_time = current_time;
87  al->cache.start_time.tv_sec -= delay;
88  al->cache.trTime.tv_sec = delay;
89  al->cache.trTime.tv_usec = 0;
90 }
91 
100 
105 
106 /* icp_common_t */
108  opcode(ICP_INVALID), version(0), length(0), reqnum(0),
109  flags(0), pad(0), shostid(0)
110 {}
111 
112 icp_common_t::icp_common_t(char *buf, unsigned int len) :
113  opcode(ICP_INVALID), version(0), reqnum(0), flags(0), pad(0), shostid(0)
114 {
115  if (len < sizeof(icp_common_t)) {
116  /* mark as invalid */
117  length = len + 1;
118  return;
119  }
120 
121  memcpy(this, buf, sizeof(icp_common_t));
122  /*
123  * Convert network order sensitive fields
124  */
125  length = ntohs(length);
126  reqnum = ntohl(reqnum);
127  flags = ntohl(flags);
128  pad = ntohl(pad);
129 }
130 
133 {
134  if (opcode > static_cast<char>(icp_opcode::ICP_END))
135  return ICP_INVALID;
136 
137  return static_cast<icp_opcode>(opcode);
138 }
139 
140 /* ICPState */
141 
143  header(aHeader),
144  request(aRequest),
145  fd(-1),
146  url(NULL)
147 {
149 }
150 
152 {
153  safe_free(url);
155 }
156 
157 bool
159 {
160  if (!e.validToSend())
161  return false;
162 
164  return false;
165 
166  if (e.hittingRequiresCollapsing() && !startCollapsingOn(e, false))
167  return false;
168 
169  return true;
170 }
171 
172 LogTags *
174 {
175  // calling icpSyncAle(LOG_TAG_NONE) here would not change cache.code
176  if (!al)
177  al = new AccessLogEntry();
178  return &al->cache.code;
179 }
180 
181 void
183 {
184  checklist.setRequest(request);
185  icpSyncAle(al, from, url, 0, 0);
186  checklist.al = al;
187 }
188 
189 /* End ICPState */
190 
191 /* ICP2State */
192 
194 class ICP2State: public ICPState
195 {
196 
197 public:
198  ICP2State(icp_common_t & aHeader, HttpRequest *aRequest):
199  ICPState(aHeader, aRequest),rtt(0),src_rtt(0),flags(0) {}
200 
201  ~ICP2State();
202  virtual void created(StoreEntry * newEntry) override;
203 
204  int rtt;
205  int src_rtt;
206  uint32_t flags;
207 };
208 
210 {}
211 
212 void
214 {
215  debugs(12, 5, "icpHandleIcpV2: OPCODE " << icp_opcode_str[header.opcode]);
216  icp_opcode codeToSend;
217 
218  if (e && confirmAndPrepHit(*e)) {
219  codeToSend = ICP_HIT;
220  } else {
221 #if USE_ICMP
222  if (Config.onoff.test_reachability && rtt == 0) {
223  if ((rtt = netdbHostRtt(request->url.host())) == 0)
225  }
226 #endif /* USE_ICMP */
227 
228  if (icpGetCommonOpcode() != ICP_ERR)
229  codeToSend = icpGetCommonOpcode();
230  else if (Config.onoff.test_reachability && rtt == 0)
231  codeToSend = ICP_MISS_NOFETCH;
232  else
233  codeToSend = ICP_MISS;
234  }
235 
236  icpCreateAndSend(codeToSend, flags, url, header.reqnum, src_rtt, fd, from, al);
237 
238  // TODO: StoreClients must either store/lock or abandon found entries.
239  //if (e)
240  // e->abandon();
241 
242  delete this;
243 }
244 
245 /* End ICP2State */
246 
248 static void
249 icpLogIcp(const Ip::Address &caddr, const LogTags_ot logcode, const int len, const char *url, int delay, AccessLogEntry::Pointer &al)
250 {
251  assert(logcode != LOG_TAG_NONE);
252 
253  // Optimization: No premature (ALE creation in) icpSyncAle().
254  if (al) {
255  icpSyncAle(al, caddr, url, len, delay);
256  al->cache.code.update(logcode);
257  }
258 
259  if (logcode == LOG_ICP_QUERY)
260  return; // we never log queries
261 
262  if (!Config.onoff.log_udp) {
263  clientdbUpdate(caddr, al ? al->cache.code : LogTags(logcode), AnyP::PROTO_ICP, len);
264  return;
265  }
266 
267  if (!al) {
268  // The above attempt to optimize ALE creation has failed. We do need it.
269  icpSyncAle(al, caddr, url, len, delay);
270  al->cache.code.update(logcode);
271  }
272  clientdbUpdate(caddr, al->cache.code, AnyP::PROTO_ICP, len);
273  accessLogLog(al, NULL);
274 }
275 
277 void
278 icpUdpSendQueue(int fd, void *)
279 {
280  DelayedUdpSend *q;
281 
282  while ((q = IcpQueueHead) != NULL) {
283  int delay = tvSubUsec(q->queue_time, current_time);
284  /* increment delay to prevent looping */
285  const int x = icpUdpSend(fd, q->address, q->msg, ++delay, q->ale);
286  IcpQueueHead = q->next;
287  delete q;
288 
289  if (x < 0)
290  break;
291  }
292 }
293 
294 icp_common_t *
296  icp_opcode opcode,
297  int flags,
298  const char *url,
299  int reqnum,
300  int pad)
301 {
302  char *buf = NULL;
303  icp_common_t *headerp = NULL;
304  char *urloffset = NULL;
305  int buf_len;
306  buf_len = sizeof(icp_common_t) + strlen(url) + 1;
307 
308  if (opcode == ICP_QUERY)
309  buf_len += sizeof(uint32_t);
310 
311  buf = (char *) xcalloc(buf_len, 1);
312 
313  headerp = (icp_common_t *) (void *) buf;
314 
315  headerp->opcode = (char) opcode;
316 
317  headerp->version = ICP_VERSION_CURRENT;
318 
319  headerp->length = (uint16_t) htons(buf_len);
320 
321  headerp->reqnum = htonl(reqnum);
322 
323  headerp->flags = htonl(flags);
324 
325  headerp->pad = htonl(pad);
326 
327  headerp->shostid = 0;
328 
329  urloffset = buf + sizeof(icp_common_t);
330 
331  if (opcode == ICP_QUERY)
332  urloffset += sizeof(uint32_t);
333 
334  memcpy(urloffset, url, strlen(url));
335 
336  return (icp_common_t *)buf;
337 }
338 
339 // TODO: Move retries to icpCreateAndSend(); the other caller does not retry.
342 static int
343 icpUdpSend(int fd,
344  const Ip::Address &to,
345  icp_common_t * msg,
346  int delay,
348 {
349  int x;
350  int len;
351  len = (int) ntohs(msg->length);
352  debugs(12, 5, "icpUdpSend: FD " << fd << " sending " <<
353  icp_opcode_str[msg->opcode] << ", " << len << " bytes to " << to);
354 
355  x = comm_udp_sendto(fd, to, msg, len);
356 
357  if (x >= 0) {
358  /* successfully written */
359  const auto logcode = icpLogFromICPCode(static_cast<icp_opcode>(msg->opcode));
360  icpLogIcp(to, logcode, len, (char *) (msg + 1), delay, al);
361  icpCount(msg, SENT, (size_t) len, delay);
362  safe_free(msg);
363  } else if (0 == delay) {
364  /* send failed, but queue it */
365  const auto queue = new DelayedUdpSend();
366  queue->address = to;
367  queue->msg = msg;
368  queue->queue_time = current_time;
369  queue->ale = al;
370 
371  if (IcpQueueHead == NULL) {
372  IcpQueueHead = queue;
373  IcpQueueTail = queue;
374  } else if (IcpQueueTail == IcpQueueHead) {
375  IcpQueueTail = queue;
376  IcpQueueHead->next = queue;
377  } else {
378  IcpQueueTail->next = queue;
379  IcpQueueTail = queue;
380  }
381 
384  } else {
385  /* don't queue it */
386  // XXX: safe_free(msg)
388  }
389 
390  return x;
391 }
392 
401 {
402  /* if store is rebuilding, return a UDP_MISS_NOFETCH */
403 
406  return ICP_MISS_NOFETCH;
407  }
408 
409  return ICP_ERR;
410 }
411 
412 static LogTags_ot
414 {
415  if (opcode == ICP_ERR)
416  return LOG_UDP_INVALID;
417 
418  if (opcode == ICP_DENIED)
419  return LOG_UDP_DENIED;
420 
421  if (opcode == ICP_HIT)
422  return LOG_UDP_HIT;
423 
424  if (opcode == ICP_MISS)
425  return LOG_UDP_MISS;
426 
427  if (opcode == ICP_MISS_NOFETCH)
428  return LOG_UDP_MISS_NOFETCH;
429 
430  if (opcode == ICP_DECHO)
431  return LOG_ICP_QUERY;
432 
433  if (opcode == ICP_QUERY)
434  return LOG_ICP_QUERY;
435 
436  fatal("expected ICP opcode\n");
437 
438  return LOG_UDP_INVALID;
439 }
440 
441 void
442 icpCreateAndSend(icp_opcode opcode, int flags, char const *url, int reqnum, int pad, int fd, const Ip::Address &from, AccessLogEntry::Pointer al)
443 {
444  // update potentially shared ALE ASAP; the ICP query itself may be delayed
445  if (al)
446  al->cache.code.update(icpLogFromICPCode(opcode));
447  icp_common_t *reply = icp_common_t::CreateMessage(opcode, flags, url, reqnum, pad);
448  icpUdpSend(fd, from, reply, 0, al);
449 }
450 
451 void
452 icpDenyAccess(Ip::Address &from, char *url, int reqnum, int fd)
453 {
454  debugs(12, 2, "icpDenyAccess: Access Denied for " << from << " by " << AclMatchedName << ".");
455 
456  if (clientdbCutoffDenied(from)) {
457  /*
458  * count this DENIED query in the clientdb, even though
459  * we're not sending an ICP reply...
460  */
462  } else {
463  icpCreateAndSend(ICP_DENIED, 0, url, reqnum, 0, fd, from, nullptr);
464  }
465 }
466 
467 bool
469 {
470  /* absent any explicit rules, we deny all */
471  if (!Config.accessList.icp)
472  return false;
473 
474  ACLFilledChecklist checklist(Config.accessList.icp, icp_request, NULL);
475  checklist.src_addr = from;
476  checklist.my_addr.setNoAddr();
477  return checklist.fastCheck().allowed();
478 }
479 
480 char const *
481 icpGetUrlToSend(char *url)
482 {
483  if (strpbrk(url, w_space))
484  return rfc1738_escape(url);
485  else
486  return url;
487 }
488 
489 HttpRequest *
490 icpGetRequest(char *url, int reqnum, int fd, Ip::Address &from)
491 {
492  if (strpbrk(url, w_space)) {
493  url = rfc1738_escape(url);
494  icpCreateAndSend(ICP_ERR, 0, rfc1738_escape(url), reqnum, 0, fd, from, nullptr);
495  return NULL;
496  }
497 
498  HttpRequest *result;
500  if ((result = HttpRequest::FromUrl(url, mx)) == NULL)
501  icpCreateAndSend(ICP_ERR, 0, url, reqnum, 0, fd, from, nullptr);
502 
503  return result;
504 
505 }
506 
507 static void
508 doV2Query(int fd, Ip::Address &from, char *buf, icp_common_t header)
509 {
510  int rtt = 0;
511  int src_rtt = 0;
512  uint32_t flags = 0;
513  /* We have a valid packet */
514  char *url = buf + sizeof(icp_common_t) + sizeof(uint32_t);
515  HttpRequest *icp_request = icpGetRequest(url, header.reqnum, fd, from);
516 
517  if (!icp_request)
518  return;
519 
520  HTTPMSGLOCK(icp_request);
521 
522  if (!icpAccessAllowed(from, icp_request)) {
523  icpDenyAccess(from, url, header.reqnum, fd);
524  HTTPMSGUNLOCK(icp_request);
525  return;
526  }
527 #if USE_ICMP
528  if (header.flags & ICP_FLAG_SRC_RTT) {
529  rtt = netdbHostRtt(icp_request->url.host());
530  int hops = netdbHostHops(icp_request->url.host());
531  src_rtt = ((hops & 0xFFFF) << 16) | (rtt & 0xFFFF);
532 
533  if (rtt)
534  flags |= ICP_FLAG_SRC_RTT;
535  }
536 #endif /* USE_ICMP */
537 
538  /* The peer is allowed to use this cache */
539  ICP2State *state = new ICP2State(header, icp_request);
540  state->fd = fd;
541  state->from = from;
542  state->url = xstrdup(url);
543  state->flags = flags;
544  state->rtt = rtt;
545  state->src_rtt = src_rtt;
546 
548 
549  HTTPMSGUNLOCK(icp_request);
550 }
551 
552 void
554 {
555  if (neighbors_do_private_keys && reqnum == 0) {
556  debugs(12, DBG_CRITICAL, "icpHandleIcpV2: Neighbor " << from << " returned reqnum = 0");
557  debugs(12, DBG_CRITICAL, "icpHandleIcpV2: Disabling use of private keys");
559  }
560 
561  char *url = buf + sizeof(icp_common_t);
562  debugs(12, 3, "icpHandleIcpV2: " << icp_opcode_str[opcode] << " from " << from << " for '" << url << "'");
563 
564  const cache_key *key = icpGetCacheKey(url, (int) reqnum);
565  /* call neighborsUdpAck even if ping_status != PING_WAITING */
566  neighborsUdpAck(key, this, from);
567 }
568 
569 static void
570 icpHandleIcpV2(int fd, Ip::Address &from, char *buf, int len)
571 {
572  if (len <= 0) {
573  debugs(12, 3, "icpHandleIcpV2: ICP message is too small");
574  return;
575  }
576 
577  icp_common_t header(buf, len);
578  /*
579  * Length field should match the number of bytes read
580  */
581 
582  if (len != header.length) {
583  debugs(12, 3, "icpHandleIcpV2: ICP message is too small");
584  return;
585  }
586 
587  switch (header.opcode) {
588 
589  case ICP_QUERY:
590  /* We have a valid packet */
591  doV2Query(fd, from, buf, header);
592  break;
593 
594  case ICP_HIT:
595 
596  case ICP_DECHO:
597 
598  case ICP_MISS:
599 
600  case ICP_DENIED:
601 
602  case ICP_MISS_NOFETCH:
603  header.handleReply(buf, from);
604  break;
605 
606  case ICP_INVALID:
607 
608  case ICP_ERR:
609  break;
610 
611  default:
612  debugs(12, DBG_CRITICAL, "icpHandleIcpV2: UNKNOWN OPCODE: " << header.opcode << " from " << from);
613 
614  break;
615  }
616 }
617 
618 #ifdef ICP_PKT_DUMP
619 static void
620 icpPktDump(icp_common_t * pkt)
621 {
622  Ip::Address a;
623 
624  debugs(12, 9, "opcode: " << std::setw(3) << pkt->opcode << " " << icp_opcode_str[pkt->opcode]);
625  debugs(12, 9, "version: "<< std::left << std::setw(8) << pkt->version);
626  debugs(12, 9, "length: "<< std::left << std::setw(8) << ntohs(pkt->length));
627  debugs(12, 9, "reqnum: "<< std::left << std::setw(8) << ntohl(pkt->reqnum));
628  debugs(12, 9, "flags: "<< std::left << std::hex << std::setw(8) << ntohl(pkt->flags));
629  a = (struct in_addr)pkt->shostid;
630  debugs(12, 9, "shostid: " << a );
631  debugs(12, 9, "payload: " << (char *) pkt + sizeof(icp_common_t));
632 }
633 
634 #endif
635 
636 void
637 icpHandleUdp(int sock, void *)
638 {
639  int *N = &incoming_sockets_accepted;
640 
641  Ip::Address from;
643  int len;
644  int icp_version;
645  int max = INCOMING_UDP_MAX;
647 
648  while (max) {
649  --max;
650  len = comm_udp_recvfrom(sock,
651  buf,
653  0,
654  from);
655 
656  if (len == 0)
657  break;
658 
659  if (len < 0) {
660  int xerrno = errno;
661  if (ignoreErrno(xerrno))
662  break;
663 
664 #if _SQUID_LINUX_
665  /* Some Linux systems seem to set the FD for reading and then
666  * return ECONNREFUSED when sendto() fails and generates an ICMP
667  * port unreachable message. */
668  /* or maybe an EHOSTUNREACH "No route to host" message */
669  if (xerrno != ECONNREFUSED && xerrno != EHOSTUNREACH)
670 #endif
671  debugs(50, DBG_IMPORTANT, "icpHandleUdp: FD " << sock << " recvfrom: " << xstrerr(xerrno));
672 
673  break;
674  }
675 
676  ++(*N);
677  icpCount(buf, RECV, (size_t) len, 0);
678  buf[len] = '\0';
679  debugs(12, 4, "icpHandleUdp: FD " << sock << ": received " <<
680  (unsigned long int)len << " bytes from " << from);
681 
682 #ifdef ICP_PACKET_DUMP
683 
684  icpPktDump(buf);
685 #endif
686 
687  if ((size_t) len < sizeof(icp_common_t)) {
688  debugs(12, 4, "icpHandleUdp: Ignoring too-small UDP packet");
689  break;
690  }
691 
692  icp_version = (int) buf[1]; /* cheat! */
693 
694  if (icpOutgoingConn->local == from)
695  // ignore ICP packets which loop back (multicast usually)
696  debugs(12, 4, "icpHandleUdp: Ignoring UDP packet sent by myself");
697  else if (icp_version == ICP_VERSION_2)
698  icpHandleIcpV2(sock, from, buf, len);
699  else if (icp_version == ICP_VERSION_3)
700  icpHandleIcpV3(sock, from, buf, len);
701  else
702  debugs(12, DBG_IMPORTANT, "WARNING: Unused ICP version " << icp_version <<
703  " received from " << from);
704  }
705 }
706 
707 void
709 {
710  uint16_t port;
711 
712  if ((port = Config.Port.icp) <= 0)
713  return;
714 
715  icpIncomingConn = new Comm::Connection;
716  icpIncomingConn->local = Config.Addrs.udp_incoming;
717  icpIncomingConn->local.port(port);
718 
719  if (!Ip::EnableIpv6 && !icpIncomingConn->local.setIPv4()) {
720  debugs(12, DBG_CRITICAL, "ERROR: IPv6 is disabled. " << icpIncomingConn->local << " is not an IPv4 address.");
721  fatal("ICP port cannot be opened.");
722  }
723  /* split-stack for now requires default IPv4-only ICP */
724  if (Ip::EnableIpv6&IPV6_SPECIAL_SPLITSTACK && icpIncomingConn->local.isAnyAddr()) {
725  icpIncomingConn->local.setIPv4();
726  }
727 
728  AsyncCall::Pointer call = asyncCall(12, 2,
729  "icpIncomingConnectionOpened",
731 
732  Ipc::StartListening(SOCK_DGRAM,
733  IPPROTO_UDP,
734  icpIncomingConn,
735  Ipc::fdnInIcpSocket, call);
736 
737  if ( !Config.Addrs.udp_outgoing.isNoAddr() ) {
738  icpOutgoingConn = new Comm::Connection;
739  icpOutgoingConn->local = Config.Addrs.udp_outgoing;
740  icpOutgoingConn->local.port(port);
741 
742  if (!Ip::EnableIpv6 && !icpOutgoingConn->local.setIPv4()) {
743  debugs(49, DBG_CRITICAL, "ERROR: IPv6 is disabled. " << icpOutgoingConn->local << " is not an IPv4 address.");
744  fatal("ICP port cannot be opened.");
745  }
746  /* split-stack for now requires default IPv4-only ICP */
747  if (Ip::EnableIpv6&IPV6_SPECIAL_SPLITSTACK && icpOutgoingConn->local.isAnyAddr()) {
748  icpOutgoingConn->local.setIPv4();
749  }
750 
751  enter_suid();
752  comm_open_listener(SOCK_DGRAM, IPPROTO_UDP, icpOutgoingConn, "Outgoing ICP Port");
753  leave_suid();
754 
755  if (!Comm::IsConnOpen(icpOutgoingConn))
756  fatal("Cannot open Outgoing ICP Port");
757 
758  debugs(12, DBG_CRITICAL, "Sending ICP messages from " << icpOutgoingConn->local);
759 
760  Comm::SetSelect(icpOutgoingConn->fd, COMM_SELECT_READ, icpHandleUdp, NULL, 0);
761  fd_note(icpOutgoingConn->fd, "Outgoing ICP socket");
762  }
763 }
764 
765 static void
767 {
768  if (!Comm::IsConnOpen(conn))
769  fatal("Cannot open ICP Port");
770 
772 
773  for (const wordlist *s = Config.mcast_group_list; s; s = s->next)
774  ipcache_nbgethostbyname(s->key, mcastJoinGroups, NULL); // XXX: pass the conn for mcastJoinGroups usage.
775 
776  debugs(12, DBG_IMPORTANT, "Accepting ICP messages on " << conn->local);
777 
778  fd_note(conn->fd, "Incoming ICP port");
779 
781  icpOutgoingConn = conn;
782  debugs(12, DBG_IMPORTANT, "Sending ICP messages from " << icpOutgoingConn->local);
783  }
784 }
785 
790 void
792 {
793  if (!Comm::IsConnOpen(icpIncomingConn))
794  return;
795 
796  debugs(12, DBG_IMPORTANT, "Stop receiving ICP on " << icpIncomingConn->local);
797 
802  icpIncomingConn = NULL;
803 
810  assert(Comm::IsConnOpen(icpOutgoingConn));
811 
812  Comm::SetSelect(icpOutgoingConn->fd, COMM_SELECT_READ, NULL, NULL, 0);
813 }
814 
815 void
817 {
819 
820  if (icpOutgoingConn != NULL) {
821  debugs(12, DBG_IMPORTANT, "Stop sending ICP from " << icpOutgoingConn->local);
822  icpOutgoingConn = NULL;
823  }
824 }
825 
826 static void
827 icpCount(void *buf, int which, size_t len, int delay)
828 {
829  icp_common_t *icp = (icp_common_t *) buf;
830 
831  if (len < sizeof(*icp))
832  return;
833 
834  if (SENT == which) {
837 
838  if (ICP_QUERY == icp->opcode) {
841  } else {
844  /* this is the sent-reply service time */
846  }
847 
848  if (ICP_HIT == icp->opcode)
850  } else if (RECV == which) {
853 
854  if (ICP_QUERY == icp->opcode) {
857  } else {
860  /* statCounter.icp.querySvcTime set in clientUpdateCounters */
861  }
862 
863  if (ICP_HIT == icp->opcode)
865  }
866 }
867 
868 #define N_QUERIED_KEYS 8192
869 #define N_QUERIED_KEYS_MASK 8191
871 
872 int
874 {
875  static int reqnum = 0;
876 
877  if (++reqnum < 0)
878  reqnum = 1;
879 
880  storeKeyCopy(queried_keys[reqnum & N_QUERIED_KEYS_MASK], key);
881 
882  return reqnum;
883 }
884 
885 const cache_key *
886 icpGetCacheKey(const char *url, int reqnum)
887 {
888  if (neighbors_do_private_keys && reqnum)
889  return queried_keys[reqnum & N_QUERIED_KEYS_MASK];
890 
891  return storeKeyPublic(url, Http::METHOD_GET);
892 }
893 
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:75
static int store_dirs_rebuilding
the number of cache_dirs being rebuilt; TODO: move to Disks::Rebuilding
Definition: Controller.h:139
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:236
int src_rtt
Definition: icp_v2.cc:205
icp_common_t()
Definition: icp_v2.cc:107
ByteCounter r_kbytes_recv
Definition: StatCounters.h:81
int neighbors_do_private_keys
Comm::ConnectionPointer icpIncomingConn
Definition: icp_v2.cc:102
ByteCounter kbytes_recv
Definition: StatCounters.h:79
PF icpHandleUdp
Definition: ICP.h:109
#define ICP_VERSION_3
Definition: defines.h:77
int validToSend() const
Definition: store.cc:1414
void fd_note(int fd, const char *s)
Definition: fd.cc:250
Ip::Address from
Definition: ICP.h:75
icp_opcode icpGetCommonOpcode()
Definition: icp_v2.cc:400
void accessLogLog(AccessLogEntry::Pointer &, ACLChecklist *checklist)
Definition: access_log.cc:144
void icpUdpSendQueue(int fd, void *)
Definition: icp_v2.cc:278
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:249
const cache_key * icpGetCacheKey(const char *url, int reqnum)
Definition: icp_v2.cc:886
ByteCounter r_kbytes_sent
Definition: StatCounters.h:78
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:158
static DelayedUdpSend * IcpQueueTail
Definition: icp_v2.cc:99
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:791
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:213
IPH mcastJoinGroups
#define safe_free(x)
Definition: xalloc.h:73
wordlist * mcast_group_list
Definition: SquidConfig.h:246
AccessLogEntry::Pointer al
info for the future access.log, and external ACL
#define rfc1738_escape(x)
Definition: rfc1738.h:52
ByteCounter kbytes_sent
Definition: StatCounters.h:76
char const * icpGetUrlToSend(char *url)
Definition: icp_v2.cc:481
void HTTPMSGLOCK(Http::Message *a)
Definition: Message.h:160
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:182
int fd
Definition: ICP.h:73
void handleReply(char *buf, Ip::Address &from)
Definition: icp_v2.cc:553
#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:468
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:873
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:708
int replies_queued
Definition: StatCounters.h:74
static DelayedUdpSend * IcpQueueHead
Definition: icp_v2.cc:97
StatHist replySvcTime
Definition: StatCounters.h:83
static void getPublic(StoreClient *aClient, const char *uri, const HttpRequestMethod &method)
Definition: store.cc:509
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
struct SquidConfig::@99 Port
#define SQUID_MD5_DIGEST_LENGTH
Definition: md5.h:66
~ICP2State()
Definition: icp_v2.cc:209
#define INCOMING_UDP_MAX
Definition: Loops.h:50
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:508
#define COMM_SELECT_WRITE
Definition: defines.h:37
unsigned short icp
Definition: SquidConfig.h:135
AnyP::Uri url
the request URI
Definition: HttpRequest.h:107
void icpClosePorts(void)
Definition: icp_v2.cc:816
void fatal(const char *message)
Definition: fatal.cc:28
char * url
Definition: ICP.h:76
struct SquidConfig::@113 accessList
int incoming_sockets_accepted
Ip::Address udp_incoming
Definition: SquidConfig.h:235
bool allowed() const
Definition: Acl.h:141
int icp_hit_stale
Definition: SquidConfig.h:283
icp_opcode
Definition: icp_opcode.h:13
icp_common_t * msg
ICP message with network byte order fields.
Definition: icp_v2.cc:54
Comm::ConnectionPointer icpOutgoingConn
Definition: icp_v2.cc:104
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:206
int test_reachability
Definition: SquidConfig.h:290
static LogTags_ot icpLogFromICPCode(icp_opcode)
Definition: icp_v2.cc:413
#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:151
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:523
HttpRequest * icpGetRequest(char *url, int reqnum, int fd, Ip::Address &from)
Definition: icp_v2.cc:490
void const char * buf
Definition: stub_helper.cc:16
uint32_t flags
Definition: ICP.h:45
class AccessLogEntry::CacheDetails cache
void icpCreateAndSend(icp_opcode, int flags, char const *url, int reqnum, int pad, int fd, const Ip::Address &from, AccessLogEntryPointer)
Definition: icp_v2.cc:442
static void icpSyncAle(AccessLogEntryPointer &al, const Ip::Address &caddr, const char *url, int len, int delay)
Definition: icp_v2.cc:76
struct SquidConfig::@112 onoff
unsigned short port() const
Definition: Address.cc:771
uint32_t pad
Definition: ICP.h:46
struct SquidConfig::@107 Addrs
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:766
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:868
ICP2State(icp_common_t &aHeader, HttpRequest *aRequest)
Definition: icp_v2.cc:198
icp_opcode getOpCode() const
Definition: icp_v2.cc:132
uint32_t shostid
Definition: ICP.h:48
void HTTPMSGUNLOCK(M *&a)
Definition: Message.h:149
int clientdbCutoffDenied(const Ip::Address &addr)
Definition: client_db.cc:210
void icpHandleIcpV3(int, Ip::Address &, char *, int)
Definition: icp_v3.cc:88
struct StatCounters::@130 icp
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:869
void icpDenyAccess(Ip::Address &from, char *url, int reqnum, int fd)
Definition: icp_v2.cc:452
static cache_key queried_keys[N_QUERIED_KEYS][SQUID_MD5_DIGEST_LENGTH]
Definition: icp_v2.cc:870
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:570
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:204
time_t hit_only_mode_until
the ICP/neighbors subsystem
Definition: enums.h:167
virtual LogTags * loggingTags() override
Definition: icp_v2.cc:173
ByteCounter q_kbytes_recv
Definition: StatCounters.h:80
ICPState(icp_common_t &aHeader, HttpRequest *aRequest)
Definition: icp_v2.cc:142
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:77
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&#39;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:295
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:343
#define NULL
Definition: types.h:166
static void icpCount(void *, int, size_t, int)
Definition: icp_v2.cc:827
Definition: enums.h:168
const char * icp_opcode_str[]
wordlist * next
Definition: wordlist.h:34

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors