snmp_core.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2019 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/CbcPointer.h"
14 #include "CachePeer.h"
15 #include "client_db.h"
16 #include "comm.h"
17 #include "comm/Connection.h"
18 #include "comm/Loops.h"
19 #include "comm/UdpOpenDialer.h"
20 #include "fatal.h"
21 #include "ip/Address.h"
22 #include "ip/tools.h"
23 #include "snmp/Forwarder.h"
24 #include "snmp_agent.h"
25 #include "snmp_core.h"
26 #include "SnmpRequest.h"
27 #include "SquidConfig.h"
28 #include "tools.h"
29 
30 static void snmpPortOpened(const Comm::ConnectionPointer &conn, int errNo);
31 
34 
37 
38 static mib_tree_entry * snmpAddNodeStr(const char *base_str, int o, oid_ParseFn * parsefunction, instance_Fn * instancefunction, AggrType aggrType = atNone);
39 static mib_tree_entry *snmpAddNode(oid * name, int len, oid_ParseFn * parsefunction, instance_Fn * instancefunction, AggrType aggrType, int children,...);
40 static oid *snmpCreateOid(int length,...);
41 mib_tree_entry * snmpLookupNodeStr(mib_tree_entry *entry, const char *str);
42 bool snmpCreateOidFromStr(const char *str, oid **name, int *nl);
44 static oid *static_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn);
45 static oid *time_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn);
46 static oid *peer_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn);
47 static oid *client_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn);
48 static void snmpDecodePacket(SnmpRequest * rq);
49 static void snmpConstructReponse(SnmpRequest * rq);
50 
51 static oid_ParseFn *snmpTreeNext(oid * Current, snint CurrentLen, oid ** Next, snint * NextLen);
52 static oid_ParseFn *snmpTreeGet(oid * Current, snint CurrentLen);
53 static mib_tree_entry *snmpTreeEntry(oid entry, snint len, mib_tree_entry * current);
55 extern "C" void snmpSnmplibDebug(int lvl, char *buf);
56 
57 /*
58  * The functions used during startup:
59  * snmpInit
60  * snmpConnectionOpen
61  * snmpConnectionClose
62  */
63 
64 /*
65  * Turns the MIB into a Tree structure. Called during the startup process.
66  */
67 void
68 snmpInit(void)
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, NULL, NULL, atNone, 0);
80 
81  assert(mib_tree_head);
82  debugs(49, 5, "snmpInit: root is " << mib_tree_head);
83  snmpAddNodeStr("1", 3, NULL, NULL);
84 
85  snmpAddNodeStr("1.3", 6, NULL, NULL);
86 
87  snmpAddNodeStr("1.3.6", 1, NULL, NULL);
88  snmpAddNodeStr("1.3.6.1", 4, NULL, NULL);
89  snmpAddNodeStr("1.3.6.1.4", 1, NULL, NULL);
90  snmpAddNodeStr("1.3.6.1.4.1", 3495, NULL, NULL);
91  mib_tree_entry *m2 = snmpAddNodeStr("1.3.6.1.4.1.3495", 1, NULL, NULL);
92 
93  mib_tree_entry *n = snmpLookupNodeStr(NULL, "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, NULL, NULL);
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, NULL, NULL);
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, NULL, NULL);
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, NULL, NULL); /* 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, NULL, NULL);
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);
129  snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.1", PERF_SYS_NUMOBJCNT, 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);
139  snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.1", PERF_SYS_CURUNLREQ, snmp_prfSysFn, static_Inst, atSum);
142  snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.1", PERF_SYS_CURUSED_FD, snmp_prfSysFn, static_Inst, atSum);
143  snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.1", PERF_SYS_CURMAX_FD, snmp_prfSysFn, static_Inst, atMax);
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, NULL, NULL);
147  snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2", PERF_PROTOSTAT_AGGR, NULL, NULL);
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, NULL, NULL);
167 
168  /* cacheMedianSvcEntry */
169  snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.2", 1, NULL, NULL);
170  snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.2.1", PERF_MEDIAN_TIME, snmp_prfProtoFn, time_Inst, atAverage);
171  snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.2.1", PERF_MEDIAN_HTTP_ALL, snmp_prfProtoFn, time_Inst, atAverage);
172  snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.2.1", PERF_MEDIAN_HTTP_MISS, 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);
174  snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.2.1", PERF_MEDIAN_HTTP_HIT, snmp_prfProtoFn, time_Inst, atAverage);
175  snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.2.1", PERF_MEDIAN_ICP_QUERY, snmp_prfProtoFn, time_Inst, atAverage);
176  snmpAddNodeStr("1.3.6.1.4.1.3495.1.3.2.2.1", PERF_MEDIAN_ICP_REPLY, 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, NULL, NULL);
184 
185  snmpAddNodeStr("1.3.6.1.4.1.3495.1.4", NET_IP_CACHE, NULL, NULL);
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, NULL, NULL);
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, NULL, NULL);
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, NULL, NULL);
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, NULL, NULL);
214 
215  /* CachePeerTableEntry (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, NULL, NULL);
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, NULL, NULL);
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, NULL, NULL);
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);
250  mib_tree_last = snmpAddNodeStr("1.3.6.1.4.1.3495.1.5.2.2", MESH_CTBL_ICPHITBYTES, snmp_meshCtblFn, client_Inst);
251 
252  debugs(49, 9, "snmpInit: Completed SNMP mib tree structure");
253 }
254 
255 void
257 {
258  debugs(49, 5, "snmpConnectionOpen: Called");
259 
260  if (Config.Port.snmp <= 0)
261  return;
262 
263  snmpIncomingConn = new Comm::Connection;
264  snmpIncomingConn->local = Config.Addrs.snmp_incoming;
265  snmpIncomingConn->local.port(Config.Port.snmp);
266 
267  if (!Ip::EnableIpv6 && !snmpIncomingConn->local.setIPv4()) {
268  debugs(49, DBG_CRITICAL, "ERROR: IPv6 is disabled. " << snmpIncomingConn->local << " is not an IPv4 address.");
269  fatal("SNMP port cannot be opened.");
270  }
271  /* split-stack for now requires IPv4-only SNMP */
272  if (Ip::EnableIpv6&IPV6_SPECIAL_SPLITSTACK && snmpIncomingConn->local.isAnyAddr()) {
273  snmpIncomingConn->local.setIPv4();
274  }
275 
276  AsyncCall::Pointer call = asyncCall(49, 2, "snmpIncomingConnectionOpened",
278  Ipc::StartListening(SOCK_DGRAM, IPPROTO_UDP, snmpIncomingConn, Ipc::fdnInSnmpSocket, call);
279 
281  snmpOutgoingConn = new Comm::Connection;
282  snmpOutgoingConn->local = Config.Addrs.snmp_outgoing;
283  snmpOutgoingConn->local.port(Config.Port.snmp);
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()) {
291  snmpOutgoingConn->local.setIPv4();
292  }
293  AsyncCall::Pointer c = asyncCall(49, 2, "snmpOutgoingConnectionOpened",
295  Ipc::StartListening(SOCK_DGRAM, IPPROTO_UDP, snmpOutgoingConn, Ipc::fdnOutSnmpSocket, c);
296  } else {
297  snmpOutgoingConn = snmpIncomingConn;
298  debugs(1, DBG_IMPORTANT, "Sending SNMP messages from " << snmpOutgoingConn->local);
299  }
300 }
301 
302 static void
304 {
305  if (!Comm::IsConnOpen(conn))
306  fatalf("Cannot open SNMP %s Port",(conn->fd == snmpIncomingConn->fd?"receiving":"sending"));
307 
309 
310  if (conn->fd == snmpIncomingConn->fd)
311  debugs(1, DBG_IMPORTANT, "Accepting SNMP messages on " << snmpIncomingConn->local);
312  else if (conn->fd == snmpOutgoingConn->fd)
313  debugs(1, DBG_IMPORTANT, "Sending SNMP messages from " << snmpOutgoingConn->local);
314  else
315  fatalf("Lost SNMP port (%d) on FD %d", (int)conn->local.port(), conn->fd);
316 }
317 
318 void
320 {
321  if (Comm::IsConnOpen(snmpIncomingConn)) {
322  debugs(49, DBG_IMPORTANT, "Closing SNMP receiving port " << snmpIncomingConn->local);
323  snmpIncomingConn->close();
324  }
325  snmpIncomingConn = NULL;
326 
327  if (Comm::IsConnOpen(snmpOutgoingConn) && snmpIncomingConn != snmpOutgoingConn) {
328  // Perform OUT port closure so as not to step on IN port when sharing a conn.
329  debugs(49, DBG_IMPORTANT, "Closing SNMP sending port " << snmpOutgoingConn->local);
330  snmpOutgoingConn->close();
331  }
332  snmpOutgoingConn = NULL;
333 }
334 
335 /*
336  * Functions for handling the requests.
337  */
338 
339 /*
340  * Accept the UDP packet
341  */
342 void
343 snmpHandleUdp(int sock, void *)
344 {
345  static char buf[SNMP_REQUEST_SIZE];
346  Ip::Address from;
347  SnmpRequest *snmp_rq;
348  int len;
349 
350  debugs(49, 5, "snmpHandleUdp: Called.");
351 
353 
354  memset(buf, '\0', sizeof(buf));
355 
356  len = comm_udp_recvfrom(sock, buf, sizeof(buf)-1, 0, from);
357 
358  if (len > 0) {
359  debugs(49, 3, "snmpHandleUdp: FD " << sock << ": received " << len << " bytes from " << from << ".");
360 
361  snmp_rq = (SnmpRequest *)xcalloc(1, sizeof(SnmpRequest));
362  snmp_rq->buf = (u_char *) buf;
363  snmp_rq->len = len;
364  snmp_rq->sock = sock;
365  snmp_rq->outbuf = (unsigned char *)xmalloc(snmp_rq->outlen = SNMP_REQUEST_SIZE);
366  snmp_rq->from = from;
367  snmpDecodePacket(snmp_rq);
368  xfree(snmp_rq->outbuf);
369  xfree(snmp_rq);
370  } else {
371  int xerrno = errno;
372  debugs(49, DBG_IMPORTANT, "snmpHandleUdp: FD " << sock << " recvfrom: " << xstrerr(xerrno));
373  }
374 }
375 
376 /*
377  * Turn SNMP packet into a PDU, check available ACL's
378  */
379 static void
381 {
382  struct snmp_pdu *PDU;
383  u_char *Community;
384  u_char *buf = rq->buf;
385  int len = rq->len;
386 
387  if (!Config.accessList.snmp) {
388  debugs(49, DBG_IMPORTANT, "WARNING: snmp_access not configured. agent query DENIED from : " << rq->from);
389  return;
390  }
391 
392  debugs(49, 5, HERE << "Called.");
393  PDU = snmp_pdu_create(0);
394  /* Allways answer on SNMPv1 */
396  Community = snmp_parse(&rq->session, PDU, buf, len);
397 
398  /* Check if we have explicit permission to access SNMP data.
399  * default (set above) is to deny all */
400  if (Community) {
402  checklist.src_addr = rq->from;
403  checklist.snmp_community = (char *) Community;
404 
405  if (checklist.fastCheck().allowed() && (snmp_coexist_V2toV1(PDU))) {
406  rq->community = Community;
407  rq->PDU = PDU;
408  debugs(49, 5, "snmpAgentParse: reqid=[" << PDU->reqid << "]");
410  } else {
411  debugs(49, DBG_IMPORTANT, "WARNING: SNMP agent query DENIED from : " << rq->from);
412  snmp_free_pdu(PDU);
413  }
414  xfree(Community);
415 
416  } else {
417  debugs(49, DBG_IMPORTANT, "WARNING: Failed SNMP agent query from : " << rq->from);
418  snmp_free_pdu(PDU);
419  }
420 }
421 
422 /*
423  * Packet OK, ACL Check OK, Create reponse.
424  */
425 static void
427 {
428 
429  struct snmp_pdu *RespPDU;
430 
431  debugs(49, 5, "snmpConstructReponse: Called.");
432 
433  if (UsingSmp() && IamWorkerProcess()) {
434  AsyncJob::Start(new Snmp::Forwarder(static_cast<Snmp::Pdu&>(*rq->PDU),
435  static_cast<Snmp::Session&>(rq->session), rq->sock, rq->from));
436  snmp_free_pdu(rq->PDU);
437  return;
438  }
439 
440  RespPDU = snmpAgentResponse(rq->PDU);
441  snmp_free_pdu(rq->PDU);
442 
443  if (RespPDU != NULL) {
444  snmp_build(&rq->session, RespPDU, rq->outbuf, &rq->outlen);
445  comm_udp_sendto(rq->sock, rq->from, rq->outbuf, rq->outlen);
446  snmp_free_pdu(RespPDU);
447  }
448 }
449 
450 /*
451  * Decide how to respond to the request, construct a response and
452  * return the response to the requester.
453  */
454 
455 struct snmp_pdu *
457 
458  struct snmp_pdu *Answer = NULL;
459 
460  debugs(49, 5, "snmpAgentResponse: Called.");
461 
462  if ((Answer = snmp_pdu_create(SNMP_PDU_RESPONSE))) {
463  Answer->reqid = PDU->reqid;
464  Answer->errindex = 0;
465 
466  if (PDU->command == SNMP_PDU_GET || PDU->command == SNMP_PDU_GETNEXT) {
467  /* Indirect way */
468  int get_next = (PDU->command == SNMP_PDU_GETNEXT);
469  variable_list *VarPtr_;
470  variable_list **RespVars = &(Answer->variables);
471  oid_ParseFn *ParseFn;
472  int index = 0;
473  /* Loop through all variables */
474 
475  for (VarPtr_ = PDU->variables; VarPtr_; VarPtr_ = VarPtr_->next_variable) {
476  variable_list *VarPtr = VarPtr_;
477  variable_list *VarNew = NULL;
478  oid *NextOidName = NULL;
479  snint NextOidNameLen = 0;
480 
481  ++index;
482 
483  if (get_next)
484  ParseFn = snmpTreeNext(VarPtr->name, VarPtr->name_length, &NextOidName, &NextOidNameLen);
485  else
486  ParseFn = snmpTreeGet(VarPtr->name, VarPtr->name_length);
487 
488  if (ParseFn == NULL) {
489  Answer->errstat = SNMP_ERR_NOSUCHNAME;
490  debugs(49, 5, "snmpAgentResponse: No such oid. ");
491  } else {
492  if (get_next) {
493  VarPtr = snmp_var_new(NextOidName, NextOidNameLen);
494  xfree(NextOidName);
495  }
496 
497  int * errstatTmp = &(Answer->errstat);
498 
499  VarNew = (*ParseFn) (VarPtr, (snint *) errstatTmp);
500 
501  if (get_next)
502  snmp_var_free(VarPtr);
503  }
504 
505  if ((Answer->errstat != SNMP_ERR_NOERROR) || (VarNew == NULL)) {
506  Answer->errindex = index;
507  debugs(49, 5, "snmpAgentResponse: error.");
508 
509  if (VarNew)
510  snmp_var_free(VarNew);
511 
512  while ((VarPtr = Answer->variables) != NULL) {
513  Answer->variables = VarPtr->next_variable;
514  snmp_var_free(VarPtr);
515  }
516 
517  /* Steal the original PDU list of variables for the error response */
518  Answer->variables = PDU->variables;
519 
520  PDU->variables = NULL;
521 
522  return (Answer);
523  }
524 
525  /* No error. Insert this var at the end, and move on to the next.
526  */
527  *RespVars = VarNew;
528 
529  RespVars = &(VarNew->next_variable);
530  }
531  }
532  }
533 
534  return (Answer);
535 }
536 
537 static oid_ParseFn *
538 snmpTreeGet(oid * Current, snint CurrentLen)
539 {
540  oid_ParseFn *Fn = NULL;
541  mib_tree_entry *mibTreeEntry = NULL;
542  int count = 0;
543 
544  debugs(49, 5, "snmpTreeGet: Called");
545 
546  MemBuf tmp;
547  debugs(49, 6, "snmpTreeGet: Current : " << snmpDebugOid(Current, CurrentLen, tmp) );
548 
549  mibTreeEntry = mib_tree_head;
550 
551  if (Current[count] == mibTreeEntry->name[count]) {
552  ++count;
553 
554  while ((mibTreeEntry) && (count < CurrentLen) && (!mibTreeEntry->parsefunction)) {
555  mibTreeEntry = snmpTreeEntry(Current[count], count, mibTreeEntry);
556  ++count;
557  }
558  }
559 
560  if (mibTreeEntry && mibTreeEntry->parsefunction)
561  Fn = mibTreeEntry->parsefunction;
562 
563  debugs(49, 5, "snmpTreeGet: return");
564 
565  return (Fn);
566 }
567 
568 AggrType
569 snmpAggrType(oid* Current, snint CurrentLen)
570 {
571  debugs(49, 5, HERE);
572 
573  mib_tree_entry* mibTreeEntry = mib_tree_head;
574  AggrType type = atNone;
575  int count = 0;
576 
577  if (Current[count] == mibTreeEntry->name[count]) {
578  ++count;
579 
580  while (mibTreeEntry != NULL && count < CurrentLen) {
581  mibTreeEntry = snmpTreeEntry(Current[count], count, mibTreeEntry);
582  if (mibTreeEntry != NULL)
583  type = mibTreeEntry->aggrType;
584  ++count;
585  }
586  }
587 
588  return type;
589 }
590 
591 static oid_ParseFn *
592 snmpTreeNext(oid * Current, snint CurrentLen, oid ** Next, snint * NextLen)
593 {
594  oid_ParseFn *Fn = NULL;
595  int count = 0;
596 
597  debugs(49, 5, "snmpTreeNext: Called");
598 
599  MemBuf tmp;
600  debugs(49, 6, "snmpTreeNext: Current : " << snmpDebugOid(Current, CurrentLen, tmp));
601 
602  mib_tree_entry *mibTreeEntry = mib_tree_head;
603 
604  if (mibTreeEntry && Current[count] == mibTreeEntry->name[count]) {
605  ++count;
606 
607  while ((mibTreeEntry) && (count < CurrentLen) && (!mibTreeEntry->parsefunction)) {
608  mib_tree_entry *nextmibTreeEntry = snmpTreeEntry(Current[count], count, mibTreeEntry);
609 
610  if (!nextmibTreeEntry)
611  break;
612  else
613  mibTreeEntry = nextmibTreeEntry;
614 
615  ++count;
616  }
617  debugs(49, 5, "snmpTreeNext: Recursed down to requested object");
618  } else {
619  return NULL;
620  }
621 
622  if (mibTreeEntry == mib_tree_last)
623  return (Fn);
624 
625  if ((mibTreeEntry) && (mibTreeEntry->parsefunction)) {
626  *NextLen = CurrentLen;
627  *Next = (*mibTreeEntry->instancefunction) (Current, NextLen, mibTreeEntry, &Fn);
628  if (*Next) {
629  debugs(49, 6, "snmpTreeNext: Next : " << snmpDebugOid(*Next, *NextLen, tmp));
630  return (Fn);
631  }
632  }
633 
634  if ((mibTreeEntry) && (mibTreeEntry->parsefunction)) {
635  --count;
636  mib_tree_entry *nextoid = snmpTreeSiblingEntry(Current[count], count, mibTreeEntry->parent);
637  if (nextoid) {
638  debugs(49, 5, "snmpTreeNext: Next OID found for sibling" << nextoid );
639  mibTreeEntry = nextoid;
640  ++count;
641  } else {
642  debugs(49, 5, "snmpTreeNext: Attempting to recurse up for next object");
643 
644  while (!nextoid) {
645  --count;
646 
647  if (mibTreeEntry->parent->parent) {
648  nextoid = mibTreeEntry->parent;
649  mibTreeEntry = snmpTreeEntry(Current[count] + 1, count, nextoid->parent);
650 
651  if (!mibTreeEntry) {
652  mibTreeEntry = nextoid;
653  nextoid = NULL;
654  }
655  } else {
656  nextoid = mibTreeEntry;
657  mibTreeEntry = NULL;
658  }
659  }
660  }
661  }
662  while ((mibTreeEntry) && (!mibTreeEntry->parsefunction)) {
663  mibTreeEntry = mibTreeEntry->leaves[0];
664  }
665 
666  if (mibTreeEntry) {
667  *NextLen = mibTreeEntry->len;
668  *Next = (*mibTreeEntry->instancefunction) (mibTreeEntry->name, NextLen, mibTreeEntry, &Fn);
669  }
670 
671  if (*Next) {
672  debugs(49, 6, "snmpTreeNext: Next : " << snmpDebugOid(*Next, *NextLen, tmp));
673  return (Fn);
674  } else
675  return NULL;
676 }
677 
678 static oid *
679 static_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn)
680 {
681  oid *instance = NULL;
682  if (*len <= current->len) {
683  instance = (oid *)xmalloc(sizeof(*name) * (*len + 1));
684  memcpy(instance, name, sizeof(*name) * (*len));
685  instance[*len] = 0;
686  *len += 1;
687  }
688  *Fn = current->parsefunction;
689  return (instance);
690 }
691 
692 static oid *
693 time_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn)
694 {
695  oid *instance = NULL;
696  int identifier = 0, loop = 0;
697  int index[TIME_INDEX_LEN] = {TIME_INDEX};
698 
699  if (*len <= current->len) {
700  instance = (oid *)xmalloc(sizeof(*name) * (*len + 1));
701  memcpy(instance, name, sizeof(*name) * (*len));
702  instance[*len] = *index;
703  *len += 1;
704  } else {
705  identifier = name[*len - 1];
706 
707  while ((loop < TIME_INDEX_LEN) && (identifier != index[loop]))
708  ++loop;
709 
710  if (loop < (TIME_INDEX_LEN - 1)) {
711  instance = (oid *)xmalloc(sizeof(*name) * (*len));
712  memcpy(instance, name, sizeof(*name) * (*len));
713  instance[*len - 1] = index[++loop];
714  }
715  }
716 
717  *Fn = current->parsefunction;
718  return (instance);
719 }
720 
721 static oid *
722 peer_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn)
723 {
724  oid *instance = NULL;
725  CachePeer *peers = Config.peers;
726 
727  if (peers == NULL) {
728  debugs(49, 6, "snmp peer_Inst: No Peers.");
729  current = current->parent->parent->parent->leaves[1];
730  while ((current) && (!current->parsefunction))
731  current = current->leaves[0];
732 
733  if (!current)
734  return (instance);
735 
736  instance = client_Inst(current->name, len, current, Fn);
737  } else if (*len <= current->len) {
738  debugs(49, 6, "snmp peer_Inst: *len <= current->len ???");
739  instance = (oid *)xmalloc(sizeof(*name) * ( *len + 1));
740  memcpy(instance, name, sizeof(*name) * (*len));
741  instance[*len] = 1 ;
742  *len += 1;
743  } else {
744  int no = name[current->len] ;
745  int i;
746  // Note: This works because the Config.peers keeps its index according to its position.
747  for ( i=0 ; peers && (i < no) ; peers = peers->next, ++i ) ;
748 
749  if (peers) {
750  debugs(49, 6, "snmp peer_Inst: Encode peer #" << i);
751  instance = (oid *)xmalloc(sizeof(*name) * (current->len + 1 ));
752  memcpy(instance, name, (sizeof(*name) * current->len ));
753  instance[current->len] = no + 1 ; // i.e. the next index on cache_peeer table.
754  } else {
755  debugs(49, 6, "snmp peer_Inst: We have " << i << " peers. Can't find #" << no);
756  return (instance);
757  }
758  }
759  *Fn = current->parsefunction;
760  return (instance);
761 }
762 
763 static oid *
764 client_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn)
765 {
766  oid *instance = NULL;
767  Ip::Address laddr;
768  Ip::Address *aux;
769  int size = 0;
770  int newshift = 0;
771 
772  if (*len <= current->len) {
773  aux = client_entry(NULL);
774  if (aux)
775  laddr = *aux;
776  else
777  laddr.setAnyAddr();
778 
779  if (laddr.isIPv4())
780  size = sizeof(in_addr);
781  else
782  size = sizeof(in6_addr);
783 
784  debugs(49, 6, HERE << "len" << *len << ", current-len" << current->len << ", addr=" << laddr << ", size=" << size);
785 
786  instance = (oid *)xmalloc(sizeof(*name) * (*len + size ));
787  memcpy(instance, name, (sizeof(*name) * (*len)));
788 
789  if ( !laddr.isAnyAddr() ) {
790  addr2oid(laddr, &instance[ *len]); // the addr
791  *len += size ;
792  }
793  } else {
794  int shift = *len - current->len ; // i.e 4 or 16
795  oid2addr(&name[*len - shift], laddr,shift);
796  aux = client_entry(&laddr);
797  if (aux)
798  laddr = *aux;
799  else
800  laddr.setAnyAddr();
801 
802  if (!laddr.isAnyAddr()) {
803  if (laddr.isIPv4())
804  newshift = sizeof(in_addr);
805  else
806  newshift = sizeof(in6_addr);
807 
808  debugs(49, 6, HERE << "len" << *len << ", current-len" << current->len << ", addr=" << laddr << ", newshift=" << newshift);
809 
810  instance = (oid *)xmalloc(sizeof(*name) * (current->len + newshift));
811  memcpy(instance, name, (sizeof(*name) * (current->len)));
812  addr2oid(laddr, &instance[current->len]); // the addr.
813  *len = current->len + newshift ;
814  }
815  }
816 
817  *Fn = current->parsefunction;
818  return (instance);
819 }
820 
821 /*
822  * Utility functions
823  */
824 
825 /*
826  * Tree utility functions.
827  */
828 
829 /*
830  * Returns a sibling object for the requested child object or NULL
831  * if it does not exit
832  */
833 static mib_tree_entry *
835 {
836  mib_tree_entry *next = NULL;
837  int count = 0;
838 
839  while ((!next) && (count < current->children)) {
840  if (current->leaves[count]->name[len] == entry) {
841  next = current->leaves[count];
842  }
843 
844  ++count;
845  }
846 
847  /* Exactly the sibling on right */
848  if (count < current->children) {
849  next = current->leaves[count];
850  } else {
851  next = NULL;
852  }
853 
854  return (next);
855 }
856 
857 /*
858  * Returns the requested child object or NULL if it does not exist
859  */
860 static mib_tree_entry *
862 {
863  mib_tree_entry *next = NULL;
864  int count = 0;
865 
866  while ((!next) && current && (count < current->children)) {
867  if (current->leaves[count]->name[len] == entry) {
868  next = current->leaves[count];
869  }
870 
871  ++count;
872  }
873 
874  return (next);
875 }
876 
877 void
879 {
880  debugs(49, 5, "snmpAddNodeChild: assigning " << child << " to parent " << entry);
881  entry->leaves = (mib_tree_entry **)xrealloc(entry->leaves, sizeof(mib_tree_entry *) * (entry->children + 1));
882  entry->leaves[entry->children] = child;
883  entry->leaves[entry->children]->parent = entry;
884  ++ entry->children;
885 }
886 
888 snmpLookupNodeStr(mib_tree_entry *root, const char *str)
889 {
890  oid *name;
891  int namelen;
892  mib_tree_entry *e;
893 
894  if (root)
895  e = root;
896  else
897  e = mib_tree_head;
898 
899  if (! snmpCreateOidFromStr(str, &name, &namelen))
900  return NULL;
901 
902  /* I wish there were some kind of sensible existing tree traversal
903  * routine to use. I'll worry about that later */
904  if (namelen <= 1) {
905  xfree(name);
906  return e; /* XXX it should only be this? */
907  }
908 
909  int i, r = 1;
910  while (r < namelen) {
911 
912  /* Find the child node which matches this */
913  for (i = 0; i < e->children && e->leaves[i]->name[r] != name[r]; ++i) ; // seek-loop
914 
915  /* Are we pointing to that node? */
916  if (i >= e->children)
917  break;
918  assert(e->leaves[i]->name[r] == name[r]);
919 
920  /* Skip to that node! */
921  e = e->leaves[i];
922  ++r;
923  }
924 
925  xfree(name);
926  return e;
927 }
928 
929 bool
930 snmpCreateOidFromStr(const char *str, oid **name, int *nl)
931 {
932  char const *delim = ".";
933 
934  *name = NULL;
935  *nl = 0;
936  const char *s = str;
937 
938  /* Parse the OID string into oid bits */
939  while (size_t len = strcspn(s, delim)) {
940  *name = (oid*)xrealloc(*name, sizeof(oid) * ((*nl) + 1));
941  (*name)[*nl] = atoi(s); // stops at the '.' delimiter
942  ++(*nl);
943  // exit with true when the last octet has been parsed
944  if (s[len] == '\0')
945  return true;
946  s += len+1;
947  }
948 
949  // if we aborted before the lst octet was found, return false.
950  safe_free(name);
951  return false;
952 }
953 
954 /*
955  * Create an entry. Return a pointer to the newly created node, or NULL
956  * on failure.
957  */
958 static mib_tree_entry *
959 snmpAddNodeStr(const char *base_str, int o, oid_ParseFn * parsefunction, instance_Fn * instancefunction, AggrType aggrType)
960 {
961  mib_tree_entry *m, *b;
962  oid *n;
963  int nl;
964  char s[1024];
965 
966  /* Find base node */
967  b = snmpLookupNodeStr(mib_tree_head, base_str);
968  if (! b)
969  return NULL;
970  debugs(49, 5, "snmpAddNodeStr: " << base_str << ": -> " << b);
971 
972  /* Create OID string for new entry */
973  snprintf(s, 1024, "%s.%d", base_str, o);
974  if (! snmpCreateOidFromStr(s, &n, &nl))
975  return NULL;
976 
977  /* Create a node */
978  m = snmpAddNode(n, nl, parsefunction, instancefunction, aggrType, 0);
979 
980  /* Link it into the existing tree */
981  snmpAddNodeChild(b, m);
982 
983  /* Return the node */
984  return m;
985 }
986 
987 /*
988  * Adds a node to the MIB tree structure and adds the appropriate children
989  */
990 static mib_tree_entry *
991 snmpAddNode(oid * name, int len, oid_ParseFn * parsefunction, instance_Fn * instancefunction, AggrType aggrType, int children,...)
992 {
993  va_list args;
994  int loop;
995  mib_tree_entry *entry = NULL;
996  va_start(args, children);
997 
998  MemBuf tmp;
999  debugs(49, 6, "snmpAddNode: Children : " << children << ", Oid : " << snmpDebugOid(name, len, tmp));
1000 
1001  va_start(args, children);
1002  entry = (mib_tree_entry *)xmalloc(sizeof(mib_tree_entry));
1003  entry->name = name;
1004  entry->len = len;
1005  entry->parsefunction = parsefunction;
1006  entry->instancefunction = instancefunction;
1007  entry->children = children;
1008  entry->leaves = NULL;
1009  entry->aggrType = aggrType;
1010 
1011  if (children > 0) {
1012  entry->leaves = (mib_tree_entry **)xmalloc(sizeof(mib_tree_entry *) * children);
1013 
1014  for (loop = 0; loop < children; ++loop) {
1015  entry->leaves[loop] = va_arg(args, mib_tree_entry *);
1016  entry->leaves[loop]->parent = entry;
1017  }
1018  }
1019 
1020  va_end(args);
1021  return (entry);
1022 }
1023 /* End of tree utility functions */
1024 
1025 /*
1026  * Returns the list of parameters in an oid
1027  */
1028 static oid *
1029 snmpCreateOid(int length,...)
1030 {
1031  va_list args;
1032  oid *new_oid;
1033  int loop;
1034  va_start(args, length);
1035 
1036  new_oid = (oid *)xmalloc(sizeof(oid) * length);
1037 
1038  if (length > 0) {
1039  for (loop = 0; loop < length; ++loop) {
1040  new_oid[loop] = va_arg(args, int);
1041  }
1042  }
1043 
1044  va_end(args);
1045  return (new_oid);
1046 }
1047 
1048 /*
1049  * Debug calls, prints out the OID for debugging purposes.
1050  */
1051 const char *
1052 snmpDebugOid(oid * Name, snint Len, MemBuf &outbuf)
1053 {
1054  char mbuf[16];
1055  int x;
1056  if (outbuf.isNull())
1057  outbuf.init(16, MAX_IPSTRLEN);
1058 
1059  for (x = 0; x < Len; ++x) {
1060  size_t bytes = snprintf(mbuf, sizeof(mbuf), ".%u", (unsigned int) Name[x]);
1061  outbuf.append(mbuf, bytes);
1062  }
1063  return outbuf.content();
1064 }
1065 
1066 void
1067 snmpSnmplibDebug(int lvl, char *buf)
1068 {
1069  debugs(49, lvl, buf);
1070 }
1071 
1072 /*
1073  IPv4 address: 10.10.0.9 ==>
1074  oid == 10.10.0.9
1075  IPv6 adress : 20:01:32:ef:a2:21:fb:32:00:00:00:00:00:00:00:00:OO:01 ==>
1076  oid == 32.1.50.239.162.33.251.20.50.0.0.0.0.0.0.0.0.0.1
1077 */
1078 void
1080 {
1081  u_int i ;
1082  u_char *cp = NULL;
1083  struct in_addr i4addr;
1084  struct in6_addr i6addr;
1086  u_int size = (code == INETADDRESSTYPE_IPV4) ? sizeof(struct in_addr):sizeof(struct in6_addr);
1087  // Dest[0] = code ;
1088  if ( code == INETADDRESSTYPE_IPV4 ) {
1089  addr.getInAddr(i4addr);
1090  cp = (u_char *) &(i4addr.s_addr);
1091  } else {
1092  addr.getInAddr(i6addr);
1093  cp = (u_char *) &i6addr;
1094  }
1095  for ( i=0 ; i < size ; ++i) {
1096  // OID's are in network order
1097  Dest[i] = *cp;
1098  ++cp;
1099  }
1100  MemBuf tmp;
1101  debugs(49, 7, "addr2oid: Dest : " << snmpDebugOid(Dest, size, tmp));
1102 }
1103 
1104 /*
1105  oid == 10.10.0.9 ==>
1106  IPv4 address: 10.10.0.9
1107  oid == 32.1.50.239.162.33.251.20.50.0.0.0.0.0.0.0.0.0.1 ==>
1108  IPv6 adress : 20:01:32:ef:a2:21:fb:32:00:00:00:00:00:00:00:00:OO:01
1109 */
1110 void
1112 {
1113  struct in_addr i4addr;
1114  struct in6_addr i6addr;
1115  u_int i;
1116  u_char *cp;
1117  if ( size == sizeof(struct in_addr) )
1118  cp = (u_char *) &(i4addr.s_addr);
1119  else
1120  cp = (u_char *) &(i6addr);
1121  MemBuf tmp;
1122  debugs(49, 7, "oid2addr: id : " << snmpDebugOid(id, size, tmp) );
1123  for (i=0 ; i<size; ++i) {
1124  cp[i] = id[i];
1125  }
1126  if ( size == sizeof(struct in_addr) )
1127  addr = i4addr;
1128  else
1129  addr = i6addr;
1130 }
1131 
1132 int
1134 {
1135  return data->match (checklist->snmp_community);
1136 }
1137 
bool setIPv4()
Definition: Address.cc:224
struct _mib_tree_entry ** leaves
Definition: snmp_core.h:36
int comm_udp_recvfrom(int fd, void *buf, size_t len, int flags, Ip::Address &from)
Definition: comm.cc:121
variable_list *() oid_ParseFn(variable_list *, snint *)
Definition: snmp_core.h:24
#define COMM_SELECT_READ
Definition: defines.h:36
void StartListening(int sock_type, int proto, const Comm::ConnectionPointer &listenConn, FdNoteId fdNote, AsyncCall::Pointer &callback)
unsigned short port() const
Definition: Address.cc:778
#define assert(EX)
Definition: assert.h:17
virtual bool match(M)=0
variable_list * snmp_meshCtblFn(variable_list *Var, snint *ErrP)
Definition: client_db.cc:451
static mib_tree_entry * snmpTreeSiblingEntry(oid entry, snint len, mib_tree_entry *current)
Definition: snmp_core.cc:834
oid *() instance_Fn(oid *name, snint *len, mib_tree_entry *current, oid_ParseFn **Fn)
Definition: snmp_core.h:26
virtual void append(const char *c, int sz)
Definition: MemBuf.cc:216
bool getInAddr(struct in_addr &) const
Definition: Address.cc:1030
#define SNMP_ERR_NOSUCHNAME
Definition: snmp_error.h:44
Ip::Address snmp_outgoing
Definition: SquidConfig.h:239
CachePeer * next
Definition: CachePeer.h:150
static void snmpConstructReponse(SnmpRequest *rq)
Definition: snmp_core.cc:426
struct variable_list * snmp_var_new(oid *, int)
Definition: snmp_vars.c:112
int type
Definition: errorpage.cc:152
Ip::Address snmp_incoming
Definition: SquidConfig.h:238
bool snmpCreateOidFromStr(const char *str, oid **name, int *nl)
Definition: snmp_core.cc:930
void addr2oid(Ip::Address &addr, oid *Dest)
Definition: snmp_core.cc:1079
void oid2addr(oid *id, Ip::Address &addr, u_int size)
Definition: snmp_core.cc:1111
AggrType aggrType
Definition: snmp_core.h:39
#define xcalloc
Definition: membanger.c:57
struct snmp_pdu * snmp_pdu_create(int)
Definition: snmp_pdu.c:113
bool isNoAddr() const
Definition: Address.cc:284
Ip::Address src_addr
CachePeer * peers
Definition: SquidConfig.h:247
#define SQUIDCEXTERN
Definition: squid.h:26
int i
Definition: membanger.c:49
static oid * snmpCreateOid(int length,...)
Definition: snmp_core.cc:1029
unsigned short snmp
Definition: SquidConfig.h:142
int name_length
Definition: snmp_vars.h:47
variable_list * snmp_netFqdnFn(variable_list *Var, snint *ErrP)
Definition: fqdncache.cc:729
#define safe_free(x)
Definition: xalloc.h:73
static oid_ParseFn * snmpTreeNext(oid *Current, snint CurrentLen, oid **Next, snint *NextLen)
Definition: snmp_core.cc:592
variable_list * snmp_netIpFn(variable_list *Var, snint *ErrP)
Definition: ipcache.cc:1171
variable_list * snmp_netDnsFn(variable_list *Var, snint *ErrP)
#define DBG_CRITICAL
Definition: Debug.h:45
static mib_tree_entry * snmpTreeEntry(oid entry, snint len, mib_tree_entry *current)
Definition: snmp_core.cc:861
int conn
the current server connection FD
Definition: Transport.cc:26
#define TIME_INDEX_LEN
Definition: cache_snmp.h:38
SQUIDCEXTERN void(* snmplib_debug_hook)(int, char *)
Definition: snmp_core.cc:43
char mbuf[256]
Definition: membanger.c:41
oid * name
Definition: snmp_core.h:30
u_char * buf
Definition: SnmpRequest.h:19
int comm_udp_sendto(int fd, const Ip::Address &to_addr, const void *buf, int len)
Definition: comm.cc:927
bool IamWorkerProcess()
whether the current process handles HTTP transactions and such
Definition: stub_tools.cc:49
#define SNMP_PDU_RESPONSE
Definition: snmp_pdu.h:94
void snmpAddNodeChild(mib_tree_entry *entry, mib_tree_entry *child)
Definition: snmp_core.cc:878
#define INETADDRESSTYPE_IPV4
Definition: snmp_vars.h:93
struct variable_list * variables
Definition: snmp_pdu.h:62
AsyncCall * asyncCall(int aDebugSection, int aDebugLevel, const char *aName, const Dialer &aDialer)
Definition: AsyncCall.h:156
void init(mb_size_t szInit, mb_size_t szMax)
Definition: MemBuf.cc:96
void fatalf(const char *fmt,...)
Definition: fatal.cc:68
bool isIPv4() const
Definition: Address.cc:158
static Pointer Start(AsyncJob *job)
starts a freshly created job (i.e., makes the job asynchronous)
Definition: AsyncJob.cc:23
const char * xstrerr(int error)
Definition: xstrerror.cc:83
bool IsConnOpen(const Comm::ConnectionPointer &conn)
Definition: Connection.cc:24
virtual int match(ACLData< MatchType > *&data, ACLFilledChecklist *checklist) override
Definition: snmp_core.cc:1133
void const char HLPCB void * data
Definition: stub_helper.cc:16
#define SNMP_PDU_GETNEXT
Definition: snmp_pdu.h:93
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:124
#define DBG_IMPORTANT
Definition: Debug.h:46
void SetSelect(int, unsigned int, PF *, void *, time_t)
Mark an FD to be watched for its IO status.
Definition: ModDevPoll.cc:225
int64_t snint
Definition: cache_snmp.h:14
struct SquidConfig::@99 Port
struct snmp_session session
Definition: SnmpRequest.h:32
void snmpSnmplibDebug(int lvl, char *buf)
Definition: snmp_core.cc:1067
oid_ParseFn * parsefunction
Definition: snmp_core.h:32
#define SNMP_VERSION_1
Definition: snmp_msg.h:40
void * xrealloc(void *s, size_t sz)
Definition: xalloc.cc:137
instance_Fn * instancefunction
Definition: snmp_core.h:33
struct variable_list * next_variable
Definition: snmp_vars.h:45
void * addr
Definition: membanger.c:46
variable_list * snmp_meshPtblFn(variable_list *Var, snint *ErrP)
Definition: snmp_agent.cc:186
void snmpInit(void)
Definition: snmp_core.cc:68
void fatal(const char *message)
Definition: fatal.cc:28
#define SNMP_ERR_NOERROR
Definition: snmp_error.h:42
struct SquidConfig::@113 accessList
void snmp_var_free(struct variable_list *)
Definition: snmp_vars.c:230
mib_tree_entry * mib_tree_last
Definition: snmp_core.cc:33
static void snmpDecodePacket(SnmpRequest *rq)
Definition: snmp_core.cc:380
bool isIPv6() const
Definition: Address.cc:164
int errindex
Definition: snmp_pdu.h:56
mib_tree_entry * mib_tree_head
Definition: snmp_core.cc:32
int isNull() const
Definition: MemBuf.cc:148
Definition: snmp_core.h:29
static oid * client_Inst(oid *name, snint *len, mib_tree_entry *current, oid_ParseFn **Fn)
Definition: snmp_core.cc:764
bool isAnyAddr() const
Definition: Address.cc:170
oid * name
Definition: snmp_vars.h:46
int snmp_build(struct snmp_session *, struct snmp_pdu *, u_char *, int *)
Definition: snmp_api.c:106
int unsigned int const char *desc STUB void int len
Definition: stub_fd.cc:20
char * content()
start of the added data
Definition: MemBuf.h:41
bool UsingSmp()
Whether there should be more than one worker process running.
Definition: tools.cc:658
unsigned char code
Definition: html_quote.c:20
void const char * buf
Definition: stub_helper.cc:16
std::ostream & HERE(std::ostream &s)
Definition: Debug.h:153
u_int oid
Definition: asn1.h:42
void snmpHandleUdp(int sock, void *)
Definition: snmp_core.cc:343
static char identifier[MAXLINE]
#define TIME_INDEX
Definition: cache_snmp.h:37
struct SquidConfig::@107 Addrs
Ip::Address local
Definition: Connection.h:135
#define SNMP_PDU_GET
Definition: snmp_pdu.h:92
bool SIGHDLR int STUB void int
Definition: stub_tools.cc:68
static mib_tree_entry * snmpAddNode(oid *name, int len, oid_ParseFn *parsefunction, instance_Fn *instancefunction, AggrType aggrType, int children,...)
Definition: snmp_core.cc:991
Ip::Address * client_entry(Ip::Address *current)
Definition: client_db.cc:430
u_char * snmp_parse(struct snmp_session *, struct snmp_pdu *, u_char *, int)
Definition: snmp_api.c:133
Comm::ConnectionPointer snmpIncomingConn
Definition: snmp_core.cc:35
static oid * time_Inst(oid *name, snint *len, mib_tree_entry *current, oid_ParseFn **Fn)
Definition: snmp_core.cc:693
static oid_ParseFn * snmpTreeGet(oid *Current, snint CurrentLen)
Definition: snmp_core.cc:538
#define INETADDRESSTYPE_IPV6
Definition: snmp_vars.h:94
void snmpClosePorts(void)
Definition: snmp_core.cc:319
#define xmalloc
int command
Definition: snmp_pdu.h:51
static mib_tree_entry * snmpAddNodeStr(const char *base_str, int o, oid_ParseFn *parsefunction, instance_Fn *instancefunction, AggrType aggrType=atNone)
Definition: snmp_core.cc:959
int snmp_coexist_V2toV1(struct snmp_pdu *)
Definition: coexistance.c:108
static void snmpPortOpened(const Comm::ConnectionPointer &conn, int errNo)
Definition: snmp_core.cc:303
void setAnyAddr()
NOTE: Does NOT clear the Port stored. Ony the Address and Type.
Definition: Address.cc:177
static CacheManager * instance
variable_list * snmp_confFn(variable_list *Var, snint *ErrP)
Definition: snmp_agent.cc:80
Ip::Address from
Definition: SnmpRequest.h:26
Comm::ConnectionPointer snmpOutgoingConn
Definition: snmp_core.cc:36
void snmp_free_pdu(struct snmp_pdu *)
Definition: snmp_pdu.c:284
bool allowed() const
Definition: Acl.h:141
int EnableIpv6
Whether IPv6 is supported and type of support.
Definition: tools.h:25
Definition: MemBuf.h:23
mib_tree_entry * snmpLookupNodeStr(mib_tree_entry *entry, const char *str)
Definition: snmp_core.cc:888
allow_t const & fastCheck()
Definition: Checklist.cc:336
static oid * peer_Inst(oid *name, snint *len, mib_tree_entry *current, oid_ParseFn **Fn)
Definition: snmp_core.cc:722
int reqid
Definition: snmp_pdu.h:54
#define MAX_IPSTRLEN
Length of buffer that needs to be allocated to old a null-terminated IP-string.
Definition: forward.h:23
variable_list * snmp_prfSysFn(variable_list *Var, snint *ErrP)
Definition: snmp_agent.cc:321
variable_list * snmp_prfProtoFn(variable_list *Var, snint *ErrP)
Definition: snmp_agent.cc:423
#define IPV6_SPECIAL_SPLITSTACK
Definition: tools.h:22
AggrType snmpAggrType(oid *Current, snint CurrentLen)
Definition: snmp_core.cc:569
#define SNMP_REQUEST_SIZE
Definition: snmp_core.h:21
int errstat
Definition: snmp_pdu.h:55
#define xfree
struct snmp_pdu * PDU
Definition: SnmpRequest.h:28
int len
Definition: snmp_core.h:31
dials a UDP port-opened call
Definition: UdpOpenDialer.h:18
u_char * outbuf
Definition: SnmpRequest.h:20
class SquidConfig Config
Definition: SquidConfig.cc:12
#define NULL
Definition: types.h:166
static oid * static_Inst(oid *name, snint *len, mib_tree_entry *current, oid_ParseFn **Fn)
Definition: snmp_core.cc:679
variable_list * snmp_sysFn(variable_list *Var, snint *ErrP)
Definition: snmp_agent.cc:41
int size
Definition: ModDevPoll.cc:77
const char * snmpDebugOid(oid *Name, snint Len, MemBuf &outbuf)
Definition: snmp_core.cc:1052
struct _mib_tree_entry * parent
Definition: snmp_core.h:38
u_char * community
Definition: SnmpRequest.h:30
AggrType
Definition: snmp_core.h:27
int children
Definition: snmp_core.h:34
void snmpOpenPorts(void)
Definition: snmp_core.cc:256
struct snmp_pdu * snmpAgentResponse(struct snmp_pdu *PDU)
Definition: snmp_core.cc:456

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors