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