]> git.ipfire.org Git - thirdparty/squid.git/blame_incremental - src/snmp_core.cc
SourceFormat: enforcement
[thirdparty/squid.git] / src / snmp_core.cc
... / ...
CommitLineData
1/*
2 * DEBUG: section 49 SNMP support
3 * AUTHOR: Glenn Chisholm
4 *
5 * SQUID Web Proxy Cache http://www.squid-cache.org/
6 * ----------------------------------------------------------
7 *
8 * Squid is the result of efforts by numerous individuals from
9 * the Internet community; see the CONTRIBUTORS file for full
10 * details. Many organizations have provided support for Squid's
11 * development; see the SPONSORS file for full details. Squid is
12 * Copyrighted (C) 2001 by the Regents of the University of
13 * California; see the COPYRIGHT file for full details. Squid
14 * incorporates software developed and/or copyrighted by other
15 * sources; see the CREDITS file for full details.
16 *
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or
20 * (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
30 *
31 */
32#include "squid.h"
33#include "comm.h"
34#include "cache_snmp.h"
35#include "acl/FilledChecklist.h"
36#include "ip/IpAddress.h"
37
38#define SNMP_REQUEST_SIZE 4096
39#define MAX_PROTOSTAT 5
40
41IpAddress theOutSNMPAddr;
42
43typedef struct _mib_tree_entry mib_tree_entry;
44typedef oid *(instance_Fn) (oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn);
45
46struct _mib_tree_entry {
47 oid *name;
48 int len;
49 oid_ParseFn *parsefunction;
50 instance_Fn *instancefunction;
51 int children;
52
53 struct _mib_tree_entry **leaves;
54
55 struct _mib_tree_entry *parent;
56};
57
58mib_tree_entry *mib_tree_head;
59mib_tree_entry *mib_tree_last;
60
61static mib_tree_entry *snmpAddNode(oid * name, int len, oid_ParseFn * parsefunction, instance_Fn * instancefunction, int children,...);
62static oid *snmpCreateOid(int length,...);
63SQUIDCEXTERN void (*snmplib_debug_hook) (int, char *);
64static oid *static_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn);
65static oid *time_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn);
66static oid *peer_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn);
67static oid *client_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn);
68static void snmpDecodePacket(snmp_request_t * rq);
69static void snmpConstructReponse(snmp_request_t * rq);
70
71static struct snmp_pdu *snmpAgentResponse(struct snmp_pdu *PDU);
72static oid_ParseFn *snmpTreeNext(oid * Current, snint CurrentLen, oid ** Next, snint * NextLen);
73static oid_ParseFn *snmpTreeGet(oid * Current, snint CurrentLen);
74static mib_tree_entry *snmpTreeEntry(oid entry, snint len, mib_tree_entry * current);
75static mib_tree_entry *snmpTreeSiblingEntry(oid entry, snint len, mib_tree_entry * current);
76static void snmpSnmplibDebug(int lvl, char *buf);
77
78/*
79 * The functions used during startup:
80 * snmpInit
81 * snmpConnectionOpen
82 * snmpConnectionShutdown
83 * snmpConnectionClose
84 */
85
86/*
87 * Turns the MIB into a Tree structure. Called during the startup process.
88 */
89void
90snmpInit(void)
91{
92 debugs(49, 5, "snmpInit: Building SNMP mib tree structure");
93
94 snmplib_debug_hook = snmpSnmplibDebug;
95
96 mib_tree_head = snmpAddNode(snmpCreateOid(1, 1),
97 1, NULL, NULL, 1,
98 snmpAddNode(snmpCreateOid(2, 1, 3),
99 2, NULL, NULL, 1,
100 snmpAddNode(snmpCreateOid(3, 1, 3, 6),
101 3, NULL, NULL, 1,
102 snmpAddNode(snmpCreateOid(4, 1, 3, 6, 1),
103 4, NULL, NULL, 1,
104 snmpAddNode(snmpCreateOid(5, 1, 3, 6, 1, 4),
105 5, NULL, NULL, 1,
106 snmpAddNode(snmpCreateOid(6, 1, 3, 6, 1, 4, 1),
107 6, NULL, NULL, 1,
108 snmpAddNode(snmpCreateOid(7, 1, 3, 6, 1, 4, 1, 3495),
109 7, NULL, NULL, 1,
110 snmpAddNode(snmpCreateOid(LEN_SQUIDMIB, SQUIDMIB),
111 8, NULL, NULL, 5,
112 snmpAddNode(snmpCreateOid(LEN_SQ_SYS, SQ_SYS),
113 LEN_SQ_SYS, NULL, NULL, 3,
114 snmpAddNode(snmpCreateOid(LEN_SYS, SQ_SYS, SYSVMSIZ),
115 LEN_SYS, snmp_sysFn, static_Inst, 0),
116 snmpAddNode(snmpCreateOid(LEN_SYS, SQ_SYS, SYSSTOR),
117 LEN_SYS, snmp_sysFn, static_Inst, 0),
118 snmpAddNode(snmpCreateOid(LEN_SYS, SQ_SYS, SYS_UPTIME),
119 LEN_SYS, snmp_sysFn, static_Inst, 0)),
120 snmpAddNode(snmpCreateOid(LEN_SQ_CONF, SQ_CONF),
121 LEN_SQ_CONF, NULL, NULL, 6,
122 snmpAddNode(snmpCreateOid(LEN_SYS, SQ_CONF, CONF_ADMIN),
123 LEN_SYS, snmp_confFn, static_Inst, 0),
124 snmpAddNode(snmpCreateOid(LEN_SYS, SQ_CONF, CONF_VERSION),
125 LEN_SYS, snmp_confFn, static_Inst, 0),
126 snmpAddNode(snmpCreateOid(LEN_SYS, SQ_CONF, CONF_VERSION_ID),
127 LEN_SYS, snmp_confFn, static_Inst, 0),
128 snmpAddNode(snmpCreateOid(LEN_SYS, SQ_CONF, CONF_LOG_FAC),
129 LEN_SYS, snmp_confFn, static_Inst, 0),
130 snmpAddNode(snmpCreateOid(LEN_SYS, SQ_CONF, CONF_STORAGE),
131 LEN_SYS, NULL, NULL, 4,
132 snmpAddNode(snmpCreateOid(LEN_CONF_ST, SQ_CONF, CONF_STORAGE, CONF_ST_MMAXSZ),
133 LEN_CONF_ST, snmp_confFn, static_Inst, 0),
134 snmpAddNode(snmpCreateOid(LEN_CONF_ST, SQ_CONF, CONF_STORAGE, CONF_ST_SWMAXSZ),
135 LEN_CONF_ST, snmp_confFn, static_Inst, 0),
136 snmpAddNode(snmpCreateOid(LEN_CONF_ST, SQ_CONF, CONF_STORAGE, CONF_ST_SWHIWM),
137 LEN_CONF_ST, snmp_confFn, static_Inst, 0),
138 snmpAddNode(snmpCreateOid(LEN_CONF_ST, SQ_CONF, CONF_STORAGE, CONF_ST_SWLOWM),
139 LEN_CONF_ST, snmp_confFn, static_Inst, 0)),
140 snmpAddNode(snmpCreateOid(LEN_SYS, SQ_CONF, CONF_UNIQNAME),
141 LEN_SYS, snmp_confFn, static_Inst, 0)),
142 snmpAddNode(snmpCreateOid(LEN_SQ_PRF, SQ_PRF),
143 LEN_SQ_PRF, NULL, NULL, 2,
144 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 1, SQ_PRF, PERF_SYS),
145 LEN_SQ_PRF + 1, NULL, NULL, 13,
146 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, PERF_SYS_PF),
147 LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
148 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, PERF_SYS_NUMR),
149 LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
150 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, PERF_SYS_MEMUSAGE),
151 LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
152 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, PERF_SYS_CPUTIME),
153 LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
154 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, PERF_SYS_CPUUSAGE),
155 LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
156 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, PERF_SYS_MAXRESSZ),
157 LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
158 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, PERF_SYS_NUMOBJCNT),
159 LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
160 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, PERF_SYS_CURLRUEXP),
161 LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
162 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, PERF_SYS_CURUNLREQ),
163 LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
164 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, PERF_SYS_CURUNUSED_FD),
165 LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
166 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, PERF_SYS_CURRESERVED_FD),
167 LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
168 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, PERF_SYS_CURUSED_FD),
169 LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
170 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, PERF_SYS_CURMAX_FD),
171 LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0)),
172 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 1, SQ_PRF, PERF_PROTO),
173 LEN_SQ_PRF + 1, NULL, NULL, 2,
174 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_AGGR),
175 LEN_SQ_PRF + 2, NULL, NULL, 15,
176 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_AGGR, PERF_PROTOSTAT_AGGR_HTTP_REQ),
177 LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
178 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_AGGR, PERF_PROTOSTAT_AGGR_HTTP_HITS),
179 LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
180 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_AGGR, PERF_PROTOSTAT_AGGR_HTTP_ERRORS),
181 LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
182 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_AGGR, PERF_PROTOSTAT_AGGR_HTTP_KBYTES_IN),
183 LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
184 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_AGGR, PERF_PROTOSTAT_AGGR_HTTP_KBYTES_OUT),
185 LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
186 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_AGGR, PERF_PROTOSTAT_AGGR_ICP_S),
187 LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
188 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_AGGR, PERF_PROTOSTAT_AGGR_ICP_R),
189 LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
190 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_AGGR, PERF_PROTOSTAT_AGGR_ICP_SKB),
191 LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
192 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_AGGR, PERF_PROTOSTAT_AGGR_ICP_RKB),
193 LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
194 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_AGGR, PERF_PROTOSTAT_AGGR_REQ),
195 LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
196 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_AGGR, PERF_PROTOSTAT_AGGR_ERRORS),
197 LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
198 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_AGGR, PERF_PROTOSTAT_AGGR_KBYTES_IN),
199 LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
200 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_AGGR, PERF_PROTOSTAT_AGGR_KBYTES_OUT),
201 LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
202 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_AGGR, PERF_PROTOSTAT_AGGR_CURSWAP),
203 LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
204 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_AGGR, PERF_PROTOSTAT_AGGR_CLIENTS),
205 LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0)),
206 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_PROTO, 2),
207 LEN_SQ_PRF + 2, NULL, NULL, 1,
208 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_MEDIAN, 1),
209 LEN_SQ_PRF + 3, NULL, NULL, 11,
210 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_MEDIAN, 1, PERF_MEDIAN_TIME),
211 LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
212 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_MEDIAN, 1, PERF_MEDIAN_HTTP_ALL),
213 LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
214 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_MEDIAN, 1, PERF_MEDIAN_HTTP_MISS),
215 LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
216 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_MEDIAN, 1, PERF_MEDIAN_HTTP_NM),
217 LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
218 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_MEDIAN, 1, PERF_MEDIAN_HTTP_HIT),
219 LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
220 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_MEDIAN, 1, PERF_MEDIAN_ICP_QUERY),
221 LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
222 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_MEDIAN, 1, PERF_MEDIAN_ICP_REPLY),
223 LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
224 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_MEDIAN, 1, PERF_MEDIAN_DNS),
225 LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
226 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_MEDIAN, 1, PERF_MEDIAN_RHR),
227 LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
228 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_MEDIAN, 1, PERF_MEDIAN_BHR),
229 LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
230 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_MEDIAN, 1, PERF_MEDIAN_HTTP_NH),
231 LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0))))),
232 snmpAddNode(snmpCreateOid(LEN_SQ_NET, SQ_NET),
233 LEN_SQ_NET, NULL, NULL, 3,
234 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 1, SQ_NET, NET_IP_CACHE),
235 LEN_SQ_NET + 1, NULL, NULL, 8,
236 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_ENT),
237 LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0),
238 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_REQ),
239 LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0),
240 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_HITS),
241 LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0),
242 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_PENDHIT),
243 LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0),
244 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_NEGHIT),
245 LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0),
246 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_MISS),
247 LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0),
248 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_GHBN),
249 LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0),
250 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_LOC),
251 LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0)),
252 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 1, SQ_NET, NET_FQDN_CACHE),
253 LEN_SQ_NET + 1, NULL, NULL, 7,
254 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_FQDN_CACHE, FQDN_ENT),
255 LEN_SQ_NET + 2, snmp_netFqdnFn, static_Inst, 0),
256 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_FQDN_CACHE, FQDN_REQ),
257 LEN_SQ_NET + 2, snmp_netFqdnFn, static_Inst, 0),
258 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_FQDN_CACHE, FQDN_HITS),
259 LEN_SQ_NET + 2, snmp_netFqdnFn, static_Inst, 0),
260 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_FQDN_CACHE, FQDN_PENDHIT),
261 LEN_SQ_NET + 2, snmp_netFqdnFn, static_Inst, 0),
262 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_FQDN_CACHE, FQDN_NEGHIT),
263 LEN_SQ_NET + 2, snmp_netFqdnFn, static_Inst, 0),
264 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_FQDN_CACHE, FQDN_MISS),
265 LEN_SQ_NET + 2, snmp_netFqdnFn, static_Inst, 0),
266 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_FQDN_CACHE, FQDN_GHBN),
267 LEN_SQ_NET + 2, snmp_netFqdnFn, static_Inst, 0)),
268 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 1, SQ_NET, NET_DNS_CACHE),
269 LEN_SQ_NET + 1, NULL, NULL, 3,
270#if USE_DNSSERVERS
271 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_DNS_CACHE, DNS_REQ),
272 LEN_SQ_NET + 2, snmp_netDnsFn, static_Inst, 0),
273 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_DNS_CACHE, DNS_REP),
274 LEN_SQ_NET + 2, snmp_netDnsFn, static_Inst, 0),
275 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_DNS_CACHE, DNS_SERVERS),
276 LEN_SQ_NET + 2, snmp_netDnsFn, static_Inst, 0))),
277#else
278 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_DNS_CACHE, DNS_REQ),
279 LEN_SQ_NET + 2, snmp_netIdnsFn, static_Inst, 0),
280 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_DNS_CACHE, DNS_REP),
281 LEN_SQ_NET + 2, snmp_netIdnsFn, static_Inst, 0),
282 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_DNS_CACHE, DNS_SERVERS),
283 LEN_SQ_NET + 2, snmp_netIdnsFn, static_Inst, 0))),
284#endif
285 snmpAddNode(snmpCreateOid(LEN_SQ_MESH, SQ_MESH),
286 LEN_SQ_MESH, NULL, NULL, 2,
287 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 1, SQ_MESH, MESH_PTBL),
288 LEN_SQ_MESH + 1, NULL, NULL, 1,
289 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 2, SQ_MESH, 1, 1),
290 LEN_SQ_MESH + 2, NULL, NULL, 15,
291 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_PTBL, 1, MESH_PTBL_INDEX),
292 LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
293 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_PTBL, 1, MESH_PTBL_NAME),
294 LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
295 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_PTBL, 1, MESH_PTBL_ADDR_TYPE),
296 LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
297 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_PTBL, 1, MESH_PTBL_ADDR),
298 LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
299 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_PTBL, 1, MESH_PTBL_HTTP),
300 LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
301 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_PTBL, 1, MESH_PTBL_ICP),
302 LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
303 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_PTBL, 1, MESH_PTBL_TYPE),
304 LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
305 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_PTBL, 1, MESH_PTBL_STATE),
306 LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
307 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_PTBL, 1, MESH_PTBL_SENT),
308 LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
309 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_PTBL, 1, MESH_PTBL_PACKED),
310 LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
311 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_PTBL, 1, MESH_PTBL_FETCHES),
312 LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
313 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_PTBL, 1, MESH_PTBL_RTT),
314 LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
315 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_PTBL, 1, MESH_PTBL_IGN),
316 LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
317 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_PTBL, 1, MESH_PTBL_KEEPAL_S),
318 LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
319 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_PTBL, 1, MESH_PTBL_KEEPAL_R),
320 LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0))),
321 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 1, SQ_MESH, MESH_CTBL),
322 LEN_SQ_MESH + 1, NULL, NULL, 1,
323 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 2, SQ_MESH, MESH_CTBL, 1),
324 LEN_SQ_MESH + 2, NULL, NULL, 10,
325 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_CTBL, 1, MESH_CTBL_ADDR_TYPE),
326 LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0),
327 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_CTBL, 1, MESH_CTBL_ADDR),
328 LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0),
329 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_CTBL, 1, MESH_CTBL_HTREQ),
330 LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0),
331 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_CTBL, 1, MESH_CTBL_HTBYTES),
332 LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0),
333 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_CTBL, 1, MESH_CTBL_HTHITS),
334 LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0),
335 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_CTBL, 1, MESH_CTBL_HTHITBYTES),
336 LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0),
337 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_CTBL, 1, MESH_CTBL_ICPREQ),
338 LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0),
339 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_CTBL, 1, MESH_CTBL_ICPBYTES),
340 LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0),
341 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_CTBL, 1, MESH_CTBL_ICPHITS),
342 LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0),
343 (mib_tree_last = snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_CTBL, 1, MESH_CTBL_ICPHITBYTES),
344 LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0)))))
345 )
346 )
347 )
348 )
349 )
350 )
351 )
352 );
353
354 debugs(49, 9, "snmpInit: Completed SNMP mib tree structure");
355}
356
357void
358snmpConnectionOpen(void)
359{
360 struct addrinfo *xaddr = NULL;
361 int x;
362
363 debugs(49, 5, "snmpConnectionOpen: Called");
364
365 if (Config.Port.snmp > 0) {
366 Config.Addrs.snmp_incoming.SetPort(Config.Port.snmp);
367 enter_suid();
368 theInSnmpConnection = comm_open_listener(SOCK_DGRAM,
369 IPPROTO_UDP,
370 Config.Addrs.snmp_incoming,
371 COMM_NONBLOCKING,
372 "SNMP Port");
373 leave_suid();
374
375 if (theInSnmpConnection < 0)
376 fatal("Cannot open SNMP Port");
377
378 commSetSelect(theInSnmpConnection, COMM_SELECT_READ, snmpHandleUdp, NULL, 0);
379
380 debugs(1, 1, "Accepting SNMP messages on " << Config.Addrs.snmp_incoming << ", FD " << theInSnmpConnection << ".");
381
382 if (!Config.Addrs.snmp_outgoing.IsNoAddr()) {
383 Config.Addrs.snmp_outgoing.SetPort(Config.Port.snmp);
384 enter_suid();
385 theOutSnmpConnection = comm_open_listener(SOCK_DGRAM,
386 IPPROTO_UDP,
387 Config.Addrs.snmp_outgoing,
388 COMM_NONBLOCKING,
389 "SNMP Port");
390 leave_suid();
391
392 if (theOutSnmpConnection < 0)
393 fatal("Cannot open Outgoing SNMP Port");
394
395 commSetSelect(theOutSnmpConnection,
396 COMM_SELECT_READ,
397 snmpHandleUdp,
398 NULL, 0);
399
400 debugs(1, 1, "Outgoing SNMP messages on " << Config.Addrs.snmp_outgoing << ", FD " << theOutSnmpConnection << ".");
401
402 fd_note(theOutSnmpConnection, "Outgoing SNMP socket");
403
404 fd_note(theInSnmpConnection, "Incoming SNMP socket");
405 } else {
406 theOutSnmpConnection = theInSnmpConnection;
407 }
408
409 theOutSNMPAddr.SetEmpty();
410
411 theOutSNMPAddr.InitAddrInfo(xaddr);
412
413 x = getsockname(theOutSnmpConnection, xaddr->ai_addr, &xaddr->ai_addrlen);
414
415 if (x < 0)
416 debugs(51, 1, "theOutSnmpConnection FD " << theOutSnmpConnection << ": getsockname: " << xstrerror());
417 else
418 theOutSNMPAddr = *xaddr;
419
420 theOutSNMPAddr.FreeAddrInfo(xaddr);
421 }
422}
423
424void
425snmpConnectionShutdown(void)
426{
427 if (theInSnmpConnection < 0)
428 return;
429
430 if (theInSnmpConnection != theOutSnmpConnection) {
431 debugs(49, 1, "FD " << theInSnmpConnection << " Closing SNMP socket");
432 comm_close(theInSnmpConnection);
433 }
434
435 /*
436 * Here we set 'theInSnmpConnection' to -1 even though the SNMP 'in'
437 * and 'out' sockets might be just one FD. This prevents this
438 * function from executing repeatedly. When we are really ready to
439 * exit or restart, main will comm_close the 'out' descriptor.
440 */
441 theInSnmpConnection = -1;
442
443 /*
444 * Normally we only write to the outgoing SNMP socket, but we
445 * also have a read handler there to catch messages sent to that
446 * specific interface. During shutdown, we must disable reading
447 * on the outgoing socket.
448 */
449 assert(theOutSnmpConnection > -1);
450
451 commSetSelect(theOutSnmpConnection, COMM_SELECT_READ, NULL, NULL, 0);
452}
453
454void
455snmpConnectionClose(void)
456{
457 snmpConnectionShutdown();
458
459 if (theOutSnmpConnection > -1) {
460 debugs(49, 1, "FD " << theOutSnmpConnection << " Closing SNMP socket");
461 comm_close(theOutSnmpConnection);
462 /* make sure the SNMP out connection is unset */
463 theOutSnmpConnection = -1;
464 }
465}
466
467/*
468 * Functions for handling the requests.
469 */
470
471/*
472 * Accept the UDP packet
473 */
474void
475snmpHandleUdp(int sock, void *not_used)
476{
477 LOCAL_ARRAY(char, buf, SNMP_REQUEST_SIZE);
478 IpAddress from;
479 snmp_request_t *snmp_rq;
480 int len;
481
482 debugs(49, 5, "snmpHandleUdp: Called.");
483
484 commSetSelect(sock, COMM_SELECT_READ, snmpHandleUdp, NULL, 0);
485
486 memset(buf, '\0', SNMP_REQUEST_SIZE);
487
488 len = comm_udp_recvfrom(sock,
489 buf,
490 SNMP_REQUEST_SIZE,
491 0,
492 from);
493
494 if (len > 0) {
495 buf[len] = '\0';
496 debugs(49, 3, "snmpHandleUdp: FD " << sock << ": received " << len << " bytes from " << from << ".");
497
498 snmp_rq = (snmp_request_t *)xcalloc(1, sizeof(snmp_request_t));
499 snmp_rq->buf = (u_char *) buf;
500 snmp_rq->len = len;
501 snmp_rq->sock = sock;
502 snmp_rq->outbuf = (unsigned char *)xmalloc(snmp_rq->outlen = SNMP_REQUEST_SIZE);
503 snmp_rq->from = from;
504 snmpDecodePacket(snmp_rq);
505 xfree(snmp_rq->outbuf);
506 xfree(snmp_rq);
507 } else {
508 debugs(49, 1, "snmpHandleUdp: FD " << sock << " recvfrom: " << xstrerror());
509 }
510}
511
512/*
513 * Turn SNMP packet into a PDU, check available ACL's
514 */
515static void
516snmpDecodePacket(snmp_request_t * rq)
517{
518 struct snmp_pdu *PDU;
519 u_char *Community;
520 u_char *buf = rq->buf;
521 int len = rq->len;
522 int allow = 0;
523
524 debugs(49, 5, HERE << "Called.");
525 PDU = snmp_pdu_create(0);
526 /* Allways answer on SNMPv1 */
527 rq->session.Version = SNMP_VERSION_1;
528 Community = snmp_parse(&rq->session, PDU, buf, len);
529
530 /* Check if we have explicit permission to access SNMP data.
531 * default (set above) is to deny all */
532 if (Community && Config.accessList.snmp) {
533 ACLFilledChecklist checklist(Config.accessList.snmp, NULL, NULL);
534 checklist.src_addr = rq->from;
535 checklist.snmp_community = (char *) Community;
536 allow = checklist.fastCheck();
537 }
538
539 if ((snmp_coexist_V2toV1(PDU)) && (Community) && (allow)) {
540 rq->community = Community;
541 rq->PDU = PDU;
542 debugs(49, 5, "snmpAgentParse: reqid=[" << PDU->reqid << "]");
543 snmpConstructReponse(rq);
544 } else {
545 debugs(49, 1, HERE << "Failed SNMP agent query from : " << rq->from);
546 snmp_free_pdu(PDU);
547 }
548
549 if (Community)
550 xfree(Community);
551}
552
553/*
554 * Packet OK, ACL Check OK, Create reponse.
555 */
556static void
557snmpConstructReponse(snmp_request_t * rq)
558{
559
560 struct snmp_pdu *RespPDU;
561
562 debugs(49, 5, "snmpConstructReponse: Called.");
563 RespPDU = snmpAgentResponse(rq->PDU);
564 snmp_free_pdu(rq->PDU);
565
566 if (RespPDU != NULL) {
567 snmp_build(&rq->session, RespPDU, rq->outbuf, &rq->outlen);
568 comm_udp_sendto(rq->sock, rq->from, rq->outbuf, rq->outlen);
569 snmp_free_pdu(RespPDU);
570 }
571}
572
573/*
574 * Decide how to respond to the request, construct a response and
575 * return the response to the requester.
576 */
577
578static struct snmp_pdu *
579
580snmpAgentResponse(struct snmp_pdu *PDU) {
581
582 struct snmp_pdu *Answer = NULL;
583
584 debugs(49, 5, "snmpAgentResponse: Called.");
585
586 if ((Answer = snmp_pdu_create(SNMP_PDU_RESPONSE))) {
587 Answer->reqid = PDU->reqid;
588 Answer->errindex = 0;
589
590 if (PDU->command == SNMP_PDU_GET || PDU->command == SNMP_PDU_GETNEXT) {
591 /* Indirect way */
592 int get_next = (PDU->command == SNMP_PDU_GETNEXT);
593 variable_list *VarPtr_;
594 variable_list **RespVars = &(Answer->variables);
595 oid_ParseFn *ParseFn;
596 int index = 0;
597 /* Loop through all variables */
598
599 for (VarPtr_ = PDU->variables; VarPtr_; VarPtr_ = VarPtr_->next_variable) {
600 variable_list *VarPtr = VarPtr_;
601 variable_list *VarNew = NULL;
602 oid *NextOidName = NULL;
603 snint NextOidNameLen = 0;
604
605 index++;
606
607 if (get_next)
608 ParseFn = snmpTreeNext(VarPtr->name, VarPtr->name_length, &NextOidName, &NextOidNameLen);
609 else
610 ParseFn = snmpTreeGet(VarPtr->name, VarPtr->name_length);
611
612 if (ParseFn == NULL) {
613 Answer->errstat = SNMP_ERR_NOSUCHNAME;
614 debugs(49, 5, "snmpAgentResponse: No such oid. ");
615 } else {
616 if (get_next) {
617 VarPtr = snmp_var_new(NextOidName, NextOidNameLen);
618 xfree(NextOidName);
619 }
620
621 int * errstatTmp = &(Answer->errstat);
622
623 VarNew = (*ParseFn) (VarPtr, (snint *) errstatTmp);
624
625 if (get_next)
626 snmp_var_free(VarPtr);
627 }
628
629 if ((Answer->errstat != SNMP_ERR_NOERROR) || (VarNew == NULL)) {
630 Answer->errindex = index;
631 debugs(49, 5, "snmpAgentResponse: error.");
632
633 if (VarNew)
634 snmp_var_free(VarNew);
635
636 while ((VarPtr = Answer->variables) != NULL) {
637 Answer->variables = VarPtr->next_variable;
638 snmp_var_free(VarPtr);
639 }
640
641 /* Steal the original PDU list of variables for the error response */
642 Answer->variables = PDU->variables;
643
644 PDU->variables = NULL;
645
646 return (Answer);
647 }
648
649 /* No error. Insert this var at the end, and move on to the next.
650 */
651 *RespVars = VarNew;
652
653 RespVars = &(VarNew->next_variable);
654 }
655 }
656 }
657
658 return (Answer);
659}
660
661static oid_ParseFn *
662snmpTreeGet(oid * Current, snint CurrentLen)
663{
664 oid_ParseFn *Fn = NULL;
665 mib_tree_entry *mibTreeEntry = NULL;
666 int count = 0;
667
668 debugs(49, 5, "snmpTreeGet: Called");
669
670 debugs(49, 6, "snmpTreeGet: Current : ");
671 snmpDebugOid(6, Current, CurrentLen);
672
673 mibTreeEntry = mib_tree_head;
674
675 if (Current[count] == mibTreeEntry->name[count]) {
676 count++;
677
678 while ((mibTreeEntry) && (count < CurrentLen) && (!mibTreeEntry->parsefunction)) {
679 mibTreeEntry = snmpTreeEntry(Current[count], count, mibTreeEntry);
680 count++;
681 }
682 }
683
684 if (mibTreeEntry && mibTreeEntry->parsefunction)
685 Fn = mibTreeEntry->parsefunction;
686
687 debugs(49, 5, "snmpTreeGet: return");
688
689 return (Fn);
690}
691
692static oid_ParseFn *
693snmpTreeNext(oid * Current, snint CurrentLen, oid ** Next, snint * NextLen)
694{
695 oid_ParseFn *Fn = NULL;
696 mib_tree_entry *mibTreeEntry = NULL, *nextoid = NULL;
697 int count = 0;
698
699 debugs(49, 5, "snmpTreeNext: Called");
700
701 debugs(49, 6, "snmpTreeNext: Current : ");
702 snmpDebugOid(6, Current, CurrentLen);
703
704 mibTreeEntry = mib_tree_head;
705
706 if (Current[count] == mibTreeEntry->name[count]) {
707 count++;
708
709 while ((mibTreeEntry) && (count < CurrentLen) && (!mibTreeEntry->parsefunction)) {
710 mib_tree_entry *nextmibTreeEntry = snmpTreeEntry(Current[count], count, mibTreeEntry);
711
712 if (!nextmibTreeEntry)
713 break;
714 else
715 mibTreeEntry = nextmibTreeEntry;
716
717 count++;
718 }
719 debugs(49, 5, "snmpTreeNext: Recursed down to requested object");
720 } else {
721 return NULL;
722 }
723
724 if (mibTreeEntry == mib_tree_last)
725 return (Fn);
726
727
728 if ((mibTreeEntry) && (mibTreeEntry->parsefunction)) {
729 *NextLen = CurrentLen;
730 *Next = (*mibTreeEntry->instancefunction) (Current, NextLen, mibTreeEntry, &Fn);
731 if (*Next) {
732 debugs(49, 6, "snmpTreeNext: Next : ");
733 snmpDebugOid(6, *Next, *NextLen);
734 return (Fn);
735 }
736 }
737
738 if ((mibTreeEntry) && (mibTreeEntry->parsefunction)) {
739 count--;
740 nextoid = snmpTreeSiblingEntry(Current[count], count, mibTreeEntry->parent);
741 if (nextoid) {
742 debugs(49, 5, "snmpTreeNext: Next OID found for sibling" << nextoid );
743 mibTreeEntry = nextoid;
744 count++;
745 } else {
746 debugs(49, 5, "snmpTreeNext: Attempting to recurse up for next object");
747
748 while (!nextoid) {
749 count--;
750
751 if (mibTreeEntry->parent->parent) {
752 nextoid = mibTreeEntry->parent;
753 mibTreeEntry = snmpTreeEntry(Current[count] + 1, count, nextoid->parent);
754
755 if (!mibTreeEntry) {
756 mibTreeEntry = nextoid;
757 nextoid = NULL;
758 }
759 } else {
760 nextoid = mibTreeEntry;
761 mibTreeEntry = NULL;
762 }
763 }
764 }
765 }
766 while ((mibTreeEntry) && (!mibTreeEntry->parsefunction)) {
767 mibTreeEntry = mibTreeEntry->leaves[0];
768 }
769
770 if (mibTreeEntry) {
771 *NextLen = mibTreeEntry->len;
772 *Next = (*mibTreeEntry->instancefunction) (mibTreeEntry->name, NextLen, mibTreeEntry, &Fn);
773 }
774
775 if (*Next) {
776 debugs(49, 6, "snmpTreeNext: Next : ");
777 snmpDebugOid(6, *Next, *NextLen);
778 return (Fn);
779 } else
780 return NULL;
781}
782
783static oid *
784static_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn)
785{
786 oid *instance = NULL;
787 if (*len <= current->len) {
788 instance = (oid *)xmalloc(sizeof(name) * (*len + 1));
789 xmemcpy(instance, name, (sizeof(name) * *len));
790 instance[*len] = 0;
791 *len += 1;
792 }
793 *Fn = current->parsefunction;
794 return (instance);
795}
796
797static oid *
798time_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn)
799{
800 oid *instance = NULL;
801 int identifier = 0, loop = 0;
802 int index[TIME_INDEX_LEN] = {TIME_INDEX};
803
804 if (*len <= current->len) {
805 instance = (oid *)xmalloc(sizeof(name) * (*len + 1));
806 xmemcpy(instance, name, (sizeof(name) * *len));
807 instance[*len] = *index;
808 *len += 1;
809 } else {
810 identifier = name[*len - 1];
811
812 while ((loop < TIME_INDEX_LEN) && (identifier != index[loop]))
813 loop++;
814
815 if (loop < (TIME_INDEX_LEN - 1)) {
816 instance = (oid *)xmalloc(sizeof(name) * (*len));
817 xmemcpy(instance, name, (sizeof(name) * *len));
818 instance[*len - 1] = index[++loop];
819 }
820 }
821
822 *Fn = current->parsefunction;
823 return (instance);
824}
825
826
827static oid *
828peer_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn)
829{
830 oid *instance = NULL;
831 peer *peers = Config.peers;
832
833 if (peers == NULL) {
834 current = current->parent->parent->parent->leaves[1];
835 while ((current) && (!current->parsefunction))
836 current = current->leaves[0];
837
838 instance = client_Inst(current->name, len, current, Fn);
839 } else if (*len <= current->len) {
840 instance = (oid *)xmalloc(sizeof(name) * ( *len + 1));
841 xmemcpy(instance, name, (sizeof(name) * *len));
842 instance[*len] = 1 ;
843 *len += 1;
844 } else {
845 int no = name[current->len] ;
846 int i ; // Note: This works because the Confifg.peers
847 // keep its index acording to its position.
848 for ( i=0 ; peers && (i < no) ; peers = peers->next , i++ ) ;
849
850 if (peers) {
851 instance = (oid *)xmalloc(sizeof(name) * (current->len + 1 ));
852 xmemcpy(instance, name, (sizeof(name) * current->len ));
853 instance[current->len] = no + 1 ; // i.e. the next index on cache_peeer table.
854 } else {
855 return (instance);
856 }
857 }
858 *Fn = current->parsefunction;
859 return (instance);
860}
861
862static oid *
863client_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn)
864{
865 oid *instance = NULL;
866 IpAddress laddr;
867 IpAddress *aux;
868 int size = 0;
869 int newshift = 0;
870
871 if (*len <= current->len) {
872 aux = client_entry(NULL);
873 if (aux)
874 laddr = *aux;
875 else
876 laddr.SetAnyAddr();
877
878 if (laddr.IsIPv4())
879 size = sizeof(in_addr);
880#if USE_IPV6
881 else
882 size = sizeof(in6_addr);
883#endif
884
885 instance = (oid *)xmalloc(sizeof(name) * (*len + size ));
886 xmemcpy(instance, name, (sizeof(name) * (*len)));
887
888 if ( !laddr.IsAnyAddr() ) {
889 addr2oid(laddr, &instance[ *len]); // the addr
890 *len += size ;
891 }
892 } else {
893 int shift = *len - current->len ; // i.e 4 or 16
894 oid2addr(&name[*len - shift], laddr,shift);
895 aux = client_entry(&laddr);
896 if (aux)
897 laddr = *aux;
898 else
899 laddr.SetAnyAddr();
900
901 if (!laddr.IsAnyAddr()) {
902 if (laddr.IsIPv4())
903 newshift = sizeof(in_addr);
904#if USE_IPV6
905 else
906 newshift = sizeof(in6_addr);
907#endif
908 instance = (oid *)xmalloc(sizeof(name) * (current->len + newshift));
909 xmemcpy(instance, name, (sizeof(name) * (current->len)));
910 addr2oid(laddr, &instance[current->len]); // the addr.
911 *len = current->len + newshift ;
912 }
913 }
914
915 *Fn = current->parsefunction;
916 return (instance);
917}
918
919
920/*
921 * Utility functions
922 */
923
924/*
925 * Tree utility functions.
926 */
927
928/*
929 * Returns a sibling object for the requested child object or NULL
930 * if it does not exit
931 */
932static mib_tree_entry *
933snmpTreeSiblingEntry(oid entry, snint len, mib_tree_entry * current)
934{
935 mib_tree_entry *next = NULL;
936 int count = 0;
937
938 while ((!next) && (count < current->children)) {
939 if (current->leaves[count]->name[len] == entry) {
940 next = current->leaves[count];
941 }
942
943 count++;
944 }
945
946 /* Exactly the sibling on rigth */
947 if (count < current->children) {
948 next = current->leaves[count];
949 } else {
950 next = NULL;
951 }
952
953 return (next);
954}
955
956/*
957 * Returns the requested child object or NULL if it does not exist
958 */
959static mib_tree_entry *
960snmpTreeEntry(oid entry, snint len, mib_tree_entry * current)
961{
962 mib_tree_entry *next = NULL;
963 int count = 0;
964
965 while ((!next) && (count < current->children)) {
966 if (current->leaves[count]->name[len] == entry) {
967 next = current->leaves[count];
968 }
969
970 count++;
971 }
972
973 return (next);
974}
975
976/*
977 * Adds a node to the MIB tree structure and adds the appropriate children
978 */
979static mib_tree_entry *
980snmpAddNode(oid * name, int len, oid_ParseFn * parsefunction, instance_Fn * instancefunction, int children,...)
981{
982 va_list args;
983 int loop;
984 mib_tree_entry *entry = NULL;
985 va_start(args, children);
986
987 debugs(49, 6, "snmpAddNode: Children : " << children << ", Oid : ");
988 snmpDebugOid(6, name, len);
989
990 va_start(args, children);
991 entry = (mib_tree_entry *)xmalloc(sizeof(mib_tree_entry));
992 entry->name = name;
993 entry->len = len;
994 entry->parsefunction = parsefunction;
995 entry->instancefunction = instancefunction;
996 entry->children = children;
997
998 if (children > 0) {
999 entry->leaves = (mib_tree_entry **)xmalloc(sizeof(mib_tree_entry *) * children);
1000
1001 for (loop = 0; loop < children; loop++) {
1002 entry->leaves[loop] = va_arg(args, mib_tree_entry *);
1003 entry->leaves[loop]->parent = entry;
1004 }
1005 }
1006
1007 return (entry);
1008}
1009/* End of tree utility functions */
1010
1011/*
1012 * Returns the list of parameters in an oid
1013 */
1014static oid *
1015snmpCreateOid(int length,...)
1016{
1017 va_list args;
1018 oid *new_oid;
1019 int loop;
1020 va_start(args, length);
1021
1022 new_oid = (oid *)xmalloc(sizeof(oid) * length);
1023
1024 if (length > 0) {
1025 for (loop = 0; loop < length; loop++) {
1026 new_oid[loop] = va_arg(args, int);
1027 }
1028 }
1029
1030 return (new_oid);
1031}
1032
1033/*
1034 * Debug calls, prints out the OID for debugging purposes.
1035 */
1036void
1037snmpDebugOid(int lvl, oid * Name, snint Len)
1038{
1039 char mbuf[16], objid[1024];
1040 int x;
1041 objid[0] = '\0';
1042
1043 for (x = 0; x < Len; x++) {
1044 snprintf(mbuf, sizeof(mbuf), ".%u", (unsigned int) Name[x]);
1045 strncat(objid, mbuf, sizeof(objid) - strlen(objid) - 1);
1046 }
1047
1048 debugs(49, lvl, " oid = " << objid);
1049}
1050
1051static void
1052snmpSnmplibDebug(int lvl, char *buf)
1053{
1054 debug(49, lvl) ("%s", buf);
1055}
1056
1057
1058
1059/*
1060 IPv4 address: 10.10.0.9 ==>
1061 oid == 10.10.0.9
1062 IPv6 adress : 20:01:32:ef:a2:21:fb:32:00:00:00:00:00:00:00:00:OO:01 ==>
1063 oid == 32.1.50.239.162.33.251.20.50.0.0.0.0.0.0.0.0.0.1
1064*/
1065void
1066addr2oid(IpAddress &addr, oid * Dest)
1067{
1068 u_int i ;
1069 u_char *cp = NULL;
1070 struct in_addr iaddr;
1071#if USE_IPV6
1072 struct in6_addr i6addr;
1073 oid code = addr.IsIPv4()? INETADDRESSTYPE_IPV4 : INETADDRESSTYPE_IPV6 ;
1074 u_int size = (code == INETADDRESSTYPE_IPV4) ? sizeof(struct in_addr):sizeof(struct in6_addr);
1075#else
1076 oid code = INETADDRESSTYPE_IPV4 ;
1077 u_int size = sizeof(struct in_addr) ;
1078#endif /* USE_IPV6 */
1079 // Dest[0] = code ;
1080 if ( code == INETADDRESSTYPE_IPV4 ) {
1081 addr.GetInAddr(iaddr);
1082 cp = (u_char *) &(iaddr.s_addr);
1083 }
1084#if USE_IPV6
1085 else {
1086 addr.GetInAddr(i6addr);
1087 cp = (u_char *) &i6addr;
1088 }
1089#endif
1090 for ( i=0 ; i < size ; i++) {
1091 // OID's are in network order
1092 Dest[i] = *cp++;
1093 }
1094 debugs(49, 7, "addr2oid: Dest : ");
1095 snmpDebugOid(7, Dest, size );
1096
1097}
1098
1099/*
1100 oid == 10.10.0.9 ==>
1101 IPv4 address: 10.10.0.9
1102 oid == 32.1.50.239.162.33.251.20.50.0.0.0.0.0.0.0.0.0.1 ==>
1103 IPv6 adress : 20:01:32:ef:a2:21:fb:32:00:00:00:00:00:00:00:00:OO:01
1104*/
1105void
1106oid2addr(oid * id, IpAddress &addr, u_int size)
1107{
1108 struct in_addr iaddr;
1109 u_int i;
1110 u_char *cp;
1111#if USE_IPV6
1112 struct in6_addr i6addr;
1113 if ( size == sizeof(struct in_addr) )
1114#endif /* USE_IPV6 */
1115 cp = (u_char *) &(iaddr.s_addr);
1116#if USE_IPV6
1117 else
1118 cp = (u_char *) &(i6addr);
1119#endif /* USE_IPV6 */
1120 debugs(49, 7, "oid2addr: id : ");
1121 snmpDebugOid(7, id, size );
1122 for (i=0 ; i<size; i++) {
1123 cp[i] = id[i];
1124 }
1125#if USE_IPV6
1126 if ( size == sizeof(struct in_addr) )
1127#endif
1128 addr = iaddr;
1129#if USE_IPV6
1130 else
1131 addr = i6addr;
1132#endif
1133
1134}
1135
1136/* SNMP checklists */
1137#include "acl/Strategy.h"
1138#include "acl/Strategised.h"
1139#include "acl/StringData.h"
1140
1141class ACLSNMPCommunityStrategy : public ACLStrategy<char const *>
1142{
1143
1144public:
1145 virtual int match (ACLData<MatchType> * &, ACLFilledChecklist *);
1146 static ACLSNMPCommunityStrategy *Instance();
1147 /* Not implemented to prevent copies of the instance. */
1148 /* Not private to prevent brain dead g+++ warnings about
1149 * private constructors with no friends */
1150 ACLSNMPCommunityStrategy(ACLSNMPCommunityStrategy const &);
1151
1152private:
1153 static ACLSNMPCommunityStrategy Instance_;
1154 ACLSNMPCommunityStrategy() {}
1155
1156 ACLSNMPCommunityStrategy&operator=(ACLSNMPCommunityStrategy const &);
1157};
1158
1159class ACLSNMPCommunity
1160{
1161
1162private:
1163 static ACL::Prototype RegistryProtoype;
1164 static ACLStrategised<char const *> RegistryEntry_;
1165};
1166
1167ACL::Prototype ACLSNMPCommunity::RegistryProtoype(&ACLSNMPCommunity::RegistryEntry_, "snmp_community");
1168ACLStrategised<char const *> ACLSNMPCommunity::RegistryEntry_(new ACLStringData, ACLSNMPCommunityStrategy::Instance(), "snmp_community");
1169
1170int
1171ACLSNMPCommunityStrategy::match (ACLData<MatchType> * &data, ACLFilledChecklist *checklist)
1172{
1173 return data->match (checklist->snmp_community);
1174}
1175
1176ACLSNMPCommunityStrategy *
1177ACLSNMPCommunityStrategy::Instance()
1178{
1179 return &Instance_;
1180}
1181
1182ACLSNMPCommunityStrategy ACLSNMPCommunityStrategy::Instance_;