2 * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
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.
9 /* DEBUG: section 49 SNMP Interface */
12 #include "cache_snmp.h"
13 #include "CachePeer.h"
15 #include "mem/Meter.h"
16 #include "mem/Stats.h"
18 #include "neighbors.h"
19 #include "snmp_agent.h"
20 #include "snmp_core.h"
21 #include "SquidConfig.h"
22 #include "SquidMath.h"
24 #include "StatCounters.h"
30 /************************************************************************
32 SQUID MIB Implementation
34 ************************************************************************/
41 snmp_sysFn(variable_list
* Var
, snint
* ErrP
)
43 variable_list
*Answer
= nullptr;
45 debugs(49, 5, "snmp_sysFn: Processing request:" << snmpDebugOid(Var
->name
, Var
->name_length
, tmp
));
46 *ErrP
= SNMP_ERR_NOERROR
;
48 switch (Var
->name
[LEN_SQ_SYS
]) {
51 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
52 mem_node::StoreMemSize() >> 10,
57 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
58 Store::Root().currentSize() >> 10,
63 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
64 (int)(tvSubDsec(squid_start
, current_time
) * 100),
69 *ErrP
= SNMP_ERR_NOSUCHNAME
;
80 snmp_confFn(variable_list
* Var
, snint
* ErrP
)
82 variable_list
*Answer
= nullptr;
83 const char *cp
= nullptr;
84 debugs(49, 5, "snmp_confFn: Processing request with magic " << Var
->name
[8] << "!");
85 *ErrP
= SNMP_ERR_NOERROR
;
87 switch (Var
->name
[LEN_SQ_CONF
]) {
90 Answer
= snmp_var_new(Var
->name
, Var
->name_length
);
91 Answer
->type
= ASN_OCTET_STR
;
92 Answer
->val_len
= strlen(Config
.adminEmail
);
93 Answer
->val
.string
= (u_char
*) xstrdup(Config
.adminEmail
);
97 Answer
= snmp_var_new(Var
->name
, Var
->name_length
);
98 Answer
->type
= ASN_OCTET_STR
;
99 Answer
->val_len
= strlen(APP_SHORTNAME
);
100 Answer
->val
.string
= (u_char
*) xstrdup(APP_SHORTNAME
);
103 case CONF_VERSION_ID
:
104 Answer
= snmp_var_new(Var
->name
, Var
->name_length
);
105 Answer
->type
= ASN_OCTET_STR
;
106 Answer
->val_len
= strlen(VERSION
);
107 Answer
->val
.string
= (u_char
*) xstrdup(VERSION
);
112 switch (Var
->name
[LEN_SQ_CONF
+ 1]) {
115 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
116 (snint
) (Config
.memMaxSize
>> 20),
120 case CONF_ST_SWMAXSZ
:
121 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
122 (snint
) (Store::Root().maxSize() >> 20),
127 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
128 (snint
) Config
.Swap
.highWaterMark
,
133 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
134 (snint
) Config
.Swap
.lowWaterMark
,
139 *ErrP
= SNMP_ERR_NOSUCHNAME
;
146 Answer
= snmp_var_new(Var
->name
, Var
->name_length
);
148 if (!(cp
= Debug::debugOptions
))
151 Answer
->type
= ASN_OCTET_STR
;
153 Answer
->val_len
= strlen(cp
);
155 Answer
->val
.string
= (u_char
*) xstrdup(cp
);
160 Answer
= snmp_var_new(Var
->name
, Var
->name_length
);
162 cp
= uniqueHostname();
164 Answer
->type
= ASN_OCTET_STR
;
166 Answer
->val_len
= strlen(cp
);
168 Answer
->val
.string
= (u_char
*) xstrdup(cp
);
173 *ErrP
= SNMP_ERR_NOSUCHNAME
;
186 snmp_meshPtblFn(variable_list
* Var
, snint
* ErrP
)
188 variable_list
*Answer
= nullptr;
192 CachePeer
*p
= nullptr;
194 debugs(49, 5, "snmp_meshPtblFn: peer " << Var
->name
[LEN_SQ_MESH
+ 3] << " requested!");
195 *ErrP
= SNMP_ERR_NOERROR
;
197 u_int index
= Var
->name
[LEN_SQ_MESH
+ 3] ;
198 for (p
= Config
.peers
; p
!= nullptr; p
= p
->next
, ++cnt
) {
199 if (p
->index
== index
) {
206 *ErrP
= SNMP_ERR_NOSUCHNAME
;
210 switch (Var
->name
[LEN_SQ_MESH
+ 2]) {
211 case MESH_PTBL_INDEX
: { // XXX: Should be visible?
212 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
213 (snint
)p
->index
, SMI_INTEGER
);
219 Answer
= snmp_var_new(Var
->name
, Var
->name_length
);
220 Answer
->type
= ASN_OCTET_STR
;
221 Answer
->val_len
= strlen(cp
);
222 Answer
->val
.string
= (u_char
*) xstrdup(cp
);
226 case MESH_PTBL_ADDR_TYPE
: {
228 ival
= laddr
.isIPv4() ? INETADDRESSTYPE_IPV4
: INETADDRESSTYPE_IPV6
;
229 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
233 case MESH_PTBL_ADDR
: {
234 Answer
= snmp_var_new(Var
->name
, Var
->name_length
);
235 // InetAddress doesn't have its own ASN.1 type,
236 // like IpAddr does (SMI_IPADDRESS)
238 Answer
->type
= ASN_OCTET_STR
;
239 char host
[MAX_IPSTRLEN
];
240 laddr
.toStr(host
,MAX_IPSTRLEN
);
241 Answer
->val_len
= strlen(host
);
242 Answer
->val
.string
= (u_char
*) xstrdup(host
);
247 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
248 (snint
) p
->http_port
,
253 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
259 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
264 case MESH_PTBL_STATE
:
265 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
266 (snint
) neighborUp(p
),
271 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
276 case MESH_PTBL_PACKED
:
277 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
278 p
->stats
.pings_acked
,
282 case MESH_PTBL_FETCHES
:
283 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
289 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
295 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
296 p
->stats
.ignored_replies
,
300 case MESH_PTBL_KEEPAL_S
:
301 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
302 p
->stats
.n_keepalives_sent
,
306 case MESH_PTBL_KEEPAL_R
:
307 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
308 p
->stats
.n_keepalives_recv
,
313 *ErrP
= SNMP_ERR_NOSUCHNAME
;
321 snmp_prfSysFn(variable_list
* Var
, snint
* ErrP
)
323 variable_list
*Answer
= nullptr;
325 static struct rusage rusage
;
326 debugs(49, 5, "snmp_prfSysFn: Processing request with magic " << Var
->name
[LEN_SQ_PRF
+ 1] << "!");
327 *ErrP
= SNMP_ERR_NOERROR
;
329 switch (Var
->name
[LEN_SQ_PRF
+ 1]) {
332 squid_getrusage(&rusage
);
333 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
334 rusage_pagefaults(&rusage
),
339 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
344 case PERF_SYS_MEMUSAGE
: {
345 Mem::PoolStats stats
;
346 Mem::GlobalStats(stats
);
347 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
348 (snint
) stats
.meter
->alloc
.currentLevel() >> 10,
353 case PERF_SYS_CPUTIME
:
354 squid_getrusage(&rusage
);
355 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
356 (snint
) rusage_cputime(&rusage
),
360 case PERF_SYS_CPUUSAGE
:
361 squid_getrusage(&rusage
);
362 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
363 (snint
) Math::doublePercent(rusage_cputime(&rusage
), tvSubDsec(squid_start
, current_time
)),
367 case PERF_SYS_MAXRESSZ
:
368 squid_getrusage(&rusage
);
369 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
370 (snint
) rusage_maxrss(&rusage
),
374 case PERF_SYS_CURLRUEXP
:
375 /* No global LRU info anymore */
376 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
381 case PERF_SYS_CURUNLREQ
:
382 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
383 (snint
) statCounter
.unlink
.requests
,
387 case PERF_SYS_CURUNUSED_FD
:
388 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
389 (snint
) Squid_MaxFD
- Number_FD
,
393 case PERF_SYS_CURRESERVED_FD
:
394 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
399 case PERF_SYS_CURUSED_FD
:
400 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
405 case PERF_SYS_CURMAX_FD
:
406 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
411 case PERF_SYS_NUMOBJCNT
:
412 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
413 (snint
) StoreEntry::inUseCount(),
418 *ErrP
= SNMP_ERR_NOSUCHNAME
;
426 snmp_prfProtoFn(variable_list
* Var
, snint
* ErrP
)
428 variable_list
*Answer
= nullptr;
429 static StatCounters
*f
= nullptr;
430 static StatCounters
*l
= nullptr;
433 debugs(49, 5, "snmp_prfProtoFn: Processing request with magic " << Var
->name
[LEN_SQ_PRF
] << "!");
434 *ErrP
= SNMP_ERR_NOERROR
;
436 switch (Var
->name
[LEN_SQ_PRF
+ 1]) {
438 case PERF_PROTOSTAT_AGGR
: /* cacheProtoAggregateStats */
440 switch (Var
->name
[LEN_SQ_PRF
+ 2]) {
442 case PERF_PROTOSTAT_AGGR_HTTP_REQ
:
443 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
444 (snint
) statCounter
.client_http
.requests
,
448 case PERF_PROTOSTAT_AGGR_HTTP_HITS
:
449 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
450 (snint
) statCounter
.client_http
.hits
,
454 case PERF_PROTOSTAT_AGGR_HTTP_ERRORS
:
455 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
456 (snint
) statCounter
.client_http
.errors
,
460 case PERF_PROTOSTAT_AGGR_HTTP_KBYTES_IN
:
461 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
462 (snint
) statCounter
.client_http
.kbytes_in
.kb
,
466 case PERF_PROTOSTAT_AGGR_HTTP_KBYTES_OUT
:
467 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
468 (snint
) statCounter
.client_http
.kbytes_out
.kb
,
472 case PERF_PROTOSTAT_AGGR_ICP_S
:
473 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
474 (snint
) statCounter
.icp
.pkts_sent
,
478 case PERF_PROTOSTAT_AGGR_ICP_R
:
479 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
480 (snint
) statCounter
.icp
.pkts_recv
,
484 case PERF_PROTOSTAT_AGGR_ICP_SKB
:
485 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
486 (snint
) statCounter
.icp
.kbytes_sent
.kb
,
490 case PERF_PROTOSTAT_AGGR_ICP_RKB
:
491 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
492 (snint
) statCounter
.icp
.kbytes_recv
.kb
,
496 case PERF_PROTOSTAT_AGGR_REQ
:
497 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
498 (snint
) statCounter
.server
.all
.requests
,
502 case PERF_PROTOSTAT_AGGR_ERRORS
:
503 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
504 (snint
) statCounter
.server
.all
.errors
,
508 case PERF_PROTOSTAT_AGGR_KBYTES_IN
:
509 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
510 (snint
) statCounter
.server
.all
.kbytes_in
.kb
,
514 case PERF_PROTOSTAT_AGGR_KBYTES_OUT
:
515 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
516 (snint
) statCounter
.server
.all
.kbytes_out
.kb
,
520 case PERF_PROTOSTAT_AGGR_CURSWAP
:
521 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
522 (snint
) Store::Root().currentSize() >> 10,
526 case PERF_PROTOSTAT_AGGR_CLIENTS
:
527 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
528 (snint
) statCounter
.client_http
.clients
,
533 *ErrP
= SNMP_ERR_NOSUCHNAME
;
539 case PERF_PROTOSTAT_MEDIAN
:
541 if (Var
->name_length
== LEN_SQ_PRF
+ 5)
542 minutes
= Var
->name
[LEN_SQ_PRF
+ 4];
546 if ((minutes
< 1) || (minutes
> 60))
551 l
= snmpStatGet(minutes
);
553 debugs(49, 8, "median: min= " << minutes
<< ", " << Var
->name
[LEN_SQ_PRF
+ 3] << " l= " << l
<< " , f = " << f
);
554 debugs(49, 8, "median: l= " << l
<< " , f = " << f
);
556 switch (Var
->name
[LEN_SQ_PRF
+ 3]) {
558 case PERF_MEDIAN_TIME
:
562 case PERF_MEDIAN_HTTP_ALL
:
563 x
= statHistDeltaMedian(l
->client_http
.allSvcTime
,
564 f
->client_http
.allSvcTime
);
567 case PERF_MEDIAN_HTTP_MISS
:
568 x
= statHistDeltaMedian(l
->client_http
.missSvcTime
,
569 f
->client_http
.missSvcTime
);
572 case PERF_MEDIAN_HTTP_NM
:
573 x
= statHistDeltaMedian(l
->client_http
.nearMissSvcTime
,
574 f
->client_http
.nearMissSvcTime
);
577 case PERF_MEDIAN_HTTP_HIT
:
578 x
= statHistDeltaMedian(l
->client_http
.hitSvcTime
,
579 f
->client_http
.hitSvcTime
);
582 case PERF_MEDIAN_ICP_QUERY
:
583 x
= statHistDeltaMedian(l
->icp
.querySvcTime
, f
->icp
.querySvcTime
);
586 case PERF_MEDIAN_ICP_REPLY
:
587 x
= statHistDeltaMedian(l
->icp
.replySvcTime
, f
->icp
.replySvcTime
);
590 case PERF_MEDIAN_DNS
:
591 x
= statHistDeltaMedian(l
->dns
.svcTime
, f
->dns
.svcTime
);
594 case PERF_MEDIAN_RHR
:
595 x
= statRequestHitRatio(minutes
);
598 case PERF_MEDIAN_BHR
:
599 x
= statByteHitRatio(minutes
);
602 case PERF_MEDIAN_HTTP_NH
:
603 x
= statHistDeltaMedian(l
->client_http
.nearHitSvcTime
,
604 f
->client_http
.nearHitSvcTime
);
608 *ErrP
= SNMP_ERR_NOSUCHNAME
;
612 return snmp_var_new_integer(Var
->name
, Var
->name_length
,
617 *ErrP
= SNMP_ERR_NOSUCHNAME
;