]> git.ipfire.org Git - thirdparty/squid.git/blob - src/snmp_agent.cc
Source Format Enforcement (#1234)
[thirdparty/squid.git] / src / snmp_agent.cc
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 49 SNMP Interface */
10
11 #include "squid.h"
12 #include "cache_snmp.h"
13 #include "CachePeer.h"
14 #include "globals.h"
15 #include "mem/Meter.h"
16 #include "mem/Stats.h"
17 #include "mem_node.h"
18 #include "neighbors.h"
19 #include "snmp_agent.h"
20 #include "snmp_core.h"
21 #include "SquidConfig.h"
22 #include "SquidMath.h"
23 #include "stat.h"
24 #include "StatCounters.h"
25 #include "StatHist.h"
26 #include "Store.h"
27 #include "tools.h"
28 #include "util.h"
29
30 /************************************************************************
31
32 SQUID MIB Implementation
33
34 ************************************************************************/
35
36 /*
37 * cacheSystem group
38 */
39
40 variable_list *
41 snmp_sysFn(variable_list * Var, snint * ErrP)
42 {
43 variable_list *Answer = nullptr;
44 MemBuf tmp;
45 debugs(49, 5, "snmp_sysFn: Processing request:" << snmpDebugOid(Var->name, Var->name_length, tmp));
46 *ErrP = SNMP_ERR_NOERROR;
47
48 switch (Var->name[LEN_SQ_SYS]) {
49
50 case SYSVMSIZ:
51 Answer = snmp_var_new_integer(Var->name, Var->name_length,
52 mem_node::StoreMemSize() >> 10,
53 ASN_INTEGER);
54 break;
55
56 case SYSSTOR:
57 Answer = snmp_var_new_integer(Var->name, Var->name_length,
58 Store::Root().currentSize() >> 10,
59 ASN_INTEGER);
60 break;
61
62 case SYS_UPTIME:
63 Answer = snmp_var_new_integer(Var->name, Var->name_length,
64 (int)(tvSubDsec(squid_start, current_time) * 100),
65 SMI_TIMETICKS);
66 break;
67
68 default:
69 *ErrP = SNMP_ERR_NOSUCHNAME;
70 break;
71 }
72
73 return Answer;
74 }
75
76 /*
77 * cacheConfig group
78 */
79 variable_list *
80 snmp_confFn(variable_list * Var, snint * ErrP)
81 {
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;
86
87 switch (Var->name[LEN_SQ_CONF]) {
88
89 case CONF_ADMIN:
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);
94 break;
95
96 case CONF_VERSION:
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);
101 break;
102
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);
108 break;
109
110 case CONF_STORAGE:
111
112 switch (Var->name[LEN_SQ_CONF + 1]) {
113
114 case CONF_ST_MMAXSZ:
115 Answer = snmp_var_new_integer(Var->name, Var->name_length,
116 (snint) (Config.memMaxSize >> 20),
117 ASN_INTEGER);
118 break;
119
120 case CONF_ST_SWMAXSZ:
121 Answer = snmp_var_new_integer(Var->name, Var->name_length,
122 (snint) (Store::Root().maxSize() >> 20),
123 ASN_INTEGER);
124 break;
125
126 case CONF_ST_SWHIWM:
127 Answer = snmp_var_new_integer(Var->name, Var->name_length,
128 (snint) Config.Swap.highWaterMark,
129 ASN_INTEGER);
130 break;
131
132 case CONF_ST_SWLOWM:
133 Answer = snmp_var_new_integer(Var->name, Var->name_length,
134 (snint) Config.Swap.lowWaterMark,
135 ASN_INTEGER);
136 break;
137
138 default:
139 *ErrP = SNMP_ERR_NOSUCHNAME;
140 break;
141 }
142
143 break;
144
145 case CONF_LOG_FAC:
146 Answer = snmp_var_new(Var->name, Var->name_length);
147
148 if (!(cp = Debug::debugOptions))
149 cp = "None";
150
151 Answer->type = ASN_OCTET_STR;
152
153 Answer->val_len = strlen(cp);
154
155 Answer->val.string = (u_char *) xstrdup(cp);
156
157 break;
158
159 case CONF_UNIQNAME:
160 Answer = snmp_var_new(Var->name, Var->name_length);
161
162 cp = uniqueHostname();
163
164 Answer->type = ASN_OCTET_STR;
165
166 Answer->val_len = strlen(cp);
167
168 Answer->val.string = (u_char *) xstrdup(cp);
169
170 break;
171
172 default:
173 *ErrP = SNMP_ERR_NOSUCHNAME;
174
175 break;
176 }
177
178 return Answer;
179 }
180
181 /*
182 * cacheMesh group
183 * - cachePeerTable
184 */
185 variable_list *
186 snmp_meshPtblFn(variable_list * Var, snint * ErrP)
187 {
188 variable_list *Answer = nullptr;
189
190 Ip::Address laddr;
191 char *cp = nullptr;
192 CachePeer *p = nullptr;
193 int cnt = 0;
194 debugs(49, 5, "snmp_meshPtblFn: peer " << Var->name[LEN_SQ_MESH + 3] << " requested!");
195 *ErrP = SNMP_ERR_NOERROR;
196
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) {
200 laddr = p->in_addr ;
201 break;
202 }
203 }
204
205 if (p == nullptr) {
206 *ErrP = SNMP_ERR_NOSUCHNAME;
207 return nullptr;
208 }
209
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);
214 }
215 break;
216
217 case MESH_PTBL_NAME:
218 cp = p->host;
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);
223
224 break;
225
226 case MESH_PTBL_ADDR_TYPE: {
227 int ival;
228 ival = laddr.isIPv4() ? INETADDRESSTYPE_IPV4 : INETADDRESSTYPE_IPV6 ;
229 Answer = snmp_var_new_integer(Var->name, Var->name_length,
230 ival, SMI_INTEGER);
231 }
232 break;
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)
237 // See: rfc4001.txt
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);
243 }
244 break;
245
246 case MESH_PTBL_HTTP:
247 Answer = snmp_var_new_integer(Var->name, Var->name_length,
248 (snint) p->http_port,
249 ASN_INTEGER);
250 break;
251
252 case MESH_PTBL_ICP:
253 Answer = snmp_var_new_integer(Var->name, Var->name_length,
254 (snint) p->icp.port,
255 ASN_INTEGER);
256 break;
257
258 case MESH_PTBL_TYPE:
259 Answer = snmp_var_new_integer(Var->name, Var->name_length,
260 (snint) p->type,
261 ASN_INTEGER);
262 break;
263
264 case MESH_PTBL_STATE:
265 Answer = snmp_var_new_integer(Var->name, Var->name_length,
266 (snint) neighborUp(p),
267 ASN_INTEGER);
268 break;
269
270 case MESH_PTBL_SENT:
271 Answer = snmp_var_new_integer(Var->name, Var->name_length,
272 p->stats.pings_sent,
273 SMI_COUNTER32);
274 break;
275
276 case MESH_PTBL_PACKED:
277 Answer = snmp_var_new_integer(Var->name, Var->name_length,
278 p->stats.pings_acked,
279 SMI_COUNTER32);
280 break;
281
282 case MESH_PTBL_FETCHES:
283 Answer = snmp_var_new_integer(Var->name, Var->name_length,
284 p->stats.fetches,
285 SMI_COUNTER32);
286 break;
287
288 case MESH_PTBL_RTT:
289 Answer = snmp_var_new_integer(Var->name, Var->name_length,
290 p->stats.rtt,
291 ASN_INTEGER);
292 break;
293
294 case MESH_PTBL_IGN:
295 Answer = snmp_var_new_integer(Var->name, Var->name_length,
296 p->stats.ignored_replies,
297 SMI_COUNTER32);
298 break;
299
300 case MESH_PTBL_KEEPAL_S:
301 Answer = snmp_var_new_integer(Var->name, Var->name_length,
302 p->stats.n_keepalives_sent,
303 SMI_COUNTER32);
304 break;
305
306 case MESH_PTBL_KEEPAL_R:
307 Answer = snmp_var_new_integer(Var->name, Var->name_length,
308 p->stats.n_keepalives_recv,
309 SMI_COUNTER32);
310 break;
311
312 default:
313 *ErrP = SNMP_ERR_NOSUCHNAME;
314 break;
315 }
316
317 return Answer;
318 }
319
320 variable_list *
321 snmp_prfSysFn(variable_list * Var, snint * ErrP)
322 {
323 variable_list *Answer = nullptr;
324
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;
328
329 switch (Var->name[LEN_SQ_PRF + 1]) {
330
331 case PERF_SYS_PF:
332 squid_getrusage(&rusage);
333 Answer = snmp_var_new_integer(Var->name, Var->name_length,
334 rusage_pagefaults(&rusage),
335 SMI_COUNTER32);
336 break;
337
338 case PERF_SYS_NUMR:
339 Answer = snmp_var_new_integer(Var->name, Var->name_length,
340 IOStats.Http.reads,
341 SMI_COUNTER32);
342 break;
343
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,
349 ASN_INTEGER);
350 }
351 break;
352
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),
357 ASN_INTEGER);
358 break;
359
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)),
364 ASN_INTEGER);
365 break;
366
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),
371 ASN_INTEGER);
372 break;
373
374 case PERF_SYS_CURLRUEXP:
375 /* No global LRU info anymore */
376 Answer = snmp_var_new_integer(Var->name, Var->name_length,
377 0,
378 SMI_TIMETICKS);
379 break;
380
381 case PERF_SYS_CURUNLREQ:
382 Answer = snmp_var_new_integer(Var->name, Var->name_length,
383 (snint) statCounter.unlink.requests,
384 SMI_GAUGE32);
385 break;
386
387 case PERF_SYS_CURUNUSED_FD:
388 Answer = snmp_var_new_integer(Var->name, Var->name_length,
389 (snint) Squid_MaxFD - Number_FD,
390 SMI_GAUGE32);
391 break;
392
393 case PERF_SYS_CURRESERVED_FD:
394 Answer = snmp_var_new_integer(Var->name, Var->name_length,
395 (snint) RESERVED_FD,
396 SMI_GAUGE32);
397 break;
398
399 case PERF_SYS_CURUSED_FD:
400 Answer = snmp_var_new_integer(Var->name, Var->name_length,
401 (snint) Number_FD,
402 SMI_GAUGE32);
403 break;
404
405 case PERF_SYS_CURMAX_FD:
406 Answer = snmp_var_new_integer(Var->name, Var->name_length,
407 (snint) Biggest_FD,
408 SMI_GAUGE32);
409 break;
410
411 case PERF_SYS_NUMOBJCNT:
412 Answer = snmp_var_new_integer(Var->name, Var->name_length,
413 (snint) StoreEntry::inUseCount(),
414 SMI_GAUGE32);
415 break;
416
417 default:
418 *ErrP = SNMP_ERR_NOSUCHNAME;
419 break;
420 }
421
422 return Answer;
423 }
424
425 variable_list *
426 snmp_prfProtoFn(variable_list * Var, snint * ErrP)
427 {
428 variable_list *Answer = nullptr;
429 static StatCounters *f = nullptr;
430 static StatCounters *l = nullptr;
431 double x;
432 int minutes;
433 debugs(49, 5, "snmp_prfProtoFn: Processing request with magic " << Var->name[LEN_SQ_PRF] << "!");
434 *ErrP = SNMP_ERR_NOERROR;
435
436 switch (Var->name[LEN_SQ_PRF + 1]) {
437
438 case PERF_PROTOSTAT_AGGR: /* cacheProtoAggregateStats */
439
440 switch (Var->name[LEN_SQ_PRF + 2]) {
441
442 case PERF_PROTOSTAT_AGGR_HTTP_REQ:
443 Answer = snmp_var_new_integer(Var->name, Var->name_length,
444 (snint) statCounter.client_http.requests,
445 SMI_COUNTER32);
446 break;
447
448 case PERF_PROTOSTAT_AGGR_HTTP_HITS:
449 Answer = snmp_var_new_integer(Var->name, Var->name_length,
450 (snint) statCounter.client_http.hits,
451 SMI_COUNTER32);
452 break;
453
454 case PERF_PROTOSTAT_AGGR_HTTP_ERRORS:
455 Answer = snmp_var_new_integer(Var->name, Var->name_length,
456 (snint) statCounter.client_http.errors,
457 SMI_COUNTER32);
458 break;
459
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,
463 SMI_COUNTER32);
464 break;
465
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,
469 SMI_COUNTER32);
470 break;
471
472 case PERF_PROTOSTAT_AGGR_ICP_S:
473 Answer = snmp_var_new_integer(Var->name, Var->name_length,
474 (snint) statCounter.icp.pkts_sent,
475 SMI_COUNTER32);
476 break;
477
478 case PERF_PROTOSTAT_AGGR_ICP_R:
479 Answer = snmp_var_new_integer(Var->name, Var->name_length,
480 (snint) statCounter.icp.pkts_recv,
481 SMI_COUNTER32);
482 break;
483
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,
487 SMI_COUNTER32);
488 break;
489
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,
493 SMI_COUNTER32);
494 break;
495
496 case PERF_PROTOSTAT_AGGR_REQ:
497 Answer = snmp_var_new_integer(Var->name, Var->name_length,
498 (snint) statCounter.server.all.requests,
499 SMI_INTEGER);
500 break;
501
502 case PERF_PROTOSTAT_AGGR_ERRORS:
503 Answer = snmp_var_new_integer(Var->name, Var->name_length,
504 (snint) statCounter.server.all.errors,
505 SMI_INTEGER);
506 break;
507
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,
511 SMI_COUNTER32);
512 break;
513
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,
517 SMI_COUNTER32);
518 break;
519
520 case PERF_PROTOSTAT_AGGR_CURSWAP:
521 Answer = snmp_var_new_integer(Var->name, Var->name_length,
522 (snint) Store::Root().currentSize() >> 10,
523 SMI_GAUGE32);
524 break;
525
526 case PERF_PROTOSTAT_AGGR_CLIENTS:
527 Answer = snmp_var_new_integer(Var->name, Var->name_length,
528 (snint) statCounter.client_http.clients,
529 SMI_GAUGE32);
530 break;
531
532 default:
533 *ErrP = SNMP_ERR_NOSUCHNAME;
534 break;
535 }
536
537 return Answer;
538
539 case PERF_PROTOSTAT_MEDIAN:
540
541 if (Var->name_length == LEN_SQ_PRF + 5)
542 minutes = Var->name[LEN_SQ_PRF + 4];
543 else
544 break;
545
546 if ((minutes < 1) || (minutes > 60))
547 break;
548
549 f = snmpStatGet(0);
550
551 l = snmpStatGet(minutes);
552
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);
555
556 switch (Var->name[LEN_SQ_PRF + 3]) {
557
558 case PERF_MEDIAN_TIME:
559 x = minutes;
560 break;
561
562 case PERF_MEDIAN_HTTP_ALL:
563 x = statHistDeltaMedian(l->client_http.allSvcTime,
564 f->client_http.allSvcTime);
565 break;
566
567 case PERF_MEDIAN_HTTP_MISS:
568 x = statHistDeltaMedian(l->client_http.missSvcTime,
569 f->client_http.missSvcTime);
570 break;
571
572 case PERF_MEDIAN_HTTP_NM:
573 x = statHistDeltaMedian(l->client_http.nearMissSvcTime,
574 f->client_http.nearMissSvcTime);
575 break;
576
577 case PERF_MEDIAN_HTTP_HIT:
578 x = statHistDeltaMedian(l->client_http.hitSvcTime,
579 f->client_http.hitSvcTime);
580 break;
581
582 case PERF_MEDIAN_ICP_QUERY:
583 x = statHistDeltaMedian(l->icp.querySvcTime, f->icp.querySvcTime);
584 break;
585
586 case PERF_MEDIAN_ICP_REPLY:
587 x = statHistDeltaMedian(l->icp.replySvcTime, f->icp.replySvcTime);
588 break;
589
590 case PERF_MEDIAN_DNS:
591 x = statHistDeltaMedian(l->dns.svcTime, f->dns.svcTime);
592 break;
593
594 case PERF_MEDIAN_RHR:
595 x = statRequestHitRatio(minutes);
596 break;
597
598 case PERF_MEDIAN_BHR:
599 x = statByteHitRatio(minutes);
600 break;
601
602 case PERF_MEDIAN_HTTP_NH:
603 x = statHistDeltaMedian(l->client_http.nearHitSvcTime,
604 f->client_http.nearHitSvcTime);
605 break;
606
607 default:
608 *ErrP = SNMP_ERR_NOSUCHNAME;
609 return nullptr;
610 }
611
612 return snmp_var_new_integer(Var->name, Var->name_length,
613 (snint) x,
614 SMI_INTEGER);
615 }
616
617 *ErrP = SNMP_ERR_NOSUCHNAME;
618 return nullptr;
619 }
620