client_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 00 Client Database */
10 
11 #include "squid.h"
12 #include "base/RunnersRegistry.h"
13 #include "client_db.h"
14 #include "ClientInfo.h"
15 #include "event.h"
16 #include "format/Token.h"
17 #include "fqdncache.h"
18 #include "ip/Address.h"
19 #include "log/access_log.h"
20 #include "mgr/Registration.h"
21 #include "SquidConfig.h"
22 #include "SquidMath.h"
23 #include "StatCounters.h"
24 #include "Store.h"
25 #include "tools.h"
26 
27 #if SQUID_SNMP
28 #include "snmp_core.h"
29 #endif
30 
32 
33 static ClientInfo *clientdbAdd(const Ip::Address &addr);
35 static void clientdbStartGC(void);
36 static void clientdbScheduledGC(void *);
37 
38 #if USE_DELAY_POOLS
39 static int max_clients = 32768;
40 #else
41 static int max_clients = 32;
42 #endif
43 
44 static int cleanup_running = 0;
45 static int cleanup_scheduled = 0;
46 static int cleanup_removed;
47 
48 #if USE_DELAY_POOLS
49 #define CLIENT_DB_HASH_SIZE 65357
50 #else
51 #define CLIENT_DB_HASH_SIZE 467
52 #endif
53 
55 #if USE_DELAY_POOLS
56  BandwidthBucket(0, 0, 0),
57 #endif
58  addr(ip),
59  n_established(0),
60  last_seen(0)
61 #if USE_DELAY_POOLS
62  , writeLimitingActive(false),
63  firstTimeConnection(true),
64  quotaQueue(nullptr),
65  rationedQuota(0),
66  rationedCount(0),
67  eventWaiting(false)
68 #endif
69 {
70  debugs(77, 9, "ClientInfo constructed, this=" << static_cast<void*>(this));
71  char *buf = static_cast<char*>(xmalloc(MAX_IPSTRLEN)); // becomes hash.key
72  key = addr.toStr(buf,MAX_IPSTRLEN);
73 }
74 
75 static ClientInfo *
77 {
78  ClientInfo *c = new ClientInfo(addr);
79  hash_join(client_table, static_cast<hash_link*>(c));
81 
84  eventAdd("client_db garbage collector", clientdbScheduledGC, NULL, 90, 0);
85  }
86 
87  return c;
88 }
89 
90 static void
92 {
93  if (client_table)
94  return;
95 
97 }
98 
100 {
101 public:
102  /* RegisteredRunner API */
103  virtual void useConfig();
104 };
106 
107 void
109 {
110  clientdbInit();
111  Mgr::RegisterAction("client_list", "Cache Client List", clientdbDump, 0, 1);
112 }
113 
114 #if USE_DELAY_POOLS
115 /* returns ClientInfo for given IP addr
116  Returns NULL if no such client (or clientdb turned off)
117  (it is assumed that clientdbEstablished will be called before and create client record if needed)
118 */
120 {
121  char key[MAX_IPSTRLEN];
122  ClientInfo *c;
123 
124  if (!Config.onoff.client_db)
125  return NULL;
126 
127  addr.toStr(key,MAX_IPSTRLEN);
128 
129  c = (ClientInfo *) hash_lookup(client_table, key);
130  if (c==NULL) {
131  debugs(77, DBG_IMPORTANT,"Client db does not contain information for given IP address "<<(const char*)key);
132  return NULL;
133  }
134  return c;
135 }
136 #endif
137 void
138 clientdbUpdate(const Ip::Address &addr, const LogTags &ltype, AnyP::ProtocolType p, size_t size)
139 {
140  char key[MAX_IPSTRLEN];
141  ClientInfo *c;
142 
143  if (!Config.onoff.client_db)
144  return;
145 
146  addr.toStr(key,MAX_IPSTRLEN);
147 
148  c = (ClientInfo *) hash_lookup(client_table, key);
149 
150  if (c == NULL)
151  c = clientdbAdd(addr);
152 
153  if (c == NULL)
154  debug_trap("clientdbUpdate: Failed to add entry");
155 
156  if (p == AnyP::PROTO_HTTP) {
157  ++ c->Http.n_requests;
158  ++ c->Http.result_hist[ltype.oldType];
159  c->Http.kbytes_out += size;
160 
161  if (ltype.isTcpHit())
162  c->Http.hit_kbytes_out += size;
163  } else if (p == AnyP::PROTO_ICP) {
164  ++ c->Icp.n_requests;
165  ++ c->Icp.result_hist[ltype.oldType];
166  c->Icp.kbytes_out += size;
167 
168  if (LOG_UDP_HIT == ltype.oldType)
169  c->Icp.hit_kbytes_out += size;
170  }
171 
173 }
174 
181 int
182 clientdbEstablished(const Ip::Address &addr, int delta)
183 {
184  char key[MAX_IPSTRLEN];
185  ClientInfo *c;
186 
187  if (!Config.onoff.client_db)
188  return 0;
189 
190  addr.toStr(key,MAX_IPSTRLEN);
191 
192  c = (ClientInfo *) hash_lookup(client_table, key);
193 
194  if (c == NULL) {
195  c = clientdbAdd(addr);
196  }
197 
198  if (c == NULL)
199  debug_trap("clientdbUpdate: Failed to add entry");
200 
201  c->n_established += delta;
202 
203  return c->n_established;
204 }
205 
206 #define CUTOFF_SECONDS 3600
207 int
208 
210 {
211  char key[MAX_IPSTRLEN];
212  int NR;
213  int ND;
214  double p;
215  ClientInfo *c;
216 
217  if (!Config.onoff.client_db)
218  return 0;
219 
220  addr.toStr(key,MAX_IPSTRLEN);
221 
222  c = (ClientInfo *) hash_lookup(client_table, key);
223 
224  if (c == NULL)
225  return 0;
226 
227  /*
228  * If we are in a cutoff window, we don't send a reply
229  */
231  return 1;
232 
233  /*
234  * Calculate the percent of DENIED replies since the last
235  * cutoff time.
236  */
237  NR = c->Icp.n_requests - c->cutoff.n_req;
238 
239  if (NR < 150)
240  NR = 150;
241 
243 
244  p = 100.0 * ND / NR;
245 
246  if (p < 95.0)
247  return 0;
248 
249  debugs(1, DBG_CRITICAL, "WARNING: Probable misconfigured neighbor at " << key);
250 
251  debugs(1, DBG_CRITICAL, "WARNING: " << ND << " of the last " << NR <<
252  " ICP replies are DENIED");
253 
254  debugs(1, DBG_CRITICAL, "WARNING: No replies will be sent for the next " <<
255  CUTOFF_SECONDS << " seconds");
256 
258 
259  c->cutoff.n_req = c->Icp.n_requests;
260 
262 
263  return 1;
264 }
265 
266 void
268 {
269  const char *name;
270  int icp_total = 0;
271  int icp_hits = 0;
272  int http_total = 0;
273  int http_hits = 0;
274  storeAppendPrintf(sentry, "Cache Clients:\n");
276 
277  while (hash_link *hash = hash_next(client_table)) {
278  const ClientInfo *c = static_cast<const ClientInfo *>(hash);
279  storeAppendPrintf(sentry, "Address: %s\n", hashKeyStr(hash));
280  if ( (name = fqdncache_gethostbyaddr(c->addr, 0)) ) {
281  storeAppendPrintf(sentry, "Name: %s\n", name);
282  }
283  storeAppendPrintf(sentry, "Currently established connections: %d\n",
284  c->n_established);
285  storeAppendPrintf(sentry, " ICP Requests %d\n",
286  c->Icp.n_requests);
287 
288  for (LogTags_ot l = LOG_TAG_NONE; l < LOG_TYPE_MAX; ++l) {
289  if (c->Icp.result_hist[l] == 0)
290  continue;
291 
292  icp_total += c->Icp.result_hist[l];
293 
294  if (LOG_UDP_HIT == l)
295  icp_hits += c->Icp.result_hist[l];
296 
297  storeAppendPrintf(sentry, " %-20.20s %7d %3d%%\n", LogTags(l).c_str(), c->Icp.result_hist[l], Math::intPercent(c->Icp.result_hist[l], c->Icp.n_requests));
298  }
299 
300  storeAppendPrintf(sentry, " HTTP Requests %d\n", c->Http.n_requests);
301 
302  for (LogTags_ot l = LOG_TAG_NONE; l < LOG_TYPE_MAX; ++l) {
303  if (c->Http.result_hist[l] == 0)
304  continue;
305 
306  http_total += c->Http.result_hist[l];
307 
308  if (LogTags(l).isTcpHit())
309  http_hits += c->Http.result_hist[l];
310 
311  storeAppendPrintf(sentry,
312  " %-20.20s %7d %3d%%\n",
313  LogTags(l).c_str(),
314  c->Http.result_hist[l],
316  }
317 
318  storeAppendPrintf(sentry, "\n");
319  }
320 
321  storeAppendPrintf(sentry, "TOTALS\n");
322  storeAppendPrintf(sentry, "ICP : %d Queries, %d Hits (%3d%%)\n",
323  icp_total, icp_hits, Math::intPercent(icp_hits, icp_total));
324  storeAppendPrintf(sentry, "HTTP: %d Requests, %d Hits (%3d%%)\n",
325  http_total, http_hits, Math::intPercent(http_hits, http_total));
326 }
327 
328 static void
329 clientdbFreeItem(void *data)
330 {
331  ClientInfo *c = (ClientInfo *)data;
332  delete c;
333 }
334 
336 {
337  safe_free(key);
338 
339 #if USE_DELAY_POOLS
340  if (CommQuotaQueue *q = quotaQueue) {
341  q->clientInfo = NULL;
342  delete q; // invalidates cbdata, cancelling any pending kicks
343  }
344 #endif
345 
346  debugs(77, 9, "ClientInfo destructed, this=" << static_cast<void*>(this));
347 }
348 
349 void
351 {
354  client_table = NULL;
355 }
356 
357 static void
359 {
360  cleanup_scheduled = 0;
361  clientdbStartGC();
362 }
363 
364 static void
365 clientdbGC(void *)
366 {
367  static int bucket = 0;
368  hash_link *link_next;
369 
370  link_next = hash_get_bucket(client_table, bucket++);
371 
372  while (link_next != NULL) {
373  ClientInfo *c = (ClientInfo *)link_next;
374  int age = squid_curtime - c->last_seen;
375  link_next = link_next->next;
376 
377  if (c->n_established)
378  continue;
379 
380  if (age < 24 * 3600 && c->Http.n_requests > 100)
381  continue;
382 
383  if (age < 4 * 3600 && (c->Http.n_requests > 10 || c->Icp.n_requests > 10))
384  continue;
385 
386  if (age < 5 * 60 && (c->Http.n_requests > 1 || c->Icp.n_requests > 1))
387  continue;
388 
389  if (age < 60)
390  continue;
391 
392  hash_remove_link(client_table, static_cast<hash_link*>(c));
393 
394  clientdbFreeItem(c);
395 
397 
398  ++cleanup_removed;
399  }
400 
401  if (bucket < CLIENT_DB_HASH_SIZE)
402  eventAdd("client_db garbage collector", clientdbGC, NULL, 0.15, 0);
403  else {
404  bucket = 0;
405  cleanup_running = 0;
407 
408  if (!cleanup_scheduled) {
409  cleanup_scheduled = 1;
410  eventAdd("client_db garbage collector", clientdbScheduledGC, NULL, 6 * 3600, 0);
411  }
412 
413  debugs(49, 2, "clientdbGC: Removed " << cleanup_removed << " entries");
414  }
415 }
416 
417 static void
419 {
421  cleanup_running = 1;
422  cleanup_removed = 0;
423  clientdbGC(NULL);
424 }
425 
426 #if SQUID_SNMP
427 
428 Ip::Address *
430 {
431  char key[MAX_IPSTRLEN];
433 
434  if (current) {
435  current->toStr(key,MAX_IPSTRLEN);
436  while (hash_link *hash = hash_next(client_table)) {
437  if (!strcmp(key, hashKeyStr(hash)))
438  break;
439  }
440  }
441 
442  ClientInfo *c = static_cast<ClientInfo *>(hash_next(client_table));
443 
445 
446  return c ? &c->addr : nullptr;
447 }
448 
451 {
452  char key[MAX_IPSTRLEN];
453  ClientInfo *c = NULL;
454  Ip::Address keyIp;
455 
456  *ErrP = SNMP_ERR_NOERROR;
457  MemBuf tmp;
458  debugs(49, 6, "Current : length=" << Var->name_length << ": " << snmpDebugOid(Var->name, Var->name_length, tmp));
459  if (Var->name_length == 16) {
460  oid2addr(&(Var->name[12]), keyIp, 4);
461  } else if (Var->name_length == 28) {
462  oid2addr(&(Var->name[12]), keyIp, 16);
463  } else {
464  *ErrP = SNMP_ERR_NOSUCHNAME;
465  return NULL;
466  }
467 
468  keyIp.toStr(key, sizeof(key));
469  debugs(49, 5, "[" << key << "] requested!");
470  c = (ClientInfo *) hash_lookup(client_table, key);
471 
472  if (c == NULL) {
473  debugs(49, 5, "not found.");
474  *ErrP = SNMP_ERR_NOSUCHNAME;
475  return NULL;
476  }
477 
478  variable_list *Answer = NULL;
479  int aggr = 0;
480 
481  switch (Var->name[LEN_SQ_NET + 2]) {
482 
483  case MESH_CTBL_ADDR_TYPE: {
484  int ival;
486  Answer = snmp_var_new_integer(Var->name, Var->name_length,
487  ival, SMI_INTEGER);
488  }
489  break;
490 
491  case MESH_CTBL_ADDR: {
492  Answer = snmp_var_new(Var->name, Var->name_length);
493  // InetAddress doesn't have its own ASN.1 type,
494  // like IpAddr does (SMI_IPADDRESS)
495  // See: rfc4001.txt
496  Answer->type = ASN_OCTET_STR;
497  char client[MAX_IPSTRLEN];
498  c->addr.toStr(client,MAX_IPSTRLEN);
499  Answer->val_len = strlen(client);
500  Answer->val.string = (u_char *) xstrdup(client);
501  }
502  break;
503  case MESH_CTBL_HTBYTES:
504  Answer = snmp_var_new_integer(Var->name, Var->name_length,
505  (snint) c->Http.kbytes_out.kb,
506  SMI_COUNTER32);
507  break;
508 
509  case MESH_CTBL_HTREQ:
510  Answer = snmp_var_new_integer(Var->name, Var->name_length,
511  (snint) c->Http.n_requests,
512  SMI_COUNTER32);
513  break;
514 
515  case MESH_CTBL_HTHITS:
516  aggr = 0;
517 
518  for (LogTags_ot l = LOG_TAG_NONE; l < LOG_TYPE_MAX; ++l) {
519  if (LogTags(l).isTcpHit())
520  aggr += c->Http.result_hist[l];
521  }
522 
523  Answer = snmp_var_new_integer(Var->name, Var->name_length,
524  (snint) aggr,
525  SMI_COUNTER32);
526  break;
527 
529  Answer = snmp_var_new_integer(Var->name, Var->name_length,
531  SMI_COUNTER32);
532  break;
533 
534  case MESH_CTBL_ICPBYTES:
535  Answer = snmp_var_new_integer(Var->name, Var->name_length,
536  (snint) c->Icp.kbytes_out.kb,
537  SMI_COUNTER32);
538  break;
539 
540  case MESH_CTBL_ICPREQ:
541  Answer = snmp_var_new_integer(Var->name, Var->name_length,
542  (snint) c->Icp.n_requests,
543  SMI_COUNTER32);
544  break;
545 
546  case MESH_CTBL_ICPHITS:
547  aggr = c->Icp.result_hist[LOG_UDP_HIT];
548  Answer = snmp_var_new_integer(Var->name, Var->name_length,
549  (snint) aggr,
550  SMI_COUNTER32);
551  break;
552 
554  Answer = snmp_var_new_integer(Var->name, Var->name_length,
555  (snint) c->Icp.hit_kbytes_out.kb,
556  SMI_COUNTER32);
557  break;
558 
559  default:
560  *ErrP = SNMP_ERR_NOSUCHNAME;
561  debugs(49, 5, "snmp_meshCtblFn: illegal column.");
562  break;
563  }
564 
565  return Answer;
566 }
567 
568 #endif /*SQUID_SNMP */
569 
void clientdbFreeMemory(void)
Definition: client_db.cc:350
void oid2addr(oid *id, Ip::Address &addr, u_int size)
Definition: snmp_core.cc:1111
ByteCounter hit_kbytes_out
Definition: ClientInfo.h:52
const char * snmpDebugOid(oid *Name, snint Len, MemBuf &outbuf)
Definition: snmp_core.cc:1052
#define DBG_CRITICAL
Definition: Stream.h:40
static int cleanup_scheduled
Definition: client_db.cc:45
SQUIDCEXTERN void hash_last(hash_table *)
Definition: hash.cc:204
struct ClientInfo::Protocol Icp
#define xmalloc
int intPercent(const int a, const int b)
Definition: SquidMath.cc:13
void clientdbDump(StoreEntry *sentry)
Definition: client_db.cc:267
void FREE(void *)
Definition: forward.h:36
bool isTcpHit() const
determine if the log tag code indicates a cache HIT
Definition: LogTags.cc:101
void storeAppendPrintf(StoreEntry *e, const char *fmt,...)
Definition: store.cc:830
#define ASN_OCTET_STR
Definition: asn1.h:54
@ MESH_CTBL_ICPHITBYTES
Definition: cache_snmp.h:266
SQUIDCEXTERN void hash_remove_link(hash_table *, hash_link *)
Definition: hash.cc:220
Ip::Address addr
Definition: ClientInfo.h:41
#define xstrdup
#define CUTOFF_SECONDS
Definition: client_db.cc:206
void clientdbUpdate(const Ip::Address &addr, const LogTags &ltype, AnyP::ProtocolType p, size_t size)
Definition: client_db.cc:138
int clientdbEstablished(const Ip::Address &addr, int delta)
Definition: client_db.cc:182
Ip::Address * client_entry(Ip::Address *current)
Definition: client_db.cc:429
SQUIDCEXTERN void hashFreeItems(hash_table *, HASHFREE *)
Definition: hash.cc:252
ClientInfo(const Ip::Address &)
Definition: client_db.cc:54
#define INETADDRESSTYPE_IPV4
Definition: snmp_vars.h:93
int HASHCMP(const void *, const void *)
Definition: hash.h:13
@ MESH_CTBL_ICPHITS
Definition: cache_snmp.h:265
bool isIPv4() const
Definition: Address.cc:158
Definition: forward.h:22
@ MESH_CTBL_HTHITBYTES
Definition: cache_snmp.h:262
SQUIDCEXTERN void hash_join(hash_table *, hash_link *)
Definition: hash.cc:131
SQUIDCEXTERN void hashFreeMemory(hash_table *)
Definition: hash.cc:268
@ MESH_CTBL_ICPREQ
Definition: cache_snmp.h:263
static hash_table * client_table
Definition: client_db.cc:31
@ LOG_TYPE_MAX
Definition: LogTags.h:63
int clientdbCutoffDenied(const Ip::Address &addr)
Definition: client_db.cc:209
@ MESH_CTBL_HTHITS
Definition: cache_snmp.h:261
char * toStr(char *buf, const unsigned int blen, int force=AF_UNSPEC) const
Definition: Address.cc:792
size_t kb
Definition: ByteCounter.h:25
int name_length
Definition: snmp_vars.h:47
#define MAX_IPSTRLEN
Length of buffer that needs to be allocated to old a null-terminated IP-string.
Definition: forward.h:25
oid * name
Definition: snmp_vars.h:46
ProtocolType
Definition: ProtocolType.h:23
#define CLIENT_DB_HASH_SIZE
Definition: client_db.cc:49
static void clientdbInit(void)
Definition: client_db.cc:91
int64_t snint
Definition: cache_snmp.h:14
CommQuotaQueue * quotaQueue
clients waiting for more write quota
Definition: ClientInfo.h:68
struct ClientInfo::Protocol Http
virtual void useConfig()
Definition: client_db.cc:108
int size
Definition: ModDevPoll.cc:75
const char * fqdncache_gethostbyaddr(const Ip::Address &addr, int flags)
Definition: fqdncache.cc:482
#define NULL
Definition: types.h:166
struct variable_list * snmp_var_new(oid *, int)
Definition: snmp_vars.c:109
@ LOG_UDP_HIT
Definition: LogTags.h:57
#define SMI_INTEGER
Definition: snmp_vars.h:71
struct StatCounters::@127 client_http
static ClientInfo * clientdbAdd(const Ip::Address &addr)
Definition: client_db.cc:76
static void clientdbStartGC(void)
Definition: client_db.cc:418
@ LOG_TAG_NONE
Definition: LogTags.h:38
#define true
Definition: GnuRegex.c:234
@ MESH_CTBL_ICPBYTES
Definition: cache_snmp.h:264
u_char * string
Definition: snmp_vars.h:51
Definition: MemBuf.h:24
static FREE clientdbFreeItem
Definition: client_db.cc:34
struct variable_list * snmp_var_new_integer(oid *, int, int, unsigned char)
Definition: snmp_vars.c:151
@ MESH_CTBL_HTREQ
Definition: cache_snmp.h:259
SQUIDCEXTERN void hash_first(hash_table *)
Definition: hash.cc:172
@ MESH_CTBL_ADDR
Definition: cache_snmp.h:258
void debug_trap(const char *message)
Definition: tools.cc:455
time_t last_seen
Definition: ClientInfo.h:63
#define safe_free(x)
Definition: xalloc.h:73
Base class for Squid-to-client bandwidth limiting.
SQUIDCEXTERN const char * hashKeyStr(const hash_link *)
Definition: hash.cc:313
@ MESH_CTBL_ADDR_TYPE
Definition: cache_snmp.h:257
u_char type
Definition: snmp_vars.h:48
static int cleanup_removed
Definition: client_db.cc:46
int n_established
Definition: ClientInfo.h:62
static hash_table * hash
Definition: text_backend.cc:41
union variable_list::@20 val
time_t squid_curtime
Definition: stub_libtime.cc:20
ClientInfo * clientdbGetInfo(const Ip::Address &addr)
Definition: client_db.cc:119
static int cleanup_running
Definition: client_db.cc:44
@ PROTO_HTTP
Definition: ProtocolType.h:25
#define LEN_SQ_NET
Definition: cache_snmp.h:49
struct SquidConfig::@110 onoff
static void clientdbScheduledGC(void *)
Definition: client_db.cc:358
variable_list * snmp_meshCtblFn(variable_list *Var, snint *ErrP)
Definition: client_db.cc:450
SQUIDCEXTERN HASHHASH hash_string
Definition: hash.h:45
ByteCounter kbytes_out
Definition: ClientInfo.h:51
SQUIDCEXTERN hash_link * hash_get_bucket(hash_table *, unsigned int)
Definition: hash.cc:244
SQUIDCEXTERN hash_link * hash_next(hash_table *)
Definition: hash.cc:188
LogTags_ot
Definition: LogTags.h:37
RunnerRegistrationEntry(ClientDbRr)
#define DBG_IMPORTANT
Definition: Stream.h:41
LogTags_ot oldType
a set of client protocol, cache use, and other transaction outcome tags
Definition: LogTags.h:93
SQUIDCEXTERN hash_table * hash_create(HASHCMP *, int, HASHHASH *)
Definition: hash.cc:108
static int max_clients
Definition: client_db.cc:39
#define INETADDRESSTYPE_IPV6
Definition: snmp_vars.h:94
int result_hist[LOG_TYPE_MAX]
Definition: ClientInfo.h:48
#define SNMP_ERR_NOSUCHNAME
Definition: snmp_error.h:44
void RegisterAction(char const *action, char const *desc, OBJH *handler, int pw_req_flag, int atomic)
Definition: Registration.cc:16
struct ClientInfo::Cutoff cutoff
@ LOG_UDP_DENIED
Definition: LogTags.h:59
SQUIDCEXTERN hash_link * hash_lookup(hash_table *, const void *)
Definition: hash.cc:146
#define false
Definition: GnuRegex.c:233
static void clientdbGC(void *)
Definition: client_db.cc:365
@ MESH_CTBL_HTBYTES
Definition: cache_snmp.h:260
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:196
void eventAdd(const char *name, EVH *func, void *arg, double when, int weight, bool cbdata)
Definition: event.cc:107
@ PROTO_ICP
Definition: ProtocolType.h:33
#define SNMP_ERR_NOERROR
Definition: snmp_error.h:42
class SquidConfig Config
Definition: SquidConfig.cc:12
#define SMI_COUNTER32
Definition: snmp_vars.h:76
StatCounters statCounter
Definition: StatCounters.cc:12

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors