2 * Copyright (C) 1996-2014 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"
16 #include "neighbors.h"
17 #include "snmp_agent.h"
18 #include "snmp_core.h"
19 #include "SquidConfig.h"
20 #include "SquidMath.h"
21 #include "SquidTime.h"
23 #include "StatCounters.h"
27 // for tvSubDsec() which should be in SquidTime.h
30 /************************************************************************
32 SQUID MIB Implementation
34 ************************************************************************/
41 snmp_sysFn(variable_list
* Var
, snint
* ErrP
)
43 variable_list
*Answer
= NULL
;
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
= NULL
;
83 const char *cp
= NULL
;
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
= NULL
;
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
!= NULL
; 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
: { // FIXME INET6: 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
= NULL
;
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 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
346 (snint
) statMemoryAccounted() >> 10,
350 case PERF_SYS_CPUTIME
:
351 squid_getrusage(&rusage
);
352 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
353 (snint
) rusage_cputime(&rusage
),
357 case PERF_SYS_CPUUSAGE
:
358 squid_getrusage(&rusage
);
359 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
360 (snint
) Math::doublePercent(rusage_cputime(&rusage
), tvSubDsec(squid_start
, current_time
)),
364 case PERF_SYS_MAXRESSZ
:
365 squid_getrusage(&rusage
);
366 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
367 (snint
) rusage_maxrss(&rusage
),
371 case PERF_SYS_CURLRUEXP
:
372 /* No global LRU info anymore */
373 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
378 case PERF_SYS_CURUNLREQ
:
379 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
380 (snint
) statCounter
.unlink
.requests
,
384 case PERF_SYS_CURUNUSED_FD
:
385 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
386 (snint
) Squid_MaxFD
- Number_FD
,
390 case PERF_SYS_CURRESERVED_FD
:
391 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
396 case PERF_SYS_CURUSED_FD
:
397 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
402 case PERF_SYS_CURMAX_FD
:
403 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
408 case PERF_SYS_NUMOBJCNT
:
409 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
410 (snint
) StoreEntry::inUseCount(),
415 *ErrP
= SNMP_ERR_NOSUCHNAME
;
423 snmp_prfProtoFn(variable_list
* Var
, snint
* ErrP
)
425 variable_list
*Answer
= NULL
;
426 static StatCounters
*f
= NULL
;
427 static StatCounters
*l
= NULL
;
430 debugs(49, 5, "snmp_prfProtoFn: Processing request with magic " << Var
->name
[LEN_SQ_PRF
] << "!");
431 *ErrP
= SNMP_ERR_NOERROR
;
433 switch (Var
->name
[LEN_SQ_PRF
+ 1]) {
435 case PERF_PROTOSTAT_AGGR
: /* cacheProtoAggregateStats */
437 switch (Var
->name
[LEN_SQ_PRF
+ 2]) {
439 case PERF_PROTOSTAT_AGGR_HTTP_REQ
:
440 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
441 (snint
) statCounter
.client_http
.requests
,
445 case PERF_PROTOSTAT_AGGR_HTTP_HITS
:
446 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
447 (snint
) statCounter
.client_http
.hits
,
451 case PERF_PROTOSTAT_AGGR_HTTP_ERRORS
:
452 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
453 (snint
) statCounter
.client_http
.errors
,
457 case PERF_PROTOSTAT_AGGR_HTTP_KBYTES_IN
:
458 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
459 (snint
) statCounter
.client_http
.kbytes_in
.kb
,
463 case PERF_PROTOSTAT_AGGR_HTTP_KBYTES_OUT
:
464 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
465 (snint
) statCounter
.client_http
.kbytes_out
.kb
,
469 case PERF_PROTOSTAT_AGGR_ICP_S
:
470 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
471 (snint
) statCounter
.icp
.pkts_sent
,
475 case PERF_PROTOSTAT_AGGR_ICP_R
:
476 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
477 (snint
) statCounter
.icp
.pkts_recv
,
481 case PERF_PROTOSTAT_AGGR_ICP_SKB
:
482 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
483 (snint
) statCounter
.icp
.kbytes_sent
.kb
,
487 case PERF_PROTOSTAT_AGGR_ICP_RKB
:
488 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
489 (snint
) statCounter
.icp
.kbytes_recv
.kb
,
493 case PERF_PROTOSTAT_AGGR_REQ
:
494 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
495 (snint
) statCounter
.server
.all
.requests
,
499 case PERF_PROTOSTAT_AGGR_ERRORS
:
500 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
501 (snint
) statCounter
.server
.all
.errors
,
505 case PERF_PROTOSTAT_AGGR_KBYTES_IN
:
506 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
507 (snint
) statCounter
.server
.all
.kbytes_in
.kb
,
511 case PERF_PROTOSTAT_AGGR_KBYTES_OUT
:
512 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
513 (snint
) statCounter
.server
.all
.kbytes_out
.kb
,
517 case PERF_PROTOSTAT_AGGR_CURSWAP
:
518 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
519 (snint
) Store::Root().currentSize() >> 10,
523 case PERF_PROTOSTAT_AGGR_CLIENTS
:
524 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
525 (snint
) statCounter
.client_http
.clients
,
530 *ErrP
= SNMP_ERR_NOSUCHNAME
;
536 case PERF_PROTOSTAT_MEDIAN
:
538 if (Var
->name_length
== LEN_SQ_PRF
+ 5)
539 minutes
= Var
->name
[LEN_SQ_PRF
+ 4];
543 if ((minutes
< 1) || (minutes
> 60))
548 l
= snmpStatGet(minutes
);
550 debugs(49, 8, "median: min= " << minutes
<< ", " << Var
->name
[LEN_SQ_PRF
+ 3] << " l= " << l
<< " , f = " << f
);
551 debugs(49, 8, "median: l= " << l
<< " , f = " << f
);
553 switch (Var
->name
[LEN_SQ_PRF
+ 3]) {
555 case PERF_MEDIAN_TIME
:
559 case PERF_MEDIAN_HTTP_ALL
:
560 x
= statHistDeltaMedian(l
->client_http
.allSvcTime
,
561 f
->client_http
.allSvcTime
);
564 case PERF_MEDIAN_HTTP_MISS
:
565 x
= statHistDeltaMedian(l
->client_http
.missSvcTime
,
566 f
->client_http
.missSvcTime
);
569 case PERF_MEDIAN_HTTP_NM
:
570 x
= statHistDeltaMedian(l
->client_http
.nearMissSvcTime
,
571 f
->client_http
.nearMissSvcTime
);
574 case PERF_MEDIAN_HTTP_HIT
:
575 x
= statHistDeltaMedian(l
->client_http
.hitSvcTime
,
576 f
->client_http
.hitSvcTime
);
579 case PERF_MEDIAN_ICP_QUERY
:
580 x
= statHistDeltaMedian(l
->icp
.querySvcTime
, f
->icp
.querySvcTime
);
583 case PERF_MEDIAN_ICP_REPLY
:
584 x
= statHistDeltaMedian(l
->icp
.replySvcTime
, f
->icp
.replySvcTime
);
587 case PERF_MEDIAN_DNS
:
588 x
= statHistDeltaMedian(l
->dns
.svcTime
, f
->dns
.svcTime
);
591 case PERF_MEDIAN_RHR
:
592 x
= statRequestHitRatio(minutes
);
595 case PERF_MEDIAN_BHR
:
596 x
= statByteHitRatio(minutes
);
599 case PERF_MEDIAN_HTTP_NH
:
600 x
= statHistDeltaMedian(l
->client_http
.nearHitSvcTime
,
601 f
->client_http
.nearHitSvcTime
);
605 *ErrP
= SNMP_ERR_NOSUCHNAME
;
609 return snmp_var_new_integer(Var
->name
, Var
->name_length
,
614 *ErrP
= SNMP_ERR_NOSUCHNAME
;