Squid Web Cache master
Loading...
Searching...
No Matches
snmp_core.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2025 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 support */
10
11#include "squid.h"
12#include "acl/FilledChecklist.h"
13#include "base/AsyncCallbacks.h"
14#include "base/CbcPointer.h"
16#include "CachePeer.h"
17#include "CachePeers.h"
18#include "client_db.h"
19#include "comm.h"
20#include "comm/Connection.h"
21#include "comm/Loops.h"
22#include "fatal.h"
23#include "ip/Address.h"
24#include "ip/tools.h"
25#include "ipc/StartListening.h"
26#include "snmp/Forwarder.h"
27#include "snmp_agent.h"
28#include "snmp_core.h"
29#include "SnmpRequest.h"
30#include "SquidConfig.h"
31#include "SquidMath.h"
32#include "tools.h"
33
35
38
41
42static mib_tree_entry * snmpAddNodeStr(const char *base_str, int o, oid_ParseFn * parsefunction, instance_Fn * instancefunction, AggrType aggrType = atNone);
43static mib_tree_entry *snmpAddNode(oid * name, int len, oid_ParseFn * parsefunction, instance_Fn * instancefunction, AggrType aggrType, int children,...);
44static oid *snmpCreateOid(int length,...);
45mib_tree_entry * snmpLookupNodeStr(mib_tree_entry *entry, const char *str);
46bool snmpCreateOidFromStr(const char *str, oid **name, int *nl);
48static oid *static_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn);
49static oid *time_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn);
50static oid *peer_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn);
51static oid *client_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn);
52static void snmpDecodePacket(SnmpRequest * rq);
53static void snmpConstructReponse(SnmpRequest * rq);
54
55static oid_ParseFn *snmpTreeNext(oid * Current, snint CurrentLen, oid ** Next, snint * NextLen);
56static oid_ParseFn *snmpTreeGet(oid * Current, snint CurrentLen);
57static mib_tree_entry *snmpTreeEntry(oid entry, snint len, mib_tree_entry * current);
58static mib_tree_entry *snmpTreeSiblingEntry(oid entry, snint len, mib_tree_entry * current);
59extern "C" void snmpSnmplibDebug(int lvl, char *buf);
60
61/*
62 * Turns the MIB into a Tree structure. Called during the startup process.
63 */
64static void
66{
67 if (!IamWorkerProcess())
68 return;
69
70 debugs(49, 5, "snmpInit: Building SNMP mib tree structure");
71
73
74 /*
75 * This following bit of evil is to get the final node in the "squid" mib
76 * without having a "search" function. A search function should be written
77 * to make this and the other code much less evil.
78 */
79 mib_tree_head = snmpAddNode(snmpCreateOid(1, 1), 1, nullptr, nullptr, atNone, 0);
80
82 debugs(49, 5, "snmpInit: root is " << mib_tree_head);
83 snmpAddNodeStr("1", 3, nullptr, nullptr);
84
85 snmpAddNodeStr("1.3", 6, nullptr, nullptr);
86
87 snmpAddNodeStr("1.3.6", 1, nullptr, nullptr);
88 snmpAddNodeStr("1.3.6.1", 4, nullptr, nullptr);
89 snmpAddNodeStr("1.3.6.1.4", 1, nullptr, nullptr);
90 snmpAddNodeStr("1.3.6.1.4.1", 3495, nullptr, nullptr);
91 mib_tree_entry *m2 = snmpAddNodeStr("1.3.6.1.4.1.3495", 1, nullptr, nullptr);
92
93 mib_tree_entry *n = snmpLookupNodeStr(nullptr, "1.3.6.1.4.1.3495.1");
94 assert(m2 == n);
95
96 /* SQ_SYS - 1.3.6.1.4.1.3495.1.1 */
97 snmpAddNodeStr("1.3.6.1.4.1.3495.1", 1, nullptr, nullptr);
98 snmpAddNodeStr("1.3.6.1.4.1.3495.1.1", SYSVMSIZ, snmp_sysFn, static_Inst, atSum);
99 snmpAddNodeStr("1.3.6.1.4.1.3495.1.1", SYSSTOR, snmp_sysFn, static_Inst, atSum);
100 snmpAddNodeStr("1.3.6.1.4.1.3495.1.1", SYS_UPTIME, snmp_sysFn, static_Inst, atMax);
101
102 /* SQ_CONF - 1.3.6.1.4.1.3495.1.2 */
103 snmpAddNodeStr("1.3.6.1.4.1.3495.1", 2, nullptr, nullptr);
104 snmpAddNodeStr("1.3.6.1.4.1.3495.1.2", CONF_ADMIN, snmp_confFn, static_Inst);
105 snmpAddNodeStr("1.3.6.1.4.1.3495.1.2", CONF_VERSION, snmp_confFn, static_Inst);
106 snmpAddNodeStr("1.3.6.1.4.1.3495.1.2", CONF_VERSION_ID, snmp_confFn, static_Inst);
107 snmpAddNodeStr("1.3.6.1.4.1.3495.1.2", CONF_LOG_FAC, snmp_confFn, static_Inst);
108
109 /* SQ_CONF + CONF_STORAGE - 1.3.6.1.4.1.3495.1.5 */
110 snmpAddNodeStr("1.3.6.1.4.1.3495.1.2", CONF_STORAGE, nullptr, nullptr);
111 snmpAddNodeStr("1.3.6.1.4.1.3495.1.2.5", CONF_ST_MMAXSZ, snmp_confFn, static_Inst, atSum);
112 snmpAddNodeStr("1.3.6.1.4.1.3495.1.2.5", CONF_ST_SWMAXSZ, snmp_confFn, static_Inst, atSum);
113 snmpAddNodeStr("1.3.6.1.4.1.3495.1.2.5", CONF_ST_SWHIWM, snmp_confFn, static_Inst, atMin);
114 snmpAddNodeStr("1.3.6.1.4.1.3495.1.2.5", CONF_ST_SWLOWM, snmp_confFn, static_Inst, atMin);
115
116 snmpAddNodeStr("1.3.6.1.4.1.3495.1.2", CONF_UNIQNAME, snmp_confFn, static_Inst);
117
118 /* SQ_PRF - 1.3.6.1.4.1.3495.1.3 */
119 snmpAddNodeStr("1.3.6.1.4.1.3495.1", 3, nullptr, nullptr); /* SQ_PRF */
120
121 /* PERF_SYS - 1.3.6.1.4.1.3495.1.3.1 */
122 snmpAddNodeStr("1.3.6.1.4.1.3495.1.3", PERF_SYS, nullptr, nullptr);
123 snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.1", PERF_SYS_PF, snmp_prfSysFn, static_Inst, atSum);
124 snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.1", PERF_SYS_NUMR, snmp_prfSysFn, static_Inst, atSum);
125 snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.1", PERF_SYS_MEMUSAGE, snmp_prfSysFn, static_Inst, atSum);
126 snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.1", PERF_SYS_CPUTIME, snmp_prfSysFn, static_Inst, atSum);
127 snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.1", PERF_SYS_CPUUSAGE, snmp_prfSysFn, static_Inst, atSum);
128 snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.1", PERF_SYS_MAXRESSZ, snmp_prfSysFn, static_Inst, atSum);
130 /*
131 Amos comments:
132 The meaning of LRU is "oldest timestamped object in cache, if LRU algorithm is
133 used"...
134 What this SMP support needs to do is aggregate via a special filter equivalent to
135 min() to retain the semantic oldest-object meaning. A special one is needed that
136 works as unsigned and ignores '0' values.
137 */
138 snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.1", PERF_SYS_CURLRUEXP, snmp_prfSysFn, static_Inst);
144
145 /* PERF_PROTO - 1.3.6.1.4.1.3495.1.3.2 */
146 snmpAddNodeStr("1.3.6.1.4.1.3495.1.3", PERF_PROTO, nullptr, nullptr);
147 snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2", PERF_PROTOSTAT_AGGR, nullptr, nullptr);
163
164 /* Note this is time-series rather than 'static' */
165 /* cacheMedianSvcTable */
166 snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2", PERF_PROTOSTAT_MEDIAN, nullptr, nullptr);
167
168 /* cacheMedianSvcEntry */
169 snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.2", 1, nullptr, nullptr);
170 snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.2.1", PERF_MEDIAN_TIME, snmp_prfProtoFn, time_Inst, atAverage);
173 snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.2.1", PERF_MEDIAN_HTTP_NM, snmp_prfProtoFn, time_Inst, atAverage);
177 snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.2.1", PERF_MEDIAN_DNS, snmp_prfProtoFn, time_Inst, atAverage);
178 snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.2.1", PERF_MEDIAN_RHR, snmp_prfProtoFn, time_Inst, atAverage);
179 snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.2.1", PERF_MEDIAN_BHR, snmp_prfProtoFn, time_Inst, atAverage);
180 snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.2.1", PERF_MEDIAN_HTTP_NH, snmp_prfProtoFn, time_Inst, atAverage);
181
182 /* SQ_NET - 1.3.6.1.4.1.3495.1.4 */
183 snmpAddNodeStr("1.3.6.1.4.1.3495.1", 4, nullptr, nullptr);
184
185 snmpAddNodeStr("1.3.6.1.4.1.3495.1.4", NET_IP_CACHE, nullptr, nullptr);
186 snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.1", IP_ENT, snmp_netIpFn, static_Inst, atSum);
187 snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.1", IP_REQ, snmp_netIpFn, static_Inst, atSum);
188 snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.1", IP_HITS, snmp_netIpFn, static_Inst, atSum);
189 snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.1", IP_PENDHIT, snmp_netIpFn, static_Inst, atSum);
190 snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.1", IP_NEGHIT, snmp_netIpFn, static_Inst, atSum);
191 snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.1", IP_MISS, snmp_netIpFn, static_Inst, atSum);
192 snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.1", IP_GHBN, snmp_netIpFn, static_Inst, atSum);
193 snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.1", IP_LOC, snmp_netIpFn, static_Inst, atSum);
194
195 snmpAddNodeStr("1.3.6.1.4.1.3495.1.4", NET_FQDN_CACHE, nullptr, nullptr);
196 snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.2", FQDN_ENT, snmp_netFqdnFn, static_Inst, atSum);
197 snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.2", FQDN_REQ, snmp_netFqdnFn, static_Inst, atSum);
198 snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.2", FQDN_HITS, snmp_netFqdnFn, static_Inst, atSum);
199 snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.2", FQDN_PENDHIT, snmp_netFqdnFn, static_Inst, atSum);
200 snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.2", FQDN_NEGHIT, snmp_netFqdnFn, static_Inst, atSum);
201 snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.2", FQDN_MISS, snmp_netFqdnFn, static_Inst, atSum);
202 snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.2", FQDN_GHBN, snmp_netFqdnFn, static_Inst, atSum);
203
204 snmpAddNodeStr("1.3.6.1.4.1.3495.1.4", NET_DNS_CACHE, nullptr, nullptr);
205 snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.3", DNS_REQ, snmp_netDnsFn, static_Inst, atSum);
206 snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.3", DNS_REP, snmp_netDnsFn, static_Inst, atSum);
207 snmpAddNodeStr("1.3.6.1.4.1.3495.1.4.3", DNS_SERVERS, snmp_netDnsFn, static_Inst, atSum);
208
209 /* SQ_MESH - 1.3.6.1.4.1.3495.1.5 */
210 snmpAddNodeStr("1.3.6.1.4.1.3495.1", 5, nullptr, nullptr);
211
212 /* cachePeerTable - 1.3.6.1.4.1.3495.1.5.1 */
213 snmpAddNodeStr("1.3.6.1.4.1.3495.1.5", MESH_PTBL, nullptr, nullptr);
214
215 /* CachePeerEntry (version 3) - 1.3.6.1.4.1.3495.1.5.1.3 */
216 snmpAddNodeStr("1.3.6.1.4.1.3495.1.5.1", 3, nullptr, nullptr);
217 snmpAddNodeStr("1.3.6.1.4.1.3495.1.5.1.3", MESH_PTBL_INDEX, snmp_meshPtblFn, peer_Inst);
218 snmpAddNodeStr("1.3.6.1.4.1.3495.1.5.1.3", MESH_PTBL_NAME, snmp_meshPtblFn, peer_Inst);
219 snmpAddNodeStr("1.3.6.1.4.1.3495.1.5.1.3", MESH_PTBL_ADDR_TYPE, snmp_meshPtblFn, peer_Inst);
220 snmpAddNodeStr("1.3.6.1.4.1.3495.1.5.1.3", MESH_PTBL_ADDR, snmp_meshPtblFn, peer_Inst);
221 snmpAddNodeStr("1.3.6.1.4.1.3495.1.5.1.3", MESH_PTBL_HTTP, snmp_meshPtblFn, peer_Inst);
222 snmpAddNodeStr("1.3.6.1.4.1.3495.1.5.1.3", MESH_PTBL_ICP, snmp_meshPtblFn, peer_Inst);
223 snmpAddNodeStr("1.3.6.1.4.1.3495.1.5.1.3", MESH_PTBL_TYPE, snmp_meshPtblFn, peer_Inst);
224 snmpAddNodeStr("1.3.6.1.4.1.3495.1.5.1.3", MESH_PTBL_STATE, snmp_meshPtblFn, peer_Inst);
225 snmpAddNodeStr("1.3.6.1.4.1.3495.1.5.1.3", MESH_PTBL_SENT, snmp_meshPtblFn, peer_Inst);
226 snmpAddNodeStr("1.3.6.1.4.1.3495.1.5.1.3", MESH_PTBL_PACKED, snmp_meshPtblFn, peer_Inst);
227 snmpAddNodeStr("1.3.6.1.4.1.3495.1.5.1.3", MESH_PTBL_FETCHES, snmp_meshPtblFn, peer_Inst);
228 snmpAddNodeStr("1.3.6.1.4.1.3495.1.5.1.3", MESH_PTBL_RTT, snmp_meshPtblFn, peer_Inst);
229 snmpAddNodeStr("1.3.6.1.4.1.3495.1.5.1.3", MESH_PTBL_IGN, snmp_meshPtblFn, peer_Inst);
230 snmpAddNodeStr("1.3.6.1.4.1.3495.1.5.1.3", MESH_PTBL_KEEPAL_S, snmp_meshPtblFn, peer_Inst);
231 snmpAddNodeStr("1.3.6.1.4.1.3495.1.5.1.3", MESH_PTBL_KEEPAL_R, snmp_meshPtblFn, peer_Inst);
232
233 /* cacheClientTable - 1.3.6.1.4.1.3495.1.5.2 */
234 snmpAddNodeStr("1.3.6.1.4.1.3495.1.5", MESH_CTBL, nullptr, nullptr);
235
236 /* BUG 2811: we NEED to create a reliable index for the client DB and make version 3 of the table. */
237 /* for now we have version 2 table with OID capable of mixed IPv4 / IPv6 clients and upgraded address text format. */
238
239 /* cacheClientEntry - 1.3.6.1.4.1.3495.1.5.2.2 */
240 snmpAddNodeStr("1.3.6.1.4.1.3495.1.5.2", 2, nullptr, nullptr);
241 snmpAddNodeStr("1.3.6.1.4.1.3495.1.5.2.2", MESH_CTBL_ADDR_TYPE, snmp_meshCtblFn, client_Inst);
242 snmpAddNodeStr("1.3.6.1.4.1.3495.1.5.2.2", MESH_CTBL_ADDR, snmp_meshCtblFn, client_Inst);
243 snmpAddNodeStr("1.3.6.1.4.1.3495.1.5.2.2", MESH_CTBL_HTREQ, snmp_meshCtblFn, client_Inst);
244 snmpAddNodeStr("1.3.6.1.4.1.3495.1.5.2.2", MESH_CTBL_HTBYTES, snmp_meshCtblFn, client_Inst);
245 snmpAddNodeStr("1.3.6.1.4.1.3495.1.5.2.2", MESH_CTBL_HTHITS, snmp_meshCtblFn, client_Inst);
246 snmpAddNodeStr("1.3.6.1.4.1.3495.1.5.2.2", MESH_CTBL_HTHITBYTES, snmp_meshCtblFn, client_Inst);
247 snmpAddNodeStr("1.3.6.1.4.1.3495.1.5.2.2", MESH_CTBL_ICPREQ, snmp_meshCtblFn, client_Inst);
248 snmpAddNodeStr("1.3.6.1.4.1.3495.1.5.2.2", MESH_CTBL_ICPBYTES, snmp_meshCtblFn, client_Inst);
249 snmpAddNodeStr("1.3.6.1.4.1.3495.1.5.2.2", MESH_CTBL_ICPHITS, snmp_meshCtblFn, client_Inst);
251
252 debugs(49, 9, "snmpInit: Completed SNMP mib tree structure");
253}
254
255static void
257{
258 if (!IamWorkerProcess())
259 return;
260
261 if (Config.Port.snmp <= 0)
262 return;
263
267
268 if (!Ip::EnableIpv6 && !snmpIncomingConn->local.setIPv4()) {
269 debugs(49, DBG_CRITICAL, "ERROR: IPv6 is disabled. " << snmpIncomingConn->local << " is not an IPv4 address.");
270 fatal("SNMP port cannot be opened.");
271 }
272 /* split-stack for now requires IPv4-only SNMP */
273 if (Ip::EnableIpv6&IPV6_SPECIAL_SPLITSTACK && snmpIncomingConn->local.isAnyAddr()) {
275 }
276
277 auto call = asyncCallbackFun(49, 2, snmpPortOpened);
278 Ipc::StartListening(SOCK_DGRAM, IPPROTO_UDP, snmpIncomingConn, Ipc::fdnInSnmpSocket, call);
279
284
285 if (!Ip::EnableIpv6 && !snmpOutgoingConn->local.setIPv4()) {
286 debugs(49, DBG_CRITICAL, "ERROR: IPv6 is disabled. " << snmpOutgoingConn->local << " is not an IPv4 address.");
287 fatal("SNMP port cannot be opened.");
288 }
289 /* split-stack for now requires IPv4-only SNMP */
290 if (Ip::EnableIpv6&IPV6_SPECIAL_SPLITSTACK && snmpOutgoingConn->local.isAnyAddr()) {
292 }
293 // TODO: Add/use snmpOutgoingPortOpened() instead of snmpPortOpened().
294 auto c = asyncCallbackFun(49, 2, snmpPortOpened);
295 Ipc::StartListening(SOCK_DGRAM, IPPROTO_UDP, snmpOutgoingConn, Ipc::fdnOutSnmpSocket, c);
296 } else {
298 debugs(1, DBG_IMPORTANT, "Sending SNMP messages from " << snmpOutgoingConn->local);
299 }
300}
301
302static void
304{
305 const auto &conn = answer.conn;
306
307 if (!Comm::IsConnOpen(conn))
308 fatalf("Cannot open SNMP %s Port",(conn->fd == snmpIncomingConn->fd?"receiving":"sending"));
309
310 Comm::SetSelect(conn->fd, COMM_SELECT_READ, snmpHandleUdp, nullptr, 0);
311
312 if (conn->fd == snmpIncomingConn->fd)
313 debugs(1, DBG_IMPORTANT, "Accepting SNMP messages on " << snmpIncomingConn->local);
314 else if (conn->fd == snmpOutgoingConn->fd)
315 debugs(1, DBG_IMPORTANT, "Sending SNMP messages from " << snmpOutgoingConn->local);
316 else
317 fatalf("Lost SNMP port (%d) on FD %d", (int)conn->local.port(), conn->fd);
318}
319
320static void
322{
323 if (!IamWorkerProcess())
324 return;
325
327 debugs(49, DBG_IMPORTANT, "Closing SNMP receiving port " << snmpIncomingConn->local);
329 }
330 snmpIncomingConn = nullptr;
331
333 debugs(49, DBG_IMPORTANT, "Closing SNMP sending port " << snmpOutgoingConn->local);
335 }
336 snmpOutgoingConn = nullptr;
337}
338
340{
341public:
342 void finalizeConfig() override { snmpInit(); }
343 void useConfig() override { snmpOpenPorts(); }
344 void startReconfigure() override { snmpClosePorts(); }
345 void syncConfig() override { snmpOpenPorts(); }
346 void startShutdown() override { snmpClosePorts(); }
347};
349
350/*
351 * Accept the UDP packet
352 */
353void
354snmpHandleUdp(int sock, void *)
355{
356 static char buf[SNMP_REQUEST_SIZE];
357 Ip::Address from;
358 SnmpRequest *snmp_rq;
359 int len;
360
361 debugs(49, 5, "snmpHandleUdp: Called.");
362
364
365 memset(buf, '\0', sizeof(buf));
366
367 len = comm_udp_recvfrom(sock, buf, sizeof(buf)-1, 0, from);
368
369 if (len > 0) {
370 debugs(49, 3, "snmpHandleUdp: FD " << sock << ": received " << len << " bytes from " << from << ".");
371
372 snmp_rq = (SnmpRequest *)xcalloc(1, sizeof(SnmpRequest));
373 snmp_rq->buf = (u_char *) buf;
374 snmp_rq->len = len;
375 snmp_rq->sock = sock;
376 snmp_rq->outbuf = (unsigned char *)xmalloc(snmp_rq->outlen = SNMP_REQUEST_SIZE);
377 snmp_rq->from = from;
378 snmpDecodePacket(snmp_rq);
379 xfree(snmp_rq->outbuf);
380 xfree(snmp_rq);
381 } else {
382 int xerrno = errno;
383 debugs(49, DBG_IMPORTANT, "snmpHandleUdp: FD " << sock << " recvfrom: " << xstrerr(xerrno));
384 }
385}
386
387/*
388 * Turn SNMP packet into a PDU, check available ACL's
389 */
390static void
392{
393 struct snmp_pdu *PDU;
394 u_char *Community;
395 u_char *buf = rq->buf;
396 int len = rq->len;
397
398 if (!Config.accessList.snmp) {
399 debugs(49, DBG_IMPORTANT, "WARNING: snmp_access not configured. agent query DENIED from : " << rq->from);
400 return;
401 }
402
403 debugs(49, 5, "Called.");
404 PDU = snmp_pdu_create(0);
405 /* Always answer on SNMPv1 */
407 Community = snmp_parse(&rq->session, PDU, buf, len);
408
409 /* Check if we have explicit permission to access SNMP data.
410 * default (set above) is to deny all */
411 if (Community) {
412 ACLFilledChecklist checklist(Config.accessList.snmp, nullptr);
413 checklist.src_addr = rq->from;
414 checklist.snmp_community = (char *) Community;
415
416 if (checklist.fastCheck().allowed() && (snmp_coexist_V2toV1(PDU))) {
417 rq->community = Community;
418 rq->PDU = PDU;
419 debugs(49, 5, "snmpAgentParse: reqid=[" << PDU->reqid << "]");
421 } else {
422 debugs(49, DBG_IMPORTANT, "WARNING: SNMP agent query DENIED from : " << rq->from);
423 snmp_free_pdu(PDU);
424 }
425 xfree(Community);
426 rq->community = nullptr;
427 rq->session.community = nullptr;
428 rq->session.community_len = 0;
429 } else {
430 debugs(49, DBG_IMPORTANT, "WARNING: Failed SNMP agent query from : " << rq->from);
431 snmp_free_pdu(PDU);
432 }
433}
434
435/*
436 * Packet OK, ACL Check OK, Create response.
437 */
438static void
440{
441
442 struct snmp_pdu *RespPDU;
443
444 debugs(49, 5, "snmpConstructReponse: Called.");
445
446 if (UsingSmp() && IamWorkerProcess()) {
447 AsyncJob::Start(new Snmp::Forwarder(static_cast<Snmp::Pdu&>(*rq->PDU),
448 static_cast<Snmp::Session&>(rq->session), rq->sock, rq->from));
449 snmp_free_pdu(rq->PDU);
450 return;
451 }
452
453 RespPDU = snmpAgentResponse(rq->PDU);
454 snmp_free_pdu(rq->PDU);
455
456 if (RespPDU != nullptr) {
457 if (snmp_build(&rq->session, RespPDU, rq->outbuf, &rq->outlen) == 0)
458 comm_udp_sendto(rq->sock, rq->from, rq->outbuf, rq->outlen);
459 else
460 debugs(49, DBG_IMPORTANT, "ERROR: Failed to encode a response to SNMP agent query from " << rq->from);
461 snmp_free_pdu(RespPDU);
462 }
463}
464
465/*
466 * Decide how to respond to the request, construct a response and
467 * return the response to the requester.
468 */
469
470struct snmp_pdu *
472
473 struct snmp_pdu *Answer = nullptr;
474
475 debugs(49, 5, "snmpAgentResponse: Called.");
476
477 if ((Answer = snmp_pdu_create(SNMP_PDU_RESPONSE))) {
478 Answer->reqid = PDU->reqid;
479 Answer->errindex = 0;
480
481 if (PDU->command == SNMP_PDU_GET || PDU->command == SNMP_PDU_GETNEXT) {
482 /* Indirect way */
483 int get_next = (PDU->command == SNMP_PDU_GETNEXT);
484 variable_list *VarPtr_;
485 variable_list **RespVars = &(Answer->variables);
486 oid_ParseFn *ParseFn;
487 int index = 0;
488 /* Loop through all variables */
489
490 for (VarPtr_ = PDU->variables; VarPtr_; VarPtr_ = VarPtr_->next_variable) {
491 variable_list *VarPtr = VarPtr_;
492 variable_list *VarNew = nullptr;
493 oid *NextOidName = nullptr;
494 snint NextOidNameLen = 0;
495
496 ++index;
497
498 if (get_next)
499 ParseFn = snmpTreeNext(VarPtr->name, VarPtr->name_length, &NextOidName, &NextOidNameLen);
500 else
501 ParseFn = snmpTreeGet(VarPtr->name, VarPtr->name_length);
502
503 if (ParseFn == nullptr) {
505 debugs(49, 5, "snmpAgentResponse: No such oid. ");
506 } else {
507 if (get_next) {
508 VarPtr = snmp_var_new(NextOidName, NextOidNameLen);
509 xfree(NextOidName);
510 }
511
512 int * errstatTmp = &(Answer->errstat);
513
514 VarNew = (*ParseFn) (VarPtr, (snint *) errstatTmp);
515
516 if (get_next)
517 snmp_var_free(VarPtr);
518 }
519
520 if ((Answer->errstat != SNMP_ERR_NOERROR) || (VarNew == nullptr)) {
521 Answer->errindex = index;
522 debugs(49, 5, "snmpAgentResponse: error.");
523
524 if (VarNew)
525 snmp_var_free(VarNew);
526
527 while ((VarPtr = Answer->variables) != nullptr) {
528 Answer->variables = VarPtr->next_variable;
529 snmp_var_free(VarPtr);
530 }
531
532 /* Steal the original PDU list of variables for the error response */
533 Answer->variables = PDU->variables;
534
535 PDU->variables = nullptr;
536
537 return (Answer);
538 }
539
540 /* No error. Insert this var at the end, and move on to the next.
541 */
542 *RespVars = VarNew;
543
544 RespVars = &(VarNew->next_variable);
545 }
546 }
547 }
548
549 return (Answer);
550}
551
552static oid_ParseFn *
553snmpTreeGet(oid * Current, snint CurrentLen)
554{
555 oid_ParseFn *Fn = nullptr;
556 mib_tree_entry *mibTreeEntry = nullptr;
557 int count = 0;
558
559 debugs(49, 5, "snmpTreeGet: Called");
560
561 MemBuf tmp;
562 debugs(49, 6, "snmpTreeGet: Current : " << snmpDebugOid(Current, CurrentLen, tmp) );
563
564 mibTreeEntry = mib_tree_head;
565
566 if (Current[count] == mibTreeEntry->name[count]) {
567 ++count;
568
569 while ((mibTreeEntry) && (count < CurrentLen) && (!mibTreeEntry->parsefunction)) {
570 mibTreeEntry = snmpTreeEntry(Current[count], count, mibTreeEntry);
571 ++count;
572 }
573 }
574
575 if (mibTreeEntry && mibTreeEntry->parsefunction)
576 Fn = mibTreeEntry->parsefunction;
577
578 debugs(49, 5, "snmpTreeGet: return");
579
580 return (Fn);
581}
582
584snmpAggrType(oid* Current, snint CurrentLen)
585{
586 debugs(49, 5, MYNAME);
587
588 mib_tree_entry* mibTreeEntry = mib_tree_head;
589 AggrType type = atNone;
590 int count = 0;
591
592 if (Current[count] == mibTreeEntry->name[count]) {
593 ++count;
594
595 while (mibTreeEntry != nullptr && count < CurrentLen) {
596 mibTreeEntry = snmpTreeEntry(Current[count], count, mibTreeEntry);
597 if (mibTreeEntry != nullptr)
598 type = mibTreeEntry->aggrType;
599 ++count;
600 }
601 }
602
603 return type;
604}
605
606static oid_ParseFn *
607snmpTreeNext(oid * Current, snint CurrentLen, oid ** Next, snint * NextLen)
608{
609 oid_ParseFn *Fn = nullptr;
610 int count = 0;
611
612 debugs(49, 5, "snmpTreeNext: Called");
613
614 MemBuf tmp;
615 debugs(49, 6, "snmpTreeNext: Current : " << snmpDebugOid(Current, CurrentLen, tmp));
616
617 mib_tree_entry *mibTreeEntry = mib_tree_head;
618
619 if (mibTreeEntry && Current[count] == mibTreeEntry->name[count]) {
620 ++count;
621
622 while ((mibTreeEntry) && (count < CurrentLen) && (!mibTreeEntry->parsefunction)) {
623 mib_tree_entry *nextmibTreeEntry = snmpTreeEntry(Current[count], count, mibTreeEntry);
624
625 if (!nextmibTreeEntry)
626 break;
627 else
628 mibTreeEntry = nextmibTreeEntry;
629
630 ++count;
631 }
632 debugs(49, 5, "snmpTreeNext: Recursed down to requested object");
633 } else {
634 return nullptr;
635 }
636
637 if (mibTreeEntry == mib_tree_last)
638 return (Fn);
639
640 if ((mibTreeEntry) && (mibTreeEntry->parsefunction)) {
641 *NextLen = CurrentLen;
642 *Next = (*mibTreeEntry->instancefunction) (Current, NextLen, mibTreeEntry, &Fn);
643 if (*Next) {
644 debugs(49, 6, "snmpTreeNext: Next : " << snmpDebugOid(*Next, *NextLen, tmp));
645 return (Fn);
646 }
647 }
648
649 if ((mibTreeEntry) && (mibTreeEntry->parsefunction)) {
650 --count;
651 mib_tree_entry *nextoid = snmpTreeSiblingEntry(Current[count], count, mibTreeEntry->parent);
652 if (nextoid) {
653 debugs(49, 5, "snmpTreeNext: Next OID found for sibling" << nextoid );
654 mibTreeEntry = nextoid;
655 ++count;
656 } else {
657 debugs(49, 5, "snmpTreeNext: Attempting to recurse up for next object");
658
659 while (!nextoid) {
660 --count;
661
662 if (mibTreeEntry->parent->parent) {
663 nextoid = mibTreeEntry->parent;
664 mibTreeEntry = snmpTreeEntry(Current[count] + 1, count, nextoid->parent);
665
666 if (!mibTreeEntry) {
667 mibTreeEntry = nextoid;
668 nextoid = nullptr;
669 }
670 } else {
671 nextoid = mibTreeEntry;
672 mibTreeEntry = nullptr;
673 }
674 }
675 }
676 }
677 while ((mibTreeEntry) && (!mibTreeEntry->parsefunction)) {
678 mibTreeEntry = mibTreeEntry->leaves[0];
679 }
680
681 if (mibTreeEntry) {
682 *NextLen = mibTreeEntry->len;
683 *Next = (*mibTreeEntry->instancefunction) (mibTreeEntry->name, NextLen, mibTreeEntry, &Fn);
684 }
685
686 if (*Next) {
687 debugs(49, 6, "snmpTreeNext: Next : " << snmpDebugOid(*Next, *NextLen, tmp));
688 return (Fn);
689 } else
690 return nullptr;
691}
692
693static oid *
694static_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn)
695{
696 oid *instance = nullptr;
697 if (*len <= current->len) {
698 instance = (oid *)xmalloc(sizeof(*name) * (*len + 1));
699 memcpy(instance, name, sizeof(*name) * (*len));
700 instance[*len] = 0;
701 *len += 1;
702 }
703 *Fn = current->parsefunction;
704 return (instance);
705}
706
707static oid *
708time_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn)
709{
710 oid *instance = nullptr;
711 int identifier = 0, loop = 0;
712 int index[TIME_INDEX_LEN] = {TIME_INDEX};
713
714 if (*len <= current->len) {
715 instance = (oid *)xmalloc(sizeof(*name) * (*len + 1));
716 memcpy(instance, name, sizeof(*name) * (*len));
717 instance[*len] = *index;
718 *len += 1;
719 } else {
720 identifier = name[*len - 1];
721
722 while ((loop < TIME_INDEX_LEN) && (identifier != index[loop]))
723 ++loop;
724
725 if (loop < (TIME_INDEX_LEN - 1)) {
726 instance = (oid *)xmalloc(sizeof(*name) * (*len));
727 memcpy(instance, name, sizeof(*name) * (*len));
728 instance[*len - 1] = index[++loop];
729 }
730 }
731
732 *Fn = current->parsefunction;
733 return (instance);
734}
735
736static oid *
737peer_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn)
738{
739 oid *instance = nullptr;
740 const auto peersAvailable = CurrentCachePeers().size();
741
742 if (!peersAvailable) {
743 debugs(49, 6, "snmp peer_Inst: No Peers.");
744 current = current->parent->parent->parent->leaves[1];
745 while ((current) && (!current->parsefunction))
746 current = current->leaves[0];
747
748 if (!current)
749 return (instance);
750
751 instance = client_Inst(current->name, len, current, Fn);
752 } else if (*len <= current->len) {
753 debugs(49, 6, "snmp peer_Inst: *len <= current->len ???");
754 instance = (oid *)xmalloc(sizeof(*name) * ( *len + 1));
755 memcpy(instance, name, sizeof(*name) * (*len));
756 instance[*len] = 1 ;
757 *len += 1;
758 } else {
759 int no = name[current->len] ;
760 int i;
761 // Note: This works because the Config.peers keeps its index according to its position.
762 for (i = 0; Less(i, peersAvailable) && Less(i, no); ++i);
763
764 if (Less(i, peersAvailable)) {
765 debugs(49, 6, "snmp peer_Inst: Encode peer #" << i);
766 instance = (oid *)xmalloc(sizeof(*name) * (current->len + 1 ));
767 memcpy(instance, name, (sizeof(*name) * current->len ));
768 instance[current->len] = no + 1 ; // i.e. the next index on cache_peeer table.
769 *len = current->len + 1;
770 } else {
771 debugs(49, 6, "snmp peer_Inst: We have " << i << " peers. Can't find #" << no);
772 return (instance);
773 }
774 }
775 *Fn = current->parsefunction;
776 return (instance);
777}
778
779static oid *
780client_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn)
781{
782 oid *instance = nullptr;
783 Ip::Address laddr;
784 Ip::Address *aux;
785 int size = 0;
786 int newshift = 0;
787
788 if (*len <= current->len) {
789 aux = client_entry(nullptr);
790 if (aux)
791 laddr = *aux;
792 else
793 laddr.setAnyAddr();
794
795 if (laddr.isIPv4())
796 size = sizeof(in_addr);
797 else
798 size = sizeof(in6_addr);
799
800 debugs(49, 6, "len" << *len << ", current-len" << current->len << ", addr=" << laddr << ", size=" << size);
801
802 instance = (oid *)xmalloc(sizeof(*name) * (*len + size ));
803 memcpy(instance, name, (sizeof(*name) * (*len)));
804
805 if ( !laddr.isAnyAddr() ) {
806 addr2oid(laddr, &instance[ *len]); // the addr
807 *len += size ;
808 }
809 } else {
810 int shift = *len - current->len ; // i.e 4 or 16
811 oid2addr(&name[*len - shift], laddr,shift);
812 aux = client_entry(&laddr);
813 if (aux)
814 laddr = *aux;
815 else
816 laddr.setAnyAddr();
817
818 if (!laddr.isAnyAddr()) {
819 if (laddr.isIPv4())
820 newshift = sizeof(in_addr);
821 else
822 newshift = sizeof(in6_addr);
823
824 debugs(49, 6, "len" << *len << ", current-len" << current->len << ", addr=" << laddr << ", newshift=" << newshift);
825
826 instance = (oid *)xmalloc(sizeof(*name) * (current->len + newshift));
827 memcpy(instance, name, (sizeof(*name) * (current->len)));
828 addr2oid(laddr, &instance[current->len]); // the addr.
829 *len = current->len + newshift ;
830 }
831 }
832
833 *Fn = current->parsefunction;
834 return (instance);
835}
836
837/*
838 * Utility functions
839 */
840
841/*
842 * Tree utility functions.
843 */
844
845/*
846 * Returns a sibling object for the requested child object or NULL
847 * if it does not exit
848 */
849static mib_tree_entry *
851{
852 for (int i = 0; i < current->children; ++i) {
853 if (current->leaves[i]->name[len] == entry)
854 return (i + 1 < current->children) ? current->leaves[i + 1] : nullptr;
855 }
856 return nullptr;
857}
858
859/*
860 * Returns the requested child object or NULL if it does not exist
861 */
862static mib_tree_entry *
863snmpTreeEntry(oid entry, snint len, mib_tree_entry * current)
864{
865 mib_tree_entry *next = nullptr;
866 int count = 0;
867
868 while ((!next) && current && (count < current->children)) {
869 if (current->leaves[count]->name[len] == entry) {
870 next = current->leaves[count];
871 }
872
873 ++count;
874 }
875
876 return (next);
877}
878
879static void
881{
882 debugs(49, 5, "snmpAddNodeChild: assigning " << child << " to parent " << entry);
883 entry->leaves = (mib_tree_entry **)xrealloc(entry->leaves, sizeof(mib_tree_entry *) * (entry->children + 1));
884 entry->leaves[entry->children] = child;
885 entry->leaves[entry->children]->parent = entry;
886 ++ entry->children;
887}
888
890snmpLookupNodeStr(mib_tree_entry *root, const char *str)
891{
892 oid *name;
893 int namelen;
895
896 if (root)
897 e = root;
898 else
899 e = mib_tree_head;
900
901 if (! snmpCreateOidFromStr(str, &name, &namelen))
902 return nullptr;
903
904 /* I wish there were some kind of sensible existing tree traversal
905 * routine to use. I'll worry about that later */
906 if (namelen <= 1) {
907 xfree(name);
908 return e; /* XXX it should only be this? */
909 }
910
911 int i, r = 1;
912 while (r < namelen) {
913
914 /* Find the child node which matches this */
915 for (i = 0; i < e->children && e->leaves[i]->name[r] != name[r]; ++i) ; // seek-loop
916
917 /* Are we pointing to that node? */
918 if (i >= e->children)
919 break;
920 assert(e->leaves[i]->name[r] == name[r]);
921
922 /* Skip to that node! */
923 e = e->leaves[i];
924 ++r;
925 }
926
927 xfree(name);
928 return e;
929}
930
931bool
932snmpCreateOidFromStr(const char *str, oid **name, int *nl)
933{
934 char const *delim = ".";
935
936 *name = nullptr;
937 *nl = 0;
938 const char *s = str;
939
940 /* Parse the OID string into oid bits */
941 while (size_t len = strcspn(s, delim)) {
942 *name = (oid*)xrealloc(*name, sizeof(oid) * ((*nl) + 1));
943 (*name)[*nl] = atoi(s); // stops at the '.' delimiter
944 ++(*nl);
945 // exit with true when the last octet has been parsed
946 if (s[len] == '\0')
947 return true;
948 s += len+1;
949 }
950
951 // if we aborted before the lst octet was found, return false.
952 safe_free(*name);
953 return false;
954}
955
956/*
957 * Create an entry. Return a pointer to the newly created node, or NULL
958 * on failure.
959 */
960static mib_tree_entry *
961snmpAddNodeStr(const char *base_str, int o, oid_ParseFn * parsefunction, instance_Fn * instancefunction, AggrType aggrType)
962{
963 mib_tree_entry *m, *b;
964 oid *n;
965 int nl;
966 char s[1024];
967
968 /* Find base node */
969 b = snmpLookupNodeStr(mib_tree_head, base_str);
970 if (! b)
971 return nullptr;
972 debugs(49, 5, "snmpAddNodeStr: " << base_str << ": -> " << b);
973
974 /* Create OID string for new entry */
975 snprintf(s, 1024, "%s.%d", base_str, o);
976 if (! snmpCreateOidFromStr(s, &n, &nl))
977 return nullptr;
978
979 /* Create a node */
980 m = snmpAddNode(n, nl, parsefunction, instancefunction, aggrType, 0);
981
982 /* Link it into the existing tree */
983 snmpAddNodeChild(b, m);
984
985 /* Return the node */
986 return m;
987}
988
989/*
990 * Adds a node to the MIB tree structure and adds the appropriate children
991 */
992static mib_tree_entry *
993snmpAddNode(oid * name, int len, oid_ParseFn * parsefunction, instance_Fn * instancefunction, AggrType aggrType, int children,...)
994{
995 MemBuf tmp;
996 debugs(49, 6, "snmpAddNode: Children : " << children << ", Oid : " << snmpDebugOid(name, len, tmp));
997
998 const auto entry = static_cast<mib_tree_entry *>(xmalloc(sizeof(mib_tree_entry)));
999 entry->name = name;
1000 entry->len = len;
1001 entry->parsefunction = parsefunction;
1002 entry->instancefunction = instancefunction;
1003 entry->children = children;
1004 entry->leaves = nullptr;
1005 entry->parent = nullptr;
1006 entry->aggrType = aggrType;
1007
1008 if (children > 0) {
1009 entry->leaves = static_cast<mib_tree_entry **>(xmalloc(sizeof(mib_tree_entry *) * children));
1010
1011 va_list args;
1012 va_start(args, children);
1013 for (int loop = 0; loop < children; ++loop) {
1014 entry->leaves[loop] = va_arg(args, mib_tree_entry *);
1015 entry->leaves[loop]->parent = entry;
1016 }
1017 va_end(args);
1018 }
1019
1020 return (entry);
1021}
1022/* End of tree utility functions */
1023
1024/*
1025 * Returns the list of parameters in an oid
1026 */
1027static oid *
1028snmpCreateOid(int length,...)
1029{
1030 va_list args;
1031 oid *new_oid;
1032 int loop;
1033 va_start(args, length);
1034
1035 new_oid = (oid *)xmalloc(sizeof(oid) * length);
1036
1037 if (length > 0) {
1038 for (loop = 0; loop < length; ++loop) {
1039 new_oid[loop] = va_arg(args, int);
1040 }
1041 }
1042
1043 va_end(args);
1044 return (new_oid);
1045}
1046
1047/*
1048 * Debug calls, prints out the OID for debugging purposes.
1049 */
1050const char *
1051snmpDebugOid(oid * Name, snint Len, MemBuf &outbuf)
1052{
1053 char mbuf[16];
1054 int x;
1055 outbuf.reset();
1056
1057 for (x = 0; x < Len; ++x) {
1058 size_t bytes = snprintf(mbuf, sizeof(mbuf), ".%u", (unsigned int) Name[x]);
1059 outbuf.append(mbuf, bytes);
1060 }
1061 return outbuf.content();
1062}
1063
1064void
1065snmpSnmplibDebug(int lvl, char *buf)
1066{
1067 debugs(49, lvl, buf);
1068}
1069
1070/*
1071 IPv4 address: 10.10.0.9 ==>
1072 oid == 10.10.0.9
1073 IPv6 address : 20:01:32:ef:a2:21:fb:32:00:00:00:00:00:00:00:00:OO:01 ==>
1074 oid == 32.1.50.239.162.33.251.20.50.0.0.0.0.0.0.0.0.0.1
1075*/
1076void
1078{
1079 u_int i ;
1080 u_char *cp = nullptr;
1081 struct in_addr i4addr;
1082 struct in6_addr i6addr;
1084 u_int size = (code == INETADDRESSTYPE_IPV4) ? sizeof(struct in_addr):sizeof(struct in6_addr);
1085 // Dest[0] = code ;
1086 if ( code == INETADDRESSTYPE_IPV4 ) {
1087 addr.getInAddr(i4addr);
1088 cp = (u_char *) &(i4addr.s_addr);
1089 } else {
1090 addr.getInAddr(i6addr);
1091 cp = (u_char *) &i6addr;
1092 }
1093 for ( i=0 ; i < size ; ++i) {
1094 // OID's are in network order
1095 Dest[i] = *cp;
1096 ++cp;
1097 }
1098 MemBuf tmp;
1099 debugs(49, 7, "addr2oid: Dest : " << snmpDebugOid(Dest, size, tmp));
1100}
1101
1102/*
1103 oid == 10.10.0.9 ==>
1104 IPv4 address: 10.10.0.9
1105 oid == 32.1.50.239.162.33.251.20.50.0.0.0.0.0.0.0.0.0.1 ==>
1106 IPv6 address : 20:01:32:ef:a2:21:fb:32:00:00:00:00:00:00:00:00:OO:01
1107*/
1108void
1109oid2addr(oid * id, Ip::Address &addr, u_int size)
1110{
1111 struct in_addr i4addr;
1112 struct in6_addr i6addr;
1113 u_int i;
1114 u_char *cp;
1115 if ( size == sizeof(struct in_addr) )
1116 cp = (u_char *) &(i4addr.s_addr);
1117 else
1118 cp = (u_char *) &(i6addr);
1119 MemBuf tmp;
1120 debugs(49, 7, "oid2addr: id : " << snmpDebugOid(id, size, tmp) );
1121 for (i=0 ; i<size; ++i) {
1122 cp[i] = id[i];
1123 }
1124 if ( size == sizeof(struct in_addr) )
1125 addr = i4addr;
1126 else
1127 addr = i6addr;
1128}
1129
1130int
1132{
1133 const auto checklist = Filled(ch);
1134
1135 return data->match (checklist->snmp_community);
1136}
1137
#define asyncCallbackFun(dbgSection, dbgLevel, function)
AsyncCall for calling back a function.
const CachePeers & CurrentCachePeers()
Definition CachePeers.cc:43
ACLFilledChecklist * Filled(ACLChecklist *checklist)
convenience and safety wrapper for dynamic_cast<ACLFilledChecklist*>
int size
Definition ModDevPoll.cc:70
#define DefineRunnerRegistrator(ClassName)
class SquidConfig Config
constexpr bool Less(const A a, const B b)
whether integer a is less than integer b, with correct overflow handling
Definition SquidMath.h:48
u_int oid
Definition asn1.h:42
#define assert(EX)
Definition assert.h:17
static char identifier[MAXLINE]
@ PERF_PROTOSTAT_AGGR_REQ
Definition cache_snmp.h:149
@ PERF_PROTOSTAT_AGGR_ICP_SKB
Definition cache_snmp.h:147
@ PERF_PROTOSTAT_AGGR_ICP_S
Definition cache_snmp.h:145
@ PERF_PROTOSTAT_AGGR_HTTP_KBYTES_IN
Definition cache_snmp.h:143
@ PERF_PROTOSTAT_AGGR_ICP_RKB
Definition cache_snmp.h:148
@ PERF_PROTOSTAT_AGGR_HTTP_ERRORS
Definition cache_snmp.h:142
@ PERF_PROTOSTAT_AGGR_KBYTES_OUT
Definition cache_snmp.h:152
@ PERF_PROTOSTAT_AGGR_ICP_R
Definition cache_snmp.h:146
@ PERF_PROTOSTAT_AGGR_KBYTES_IN
Definition cache_snmp.h:151
@ PERF_PROTOSTAT_AGGR_CLIENTS
Definition cache_snmp.h:154
@ PERF_PROTOSTAT_AGGR_CURSWAP
Definition cache_snmp.h:153
@ PERF_PROTOSTAT_AGGR_HTTP_HITS
Definition cache_snmp.h:141
@ PERF_PROTOSTAT_AGGR_ERRORS
Definition cache_snmp.h:150
@ PERF_PROTOSTAT_AGGR_HTTP_KBYTES_OUT
Definition cache_snmp.h:144
@ PERF_PROTOSTAT_AGGR_HTTP_REQ
Definition cache_snmp.h:140
@ MESH_CTBL
Definition cache_snmp.h:229
@ MESH_PTBL
Definition cache_snmp.h:228
@ MESH_PTBL_INDEX
Definition cache_snmp.h:236
@ MESH_PTBL_KEEPAL_S
Definition cache_snmp.h:249
@ MESH_PTBL_IGN
Definition cache_snmp.h:248
@ MESH_PTBL_ADDR_TYPE
Definition cache_snmp.h:238
@ MESH_PTBL_RTT
Definition cache_snmp.h:247
@ MESH_PTBL_PACKED
Definition cache_snmp.h:245
@ MESH_PTBL_STATE
Definition cache_snmp.h:243
@ MESH_PTBL_HTTP
Definition cache_snmp.h:240
@ MESH_PTBL_KEEPAL_R
Definition cache_snmp.h:250
@ MESH_PTBL_ADDR
Definition cache_snmp.h:239
@ MESH_PTBL_FETCHES
Definition cache_snmp.h:246
@ MESH_PTBL_TYPE
Definition cache_snmp.h:242
@ MESH_PTBL_SENT
Definition cache_snmp.h:244
@ MESH_PTBL_ICP
Definition cache_snmp.h:241
@ MESH_PTBL_NAME
Definition cache_snmp.h:237
@ IP_HITS
Definition cache_snmp.h:191
@ IP_REQ
Definition cache_snmp.h:190
@ IP_ENT
Definition cache_snmp.h:189
@ IP_MISS
Definition cache_snmp.h:194
@ IP_NEGHIT
Definition cache_snmp.h:193
@ IP_GHBN
Definition cache_snmp.h:195
@ IP_LOC
Definition cache_snmp.h:196
@ IP_PENDHIT
Definition cache_snmp.h:192
int64_t snint
Definition cache_snmp.h:14
#define TIME_INDEX_LEN
Definition cache_snmp.h:38
@ PERF_SYS_CURUNLREQ
Definition cache_snmp.h:121
@ PERF_SYS_CURUSED_FD
Definition cache_snmp.h:124
@ PERF_SYS_CPUUSAGE
Definition cache_snmp.h:117
@ PERF_SYS_NUMOBJCNT
Definition cache_snmp.h:119
@ PERF_SYS_CPUTIME
Definition cache_snmp.h:116
@ PERF_SYS_MAXRESSZ
Definition cache_snmp.h:118
@ PERF_SYS_CURLRUEXP
Definition cache_snmp.h:120
@ PERF_SYS_NUMR
Definition cache_snmp.h:114
@ PERF_SYS_CURRESERVED_FD
Definition cache_snmp.h:123
@ PERF_SYS_CURMAX_FD
Definition cache_snmp.h:125
@ PERF_SYS_PF
Definition cache_snmp.h:113
@ PERF_SYS_MEMUSAGE
Definition cache_snmp.h:115
@ PERF_SYS_CURUNUSED_FD
Definition cache_snmp.h:122
@ PERF_PROTOSTAT_AGGR
Definition cache_snmp.h:132
@ PERF_PROTOSTAT_MEDIAN
Definition cache_snmp.h:133
@ CONF_VERSION_ID
Definition cache_snmp.h:74
@ CONF_LOG_FAC
Definition cache_snmp.h:75
@ CONF_VERSION
Definition cache_snmp.h:73
@ CONF_STORAGE
Definition cache_snmp.h:76
@ CONF_ADMIN
Definition cache_snmp.h:72
@ CONF_UNIQNAME
Definition cache_snmp.h:77
@ NET_FQDN_CACHE
Definition cache_snmp.h:181
@ NET_DNS_CACHE
Definition cache_snmp.h:182
@ NET_IP_CACHE
Definition cache_snmp.h:180
@ MESH_CTBL_HTHITBYTES
Definition cache_snmp.h:262
@ MESH_CTBL_ICPREQ
Definition cache_snmp.h:263
@ MESH_CTBL_ADDR_TYPE
Definition cache_snmp.h:257
@ MESH_CTBL_HTBYTES
Definition cache_snmp.h:260
@ MESH_CTBL_ICPBYTES
Definition cache_snmp.h:264
@ MESH_CTBL_HTHITS
Definition cache_snmp.h:261
@ MESH_CTBL_ICPHITS
Definition cache_snmp.h:265
@ MESH_CTBL_ADDR
Definition cache_snmp.h:258
@ MESH_CTBL_ICPHITBYTES
Definition cache_snmp.h:266
@ MESH_CTBL_HTREQ
Definition cache_snmp.h:259
@ FQDN_PENDHIT
Definition cache_snmp.h:206
@ FQDN_NEGHIT
Definition cache_snmp.h:207
@ FQDN_GHBN
Definition cache_snmp.h:209
@ FQDN_HITS
Definition cache_snmp.h:205
@ FQDN_MISS
Definition cache_snmp.h:208
@ FQDN_ENT
Definition cache_snmp.h:203
@ FQDN_REQ
Definition cache_snmp.h:204
@ CONF_ST_MMAXSZ
Definition cache_snmp.h:89
@ CONF_ST_SWLOWM
Definition cache_snmp.h:92
@ CONF_ST_SWHIWM
Definition cache_snmp.h:91
@ CONF_ST_SWMAXSZ
Definition cache_snmp.h:90
#define TIME_INDEX
Definition cache_snmp.h:37
@ PERF_MEDIAN_HTTP_MISS
Definition cache_snmp.h:163
@ PERF_MEDIAN_TIME
Definition cache_snmp.h:161
@ PERF_MEDIAN_ICP_QUERY
Definition cache_snmp.h:166
@ PERF_MEDIAN_ICP_REPLY
Definition cache_snmp.h:167
@ PERF_MEDIAN_RHR
Definition cache_snmp.h:169
@ PERF_MEDIAN_HTTP_HIT
Definition cache_snmp.h:165
@ PERF_MEDIAN_BHR
Definition cache_snmp.h:170
@ PERF_MEDIAN_HTTP_ALL
Definition cache_snmp.h:162
@ PERF_MEDIAN_HTTP_NH
Definition cache_snmp.h:171
@ PERF_MEDIAN_HTTP_NM
Definition cache_snmp.h:164
@ PERF_MEDIAN_DNS
Definition cache_snmp.h:168
@ DNS_REP
Definition cache_snmp.h:217
@ DNS_SERVERS
Definition cache_snmp.h:218
@ DNS_REQ
Definition cache_snmp.h:216
@ PERF_PROTO
Definition cache_snmp.h:106
@ PERF_SYS
Definition cache_snmp.h:105
@ SYSSTOR
Definition cache_snmp.h:59
@ SYS_UPTIME
Definition cache_snmp.h:60
@ SYSVMSIZ
Definition cache_snmp.h:58
Acl::Answer const & fastCheck()
Definition Checklist.cc:298
bool allowed() const
Definition Acl.h:82
int match(ACLChecklist *) override
Matches the actual data in checklist against this Acl::Node.
static void Start(const Pointer &job)
Definition AsyncJob.cc:37
auto size() const
the number of currently stored (i.e. added and not removed) cache_peers
Definition CachePeers.h:33
Ip::Address local
Definition Connection.h:149
bool setIPv4()
Definition Address.cc:244
bool isIPv4() const
Definition Address.cc:178
bool isNoAddr() const
Definition Address.cc:304
bool isAnyAddr() const
Definition Address.cc:190
bool isIPv6() const
Definition Address.cc:184
bool getInAddr(struct in_addr &) const
Definition Address.cc:1032
void setAnyAddr()
NOTE: Does NOT clear the Port stored. Only the Address and Type.
Definition Address.cc:197
unsigned short port() const
Definition Address.cc:790
StartListening() result.
Comm::ConnectionPointer conn
opened listening socket
void append(const char *c, int sz) override
Definition MemBuf.cc:209
char * content()
start of the added data
Definition MemBuf.h:41
void reset()
Definition MemBuf.cc:129
struct snmp_pdu * PDU
Definition SnmpRequest.h:30
u_char * community
Definition SnmpRequest.h:31
u_char * buf
Definition SnmpRequest.h:21
Ip::Address from
Definition SnmpRequest.h:28
struct snmp_session session
Definition SnmpRequest.h:33
u_char * outbuf
Definition SnmpRequest.h:22
void startShutdown() override
Definition snmp_core.cc:346
void syncConfig() override
Definition snmp_core.cc:345
void startReconfigure() override
Definition snmp_core.cc:344
void finalizeConfig() override
Definition snmp_core.cc:342
void useConfig() override
Definition snmp_core.cc:343
snmp_session wrapper add pack/unpack feature
Definition Session.h:23
Ip::Address snmp_outgoing
struct SquidConfig::@85 Addrs
Ip::Address snmp_incoming
struct SquidConfig::@91 accessList
struct SquidConfig::@78 Port
unsigned short snmp
Ip::Address * client_entry(Ip::Address *current)
Definition client_db.cc:421
variable_list * snmp_meshCtblFn(variable_list *Var, snint *ErrP)
Definition client_db.cc:442
int comm_udp_sendto(int fd, const Ip::Address &to_addr, const void *buf, int len)
Definition comm.cc:911
int comm_udp_recvfrom(int fd, void *buf, size_t len, int flags, Ip::Address &from)
Definition comm.cc:128
#define MYNAME
Definition Stream.h:219
#define DBG_IMPORTANT
Definition Stream.h:38
#define debugs(SECTION, LEVEL, CONTENT)
Definition Stream.h:192
#define DBG_CRITICAL
Definition Stream.h:37
#define COMM_SELECT_READ
Definition defines.h:24
variable_list * snmp_netDnsFn(variable_list *Var, snint *ErrP)
void fatal(const char *message)
Definition fatal.cc:28
void fatalf(const char *fmt,...)
Definition fatal.cc:68
variable_list * snmp_netFqdnFn(variable_list *Var, snint *ErrP)
Definition fqdncache.cc:716
variable_list * snmp_netIpFn(variable_list *Var, snint *ErrP)
Definition ipcache.cc:1173
#define IPV6_SPECIAL_SPLITSTACK
Definition tools.h:22
bool IsConnOpen(const Comm::ConnectionPointer &conn)
Definition Connection.cc:27
void SetSelect(int, unsigned int, PF *, void *, time_t)
Mark an FD to be watched for its IO status.
@ fdnInSnmpSocket
Definition FdNotes.h:22
@ fdnOutSnmpSocket
Definition FdNotes.h:22
void StartListening(int sock_type, int proto, const Comm::ConnectionPointer &listenConn, FdNoteId, StartListeningCallback &)
#define xfree
#define xmalloc
variable_list * snmp_prfSysFn(variable_list *Var, snint *ErrP)
variable_list * snmp_sysFn(variable_list *Var, snint *ErrP)
Definition snmp_agent.cc:44
variable_list * snmp_prfProtoFn(variable_list *Var, snint *ErrP)
variable_list * snmp_confFn(variable_list *Var, snint *ErrP)
Definition snmp_agent.cc:83
variable_list * snmp_meshPtblFn(variable_list *Var, snint *ErrP)
u_char * snmp_parse(struct snmp_session *, struct snmp_pdu *, u_char *, int)
Definition snmp_api.c:129
int snmp_build(struct snmp_session *, struct snmp_pdu *, u_char *, int *)
Definition snmp_api.c:106
int snmp_coexist_V2toV1(struct snmp_pdu *)
Comm::ConnectionPointer snmpOutgoingConn
Definition snmp_core.cc:40
bool snmpCreateOidFromStr(const char *str, oid **name, int *nl)
Definition snmp_core.cc:932
static void snmpAddNodeChild(mib_tree_entry *entry, mib_tree_entry *child)
Definition snmp_core.cc:880
static oid_ParseFn * snmpTreeGet(oid *Current, snint CurrentLen)
Definition snmp_core.cc:553
static oid * static_Inst(oid *name, snint *len, mib_tree_entry *current, oid_ParseFn **Fn)
Definition snmp_core.cc:694
static void snmpOpenPorts()
Definition snmp_core.cc:256
const char * snmpDebugOid(oid *Name, snint Len, MemBuf &outbuf)
static void snmpPortOpened(Ipc::StartListeningAnswer &)
Definition snmp_core.cc:303
static mib_tree_entry * snmpTreeSiblingEntry(oid entry, snint len, mib_tree_entry *current)
Definition snmp_core.cc:850
static void snmpConstructReponse(SnmpRequest *rq)
Definition snmp_core.cc:439
mib_tree_entry * mib_tree_head
Definition snmp_core.cc:36
Comm::ConnectionPointer snmpIncomingConn
Definition snmp_core.cc:39
static oid * peer_Inst(oid *name, snint *len, mib_tree_entry *current, oid_ParseFn **Fn)
Definition snmp_core.cc:737
static mib_tree_entry * snmpTreeEntry(oid entry, snint len, mib_tree_entry *current)
Definition snmp_core.cc:863
static oid * client_Inst(oid *name, snint *len, mib_tree_entry *current, oid_ParseFn **Fn)
Definition snmp_core.cc:780
struct snmp_pdu * snmpAgentResponse(struct snmp_pdu *PDU)
Definition snmp_core.cc:471
static mib_tree_entry * snmpAddNode(oid *name, int len, oid_ParseFn *parsefunction, instance_Fn *instancefunction, AggrType aggrType, int children,...)
Definition snmp_core.cc:993
static oid * snmpCreateOid(int length,...)
void addr2oid(Ip::Address &addr, oid *Dest)
static void snmpDecodePacket(SnmpRequest *rq)
Definition snmp_core.cc:391
mib_tree_entry * mib_tree_last
Definition snmp_core.cc:37
static mib_tree_entry * snmpAddNodeStr(const char *base_str, int o, oid_ParseFn *parsefunction, instance_Fn *instancefunction, AggrType aggrType=atNone)
Definition snmp_core.cc:961
void snmpSnmplibDebug(int lvl, char *buf)
AggrType snmpAggrType(oid *Current, snint CurrentLen)
Definition snmp_core.cc:584
static oid_ParseFn * snmpTreeNext(oid *Current, snint CurrentLen, oid **Next, snint *NextLen)
Definition snmp_core.cc:607
mib_tree_entry * snmpLookupNodeStr(mib_tree_entry *entry, const char *str)
Definition snmp_core.cc:890
static void snmpInit()
Definition snmp_core.cc:65
SQUIDCEXTERN void(* snmplib_debug_hook)(int, char *)
Definition snmp_core.cc:47
static void snmpClosePorts()
Definition snmp_core.cc:321
static oid * time_Inst(oid *name, snint *len, mib_tree_entry *current, oid_ParseFn **Fn)
Definition snmp_core.cc:708
void oid2addr(oid *id, Ip::Address &addr, u_int size)
PF snmpHandleUdp
oid *() instance_Fn(oid *name, snint *len, mib_tree_entry *current, oid_ParseFn **Fn)
Definition snmp_core.h:28
#define SNMP_REQUEST_SIZE
Definition snmp_core.h:23
variable_list *() oid_ParseFn(variable_list *, snint *)
Definition snmp_core.h:26
AggrType
Definition snmp_core.h:29
@ atSum
Definition snmp_core.h:29
@ atMin
Definition snmp_core.h:29
@ atNone
Definition snmp_core.h:29
@ atMax
Definition snmp_core.h:29
@ atAverage
Definition snmp_core.h:29
#define SNMP_ERR_NOERROR
Definition snmp_error.h:42
#define SNMP_ERR_NOSUCHNAME
Definition snmp_error.h:44
#define SNMP_VERSION_1
Definition snmp_msg.h:40
#define SNMP_PDU_RESPONSE
Definition snmp_pdu.h:94
#define SNMP_PDU_GET
Definition snmp_pdu.h:92
void snmp_free_pdu(struct snmp_pdu *)
Definition snmp_pdu.c:284
#define SNMP_PDU_GETNEXT
Definition snmp_pdu.h:93
struct snmp_pdu * snmp_pdu_create(int)
Definition snmp_pdu.c:113
#define INETADDRESSTYPE_IPV4
Definition snmp_vars.h:93
struct variable_list * snmp_var_new(oid *, int)
Definition snmp_vars.c:109
void snmp_var_free(struct variable_list *)
Definition snmp_vars.c:227
#define INETADDRESSTYPE_IPV6
Definition snmp_vars.h:94
#define SQUIDCEXTERN
Definition squid.h:21
Definition snmp_core.h:31
oid_ParseFn * parsefunction
Definition snmp_core.h:34
instance_Fn * instancefunction
Definition snmp_core.h:35
oid * name
Definition snmp_core.h:32
int len
Definition snmp_core.h:33
struct _mib_tree_entry ** leaves
Definition snmp_core.h:38
AggrType aggrType
Definition snmp_core.h:41
int children
Definition snmp_core.h:36
struct _mib_tree_entry * parent
Definition snmp_core.h:40
int errindex
Definition snmp_pdu.h:56
int reqid
Definition snmp_pdu.h:54
int command
Definition snmp_pdu.h:51
struct variable_list * variables
Definition snmp_pdu.h:62
int errstat
Definition snmp_pdu.h:55
u_char * community
struct variable_list * next_variable
Definition snmp_vars.h:45
int unsigned int
Definition stub_fd.cc:19
bool IamWorkerProcess()
whether the current process handles HTTP transactions and such
Definition stub_tools.cc:47
bool UsingSmp()
Whether there should be more than one worker process running.
Definition tools.cc:697
void * xrealloc(void *s, size_t sz)
Definition xalloc.cc:126
void * xcalloc(size_t n, size_t sz)
Definition xalloc.cc:71
#define safe_free(x)
Definition xalloc.h:73
const char * xstrerr(int error)
Definition xstrerror.cc:83