3 * $Id: snmp_agent.cc,v 1.63 1999/01/21 23:15:38 wessels Exp $
5 * DEBUG: section 49 SNMP Interface
6 * AUTHOR: Kostas Anagnostakis
8 * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
9 * ----------------------------------------------------------
11 * Squid is the result of efforts by numerous individuals from the
12 * Internet community. Development is led by Duane Wessels of the
13 * National Laboratory for Applied Network Research and funded by the
14 * National Science Foundation. Squid is Copyrighted (C) 1998 by
15 * Duane Wessels and the University of California San Diego. Please
16 * see the COPYRIGHT file for full details. Squid incorporates
17 * software developed and/or copyrighted by other sources. Please see
18 * the CREDITS file for full details.
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
38 #include "cache_snmp.h"
40 extern StatCounters
*snmpStatGet(int);
42 /************************************************************************
44 SQUID MIB Implementation
46 ************************************************************************/
49 snmp_sysFn(variable_list
* Var
, snint
* ErrP
)
51 variable_list
*Answer
;
53 debug(49, 5) ("snmp_sysFn: Processing request:\n", Var
->name
[LEN_SQ_SYS
]);
54 snmpDebugOid(5, Var
->name
, Var
->name_length
);
56 Answer
= snmp_var_new(Var
->name
, Var
->name_length
);
57 *ErrP
= SNMP_ERR_NOERROR
;
59 switch (Var
->name
[LEN_SQ_SYS
]) {
61 Answer
->val_len
= sizeof(snint
);
62 Answer
->val
.integer
= xmalloc(Answer
->val_len
);
63 Answer
->type
= ASN_INTEGER
;
64 *(Answer
->val
.integer
) = store_mem_size
;
67 Answer
->val_len
= sizeof(snint
);
68 Answer
->val
.integer
= xmalloc(Answer
->val_len
);
69 Answer
->type
= ASN_INTEGER
;
70 *(Answer
->val
.integer
) = store_swap_size
;
73 Answer
->val_len
= sizeof(snint
);
74 Answer
->val
.integer
= xmalloc(Answer
->val_len
);
75 Answer
->type
= SMI_TIMETICKS
;
76 *(Answer
->val
.integer
) = tvSubDsec(squid_start
, current_time
) * 100;
79 *ErrP
= SNMP_ERR_NOSUCHNAME
;
80 snmp_var_free(Answer
);
87 snmp_confFn(variable_list
* Var
, snint
* ErrP
)
89 variable_list
*Answer
;
92 debug(49, 5) ("snmp_confFn: Processing request with magic %d!\n", Var
->name
[8]);
94 Answer
= snmp_var_new(Var
->name
, Var
->name_length
);
95 *ErrP
= SNMP_ERR_NOERROR
;
97 switch (Var
->name
[LEN_SQ_CONF
]) {
99 Answer
->type
= ASN_OCTET_STR
;
100 Answer
->val_len
= strlen(Config
.adminEmail
);
101 Answer
->val
.string
= (u_char
*) xstrdup(Config
.adminEmail
);
104 Answer
->type
= ASN_OCTET_STR
;
105 Answer
->val_len
= strlen(appname
);
106 Answer
->val
.string
= (u_char
*) xstrdup(appname
);
108 case CONF_VERSION_ID
:
110 Answer
->type
= ASN_OCTET_STR
;
111 Answer
->val_len
= strlen(pp
);
112 Answer
->val
.string
= (u_char
*) xstrdup(pp
);
115 switch (Var
->name
[LEN_SQ_CONF
+ 1]) {
117 Answer
->val_len
= sizeof(snint
);
118 Answer
->val
.integer
= xmalloc(Answer
->val_len
);
119 Answer
->type
= ASN_INTEGER
;
120 *(Answer
->val
.integer
) = (snint
) Config
.MemMaxSize
;
122 case CONF_ST_MHIWM
: /* DELETE ME */
123 Answer
->val_len
= sizeof(snint
);
124 Answer
->val
.integer
= xmalloc(Answer
->val_len
);
125 Answer
->type
= ASN_INTEGER
;
126 *(Answer
->val
.integer
) = (snint
) 0;
128 case CONF_ST_MLOWM
: /* DELETE ME */
129 Answer
->val_len
= sizeof(snint
);
130 Answer
->val
.integer
= xmalloc(Answer
->val_len
);
131 Answer
->type
= ASN_INTEGER
;
132 *(Answer
->val
.integer
) = (snint
) 0;
134 case CONF_ST_SWMAXSZ
:
135 Answer
->val_len
= sizeof(snint
);
136 Answer
->val
.integer
= xmalloc(Answer
->val_len
);
137 Answer
->type
= ASN_INTEGER
;
138 *(Answer
->val
.integer
) = (snint
) Config
.Swap
.maxSize
;
141 Answer
->val_len
= sizeof(snint
);
142 Answer
->val
.integer
= xmalloc(Answer
->val_len
);
143 Answer
->type
= ASN_INTEGER
;
144 *(Answer
->val
.integer
) = (snint
) Config
.Swap
.highWaterMark
;
147 Answer
->val_len
= sizeof(snint
);
148 Answer
->val
.integer
= xmalloc(Answer
->val_len
);
149 Answer
->type
= ASN_INTEGER
;
150 *(Answer
->val
.integer
) = (snint
) Config
.Swap
.lowWaterMark
;
153 *ErrP
= SNMP_ERR_NOSUCHNAME
;
154 snmp_var_free(Answer
);
159 if (!(cp
= Config
.debugOptions
))
161 Answer
->type
= ASN_OCTET_STR
;
162 Answer
->val_len
= strlen(cp
);
163 Answer
->val
.string
= (u_char
*) xstrdup(cp
);
166 *ErrP
= SNMP_ERR_NOSUCHNAME
;
167 snmp_var_free(Answer
);
174 snmp_meshPtblFn(variable_list
* Var
, snint
* ErrP
)
176 variable_list
*Answer
;
177 struct in_addr
*laddr
;
181 debug(49, 5) ("snmp_meshPtblFn: peer %d requested!\n", Var
->name
[LEN_SQ_MESH
+ 3]);
183 Answer
= snmp_var_new(Var
->name
, Var
->name_length
);
184 *ErrP
= SNMP_ERR_NOERROR
;
186 laddr
= oid2addr(&Var
->name
[LEN_SQ_MESH
+ 3]);
188 for (p
= Config
.peers
; p
!= NULL
; p
= p
->next
, cnt
++)
189 if (p
->in_addr
.sin_addr
.s_addr
== laddr
->s_addr
)
194 cnt
= Var
->name
[LEN_SQ_MESH
+ 3];
195 debug(49, 5) ("snmp_meshPtblFn: we want .x.%d\n", Var
->name
[10]);
200 *ErrP
= SNMP_ERR_NOSUCHNAME
;
201 snmp_var_free(Answer
);
204 switch (Var
->name
[LEN_SQ_MESH
+ 2]) {
207 Answer
->type
= ASN_OCTET_STR
;
208 Answer
->val_len
= strlen(cp
);
209 Answer
->val
.string
= (u_char
*) xstrdup(cp
);
212 Answer
->type
= SMI_IPADDRESS
;
213 Answer
->val_len
= sizeof(snint
);
214 Answer
->val
.integer
= xmalloc(Answer
->val_len
);
215 *(Answer
->val
.integer
) = (snint
) (p
->in_addr
.sin_addr
.s_addr
);
218 Answer
->val_len
= sizeof(snint
);
219 Answer
->val
.integer
= xmalloc(Answer
->val_len
);
220 Answer
->type
= ASN_INTEGER
;
221 *(Answer
->val
.integer
) = (snint
) p
->http_port
;
224 Answer
->val_len
= sizeof(snint
);
225 Answer
->val
.integer
= xmalloc(Answer
->val_len
);
226 Answer
->type
= ASN_INTEGER
;
227 *(Answer
->val
.integer
) = (snint
) p
->icp
.port
;
230 Answer
->val_len
= sizeof(snint
);
231 Answer
->val
.integer
= xmalloc(Answer
->val_len
);
232 Answer
->type
= ASN_INTEGER
;
233 *(Answer
->val
.integer
) = (snint
) p
->type
;
235 case MESH_PTBL_STATE
:
236 Answer
->val_len
= sizeof(snint
);
237 Answer
->val
.integer
= xmalloc(Answer
->val_len
);
238 Answer
->type
= ASN_INTEGER
;
239 *(Answer
->val
.integer
) = (snint
) neighborUp(p
);
242 Answer
->val_len
= sizeof(snint
);
243 Answer
->val
.integer
= xmalloc(Answer
->val_len
);
244 Answer
->type
= SMI_COUNTER32
;
245 *(Answer
->val
.integer
) = p
->stats
.pings_sent
;
247 case MESH_PTBL_PACKED
:
248 Answer
->val_len
= sizeof(snint
);
249 Answer
->val
.integer
= xmalloc(Answer
->val_len
);
250 Answer
->type
= SMI_COUNTER32
;
251 *(Answer
->val
.integer
) = p
->stats
.pings_acked
;
253 case MESH_PTBL_FETCHES
:
254 Answer
->val_len
= sizeof(snint
);
255 Answer
->val
.integer
= xmalloc(Answer
->val_len
);
256 Answer
->type
= SMI_COUNTER32
;
257 *(Answer
->val
.integer
) = p
->stats
.fetches
;
260 Answer
->val_len
= sizeof(snint
);
261 Answer
->val
.integer
= xmalloc(Answer
->val_len
);
262 Answer
->type
= ASN_INTEGER
;
263 *(Answer
->val
.integer
) = p
->stats
.rtt
;
266 Answer
->val_len
= sizeof(snint
);
267 Answer
->val
.integer
= xmalloc(Answer
->val_len
);
268 Answer
->type
= SMI_COUNTER32
;
269 *(Answer
->val
.integer
) = p
->stats
.ignored_replies
;
271 case MESH_PTBL_KEEPAL_S
:
272 Answer
->val_len
= sizeof(snint
);
273 Answer
->val
.integer
= xmalloc(Answer
->val_len
);
274 Answer
->type
= SMI_COUNTER32
;
275 *(Answer
->val
.integer
) = p
->stats
.n_keepalives_sent
;
277 case MESH_PTBL_KEEPAL_R
:
278 Answer
->val_len
= sizeof(snint
);
279 Answer
->val
.integer
= xmalloc(Answer
->val_len
);
280 Answer
->type
= SMI_COUNTER32
;
281 *(Answer
->val
.integer
) = p
->stats
.n_keepalives_recv
;
285 *ErrP
= SNMP_ERR_NOSUCHNAME
;
286 snmp_var_free(Answer
);
293 snmp_prfSysFn(variable_list
* Var
, snint
* ErrP
)
295 variable_list
*Answer
;
296 static struct rusage rusage
;
298 debug(49, 5) ("snmp_prfSysFn: Processing request with magic %d!\n", Var
->name
[LEN_SQ_PRF
+ 1]);
300 Answer
= snmp_var_new(Var
->name
, Var
->name_length
);
301 *ErrP
= SNMP_ERR_NOERROR
;
302 Answer
->val_len
= sizeof(snint
);
303 Answer
->val
.integer
= xmalloc(Answer
->val_len
);
304 Answer
->type
= ASN_INTEGER
;
306 switch (Var
->name
[LEN_SQ_PRF
+ 1]) {
308 squid_getrusage(&rusage
);
309 *(Answer
->val
.integer
) = rusage_pagefaults(&rusage
);
310 Answer
->type
= SMI_COUNTER32
;
313 *(Answer
->val
.integer
) = IOStats
.Http
.reads
;
314 Answer
->type
= SMI_COUNTER32
;
316 case PERF_SYS_DEFR
: /* XXX unused, remove me */
317 Answer
->type
= SMI_COUNTER32
;
318 *(Answer
->val
.integer
) = 0;
320 case PERF_SYS_MEMUSAGE
:
321 *(Answer
->val
.integer
) = (snint
) memTotalAllocated() >> 10;
323 case PERF_SYS_CPUUSAGE
:
324 squid_getrusage(&rusage
);
325 *(Answer
->val
.integer
) = (snint
) rusage_cputime(&rusage
);
327 case PERF_SYS_MAXRESSZ
:
328 squid_getrusage(&rusage
);
329 *(Answer
->val
.integer
) = (snint
) rusage_maxrss(&rusage
);
331 case PERF_SYS_CURLRUEXP
:
332 Answer
->type
= SMI_TIMETICKS
;
333 *(Answer
->val
.integer
) = (snint
) (storeExpiredReferenceAge() * 100);
335 case PERF_SYS_CURUNLREQ
:
336 *(Answer
->val
.integer
) = (snint
) Counter
.unlink
.requests
;
337 Answer
->type
= SMI_COUNTER32
;
339 case PERF_SYS_CURUNUSED_FD
:
340 *(Answer
->val
.integer
) = (snint
) Squid_MaxFD
- Number_FD
;
341 Answer
->type
= SMI_GAUGE32
;
343 case PERF_SYS_CURRESERVED_FD
:
344 *(Answer
->val
.integer
) = (snint
) Number_FD
;
345 Answer
->type
= SMI_GAUGE32
;
347 case PERF_SYS_NUMOBJCNT
:
348 *(Answer
->val
.integer
) = (snint
) memInUse(MEM_STOREENTRY
);
349 Answer
->type
= SMI_COUNTER32
;
352 *ErrP
= SNMP_ERR_NOSUCHNAME
;
353 snmp_var_free(Answer
);
360 snmp_prfProtoFn(variable_list
* Var
, snint
* ErrP
)
362 variable_list
*Answer
;
363 static StatCounters
*f
= NULL
;
364 static StatCounters
*l
= NULL
;
368 debug(49, 5) ("snmp_prfProtoFn: Processing request with magic %d!\n", Var
->name
[LEN_SQ_PRF
]);
370 Answer
= snmp_var_new(Var
->name
, Var
->name_length
);
371 *ErrP
= SNMP_ERR_NOERROR
;
373 switch (Var
->name
[LEN_SQ_PRF
+ 1]) {
374 case PERF_PROTOSTAT_AGGR
: /* cacheProtoAggregateStats */
375 Answer
->type
= SMI_COUNTER32
;
376 Answer
->val_len
= sizeof(snint
);
377 Answer
->val
.integer
= xmalloc(Answer
->val_len
);
378 switch (Var
->name
[LEN_SQ_PRF
+ 2]) {
379 case PERF_PROTOSTAT_AGGR_HTTP_REQ
:
380 *(Answer
->val
.integer
) = (snint
) Counter
.client_http
.requests
;
382 case PERF_PROTOSTAT_AGGR_HTTP_HITS
:
383 *(Answer
->val
.integer
) = (snint
) Counter
.client_http
.hits
;
385 case PERF_PROTOSTAT_AGGR_HTTP_ERRORS
:
386 *(Answer
->val
.integer
) = (snint
) Counter
.client_http
.errors
;
388 case PERF_PROTOSTAT_AGGR_HTTP_KBYTES_IN
:
389 *(Answer
->val
.integer
) = (snint
) Counter
.client_http
.kbytes_in
.kb
;
391 case PERF_PROTOSTAT_AGGR_HTTP_KBYTES_OUT
:
392 *(Answer
->val
.integer
) = (snint
) Counter
.client_http
.kbytes_out
.kb
;
394 case PERF_PROTOSTAT_AGGR_ICP_S
:
395 *(Answer
->val
.integer
) = (snint
) Counter
.icp
.pkts_sent
;
397 case PERF_PROTOSTAT_AGGR_ICP_R
:
398 *(Answer
->val
.integer
) = (snint
) Counter
.icp
.pkts_recv
;
400 case PERF_PROTOSTAT_AGGR_ICP_SKB
:
401 *(Answer
->val
.integer
) = (snint
) Counter
.icp
.kbytes_sent
.kb
;
403 case PERF_PROTOSTAT_AGGR_ICP_RKB
:
404 *(Answer
->val
.integer
) = (snint
) Counter
.icp
.kbytes_recv
.kb
;
406 case PERF_PROTOSTAT_AGGR_REQ
:
407 *(Answer
->val
.integer
) = (snint
) Counter
.server
.all
.requests
;
408 Answer
->type
= SMI_INTEGER
;
410 case PERF_PROTOSTAT_AGGR_ERRORS
:
411 *(Answer
->val
.integer
) = (snint
) Counter
.server
.all
.errors
;
412 Answer
->type
= SMI_INTEGER
;
414 case PERF_PROTOSTAT_AGGR_KBYTES_IN
:
415 *(Answer
->val
.integer
) = (snint
) Counter
.server
.all
.kbytes_in
.kb
;
417 case PERF_PROTOSTAT_AGGR_KBYTES_OUT
:
418 *(Answer
->val
.integer
) = (snint
) Counter
.server
.all
.kbytes_out
.kb
;
420 case PERF_PROTOSTAT_AGGR_CURSWAP
:
421 *(Answer
->val
.integer
) = (snint
) store_swap_size
;
423 case PERF_PROTOSTAT_AGGR_CLIENTS
:
424 *(Answer
->val
.integer
) = (snint
) Counter
.client_http
.clients
;
427 *ErrP
= SNMP_ERR_NOSUCHNAME
;
428 snmp_var_free(Answer
);
432 case PERF_PROTOSTAT_MEDIAN
:
434 minutes
= Var
->name
[LEN_SQ_PRF
+ 4];
437 l
= snmpStatGet(minutes
);
439 debug(49, 8) ("median: min= %d, %d l= %x , f = %x\n", minutes
,
440 Var
->name
[LEN_SQ_PRF
+ 3], l
, f
);
441 Answer
->type
= SMI_INTEGER
;
442 Answer
->val_len
= sizeof(snint
);
443 Answer
->val
.integer
= xmalloc(Answer
->val_len
);
445 debug(49, 8) ("median: l= %x , f = %x\n", l
, f
);
446 switch (Var
->name
[LEN_SQ_PRF
+ 3]) {
447 case PERF_MEDIAN_TIME
:
450 case PERF_MEDIAN_HTTP_ALL
:
451 x
= statHistDeltaMedian(&l
->client_http
.all_svc_time
,
452 &f
->client_http
.all_svc_time
);
454 case PERF_MEDIAN_HTTP_MISS
:
455 x
= statHistDeltaMedian(&l
->client_http
.miss_svc_time
,
456 &f
->client_http
.miss_svc_time
);
458 case PERF_MEDIAN_HTTP_NM
:
459 x
= statHistDeltaMedian(&l
->client_http
.nm_svc_time
,
460 &f
->client_http
.nm_svc_time
);
462 case PERF_MEDIAN_HTTP_HIT
:
463 x
= statHistDeltaMedian(&l
->client_http
.hit_svc_time
,
464 &f
->client_http
.hit_svc_time
);
466 case PERF_MEDIAN_ICP_QUERY
:
467 x
= statHistDeltaMedian(&l
->icp
.query_svc_time
, &f
->icp
.query_svc_time
);
469 case PERF_MEDIAN_ICP_REPLY
:
470 x
= statHistDeltaMedian(&l
->icp
.reply_svc_time
, &f
->icp
.reply_svc_time
);
472 case PERF_MEDIAN_DNS
:
473 x
= statHistDeltaMedian(&l
->dns
.svc_time
, &f
->dns
.svc_time
);
475 case PERF_MEDIAN_RHR
:
476 x
= statRequestHitRatio(minutes
);
478 case PERF_MEDIAN_BHR
:
479 x
= statByteHitRatio(minutes
);
482 *ErrP
= SNMP_ERR_NOSUCHNAME
;
483 snmp_var_free(Answer
);
486 *(Answer
->val
.integer
) = (snint
) x
;
489 *ErrP
= SNMP_ERR_NOSUCHNAME
;
490 snmp_var_free(Answer
);
495 addr2oid(struct in_addr addr
, oid
* Dest
)
498 cp
= (u_char
*) & (addr
.s_addr
);
508 static struct in_addr laddr
;
509 u_char
*cp
= (u_char
*) & (laddr
.s_addr
);