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