net_db.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2021 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 38 Network Measurement Database */
10 
11 /*
12  * XXX XXX XXX
13  *
14  * This code may be slightly broken now. If you're getting consistent
15  * (sometimes working) corrupt data exchanges, please contact adrian
16  * (adrian@squid-cache.org) to sort them out.
17  */
18 
19 #include "squid.h"
20 #include "CachePeer.h"
21 #include "cbdata.h"
22 #include "event.h"
23 #include "fde.h"
24 #include "fs_io.h"
25 #include "FwdState.h"
26 #include "HttpReply.h"
27 #include "icmp/net_db.h"
28 #include "internal.h"
29 #include "ip/Address.h"
30 #include "log/File.h"
31 #include "MemObject.h"
32 #include "mgr/Registration.h"
33 #include "mime_header.h"
34 #include "neighbors.h"
35 #include "PeerSelectState.h"
36 #include "SquidConfig.h"
37 #include "SquidTime.h"
38 #include "Store.h"
39 #include "StoreClient.h"
40 #include "tools.h"
41 #include "wordlist.h"
42 
43 #if HAVE_SYS_STAT_H
44 #include <sys/stat.h>
45 #endif
46 
47 #if USE_ICMP
48 #include "icmp/IcmpSquid.h"
49 #include "ipcache.h"
50 #include "StoreClient.h"
51 
52 #define NETDB_REQBUF_SZ 4096
53 
54 typedef enum {
59 
61 {
63 
64 public:
66  p(aPeer),
67  r(theReq)
68  {
69  *buf = 0;
70  assert(r);
71  // TODO: check if we actually need to do this. should be implicit
73  }
74 
76  debugs(38, 3, e->url());
77  storeUnregister(sc, e, this);
78  e->unlock("netdbExchangeDone");
79  }
80 
82  StoreEntry *e = nullptr;
83  store_client *sc = nullptr;
85  int64_t used = 0;
88  int buf_ofs = 0;
90 };
91 
93 
96 
98 static void netdbRelease(netdbEntry * n);
99 
100 static void netdbHashInsert(netdbEntry * n, Ip::Address &addr);
101 static void netdbHashDelete(const char *key);
102 static void netdbHostInsert(netdbEntry * n, const char *hostname);
103 static void netdbHostDelete(const net_db_name * x);
104 static void netdbPurgeLRU(void);
105 static netdbEntry *netdbLookupHost(const char *key);
106 static net_db_peer *netdbPeerByName(const netdbEntry * n, const char *);
107 static net_db_peer *netdbPeerAdd(netdbEntry * n, CachePeer * e);
108 static const char *netdbPeerName(const char *name);
113 
114 /* We have to keep a local list of CachePeer names. The Peers structure
115  * gets freed during a reconfigure. We want this database to
116  * remain persisitent, so _net_db_peer->peername points into this
117  * linked list */
119 
120 static void
122 {
124  n->key = n->network;
126  hash_join(addr_table, n);
127 }
128 
129 static void
130 netdbHashDelete(const char *key)
131 {
132  hash_link *hptr = (hash_link *)hash_lookup(addr_table, key);
133 
134  if (hptr == NULL) {
135  debug_trap("netdbHashDelete: key not found");
136  return;
137  }
138 
140 }
141 
142 net_db_name::net_db_name(const char *hostname, netdbEntry *e) :
143  next(e ? e->hosts : nullptr),
144  net_db_entry(e)
145 {
146  key = xstrdup(hostname);
147  if (e) {
148  e->hosts = this;
149  ++ e->link_count;
150  }
151 }
152 
153 static void
154 netdbHostInsert(netdbEntry * n, const char *hostname)
155 {
156  net_db_name *x = new net_db_name(hostname, n);
157  assert(hash_lookup(host_table, hostname) == NULL);
158  hash_join(host_table, x);
159 }
160 
161 static void
163 {
164  assert(x != NULL);
165  assert(x->net_db_entry != NULL);
166 
167  netdbEntry *n = x->net_db_entry;
168  -- n->link_count;
169 
170  for (auto **X = &n->hosts; *X; X = &(*X)->next) {
171  if (*X == x) {
172  *X = x->next;
173  break;
174  }
175  }
176 
178  delete x;
179 }
180 
181 static netdbEntry *
182 netdbLookupHost(const char *key)
183 {
185  return x ? x->net_db_entry : NULL;
186 }
187 
188 static void
190 {
191  net_db_name *x;
192  net_db_name *next;
193 
194  for (x = n->hosts; x; x = next) {
195  next = x->next;
196  netdbHostDelete(x);
197  }
198 
199  n->hosts = NULL;
200  safe_free(n->peers);
201  n->peers = NULL;
202  n->n_peers = 0;
203  n->n_peers_alloc = 0;
204 
205  if (n->link_count == 0) {
207  delete n;
208  }
209 }
210 
211 static int
212 netdbLRU(const void *A, const void *B)
213 {
214  const netdbEntry *const *n1 = (const netdbEntry *const *)A;
215  const netdbEntry *const *n2 = (const netdbEntry *const *)B;
216 
217  if ((*n1)->last_use_time > (*n2)->last_use_time)
218  return (1);
219 
220  if ((*n1)->last_use_time < (*n2)->last_use_time)
221  return (-1);
222 
223  return (0);
224 }
225 
226 static void
228 {
229  netdbEntry *n;
230  netdbEntry **list;
231  int k = 0;
232  int list_count = 0;
233  int removed = 0;
234  list = (netdbEntry **)xcalloc(netdbEntry::UseCount(), sizeof(netdbEntry *));
236 
237  while ((n = (netdbEntry *) hash_next(addr_table))) {
238  assert(list_count < netdbEntry::UseCount());
239  *(list + list_count) = n;
240  ++list_count;
241  }
242 
243  qsort((char *) list,
244  list_count,
245  sizeof(netdbEntry *),
246  netdbLRU);
247 
248  for (k = 0; k < list_count; ++k) {
249  if (netdbEntry::UseCount() < Config.Netdb.low)
250  break;
251 
252  netdbRelease(*(list + k));
253 
254  ++removed;
255  }
256 
257  xfree(list);
258 }
259 
260 static netdbEntry *
262 {
263  netdbEntry *n;
264  char *key = new char[MAX_IPSTRLEN];
266  n = (netdbEntry *) hash_lookup(addr_table, key);
267  delete[] key;
268  return n;
269 }
270 
271 static netdbEntry *
273 {
274  netdbEntry *n;
275 
276  if (netdbEntry::UseCount() > Config.Netdb.high)
277  netdbPurgeLRU();
278 
279  if ((n = netdbLookupAddr(addr)) == NULL) {
280  n = new netdbEntry;
281  netdbHashInsert(n, addr);
282  }
283 
284  return n;
285 }
286 
287 static void
288 netdbSendPing(const ipcache_addrs *ia, const Dns::LookupDetails &, void *data)
289 {
290  Ip::Address addr;
291  char *hostname = NULL;
292  static_cast<generic_cbdata *>(data)->unwrap(&hostname);
293  netdbEntry *n;
294  netdbEntry *na;
295  net_db_name *x;
296  net_db_name **X;
297 
298  if (ia == NULL) {
299  xfree(hostname);
300  return;
301  }
302 
303  addr = ia->current();
304 
305  if ((n = netdbLookupHost(hostname)) == NULL) {
306  n = netdbAdd(addr);
307  netdbHostInsert(n, hostname);
308  } else if ((na = netdbLookupAddr(addr)) != n) {
309  /*
310  *hostname moved from 'network n' to 'network na'!
311  */
312 
313  if (na == NULL)
314  na = netdbAdd(addr);
315 
316  debugs(38, 3, "netdbSendPing: " << hostname << " moved from " << n->network << " to " << na->network);
317 
318  x = (net_db_name *) hash_lookup(host_table, hostname);
319 
320  if (x == NULL) {
321  debugs(38, DBG_IMPORTANT, "netdbSendPing: net_db_name list bug: " << hostname << " not found");
322  xfree(hostname);
323  return;
324  }
325 
326  /* remove net_db_name from 'network n' linked list */
327  for (X = &n->hosts; *X; X = &(*X)->next) {
328  if (*X == x) {
329  *X = x->next;
330  break;
331  }
332  }
333 
334  -- n->link_count;
335  /* point to 'network na' from host entry */
336  x->net_db_entry = na;
337  /* link net_db_name to 'network na' */
338  x->next = na->hosts;
339  na->hosts = x;
340  ++ na->link_count;
341  n = na;
342  }
343 
344  if (n->next_ping_time <= squid_curtime) {
345  debugs(38, 3, "netdbSendPing: pinging " << hostname);
346  icmpEngine.DomainPing(addr, hostname);
347  ++ n->pings_sent;
350  }
351 
352  xfree(hostname);
353 }
354 
357 {
358  Ip::Address out;
359 
360  out = in;
361 
362  /* in IPv6 the 'network' should be the routing section. */
363  if ( in.isIPv6() ) {
364  out.applyMask(64, AF_INET6);
365  debugs(14, 5, "networkFromInaddr : Masked IPv6 Address to " << in << "/64 routing part.");
366  return out;
367  }
368 
369 #if USE_CLASSFUL
370  struct in_addr b;
371 
372  in.getInAddr(b);
373 
374  if (IN_CLASSC(b.s_addr))
375  b.s_addr &= IN_CLASSC_NET;
376  else if (IN_CLASSB(b.s_addr))
377  b.s_addr &= IN_CLASSB_NET;
378  else if (IN_CLASSA(b.s_addr))
379  b.s_addr &= IN_CLASSA_NET;
380 
381  out = b;
382 
383 #endif
384 
385  debugs(14, 5, "networkFromInaddr : Masked IPv4 Address to " << out << "/24.");
386 
387  /* use /24 for everything under IPv4 */
388  out.applyMask(24, AF_INET);
389  debugs(14, 5, "networkFromInaddr : Masked IPv4 Address to " << in << "/24.");
390 
391  return out;
392 }
393 
394 static int
395 sortByRtt(const void *A, const void *B)
396 {
397  const netdbEntry *const *n1 = (const netdbEntry *const *)A;
398  const netdbEntry *const *n2 = (const netdbEntry *const *)B;
399 
400  if ((*n1)->rtt > (*n2)->rtt)
401  return 1;
402  else if ((*n1)->rtt < (*n2)->rtt)
403  return -1;
404  else
405  return 0;
406 }
407 
408 static net_db_peer *
409 netdbPeerByName(const netdbEntry * n, const char *peername)
410 {
411  int i;
412  net_db_peer *p = n->peers;
413 
414  for (i = 0; i < n->n_peers; ++i, ++p) {
415  if (!strcmp(p->peername, peername))
416  return p;
417  }
418 
419  return NULL;
420 }
421 
422 static net_db_peer *
424 {
425  net_db_peer *p;
426  net_db_peer *o;
427  int osize;
428  int i;
429 
430  if (n->n_peers == n->n_peers_alloc) {
431  o = n->peers;
432  osize = n->n_peers_alloc;
433 
434  if (n->n_peers_alloc == 0)
435  n->n_peers_alloc = 2;
436  else
437  n->n_peers_alloc <<= 1;
438 
439  debugs(38, 3, "netdbPeerAdd: Growing peer list for '" << n->network << "' to " << n->n_peers_alloc);
440 
441  n->peers = (net_db_peer *)xcalloc(n->n_peers_alloc, sizeof(net_db_peer));
442 
443  for (i = 0; i < osize; ++i)
444  *(n->peers + i) = *(o + i);
445 
446  if (osize) {
447  safe_free(o);
448  }
449  }
450 
451  p = n->peers + n->n_peers;
452  p->peername = netdbPeerName(e->host);
453  ++ n->n_peers;
454  return p;
455 }
456 
457 static int
458 sortPeerByRtt(const void *A, const void *B)
459 {
460  const net_db_peer *p1 = (net_db_peer *)A;
461  const net_db_peer *p2 = (net_db_peer *)B;
462 
463  if (p1->rtt > p2->rtt)
464  return 1;
465  else if (p1->rtt < p2->rtt)
466  return -1;
467  else
468  return 0;
469 }
470 
471 static void
473 {
474  if (strcmp(Config.netdbFilename, "none") == 0)
475  return;
476 
477  Logfile *lf;
478  netdbEntry *n;
479  net_db_name *x;
480 
481  struct timeval start = current_time;
482  int count = 0;
483  /*
484  * This was nicer when we were using stdio, but thanks to
485  * Solaris bugs, its a bad idea. fopen can fail if more than
486  * 256 FDs are open.
487  */
488  /*
489  * unlink() is here because there is currently no way to make
490  * logfileOpen() use O_TRUNC.
491  */
492  unlink(Config.netdbFilename);
493  lf = logfileOpen(Config.netdbFilename, 4096, 0);
494 
495  if (!lf) {
496  int xerrno = errno;
497  debugs(50, DBG_IMPORTANT, MYNAME << Config.netdbFilename << ": " << xstrerr(xerrno));
498  return;
499  }
500 
502 
503  while ((n = (netdbEntry *) hash_next(addr_table))) {
504  if (n->pings_recv == 0)
505  continue;
506 
507  logfilePrintf(lf, "%s %d %d %10.5f %10.5f %d %d",
508  n->network,
509  n->pings_sent,
510  n->pings_recv,
511  n->hops,
512  n->rtt,
513  (int) n->next_ping_time,
514  (int) n->last_use_time);
515 
516  for (x = n->hosts; x; x = x->next)
517  logfilePrintf(lf, " %s", hashKeyStr(x));
518 
519  logfilePrintf(lf, "\n");
520 
521  ++count;
522 
523 #undef RBUF_SZ
524 
525  }
526 
527  logfileClose(lf);
528  getCurrentTime();
529  debugs(38, DBG_IMPORTANT, "NETDB state saved; " <<
530  count << " entries, " <<
531  tvSubMsec(start, current_time) << " msec" );
532  eventAddIsh("netdbSaveState", netdbSaveState, NULL, 3600.0, 1);
533 }
534 
535 static void
537 {
538  if (strcmp(Config.netdbFilename, "none") == 0)
539  return;
540 
541  char *s;
542  int fd;
543  int l;
544 
545  struct stat sb;
546  netdbEntry *n;
547  netdbEntry N;
548 
549  Ip::Address addr;
550  int count = 0;
551 
552  struct timeval start = current_time;
553  /*
554  * This was nicer when we were using stdio, but thanks to
555  * Solaris bugs, its a bad idea. fopen can fail if more than
556  * 256 FDs are open.
557  */
558  fd = file_open(Config.netdbFilename, O_RDONLY | O_BINARY);
559 
560  if (fd < 0)
561  return;
562 
563  if (fstat(fd, &sb) < 0) {
564  file_close(fd);
565  return;
566  }
567 
568  char *t;
569  char *buf = (char *)xcalloc(1, sb.st_size + 1);
570  t = buf;
571  l = FD_READ_METHOD(fd, buf, sb.st_size);
572  file_close(fd);
573 
574  if (l <= 0) {
575  safe_free (buf);
576  return;
577  };
578 
579  while ((s = strchr(t, '\n'))) {
580  char *q;
581  assert(s - buf < l);
582  *s = '\0';
583  N = netdbEntry();
584  q = strtok(t, w_space);
585  t = s + 1;
586 
587  if (NULL == q)
588  continue;
589 
590  if (! (addr = q) )
591  continue;
592 
593  if (netdbLookupAddr(addr) != NULL) /* no dups! */
594  continue;
595 
596  if ((q = strtok(NULL, w_space)) == NULL)
597  continue;
598 
599  N.pings_sent = atoi(q);
600 
601  if ((q = strtok(NULL, w_space)) == NULL)
602  continue;
603 
604  N.pings_recv = atoi(q);
605 
606  if (N.pings_recv == 0)
607  continue;
608 
609  /* give this measurement low weight */
610  N.pings_sent = 1;
611 
612  N.pings_recv = 1;
613 
614  if ((q = strtok(NULL, w_space)) == NULL)
615  continue;
616 
617  N.hops = atof(q);
618 
619  if ((q = strtok(NULL, w_space)) == NULL)
620  continue;
621 
622  N.rtt = atof(q);
623 
624  if ((q = strtok(NULL, w_space)) == NULL)
625  continue;
626 
627  N.next_ping_time = (time_t) atoi(q);
628 
629  if ((q = strtok(NULL, w_space)) == NULL)
630  continue;
631 
632  N.last_use_time = (time_t) atoi(q);
633 
634  n = new netdbEntry;
635 
636  memcpy(n, &N, sizeof(netdbEntry));
637 
638  netdbHashInsert(n, addr);
639 
640  while ((q = strtok(NULL, w_space)) != NULL) {
641  if (netdbLookupHost(q) != NULL) /* no dups! */
642  continue;
643 
644  netdbHostInsert(n, q);
645  }
646 
647  ++count;
648  }
649 
650  xfree(buf);
651  getCurrentTime();
652  debugs(38, DBG_IMPORTANT, "NETDB state reloaded; " <<
653  count << " entries, " <<
654  tvSubMsec(start, current_time) << " msec" );
655 }
656 
657 static const char *
658 netdbPeerName(const char *name)
659 {
660  const wordlist *w;
661 
662  for (w = peer_names; w; w = w->next) {
663  if (!strcmp(w->key, name))
664  return w->key;
665  }
666 
667  return wordlistAdd(&peer_names, name);
668 }
669 
670 static void
672 {
673  netdbEntry *n = (netdbEntry *)data;
674  safe_free(n->peers);
675  delete n;
676 }
677 
678 static void
680 {
681  net_db_name *x = (net_db_name *)data;
682  delete x;
683 }
684 
685 static void
686 netdbExchangeHandleReply(void *data, StoreIOBuffer receivedData)
687 {
688  Ip::Address addr;
689 
691  int rec_sz = 0;
692  int o;
693 
694  struct in_addr line_addr;
695  double rtt;
696  double hops;
697  char *p;
698  int j;
699  size_t hdr_sz;
700  int nused = 0;
701  int size;
702  int oldbufofs = ex->buf_ofs;
703 
704  rec_sz = 0;
705  rec_sz += 1 + sizeof(struct in_addr);
706  rec_sz += 1 + sizeof(int);
707  rec_sz += 1 + sizeof(int);
708  debugs(38, 3, "netdbExchangeHandleReply: " << receivedData.length << " read bytes");
709 
710  if (!ex->p.valid()) {
711  debugs(38, 3, "netdbExchangeHandleReply: Peer became invalid");
712  delete ex;
713  return;
714  }
715 
716  debugs(38, 3, "netdbExchangeHandleReply: for '" << ex->p->host << ":" << ex->p->http_port << "'");
717 
718  if (receivedData.length == 0 && !receivedData.flags.error) {
719  debugs(38, 3, "netdbExchangeHandleReply: Done");
720  delete ex;
721  return;
722  }
723 
724  p = ex->buf;
725 
726  /* Get the size of the buffer now */
727  size = ex->buf_ofs + receivedData.length;
728  debugs(38, 3, "netdbExchangeHandleReply: " << size << " bytes buf");
729 
730  /* Check if we're still doing headers */
731 
732  if (ex->connstate == STATE_HEADER) {
733 
734  ex->buf_ofs += receivedData.length;
735 
736  /* skip reply headers */
737 
738  if ((hdr_sz = headersEnd(p, ex->buf_ofs))) {
739  debugs(38, 5, "netdbExchangeHandleReply: hdr_sz = " << hdr_sz);
740  const auto scode = ex->e->mem().baseReply().sline.status();
741  assert(scode != Http::scNone);
742  debugs(38, 3, "netdbExchangeHandleReply: reply status " << scode);
743 
744  if (scode != Http::scOkay) {
745  delete ex;
746  return;
747  }
748 
749  assert((size_t)ex->buf_ofs >= hdr_sz);
750 
751  /*
752  * Now, point p to the part of the buffer where the data
753  * starts, and update the size accordingly
754  */
755  assert(ex->used == 0);
756  ex->used = hdr_sz;
757  size = ex->buf_ofs - hdr_sz;
758  p += hdr_sz;
759 
760  /* Finally, set the conn state mode to STATE_BODY */
761  ex->connstate = STATE_BODY;
762  } else {
763  StoreIOBuffer tempBuffer;
764  tempBuffer.offset = ex->buf_ofs;
765  tempBuffer.length = ex->buf_sz - ex->buf_ofs;
766  tempBuffer.data = ex->buf + ex->buf_ofs;
767  /* Have more headers .. */
768  storeClientCopy(ex->sc, ex->e, tempBuffer,
770  return;
771  }
772  }
773 
774  assert(ex->connstate == STATE_BODY);
775 
776  /* If we get here, we have some body to parse .. */
777  debugs(38, 5, "netdbExchangeHandleReply: start parsing loop, size = " << size);
778 
779  while (size >= rec_sz) {
780  debugs(38, 5, "netdbExchangeHandleReply: in parsing loop, size = " << size);
781  addr.setAnyAddr();
782  hops = rtt = 0.0;
783 
784  for (o = 0; o < rec_sz;) {
785  switch ((int) *(p + o)) {
786 
787  case NETDB_EX_NETWORK:
788  ++o;
789  // XXX: NetDB can still only send IPv4
790  memcpy(&line_addr, p + o, sizeof(struct in_addr));
791  addr = line_addr;
792  o += sizeof(struct in_addr);
793  break;
794 
795  case NETDB_EX_RTT:
796  ++o;
797  memcpy(&j, p + o, sizeof(int));
798  o += sizeof(int);
799  rtt = (double) ntohl(j) / 1000.0;
800  break;
801 
802  case NETDB_EX_HOPS:
803  ++o;
804  memcpy(&j, p + o, sizeof(int));
805  o += sizeof(int);
806  hops = (double) ntohl(j) / 1000.0;
807  break;
808 
809  default:
810  debugs(38, DBG_IMPORTANT, "netdbExchangeHandleReply: corrupt data, aborting");
811  delete ex;
812  return;
813  }
814  }
815 
816  if (!addr.isAnyAddr() && rtt > 0)
817  netdbExchangeUpdatePeer(addr, ex->p.get(), rtt, hops);
818 
819  assert(o == rec_sz);
820 
821  ex->used += rec_sz;
822 
823  size -= rec_sz;
824 
825  p += rec_sz;
826 
827  ++nused;
828  }
829 
830  /*
831  * Copy anything that is left over to the beginning of the buffer,
832  * and adjust buf_ofs accordingly
833  */
834 
835  /*
836  * Evilly, size refers to the buf size left now,
837  * ex->buf_ofs is the original buffer size, so just copy that
838  * much data over
839  */
840  memmove(ex->buf, ex->buf + (ex->buf_ofs - size), size);
841 
842  ex->buf_ofs = size;
843 
844  /*
845  * And don't re-copy the remaining data ..
846  */
847  ex->used += size;
848 
849  /*
850  * Now the tricky bit - size _included_ the leftover bit from the _last_
851  * storeClientCopy. We don't want to include that, or our offset will be wrong.
852  * So, don't count the size of the leftover buffer we began with.
853  * This can _disappear_ when we're not tracking offsets ..
854  */
855  ex->used -= oldbufofs;
856 
857  debugs(38, 3, "netdbExchangeHandleReply: size left over in this buffer: " << size << " bytes");
858 
859  debugs(38, 3, "netdbExchangeHandleReply: used " << nused <<
860  " entries, (x " << rec_sz << " bytes) == " << nused * rec_sz <<
861  " bytes total");
862 
863  debugs(38, 3, "netdbExchangeHandleReply: used " << ex->used);
864 
865  if (EBIT_TEST(ex->e->flags, ENTRY_ABORTED)) {
866  debugs(38, 3, "netdbExchangeHandleReply: ENTRY_ABORTED");
867  delete ex;
868  } else if (ex->e->store_status == STORE_PENDING) {
869  StoreIOBuffer tempBuffer;
870  tempBuffer.offset = ex->used;
871  tempBuffer.length = ex->buf_sz - ex->buf_ofs;
872  tempBuffer.data = ex->buf + ex->buf_ofs;
873  debugs(38, 3, "netdbExchangeHandleReply: EOF not received");
874  storeClientCopy(ex->sc, ex->e, tempBuffer,
876  }
877 }
878 
879 #endif /* USE_ICMP */
880 
881 /* PUBLIC FUNCTIONS */
882 
883 void
885 {
886 #if USE_ICMP
887  Mgr::RegisterAction("netdb", "Network Measurement Database", netdbDump, 0, 1);
888 
889  if (addr_table)
890  return;
891 
892  int n = hashPrime(Config.Netdb.high / 4);
893 
894  addr_table = hash_create((HASHCMP *) strcmp, n, hash_string);
895 
896  n = hashPrime(3 * Config.Netdb.high / 4);
897 
898  host_table = hash_create((HASHCMP *) strcmp, n, hash_string);
899 
900  eventAddIsh("netdbSaveState", netdbSaveState, NULL, 3600.0, 1);
901 
903 
904 #endif
905 }
906 
907 void
908 netdbPingSite(const char *hostname)
909 {
910 #if USE_ICMP
911  netdbEntry *n;
912 
913  if ((n = netdbLookupHost(hostname)) != NULL)
914  if (n->next_ping_time > squid_curtime)
915  return;
916 
918  new generic_cbdata(xstrdup(hostname)));
919 #else
920  (void)hostname;
921 #endif
922 }
923 
924 void
925 netdbHandlePingReply(const Ip::Address &from, int hops, int rtt)
926 {
927 #if USE_ICMP
928  netdbEntry *n;
929  int N;
930  debugs(38, 3, "netdbHandlePingReply: from " << from);
931 
932  if ((n = netdbLookupAddr(from)) == NULL)
933  return;
934 
935  N = ++n->pings_recv;
936 
937  if (N > 5)
938  N = 5;
939 
940  if (rtt < 1)
941  rtt = 1;
942 
943  n->hops = ((n->hops * (N - 1)) + hops) / N;
944 
945  n->rtt = ((n->rtt * (N - 1)) + rtt) / N;
946 
947  debugs(38, 3, "netdbHandlePingReply: " << n->network << "; rtt="<<
948  std::setw(5)<< std::setprecision(2) << n->rtt << " hops="<<
949  std::setw(4) << n->hops);
950 #else
951  (void)from;
952  (void)hops;
953  (void)rtt;
954 #endif
955 }
956 
957 void
959 {
960 #if USE_ICMP
963  addr_table = NULL;
966  host_table = NULL;
968  peer_names = NULL;
969 #endif
970 }
971 
972 void
974 {
975 #if USE_ICMP
976  netdbEntry *n;
977  netdbEntry **list;
978  net_db_name *x;
979  int k;
980  int i;
981  int j;
982  net_db_peer *p;
983  storeAppendPrintf(sentry, "Network DB Statistics:\n");
984  storeAppendPrintf(sentry, "%-46.46s %9s %7s %5s %s\n", /* Max between 16 (IPv4) or 46 (IPv6) */
985  "Network",
986  "recv/sent",
987  "RTT",
988  "Hops",
989  "Hostnames");
990  list = (netdbEntry **)xcalloc(netdbEntry::UseCount(), sizeof(netdbEntry *));
991  i = 0;
993 
994  while ((n = (netdbEntry *) hash_next(addr_table))) {
995  *(list + i) = n;
996  ++i;
997  }
998 
999  if (i != netdbEntry::UseCount())
1000  debugs(38, DBG_CRITICAL, "WARNING: netdb_addrs count off, found " << i <<
1001  ", expected " << netdbEntry::UseCount());
1002 
1003  qsort((char *) list,
1004  i,
1005  sizeof(netdbEntry *),
1006  sortByRtt);
1007 
1008  for (k = 0; k < i; ++k) {
1009  n = *(list + k);
1010  storeAppendPrintf(sentry, "%-46.46s %4d/%4d %7.1f %5.1f", /* Max between 16 (IPv4) or 46 (IPv6) */
1011  n->network,
1012  n->pings_recv,
1013  n->pings_sent,
1014  n->rtt,
1015  n->hops);
1016 
1017  for (x = n->hosts; x; x = x->next)
1018  storeAppendPrintf(sentry, " %s", hashKeyStr(x));
1019 
1020  storeAppendPrintf(sentry, "\n");
1021 
1022  p = n->peers;
1023 
1024  for (j = 0; j < n->n_peers; ++j, ++p) {
1025  storeAppendPrintf(sentry, " %-22.22s %7.1f %5.1f\n",
1026  p->peername,
1027  p->rtt,
1028  p->hops);
1029  }
1030  }
1031 
1032  xfree(list);
1033 #else
1034 
1035  storeAppendPrintf(sentry,"NETDB support not compiled into this Squid cache.\n");
1036 #endif
1037 }
1038 
1039 int
1040 netdbHostHops(const char *host)
1041 {
1042 #if USE_ICMP
1043  netdbEntry *n = netdbLookupHost(host);
1044 
1045  if (n) {
1047  return (int) (n->hops + 0.5);
1048  }
1049 #else
1050  (void)host;
1051 #endif
1052  return 0;
1053 }
1054 
1055 int
1056 netdbHostRtt(const char *host)
1057 {
1058 #if USE_ICMP
1059  netdbEntry *n = netdbLookupHost(host);
1060 
1061  if (n) {
1063  return (int) (n->rtt + 0.5);
1064  }
1065 
1066 #else
1067  (void)host;
1068 #endif
1069  return 0;
1070 }
1071 
1072 void
1073 netdbHostData(const char *host, int *samp, int *rtt, int *hops)
1074 {
1075 #if USE_ICMP
1076  netdbEntry *n = netdbLookupHost(host);
1077 
1078  if (n == NULL)
1079  return;
1080 
1081  *samp = n->pings_recv;
1082 
1083  *rtt = (int) (n->rtt + 0.5);
1084 
1085  *hops = (int) (n->hops + 0.5);
1086 
1088 
1089 #else
1090  (void)hops;
1091  (void)rtt;
1092  (void)samp;
1093  (void)host;
1094 #endif
1095 }
1096 
1097 void
1098 netdbUpdatePeer(const AnyP::Uri &url, CachePeer *e, int irtt, int ihops)
1099 {
1100 #if USE_ICMP
1101  netdbEntry *n;
1102  double rtt = (double) irtt;
1103  double hops = (double) ihops;
1104  net_db_peer *p;
1105  debugs(38, 3, url.host() << ", " << ihops << " hops, " << irtt << " rtt");
1106  n = netdbLookupHost(url.host());
1107 
1108  if (n == NULL) {
1109  debugs(38, 3, "host " << url.host() << " not found");
1110  return;
1111  }
1112 
1113  if ((p = netdbPeerByName(n, e->host)) == NULL)
1114  p = netdbPeerAdd(n, e);
1115 
1116  p->rtt = rtt;
1117 
1118  p->hops = hops;
1119 
1120  p->expires = squid_curtime + 3600;
1121 
1122  if (n->n_peers < 2)
1123  return;
1124 
1125  qsort((char *) n->peers,
1126  n->n_peers,
1127  sizeof(net_db_peer),
1128  sortPeerByRtt);
1129 
1130 #else
1131  (void)ihops;
1132  (void)irtt;
1133  (void)e;
1134  (void)url;
1135 #endif
1136 }
1137 
1138 void
1139 netdbExchangeUpdatePeer(Ip::Address &addr, CachePeer * e, double rtt, double hops)
1140 {
1141 #if USE_ICMP
1142  netdbEntry *n;
1143  net_db_peer *p;
1144  debugs(38, 5, "netdbExchangeUpdatePeer: '" << addr << "', "<<
1145  std::setfill('0')<< std::setprecision(2) << hops << " hops, " <<
1146  rtt << " rtt");
1147 
1148  if ( !addr.isIPv4() ) {
1149  debugs(38, 5, "netdbExchangeUpdatePeer: Aborting peer update for '" << addr << "', NetDB cannot handle IPv6.");
1150  return;
1151  }
1152 
1153  n = netdbLookupAddr(addr);
1154 
1155  if (n == NULL)
1156  n = netdbAdd(addr);
1157 
1158  assert(NULL != n);
1159 
1160  if ((p = netdbPeerByName(n, e->host)) == NULL)
1161  p = netdbPeerAdd(n, e);
1162 
1163  p->rtt = rtt;
1164 
1165  p->hops = hops;
1166 
1167  p->expires = squid_curtime + 3600; /* XXX ? */
1168 
1169  if (n->n_peers < 2)
1170  return;
1171 
1172  qsort((char *) n->peers,
1173  n->n_peers,
1174  sizeof(net_db_peer),
1175  sortPeerByRtt);
1176 
1177 #else
1178  (void)hops;
1179  (void)rtt;
1180  (void)e;
1181  (void)addr;
1182 #endif
1183 }
1184 
1185 void
1187 {
1188 #if USE_ICMP
1189  netdbEntry *n = netdbLookupAddr(addr);
1190 
1191  if (n == NULL)
1192  return;
1193 
1194  debugs(38, 3, "netdbDeleteAddrNetwork: " << n->network);
1195 
1196  netdbRelease(n);
1197 #else
1198  (void)addr;
1199 #endif
1200 }
1201 
1202 void
1204 {
1205  HttpReply *reply = new HttpReply;
1206 #if USE_ICMP
1207 
1208  Ip::Address addr;
1209 
1210  netdbEntry *n;
1211  int i;
1212  int j;
1213  int rec_sz;
1214  char *buf;
1215 
1216  struct in_addr line_addr;
1217  s->buffer();
1218  reply->setHeaders(Http::scOkay, "OK", NULL, -1, squid_curtime, -2);
1219  s->replaceHttpReply(reply);
1220  rec_sz = 0;
1221  rec_sz += 1 + sizeof(struct in_addr);
1222  rec_sz += 1 + sizeof(int);
1223  rec_sz += 1 + sizeof(int);
1224  buf = (char *)memAllocate(MEM_4K_BUF);
1225  i = 0;
1227 
1228  while ((n = (netdbEntry *) hash_next(addr_table))) {
1229  if (0.0 == n->rtt)
1230  continue;
1231 
1232  if (n->rtt > 60000) /* RTT > 1 MIN probably bogus */
1233  continue;
1234 
1235  if (! (addr = n->network) )
1236  continue;
1237 
1238  // XXX: NetDB cannot yet handle IPv6 addresses
1239  if ( !addr.isIPv4() )
1240  continue;
1241 
1242  buf[i] = (char) NETDB_EX_NETWORK;
1243  ++i;
1244 
1245  addr.getInAddr(line_addr);
1246  memcpy(&buf[i], &line_addr, sizeof(struct in_addr));
1247 
1248  i += sizeof(struct in_addr);
1249 
1250  buf[i] = (char) NETDB_EX_RTT;
1251  ++i;
1252 
1253  j = htonl((int) (n->rtt * 1000));
1254 
1255  memcpy(&buf[i], &j, sizeof(int));
1256 
1257  i += sizeof(int);
1258 
1259  buf[i] = (char) NETDB_EX_HOPS;
1260  ++i;
1261 
1262  j = htonl((int) (n->hops * 1000));
1263 
1264  memcpy(&buf[i], &j, sizeof(int));
1265 
1266  i += sizeof(int);
1267 
1268  if (i + rec_sz > 4096) {
1269  s->append(buf, i);
1270  i = 0;
1271  }
1272  }
1273 
1274  if (i > 0) {
1275  s->append(buf, i);
1276  i = 0;
1277  }
1278 
1279  assert(0 == i);
1280  s->flush();
1281  memFree(buf, MEM_4K_BUF);
1282 #else
1283 
1284  reply->setHeaders(Http::scBadRequest, "Bad Request", NULL, -1, squid_curtime, -2);
1285  s->replaceHttpReply(reply);
1286  storeAppendPrintf(s, "NETDB support not compiled into this Squid cache.\n");
1287 #endif
1288 
1289  s->complete();
1290 }
1291 
1292 void
1294 {
1295 #if USE_ICMP
1296  CachePeer *p = (CachePeer *)data;
1297  static const SBuf netDB("netdb");
1298  char *uri = internalRemoteUri(p->secure.encryptTransport, p->host, p->http_port, "/squid-internal-dynamic/", netDB);
1299  debugs(38, 3, "Requesting '" << uri << "'");
1302 
1303  if (!req) {
1304  debugs(38, DBG_IMPORTANT, MYNAME << ": Bad URI " << uri);
1305  return;
1306  }
1307 
1308  netdbExchangeState *ex = new netdbExchangeState(p, req);
1309  ex->e = storeCreateEntry(uri, uri, RequestFlags(), Http::METHOD_GET);
1310  assert(NULL != ex->e);
1311 
1312  StoreIOBuffer tempBuffer;
1313  tempBuffer.length = ex->buf_sz;
1314  tempBuffer.data = ex->buf;
1315 
1316  ex->sc = storeClientListAdd(ex->e, ex);
1317 
1318  storeClientCopy(ex->sc, ex->e, tempBuffer,
1320  ex->r->flags.loopDetected = true; /* cheat! -- force direct */
1321 
1322  // XXX: send as Proxy-Authenticate instead
1323  if (p->login)
1324  ex->r->url.userInfo(SBuf(p->login));
1325 
1327 #else
1328  (void)data;
1329 #endif
1330 }
1331 
1332 CachePeer *
1334 {
1335 #if USE_ICMP
1336  assert(ps);
1337  HttpRequest *request = ps->request;
1338 
1339  CachePeer *p = NULL;
1340  netdbEntry *n;
1341  const ipcache_addrs *ia;
1342  net_db_peer *h;
1343  int i;
1344  n = netdbLookupHost(request->url.host());
1345 
1346  if (NULL == n) {
1347  /* try IP addr */
1348  ia = ipcache_gethostbyname(request->url.host(), 0);
1349 
1350  if (NULL != ia)
1351  n = netdbLookupAddr(ia->current());
1352  }
1353 
1354  if (NULL == n)
1355  return NULL;
1356 
1357  if (0 == n->n_peers)
1358  return NULL;
1359 
1361 
1362  /*
1363  * Find the parent with the least RTT to the origin server.
1364  * Make sure we don't return a parent who is farther away than
1365  * we are. Note, the n->peers list is pre-sorted by RTT.
1366  */
1367  for (i = 0; i < n->n_peers; ++i) {
1368  h = &n->peers[i];
1369 
1370  if (n->rtt > 0)
1371  if (n->rtt < h->rtt)
1372  break;
1373 
1374  p = peerFindByName(h->peername);
1375 
1376  if (NULL == p) /* not found */
1377  continue;
1378 
1379  if (neighborType(p, request->url) != PEER_PARENT)
1380  continue;
1381 
1382  if (!peerHTTPOkay(p, ps)) /* not allowed */
1383  continue;
1384 
1385  return p;
1386  }
1387 
1388 #else
1389  (void)ps;
1390 #endif
1391  return NULL;
1392 }
1393 
const char * xstrerr(int error)
Definition: xstrerror.cc:83
Cbc * get() const
a temporary valid raw Cbc pointer or NULL
Definition: CbcPointer.h:162
time_t period
Definition: SquidConfig.h:234
#define MYNAME
Definition: Debug.h:165
void * xcalloc(size_t n, size_t sz)
Definition: xalloc.cc:71
void wordlistDestroy(wordlist **list)
destroy a wordlist
Definition: wordlist.cc:16
CachePeer * peerFindByName(const char *name)
Definition: neighbors.cc:1133
AnyP::ProtocolVersion http_ver
Definition: Message.h:73
void userInfo(const SBuf &s)
Definition: Uri.h:79
char * netdbFilename
Definition: SquidConfig.h:223
AnyP::Uri url
the request URI
Definition: HttpRequest.h:115
CachePeer * netdbClosestParent(PeerSelector *ps)
Definition: net_db.cc:1333
Cbc * valid() const
was set and is valid
Definition: CbcPointer.h:41
net_db_name * next
Definition: net_db.h:32
void logfileClose(Logfile *lf)
Definition: File.cc:92
int link_count
Definition: net_db.h:61
Definition: Uri.h:31
HttpRequest * request
void netdbFreeMemory(void)
Definition: net_db.cc:958
@ scBadRequest
Definition: StatusCode.h:44
static net_db_peer * netdbPeerByName(const netdbEntry *n, const char *)
Definition: net_db.cc:409
@ scNone
Definition: StatusCode.h:21
void FREE(void *)
Definition: forward.h:36
netdb_conn_state_t
Definition: net_db.cc:54
RequestFlags flags
Definition: HttpRequest.h:141
void netdbUpdatePeer(const AnyP::Uri &url, CachePeer *e, int irtt, int ihops)
Definition: net_db.cc:1098
const char * url() const
Definition: store.cc:1583
net_db_name(const char *name, netdbEntry *)
Definition: net_db.cc:142
static void netdbReloadState(void)
Definition: net_db.cc:536
bool isAnyAddr() const
Definition: Address.cc:170
static hash_table * addr_table
Definition: net_db.cc:94
MemObject & mem()
Definition: Store.h:52
IcmpSquid icmpEngine
Definition: IcmpSquid.cc:27
void storeAppendPrintf(StoreEntry *e, const char *fmt,...)
Definition: store.cc:869
bool loopDetected
Definition: RequestFlags.h:36
char * login
Definition: CachePeer.h:174
int64_t offset
Definition: StoreIOBuffer.h:55
SQUIDCEXTERN void hash_remove_link(hash_table *, hash_link *)
Definition: hash.cc:220
static net_db_peer * netdbPeerAdd(netdbEntry *n, CachePeer *e)
Definition: net_db.cc:423
Definition: SBuf.h:87
void netdbExchangeStart(void *data)
Definition: net_db.cc:1293
store_client * sc
Definition: net_db.cc:83
#define xstrdup
static netdbEntry * netdbLookupHost(const char *key)
Definition: net_db.cc:182
bool getInAddr(struct in_addr &) const
Definition: Address.cc:1020
const ipcache_addrs * ipcache_gethostbyname(const char *name, int flags)
Definition: ipcache.cc:720
struct SquidConfig::@110 Netdb
net_db_peer * peers
Definition: net_db.h:63
C * getRaw() const
Definition: RefCount.h:80
SQUIDCEXTERN void hashFreeItems(hash_table *, HASHFREE *)
Definition: hash.cc:252
uint16_t flags
Definition: Store.h:233
CbcPointer< CachePeer > p
Definition: net_db.cc:81
Http::StatusLine sline
Definition: HttpReply.h:56
const Ip::Address & current() const
Definition: ipcache.h:59
@ STATE_BODY
Definition: net_db.cc:57
struct StoreIOBuffer::@147 flags
int HASHCMP(const void *, const void *)
Definition: hash.h:13
int netdbHostRtt(const char *host)
Definition: net_db.cc:1056
time_t last_use_time
Definition: net_db.h:60
void * memAllocate(mem_type)
Allocate one element from the typed pool.
Definition: old_api.cc:214
#define DBG_CRITICAL
Definition: Debug.h:40
bool isIPv4() const
Definition: Address.cc:158
CBDATA_CLASS_INIT(netdbExchangeState)
void file_close(int fd)
Definition: fs_io.cc:73
@ NETDB_EX_HOPS
Definition: enums.h:186
SQUIDCEXTERN void hash_join(hash_table *, hash_link *)
Definition: hash.cc:131
SQUIDCEXTERN void hashFreeMemory(hash_table *)
Definition: hash.cc:268
time_t getCurrentTime(void)
Get current time.
#define DBG_IMPORTANT
Definition: Debug.h:41
#define w_space
CBDATA_CLASS(netdbExchangeState)
char * toStr(char *buf, const unsigned int blen, int force=AF_UNSPEC) const
Definition: Address.cc:792
void logfilePrintf(Logfile *lf, const char *fmt,...)
Definition: File.cc:114
int n_peers
Definition: net_db.h:65
peer_t neighborType(const CachePeer *p, const AnyP::Uri &url)
Definition: neighbors.cc:116
#define MAX_IPSTRLEN
Length of buffer that needs to be allocated to old a null-terminated IP-string.
Definition: forward.h:25
@ ENTRY_ABORTED
Definition: enums.h:115
netdbEntry * net_db_entry
Definition: net_db.h:33
void netdbInit(void)
Definition: net_db.cc:884
char * internalRemoteUri(bool encrypt, const char *host, unsigned short port, const char *dir, const SBuf &name)
Definition: internal.cc:87
#define O_BINARY
Definition: defines.h:143
char buf[NETDB_REQBUF_SZ]
Definition: net_db.cc:87
int size
Definition: ModDevPoll.cc:76
#define NULL
Definition: types.h:166
static int netdbLRU(const void *A, const void *B)
Definition: net_db.cc:212
static netdbEntry * netdbLookupAddr(const Ip::Address &addr)
Definition: net_db.cc:261
time_t expires
Definition: net_db.h:43
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:123
@ PEER_PARENT
Definition: enums.h:30
Http::StatusCode status() const
retrieve the status code for this status line
Definition: StatusLine.h:45
const HttpReply & baseReply() const
Definition: MemObject.h:59
static IPH netdbSendPing
Definition: net_db.cc:109
void netdbDump(StoreEntry *sentry)
Definition: net_db.cc:973
static uint32 A
Definition: md4.c:43
#define NETDB_REQBUF_SZ
Definition: net_db.cc:52
@ STATE_NONE
Definition: net_db.cc:55
double rtt
Definition: net_db.h:58
bool isIPv6() const
Definition: Address.cc:164
unsigned error
Definition: StoreIOBuffer.h:52
#define EBIT_TEST(flag, bit)
Definition: defines.h:69
void ipcache_nbgethostbyname(const char *name, IPH *handler, void *handlerData)
Definition: ipcache.cc:600
netdb_conn_state_t connstate
Definition: net_db.cc:89
int n_peers_alloc
Definition: net_db.h:64
StoreEntry * e
Definition: net_db.cc:82
static FREE netdbFreeNetdbEntry
Definition: net_db.cc:111
static void netdbSaveState(void *)
Definition: net_db.cc:472
static FREE netdbFreeNameEntry
Definition: net_db.cc:110
SQUIDCEXTERN void hash_first(hash_table *)
Definition: hash.cc:172
void debug_trap(const char *message)
Definition: tools.cc:405
int unlock(const char *context)
Definition: store.cc:483
Logfile * logfileOpen(const char *path, size_t bufsz, int fatal_flag)
Definition: File.cc:40
#define safe_free(x)
Definition: xalloc.h:73
int tvSubMsec(struct timeval, struct timeval)
Definition: time.cc:37
store_status_t store_status
Definition: Store.h:245
#define assert(EX)
Definition: assert.h:19
const char * peername
Definition: net_db.h:40
SQUIDCEXTERN const char * hashKeyStr(const hash_link *)
Definition: hash.cc:313
static void netdbPurgeLRU(void)
Definition: net_db.cc:227
void EVH void double
Definition: stub_event.cc:16
HttpRequestPointer r
Definition: net_db.cc:84
@ NETDB_EX_RTT
Definition: enums.h:185
encapsulates DNS lookup results
Definition: LookupDetails.h:21
time_t next_ping_time
Definition: net_db.h:59
@ initIcmp
the ICMP RTT database (NetDB) neighbors exchange subsystem
static void netdbRelease(netdbEntry *n)
Definition: net_db.cc:189
double rtt
Definition: net_db.h:42
time_t squid_curtime
Definition: stub_time.cc:17
netdbExchangeState(CachePeer *aPeer, const HttpRequestPointer &theReq)
Definition: net_db.cc:65
StoreEntry * storeCreateEntry(const char *url, const char *logUrl, const RequestFlags &flags, const HttpRequestMethod &method)
Definition: store.cc:773
static int sortPeerByRtt(const void *A, const void *B)
Definition: net_db.cc:458
#define xfree
int64_t used
Definition: net_db.cc:85
Definition: File.h:39
wordlist * next
Definition: wordlist.h:33
static void netdbHostInsert(netdbEntry *n, const char *hostname)
Definition: net_db.cc:154
int FD_READ_METHOD(int fd, char *buf, int len)
Definition: fde.h:194
static void netdbHashInsert(netdbEntry *n, Ip::Address &addr)
Definition: net_db.cc:121
int applyMask(const Address &mask)
Definition: Address.cc:87
int pings_recv
Definition: net_db.h:56
@ MEM_4K_BUF
Definition: forward.h:42
char * host
Definition: CachePeer.h:40
char * key
Definition: wordlist.h:32
struct timeval current_time
Definition: stub_time.cc:15
int netdbHostHops(const char *host)
Definition: net_db.cc:1040
static void netdbHostDelete(const net_db_name *x)
Definition: net_db.cc:162
int pings_sent
Definition: net_db.h:55
Ip::Address networkFromInaddr(const Ip::Address &a)
Definition: net_db.cc:356
SQUIDCEXTERN HASHHASH hash_string
Definition: hash.h:45
static hash_table * host_table
Definition: net_db.cc:95
char * url
Definition: tcp-banger2.c:114
void memFree(void *, int type)
Free a element allocated by memAllocate()
Definition: old_api.cc:222
SQUIDCEXTERN hash_link * hash_next(hash_table *)
Definition: hash.cc:188
static HttpRequest * FromUrlXXX(const char *url, const MasterXaction::Pointer &, const HttpRequestMethod &method=Http::METHOD_GET)
Definition: HttpRequest.cc:529
void netdbDeleteAddrNetwork(Ip::Address &addr)
Definition: net_db.cc:1186
void DomainPing(Ip::Address &to, const char *domain)
Definition: IcmpSquid.cc:178
void setAnyAddr()
NOTE: Does NOT clear the Port stored. Only the Address and Type.
Definition: Address.cc:177
void netdbExchangeUpdatePeer(Ip::Address &addr, CachePeer *e, double rtt, double hops)
Definition: net_db.cc:1139
@ STATE_HEADER
Definition: net_db.cc:56
double hops
Definition: net_db.h:57
SQUIDCEXTERN hash_table * hash_create(HASHCMP *, int, HASHHASH *)
Definition: hash.cc:108
static void netdbHashDelete(const char *key)
Definition: net_db.cc:130
void netdbBinaryExchange(StoreEntry *s)
Definition: net_db.cc:1203
static const char * netdbPeerName(const char *name)
Definition: net_db.cc:658
static void fwdStart(const Comm::ConnectionPointer &client, StoreEntry *, HttpRequest *)
Same as Start() but no master xaction info (AccessLogEntry) available.
Definition: FwdState.cc:439
void netdbHostData(const char *host, int *samp, int *rtt, int *hops)
Definition: net_db.cc:1073
bool encryptTransport
whether transport encryption (TLS/SSL) is to be used on connections to the peer
Definition: PeerOptions.h:145
static wordlist * peer_names
Definition: net_db.cc:118
static STCB netdbExchangeHandleReply
Definition: net_db.cc:112
void setHeaders(Http::StatusCode status, const char *reason, const char *ctype, int64_t clen, time_t lmt, time_t expires)
Definition: HttpReply.cc:168
void eventAddIsh(const char *name, EVH *func, void *arg, double delta_ish, int weight)
Definition: event.cc:115
int file_open(const char *path, int mode)
Definition: fs_io.cc:45
static struct stat sb
Definition: squidclient.cc:71
static uint32 B
Definition: md4.c:43
@ scOkay
Definition: StatusCode.h:26
int peerHTTPOkay(const CachePeer *p, PeerSelector *ps)
Definition: neighbors.cc:259
void RegisterAction(char const *action, char const *desc, OBJH *handler, int pw_req_flag, int atomic)
Definition: Registration.cc:16
void netdbHandlePingReply(const Ip::Address &from, int hops, int rtt)
Definition: net_db.cc:925
@ METHOD_GET
Definition: MethodType.h:25
double hops
Definition: net_db.h:41
const char * wordlistAdd(wordlist **list, const char *key)
Definition: wordlist.cc:25
SQUIDCEXTERN hash_link * hash_lookup(hash_table *, const void *)
Definition: hash.cc:146
static StatHist s
int storeUnregister(store_client *sc, StoreEntry *e, void *data)
size_t headersEnd(const char *mime, size_t l, bool &containsObsFold)
Definition: mime_header.cc:17
SQUIDCEXTERN int hashPrime(int n)
Definition: hash.cc:293
static netdbEntry * netdbAdd(Ip::Address &addr)
Definition: net_db.cc:272
Security::PeerOptions secure
security settings for peer connection
Definition: CachePeer.h:190
void storeClientCopy(store_client *sc, StoreEntry *e, StoreIOBuffer copyInto, STCB *callback, void *data)
void host(const char *src)
Definition: Uri.cc:98
void netdbPingSite(const char *hostname)
Definition: net_db.cc:908
struct _request * request(char *urlin)
Definition: tcp-banger2.c:291
net_db_name * hosts
Definition: net_db.h:62
char network[MAX_IPSTRLEN]
Definition: net_db.h:54
unsigned short http_port
Definition: CachePeer.h:77
void STCB(void *, StoreIOBuffer)
Definition: StoreClient.h:18
void IPH(const ipcache_addrs *, const Dns::LookupDetails &details, void *)
Definition: ipcache.h:219
static int sortByRtt(const void *A, const void *B)
Definition: net_db.cc:395
class SquidConfig Config
Definition: SquidConfig.cc:12
store_client * storeClientListAdd(StoreEntry *e, void *data)
int unsigned int
Definition: stub_fd.cc:19
@ NETDB_EX_NETWORK
Definition: enums.h:184
AnyP::ProtocolVersion ProtocolVersion(unsigned int aMajor, unsigned int aMinor)
HTTP version label information.
@ STORE_PENDING
Definition: enums.h:51

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors