Asn.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2023 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 53 AS Number handling */
10 
11 #include "squid.h"
12 #include "acl/Acl.h"
13 #include "acl/Asn.h"
14 #include "acl/DestinationAsn.h"
15 #include "acl/DestinationIp.h"
16 #include "acl/FilledChecklist.h"
17 #include "acl/SourceAsn.h"
18 #include "base/CharacterSet.h"
19 #include "FwdState.h"
20 #include "HttpReply.h"
21 #include "HttpRequest.h"
22 #include "ipcache.h"
23 #include "MasterXaction.h"
24 #include "mgr/Registration.h"
25 #include "parser/Tokenizer.h"
26 #include "radix.h"
27 #include "RequestFlags.h"
28 #include "sbuf/SBuf.h"
29 #include "SquidConfig.h"
30 #include "Store.h"
31 #include "StoreClient.h"
32 
33 /* BEGIN of definitions for radix tree entries */
34 
35 /* 32/128 bits address in memory with length */
36 class m_ADDR
37 {
38 public:
39  uint8_t len;
41 
42  m_ADDR() : len(sizeof(Ip::Address)) {};
43 };
44 
45 /* END of definitions for radix tree entries */
46 
47 /* Head for ip to asn radix tree */
48 
50 
51 /* explicit instantiation required for some systems */
52 
56 
62 struct as_info {
64  time_t expires; /* NOTUSED */
65 };
66 
67 class ASState
68 {
70 
71 public:
72  ASState() = default;
73 
75  if (entry) {
76  debugs(53, 3, entry->url());
77  storeUnregister(sc, entry, this);
78  entry->unlock("~ASState");
79  }
80  }
81 
82 public:
83  StoreEntry *entry = nullptr;
84  store_client *sc = nullptr;
86  int as_number = 0;
87 
90 };
91 
93 
95 struct rtentry_t {
96  struct squid_radix_node e_nodes[2];
100 };
101 
102 static int asnAddNet(const SBuf &, int);
103 
104 static void asnCacheStart(int as);
105 
107 
108 #if defined(__cplusplus)
109 extern "C" {
110 #endif
111 
112 static int destroyRadixNode(struct squid_radix_node *rn, void *w);
113 static int printRadixNode(struct squid_radix_node *rn, void *sentry);
114 
115 #if defined(__cplusplus)
116 }
117 #endif
118 
119 static void destroyRadixNodeInfo(as_info *);
120 
121 static OBJH asnStats;
122 
123 /* PUBLIC */
124 
125 int
127 {
128  struct squid_radix_node *rn;
129  as_info *e;
130  m_ADDR m_addr;
131  CbDataList<int> *a = nullptr;
132  CbDataList<int> *b = nullptr;
133 
134  debugs(53, 3, "asnMatchIp: Called for " << addr );
135 
136  if (AS_tree_head == nullptr)
137  return 0;
138 
139  if (addr.isNoAddr())
140  return 0;
141 
142  if (addr.isAnyAddr())
143  return 0;
144 
145  m_addr.addr = addr;
146 
147  rn = squid_rn_match(&m_addr, AS_tree_head);
148 
149  if (rn == nullptr) {
150  debugs(53, 3, "asnMatchIp: Address not in as db.");
151  return 0;
152  }
153 
154  debugs(53, 3, "asnMatchIp: Found in db!");
155  e = ((rtentry_t *) rn)->e_info;
156  assert(e);
157 
158  for (a = data; a; a = a->next)
159  for (b = e->as_number; b; b = b->next)
160  if (a->element == b->element) {
161  debugs(53, 5, "asnMatchIp: Found a match!");
162  return 1;
163  }
164 
165  debugs(53, 5, "asnMatchIp: AS not in as db.");
166  return 0;
167 }
168 
169 void
171 {
172  for (CbDataList<int> *i = data; i; i = i->
173  next)
174  asnCacheStart(i->element);
175 }
176 
177 static void
179 {
180  Mgr::RegisterAction("asndb", "AS Number Database", asnStats, 0, 1);
181 }
182 
183 /* initialize the radix tree structure */
184 
185 SQUIDCEXTERN int squid_max_keylen; /* yuck.. this is in lib/radix.c */
186 
187 void
188 asnInit(void)
189 {
190  static bool inited = false;
191  squid_max_keylen = 40;
192 
193  if (!inited) {
194  inited = true;
195  squid_rn_init();
196  }
197 
199 
201 }
202 
203 void
205 {
207 
208  destroyRadixNode((struct squid_radix_node *) nullptr, (void *) AS_tree_head);
209 }
210 
211 static void
213 {
214  storeAppendPrintf(sentry, "Address \tAS Numbers\n");
216 }
217 
218 /* PRIVATE */
219 
220 static void
222 {
223  AnyP::Uri whoisUrl(AnyP::PROTO_WHOIS);
224  whoisUrl.host(Config.as_whois_server);
225  whoisUrl.defaultPort();
226 
227  SBuf asPath("/!gAS");
228  asPath.appendf("%d", as);
229  whoisUrl.path(asPath);
230 
231  debugs(53, 3, "AS " << as);
232  ASState *asState = new ASState;
233  asState->as_number = as;
234  const auto mx = MasterXaction::MakePortless<XactionInitiator::initAsn>();
235  asState->request = new HttpRequest(mx);
236  asState->request->url = whoisUrl;
237  asState->request->method = Http::METHOD_GET;
238 
239  // XXX: performance regression, c_str() reallocates
240  const auto asres = xstrdup(whoisUrl.absolute().c_str());
241 
242  // XXX: Missing a hittingRequiresCollapsing() && startCollapsingOn() check.
243  auto e = storeGetPublic(asres, Http::METHOD_GET);
244  if (!e) {
245  e = storeCreateEntry(asres, asres, RequestFlags(), Http::METHOD_GET);
246  asState->sc = storeClientListAdd(e, asState);
248  } else {
249  e->lock("Asn");
250  asState->sc = storeClientListAdd(e, asState);
251  }
252  xfree(asres);
253 
254  asState->entry = e;
255  storeClientCopy(asState->sc, e, asState->parsingBuffer.makeInitialSpace(), asHandleReply, asState);
256 }
257 
258 static void
259 asHandleReply(void *data, StoreIOBuffer result)
260 {
261  ASState *asState = (ASState *)data;
262  StoreEntry *e = asState->entry;
263 
264  debugs(53, 3, result << " for " << asState->as_number << " with " << *e);
265 
266  /* First figure out whether we should abort the request */
267 
268  if (EBIT_TEST(e->flags, ENTRY_ABORTED)) {
269  delete asState;
270  return;
271  }
272 
273  if (result.flags.error) {
274  debugs(53, DBG_IMPORTANT, "ERROR: asHandleReply: Called with Error set and size=" << (unsigned int) result.length);
275  delete asState;
276  return;
277  } else if (e->mem().baseReply().sline.status() != Http::scOkay) {
278  debugs(53, DBG_IMPORTANT, "WARNING: AS " << asState->as_number << " whois request failed");
279  delete asState;
280  return;
281  }
282 
283  asState->parsingBuffer.appended(result.data, result.length);
285  SBuf address;
286  // Word delimiters in WHOIS ASN replies. RFC 3912 mentions SP, CR, and LF.
287  // Others are added to mimic an earlier isspace()-based implementation.
288  static const auto WhoisSpaces = CharacterSet("ASCII_spaces", " \f\r\n\t\v");
289  while (tok.token(address, WhoisSpaces)) {
290  (void)asnAddNet(address, asState->as_number);
291  }
292  asState->parsingBuffer.consume(tok.parsedSize());
293  const auto leftoverBytes = asState->parsingBuffer.contentSize();
294 
295  if (asState->sc->atEof()) {
296  if (leftoverBytes)
297  debugs(53, 2, "WHOIS: Discarding the last " << leftoverBytes << " received bytes of a truncated AS response");
298  delete asState;
299  return;
300  }
301 
302  const auto remainingSpace = asState->parsingBuffer.space().positionAt(result.offset + result.length);
303 
304  if (!remainingSpace.length) {
305  Assure(leftoverBytes);
306  debugs(53, DBG_IMPORTANT, "WARNING: Ignoring the tail of a WHOIS AS response" <<
307  " with an unparsable section of " << leftoverBytes <<
308  " bytes ending at offset " << remainingSpace.offset);
309  delete asState;
310  return;
311  }
312 
313  const decltype(StoreIOBuffer::offset) stillReasonableOffset = 100000; // an arbitrary limit in bytes
314  if (remainingSpace.offset > stillReasonableOffset) {
315  // stop suspicious accumulation of parsed addresses and/or work
316  debugs(53, DBG_IMPORTANT, "WARNING: Ignoring the tail of a suspiciously large WHOIS AS response" <<
317  " exceeding " << stillReasonableOffset << " bytes");
318  delete asState;
319  return;
320  }
321 
322  storeClientCopy(asState->sc, e, remainingSpace, asHandleReply, asState);
323 }
324 
328 static int
329 asnAddNet(const SBuf &addressAndMask, const int as_number)
330 {
331  struct squid_radix_node *rn;
332  CbDataList<int> **Tail = nullptr;
333  CbDataList<int> *q = nullptr;
334  as_info *asinfo = nullptr;
335 
336  static const CharacterSet NonSlashSet = CharacterSet("slash", "/").complement("non-slash");
337  Parser::Tokenizer tok(addressAndMask);
338  SBuf addressToken;
339  if (!(tok.prefix(addressToken, NonSlashSet) && tok.skip('/'))) {
340  debugs(53, 3, "asnAddNet: failed, invalid response from whois server.");
341  return 0;
342  }
343  const Ip::Address addr = addressToken.c_str();
344 
345  // INET6 TODO : find a better way of identifying the base IPA family for mask than this.
346  const auto addrFamily = (addressToken.find('.') != SBuf::npos) ? AF_INET : AF_INET6;
347 
348  // generate Netbits Format Mask
349  Ip::Address mask;
350  mask.setNoAddr();
351  int64_t bitl = 0;
352  if (tok.int64(bitl, 10, false))
353  mask.applyMask(bitl, addrFamily);
354 
355  debugs(53, 3, "asnAddNet: called for " << addr << "/" << mask );
356 
357  rtentry_t *e = (rtentry_t *)xcalloc(1, sizeof(rtentry_t));
358 
359  e->e_addr.addr = addr;
360 
361  e->e_mask.addr = mask;
362 
363  rn = squid_rn_lookup(&e->e_addr, &e->e_mask, AS_tree_head);
364 
365  if (rn != nullptr) {
366  asinfo = ((rtentry_t *) rn)->e_info;
367 
368  if (asinfo->as_number->find(as_number)) {
369  debugs(53, 3, "asnAddNet: Ignoring repeated network '" << addr << "/" << bitl << "' for AS " << as_number);
370  } else {
371  debugs(53, 3, "asnAddNet: Warning: Found a network with multiple AS numbers!");
372 
373  for (Tail = &asinfo->as_number; *Tail; Tail = &(*Tail)->next);
374  q = new CbDataList<int> (as_number);
375 
376  *(Tail) = q;
377 
378  e->e_info = asinfo;
379  }
380  } else {
381  q = new CbDataList<int> (as_number);
382  asinfo = (as_info *)xmalloc(sizeof(as_info));
383  asinfo->as_number = q;
386  assert(rn != nullptr);
387  e->e_info = asinfo;
388  }
389 
390  if (rn == nullptr) { /* assert might expand to nothing */
391  xfree(asinfo);
392  delete q;
393  xfree(e);
394  debugs(53, 3, "asnAddNet: Could not add entry.");
395  return 0;
396  }
397 
398  e->e_info = asinfo;
399  return 1;
400 }
401 
402 static int
403 destroyRadixNode(struct squid_radix_node *rn, void *w)
404 {
405 
406  struct squid_radix_node_head *rnh = (struct squid_radix_node_head *) w;
407 
408  if (rn && !(rn->rn_flags & RNF_ROOT)) {
409  rtentry_t *e = (rtentry_t *) rn;
410  rn = squid_rn_delete(rn->rn_key, rn->rn_mask, rnh);
411 
412  if (rn == nullptr)
413  debugs(53, 3, "destroyRadixNode: internal screwup");
414 
416 
417  xfree(rn);
418  }
419 
420  return 1;
421 }
422 
423 static void
425 {
426  CbDataList<int> *prev = nullptr;
427  CbDataList<int> *data = e_info->as_number;
428 
429  while (data) {
430  prev = data;
431  data = data->next;
432  delete prev;
433  }
434 }
435 
436 static int
437 printRadixNode(struct squid_radix_node *rn, void *_sentry)
438 {
439  StoreEntry *sentry = (StoreEntry *)_sentry;
440  rtentry_t *e = (rtentry_t *) rn;
441  CbDataList<int> *q;
442  as_info *asinfo;
443  char buf[MAX_IPSTRLEN];
444  Ip::Address addr;
445  Ip::Address mask;
446 
447  assert(e);
448  assert(e->e_info);
449  addr = e->e_addr.addr;
450  mask = e->e_mask.addr;
451  storeAppendPrintf(sentry, "%s/%d\t",
452  addr.toStr(buf, MAX_IPSTRLEN),
453  mask.cidr() );
454  asinfo = e->e_info;
455  assert(asinfo->as_number);
456 
457  for (q = asinfo->as_number; q; q = q->next)
458  storeAppendPrintf(sentry, " %d", q->element);
459 
460  storeAppendPrintf(sentry, "\n");
461 
462  return 0;
463 }
464 
466 {
467  if (data)
468  delete data;
469 }
470 
471 bool
472 
474 {
475  return asnMatchIp(data, toMatch);
476 }
477 
478 SBufList
480 {
481  SBufList sl;
482 
483  CbDataList<int> *ldata = data;
484 
485  while (ldata != nullptr) {
486  SBuf s;
487  s.Printf("%d", ldata->element);
488  sl.push_back(s);
489  ldata = ldata->next;
490  }
491 
492  return sl;
493 }
494 
495 bool
497 {
498  return data == nullptr;
499 }
500 
501 void
503 {
504  CbDataList<int> **curlist = &data;
505  CbDataList<int> **Tail;
506  CbDataList<int> *q = nullptr;
507  char *t = nullptr;
508 
509  for (Tail = curlist; *Tail; Tail = &((*Tail)->next));
510  while ((t = ConfigParser::strtokFile())) {
511  q = new CbDataList<int> (atoi(t));
512  *(Tail) = q;
513  Tail = &q->next;
514  }
515 }
516 
517 int
519 {
520  const auto checklist = Filled(ch);
521 
522  return data->match(checklist->src_addr);
523 }
524 
525 int
527 {
528  const auto checklist = Filled(ch);
529 
530  const ipcache_addrs *ia = ipcache_gethostbyname(checklist->request->url.host(), IP_LOOKUP_IF_MISS);
531 
532  if (ia) {
533  for (const auto &ip: ia->goodAndBad()) {
534  if (data->match(ip))
535  return 1;
536  }
537 
538  return 0;
539 
540  } else if (!checklist->request->flags.destinationIpLookedUp) {
541  /* No entry in cache, lookup not attempted */
542  debugs(28, 3, "can't yet compare '" << name << "' ACL for " << checklist->request->url.host());
543  if (checklist->goAsync(ACLDestinationIP::StartLookup, *this))
544  return -1;
545  // else fall through to noaddr match, hiding the lookup failure (XXX)
546  }
547  Ip::Address noaddr;
548  noaddr.setNoAddr();
549  return data->match(noaddr);
550 }
551 
m_ADDR e_addr
Definition: Asn.cc:98
CbDataList< int > * as_number
Definition: Asn.cc:63
#define IP_LOOKUP_IF_MISS
Definition: defines.h:37
Store::ParsingBuffer parsingBuffer
for receiving a WHOIS reply body from Store and interpreting it
Definition: Asn.cc:89
void * xcalloc(size_t n, size_t sz)
Definition: xalloc.cc:71
size_type find(char c, size_type startPos=0) const
Definition: SBuf.cc:584
void push_back(char)
Append a single character. The character may be NUL (\0).
Definition: SBuf.cc:208
~ASState()
Definition: Asn.cc:74
static void asnRegisterWithCacheManager(void)
Definition: Asn.cc:178
struct StoreIOBuffer::@130 flags
AnyP::Uri url
the request URI
Definition: HttpRequest.h:115
#define xmalloc
static void destroyRadixNodeInfo(as_info *)
Definition: Asn.cc:424
Definition: Uri.h:31
SBufList dump() const override
Definition: Asn.cc:479
static void asnCacheStart(int as)
Definition: Asn.cc:221
static char * strtokFile()
Definition: ConfigParser.cc:65
~ACLASN() override
Definition: Asn.cc:465
static int asnAddNet(const SBuf &, int)
Definition: Asn.cc:329
Definition: Asn.cc:36
bool isAnyAddr() const
Definition: Address.cc:190
MemObject & mem()
Definition: Store.h:47
static OBJH asnStats
Definition: Asn.cc:121
std::list< SBuf > SBufList
Definition: forward.h:22
void storeAppendPrintf(StoreEntry *e, const char *fmt,...)
Definition: store.cc:855
@ ENTRY_ABORTED
Definition: enums.h:110
struct squid_radix_node e_nodes[2]
Definition: Asn.cc:96
#define CBDATA_CLASS(type)
Definition: cbdata.h:289
int64_t offset
Definition: StoreIOBuffer.h:58
Definition: SBuf.h:93
void defaultPort()
reset the port to the default port number for the current scheme
Definition: Uri.h:94
CbDataList * next
Definition: CbDataList.h:31
CharacterSet complement(const char *complementLabel=nullptr) const
Definition: CharacterSet.cc:74
#define xstrdup
const ipcache_addrs * ipcache_gethostbyname(const char *name, int flags)
Definition: ipcache.cc:729
StoreIOBuffer & positionAt(const int64_t newOffset)
convenience method for changing the offset of a being-configured buffer
Definition: StoreIOBuffer.h:47
static STCB asHandleReply
Definition: Asn.cc:106
C * getRaw() const
Definition: RefCount.h:89
Definition: Asn.cc:62
uint16_t flags
Definition: Store.h:231
struct squid_radix_node_head * AS_tree_head
Definition: Asn.cc:49
Http::StatusLine sline
Definition: HttpReply.h:56
bool find(C const &) const
Definition: CbDataList.h:110
Definition: Asn.cc:67
unsigned char rn_flags
Definition: radix.h:58
static int destroyRadixNode(struct squid_radix_node *rn, void *w)
Definition: Asn.cc:403
HttpRequest::Pointer request
Definition: Asn.cc:85
SQUIDCEXTERN int squid_rn_walktree(struct squid_radix_node_head *, int(*)(struct squid_radix_node *, void *), void *)
Definition: radix.c:817
char * toStr(char *buf, const unsigned int blen, int force=AF_UNSPEC) const
Definition: Address.cc:812
#define MAX_IPSTRLEN
Length of buffer that needs to be allocated to old a null-terminated IP-string.
Definition: forward.h:25
static void StartLookup(ACLFilledChecklist &, const Acl::Node &)
bool match(Ip::Address) override
Definition: Asn.cc:473
SQUIDCEXTERN int squid_max_keylen
Definition: Asn.cc:185
SQUIDCEXTERN void squid_rn_init(void)
Definition: radix.c:883
void OBJH(StoreEntry *)
Definition: forward.h:44
int asnMatchIp(CbDataList< int > *data, Ip::Address &addr)
Definition: Asn.cc:126
Ip::Address addr
Definition: Asn.cc:40
Http::StatusCode status() const
retrieve the status code for this status line
Definition: StatusLine.h:45
const HttpReply & baseReply() const
Definition: MemObject.h:60
void setNoAddr()
Definition: Address.cc:312
Definition: Asn.cc:95
void asnFreeMemory(void)
Definition: Asn.cc:204
ACLFilledChecklist * Filled(ACLChecklist *checklist)
convenience and safety wrapper for dynamic_cast<ACLFilledChecklist*>
void consume(size_t)
get rid of previously appended() prefix of a given size
void appended(const char *, size_t)
remember the new bytes received into the previously provided space()
static int printRadixNode(struct squid_radix_node *rn, void *sentry)
Definition: Asn.cc:437
#define SQUIDCEXTERN
Definition: squid.h:21
unsigned error
Definition: StoreIOBuffer.h:55
StoreEntry * entry
Definition: Asn.cc:83
int cbdata_type
Definition: cbdata.h:195
#define EBIT_TEST(flag, bit)
Definition: defines.h:67
SBuf & Printf(const char *fmt,...) PRINTF_FORMAT_ARG2
Definition: SBuf.cc:214
SQUIDCEXTERN int squid_rn_inithead(struct squid_radix_node_head **, int)
Definition: radix.c:853
CbDataList< int > * data
Definition: Asn.h:40
SQUIDCEXTERN struct squid_radix_node * squid_rn_addroute(void *, void *, struct squid_radix_node_head *, struct squid_radix_node[2])
Definition: radix.c:519
#define assert(EX)
Definition: assert.h:17
int match(ACLChecklist *) override
Matches the actual data in checklist against this Acl::Node.
Definition: Asn.cc:526
int cidr() const
Definition: Address.cc:54
char * as_whois_server
Definition: SquidConfig.h:181
#define Assure(condition)
Definition: Assure.h:35
static int sc[16]
Definition: smbdes.c:121
const char * c_str()
Definition: SBuf.cc:516
as_info * e_info
Definition: Asn.cc:97
StoreEntry * storeCreateEntry(const char *url, const char *logUrl, const RequestFlags &flags, const HttpRequestMethod &method)
Definition: store.cc:759
bool isNoAddr() const
Definition: Address.cc:304
#define xfree
#define RNF_ROOT
Definition: radix.h:60
static const size_type npos
Definition: SBuf.h:100
Definition: Xaction.cc:137
void parse() override
Definition: Asn.cc:502
time_t expires
Definition: Asn.cc:64
int applyMask(const Address &mask)
Definition: Address.cc:97
StoreIOBuffer content() const
SBuf & absolute() const
Definition: Uri.cc:711
@ PROTO_WHOIS
Definition: ProtocolType.h:36
int match(ACLChecklist *) override
Matches the actual data in checklist against this Acl::Node.
Definition: Asn.cc:518
int as_number
Definition: Asn.cc:86
HttpRequestMethod method
Definition: HttpRequest.h:114
void path(const char *p)
Definition: Uri.h:96
StoreIOBuffer makeInitialSpace()
Definition: ParsingBuffer.h:84
SQUIDCEXTERN struct squid_radix_node * squid_rn_match(void *, struct squid_radix_node_head *)
Definition: radix.c:244
CBDATA_CLASS_INIT(ASState)
SQUIDCEXTERN struct squid_radix_node * squid_rn_lookup(void *, void *, struct squid_radix_node_head *)
Definition: radix.c:206
Definition: parse.c:160
void prepareForUse() override
Definition: Asn.cc:170
SQUIDCEXTERN struct squid_radix_node * squid_rn_delete(void *, void *, struct squid_radix_node_head *)
Definition: radix.c:664
void RegisterAction(char const *action, char const *desc, OBJH *handler, Protected, Atomic, Format)
Definition: Registration.cc:54
void asnInit(void)
Definition: Asn.cc:188
#define DBG_IMPORTANT
Definition: Stream.h:38
uint8_t len
Definition: Asn.cc:39
StoreEntry * storeGetPublic(const char *uri, const HttpRequestMethod &method)
Definition: store.cc:504
m_ADDR e_mask
Definition: Asn.cc:99
static void fwdStart(const Comm::ConnectionPointer &client, StoreEntry *, HttpRequest *)
Same as Start() but no master xaction info (AccessLogEntry) available.
Definition: FwdState.cc:407
store_client * sc
Definition: Asn.cc:84
int token
Definition: parse.c:163
optimized set of C chars, with quick membership test and merge support
Definition: CharacterSet.h:17
bool atEof() const
Definition: StoreClient.h:106
@ scOkay
Definition: StatusCode.h:27
void(void *, StoreIOBuffer) STCB
Definition: StoreClient.h:32
m_ADDR()
Definition: Asn.cc:42
SBuf & appendf(const char *fmt,...) PRINTF_FORMAT_ARG2
Definition: SBuf.cc:229
@ METHOD_GET
Definition: MethodType.h:25
int storeUnregister(store_client *sc, StoreEntry *e, void *data)
void storeClientCopy(store_client *sc, StoreEntry *e, StoreIOBuffer copyInto, STCB *callback, void *data)
size_t contentSize() const
the total number of append()ed bytes that were not consume()d
void host(const char *src)
Definition: Uri.cc:123
StoreIOBuffer space()
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:192
bool empty() const override
Definition: Asn.cc:496
class SquidConfig Config
Definition: SquidConfig.cc:12
store_client * storeClientListAdd(StoreEntry *e, void *data)
IpsSelector< IpsIterator > goodAndBad() const
all IPs
Definition: ipcache.h:249

 

Introduction

Documentation

Support

Miscellaneous