]> git.ipfire.org Git - thirdparty/squid.git/blob - src/snmp_core.cc
Merge from trunk
[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 */
449 theInSnmpConnection = -1;
450
451 /*
452 * Normally we only write to the outgoing SNMP socket, but we
453 * also have a read handler there to catch messages sent to that
454 * specific interface. During shutdown, we must disable reading
455 * on the outgoing socket.
456 */
457 assert(theOutSnmpConnection > -1);
458
459 commSetSelect(theOutSnmpConnection, COMM_SELECT_READ, NULL, NULL, 0);
460 }
461
462 void
463 snmpConnectionClose(void)
464 {
465 snmpConnectionShutdown();
466
467 if (theOutSnmpConnection > -1) {
468 debugs(49, 1, "FD " << theOutSnmpConnection << " Closing SNMP socket");
469 comm_close(theOutSnmpConnection);
470 /* make sure the SNMP out connection is unset */
471 theOutSnmpConnection = -1;
472 }
473 }
474
475 /*
476 * Functions for handling the requests.
477 */
478
479 /*
480 * Accept the UDP packet
481 */
482 void
483 snmpHandleUdp(int sock, void *not_used)
484 {
485 LOCAL_ARRAY(char, buf, SNMP_REQUEST_SIZE);
486 IPAddress from;
487 snmp_request_t *snmp_rq;
488 int len;
489
490 debugs(49, 5, "snmpHandleUdp: Called.");
491
492 commSetSelect(sock, COMM_SELECT_READ, snmpHandleUdp, NULL, 0);
493
494 memset(buf, '\0', SNMP_REQUEST_SIZE);
495
496 len = comm_udp_recvfrom(sock,
497 buf,
498 SNMP_REQUEST_SIZE,
499 0,
500 from);
501
502 if (len > 0) {
503 buf[len] = '\0';
504 debugs(49, 3, "snmpHandleUdp: FD " << sock << ": received " << len << " bytes from " << from << ".");
505
506 snmp_rq = (snmp_request_t *)xcalloc(1, sizeof(snmp_request_t));
507 snmp_rq->buf = (u_char *) buf;
508 snmp_rq->len = len;
509 snmp_rq->sock = sock;
510 snmp_rq->outbuf = (unsigned char *)xmalloc(snmp_rq->outlen = SNMP_REQUEST_SIZE);
511 snmp_rq->from = from;
512 snmpDecodePacket(snmp_rq);
513 xfree(snmp_rq->outbuf);
514 xfree(snmp_rq);
515 } else {
516 debugs(49, 1, "snmpHandleUdp: FD " << sock << " recvfrom: " << xstrerror());
517 }
518 }
519
520 /*
521 * Turn SNMP packet into a PDU, check available ACL's
522 */
523 static void
524 snmpDecodePacket(snmp_request_t * rq)
525 {
526 struct snmp_pdu *PDU;
527 u_char *Community;
528 u_char *buf = rq->buf;
529 int len = rq->len;
530 int allow = 0;
531
532 debugs(49, 5, HERE << "Called.");
533 PDU = snmp_pdu_create(0);
534 /* Allways answer on SNMPv1 */
535 rq->session.Version = SNMP_VERSION_1;
536 Community = snmp_parse(&rq->session, PDU, buf, len);
537
538 if (Community) {
539 ACLChecklist checklist;
540 checklist.accessList = cbdataReference(Config.accessList.snmp);
541 checklist.src_addr = rq->from;
542 checklist.snmp_community = (char *) Community;
543 /* cbdataReferenceDone() happens in either fastCheck() or ~ACLCheckList */
544 allow = checklist.fastCheck();
545 }
546
547 if ((snmp_coexist_V2toV1(PDU)) && (Community) && (allow)) {
548 rq->community = Community;
549 rq->PDU = PDU;
550 debugs(49, 5, "snmpAgentParse: reqid=[" << PDU->reqid << "]");
551 snmpConstructReponse(rq);
552 } else {
553 debugs(49, 1, HERE << "Failed SNMP agent query from : " << rq->from);
554 snmp_free_pdu(PDU);
555 }
556
557 if (Community)
558 xfree(Community);
559 }
560
561 /*
562 * Packet OK, ACL Check OK, Create reponse.
563 */
564 static void
565 snmpConstructReponse(snmp_request_t * rq)
566 {
567
568 struct snmp_pdu *RespPDU;
569
570 debugs(49, 5, "snmpConstructReponse: Called.");
571 RespPDU = snmpAgentResponse(rq->PDU);
572 snmp_free_pdu(rq->PDU);
573
574 if (RespPDU != NULL) {
575 snmp_build(&rq->session, RespPDU, rq->outbuf, &rq->outlen);
576 comm_udp_sendto(rq->sock, rq->from, rq->outbuf, rq->outlen);
577 snmp_free_pdu(RespPDU);
578 }
579 }
580
581 /*
582 * Decide how to respond to the request, construct a response and
583 * return the response to the requester.
584 */
585
586 static struct snmp_pdu *
587
588 snmpAgentResponse(struct snmp_pdu *PDU)
589 {
590
591 struct snmp_pdu *Answer = NULL;
592
593 debugs(49, 5, "snmpAgentResponse: Called.");
594
595 if ((Answer = snmp_pdu_create(SNMP_PDU_RESPONSE)))
596 {
597 Answer->reqid = PDU->reqid;
598 Answer->errindex = 0;
599
600 if (PDU->command == SNMP_PDU_GET || PDU->command == SNMP_PDU_GETNEXT) {
601 /* Indirect way */
602 int get_next = (PDU->command == SNMP_PDU_GETNEXT);
603 variable_list *VarPtr_;
604 variable_list **RespVars = &(Answer->variables);
605 oid_ParseFn *ParseFn;
606 int index = 0;
607 /* Loop through all variables */
608
609 for (VarPtr_ = PDU->variables; VarPtr_; VarPtr_ = VarPtr_->next_variable) {
610 variable_list *VarPtr = VarPtr_;
611 variable_list *VarNew = NULL;
612 oid *NextOidName = NULL;
613 snint NextOidNameLen = 0;
614
615 index++;
616
617 if (get_next)
618 ParseFn = snmpTreeNext(VarPtr->name, VarPtr->name_length, &NextOidName, &NextOidNameLen);
619 else
620 ParseFn = snmpTreeGet(VarPtr->name, VarPtr->name_length);
621
622 if (ParseFn == NULL) {
623 Answer->errstat = SNMP_ERR_NOSUCHNAME;
624 debugs(49, 5, "snmpAgentResponse: No such oid. ");
625 } else {
626 if (get_next) {
627 VarPtr = snmp_var_new(NextOidName, NextOidNameLen);
628 xfree(NextOidName);
629 }
630
631 int * errstatTmp = &(Answer->errstat);
632
633 VarNew = (*ParseFn) (VarPtr, (snint *) errstatTmp);
634
635 if (get_next)
636 snmp_var_free(VarPtr);
637 }
638
639 if ((Answer->errstat != SNMP_ERR_NOERROR) || (VarNew == NULL)) {
640 Answer->errindex = index;
641 debugs(49, 5, "snmpAgentResponse: error.");
642
643 if (VarNew)
644 snmp_var_free(VarNew);
645
646 while ((VarPtr = Answer->variables) != NULL) {
647 Answer->variables = VarPtr->next_variable;
648 snmp_var_free(VarPtr);
649 }
650
651 /* Steal the original PDU list of variables for the error response */
652 Answer->variables = PDU->variables;
653
654 PDU->variables = NULL;
655
656 return (Answer);
657 }
658
659 /* No error. Insert this var at the end, and move on to the next.
660 */
661 *RespVars = VarNew;
662
663 RespVars = &(VarNew->next_variable);
664 }
665 }
666 }
667
668 return (Answer);
669 }
670
671 static oid_ParseFn *
672 snmpTreeGet(oid * Current, snint CurrentLen)
673 {
674 oid_ParseFn *Fn = NULL;
675 mib_tree_entry *mibTreeEntry = NULL;
676 int count = 0;
677
678 debugs(49, 5, "snmpTreeGet: Called");
679
680 debugs(49, 6, "snmpTreeGet: Current : ");
681 snmpDebugOid(6, Current, CurrentLen);
682
683 mibTreeEntry = mib_tree_head;
684
685 if (Current[count] == mibTreeEntry->name[count]) {
686 count++;
687
688 while ((mibTreeEntry) && (count < CurrentLen) && (!mibTreeEntry->parsefunction)) {
689 mibTreeEntry = snmpTreeEntry(Current[count], count, mibTreeEntry);
690 count++;
691 }
692 }
693
694 if (mibTreeEntry && mibTreeEntry->parsefunction)
695 Fn = mibTreeEntry->parsefunction;
696
697 debugs(49, 5, "snmpTreeGet: return");
698
699 return (Fn);
700 }
701
702 static oid_ParseFn *
703 snmpTreeNext(oid * Current, snint CurrentLen, oid ** Next, snint * NextLen)
704 {
705 oid_ParseFn *Fn = NULL;
706 mib_tree_entry *mibTreeEntry = NULL, *nextoid = NULL;
707 int count = 0;
708
709 debugs(49, 5, "snmpTreeNext: Called");
710
711 debugs(49, 6, "snmpTreeNext: Current : ");
712 snmpDebugOid(6, Current, CurrentLen);
713
714 mibTreeEntry = mib_tree_head;
715
716 if (Current[count] == mibTreeEntry->name[count]) {
717 count++;
718
719 while ((mibTreeEntry) && (count < CurrentLen) && (!mibTreeEntry->parsefunction)) {
720 mib_tree_entry *nextmibTreeEntry = snmpTreeEntry(Current[count], count, mibTreeEntry);
721
722 if (!nextmibTreeEntry)
723 break;
724 else
725 mibTreeEntry = nextmibTreeEntry;
726
727 count++;
728 }
729 debugs(49, 5, "snmpTreeNext: Recursed down to requested object");
730 } else {
731 return NULL;
732 }
733
734 if (mibTreeEntry == mib_tree_last)
735 return (Fn);
736
737
738 if ((mibTreeEntry) && (mibTreeEntry->parsefunction)) {
739 *NextLen = CurrentLen;
740 *Next = (*mibTreeEntry->instancefunction) (Current, NextLen, mibTreeEntry, &Fn);
741 if (*Next)
742 {
743 debugs(49, 6, "snmpTreeNext: Next : ");
744 snmpDebugOid(6, *Next, *NextLen);
745 return (Fn);
746 }
747 }
748
749 if ((mibTreeEntry) && (mibTreeEntry->parsefunction)) {
750 count--;
751 nextoid = snmpTreeSiblingEntry(Current[count], count, mibTreeEntry->parent);
752 if (nextoid) {
753 debugs(49, 5, "snmpTreeNext: Next OID found for sibling" << nextoid );
754 mibTreeEntry = nextoid;
755 count++;
756 } else {
757 debugs(49, 5, "snmpTreeNext: Attempting to recurse up for next object");
758
759 while (!nextoid) {
760 count--;
761
762 if (mibTreeEntry->parent->parent) {
763 nextoid = mibTreeEntry->parent;
764 mibTreeEntry = snmpTreeEntry(Current[count] + 1, count, nextoid->parent);
765
766 if (!mibTreeEntry) {
767 mibTreeEntry = nextoid;
768 nextoid = NULL;
769 }
770 } else {
771 nextoid = mibTreeEntry;
772 mibTreeEntry = NULL;
773 }
774 }
775 }
776 }
777 while ((mibTreeEntry) && (!mibTreeEntry->parsefunction)) {
778 mibTreeEntry = mibTreeEntry->leaves[0];
779 }
780
781 if (mibTreeEntry) {
782 *NextLen = mibTreeEntry->len;
783 *Next = (*mibTreeEntry->instancefunction) (mibTreeEntry->name, NextLen, mibTreeEntry, &Fn);
784 }
785
786 if (*Next)
787 {
788 debugs(49, 6, "snmpTreeNext: Next : ");
789 snmpDebugOid(6, *Next, *NextLen);
790 return (Fn);
791 }
792 else
793 return NULL;
794 }
795
796 static oid *
797 static_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn)
798 {
799 oid *instance = NULL;
800 if (*len <= current->len) {
801 instance = (oid *)xmalloc(sizeof(name) * (*len + 1));
802 xmemcpy(instance, name, (sizeof(name) * *len));
803 instance[*len] = 0;
804 *len += 1;
805 }
806 *Fn = current->parsefunction;
807 return (instance);
808 }
809
810 static oid *
811 time_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn)
812 {
813 oid *instance = NULL;
814 int identifier = 0, loop = 0;
815 int index[TIME_INDEX_LEN] = {TIME_INDEX};
816
817 if (*len <= current->len) {
818 instance = (oid *)xmalloc(sizeof(name) * (*len + 1));
819 xmemcpy(instance, name, (sizeof(name) * *len));
820 instance[*len] = *index;
821 *len += 1;
822 } else {
823 identifier = name[*len - 1];
824
825 while ((loop < TIME_INDEX_LEN) && (identifier != index[loop]))
826 loop++;
827
828 if (loop < (TIME_INDEX_LEN - 1)) {
829 instance = (oid *)xmalloc(sizeof(name) * (*len));
830 xmemcpy(instance, name, (sizeof(name) * *len));
831 instance[*len - 1] = index[++loop];
832 }
833 }
834
835 *Fn = current->parsefunction;
836 return (instance);
837 }
838
839
840 static oid *
841 peer_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn)
842 {
843 oid *instance = NULL;
844 peer *peers = Config.peers;
845
846 if (peers == NULL) {
847 current = current->parent->parent->parent->leaves[1];
848 while ((current) && (!current->parsefunction))
849 current = current->leaves[0];
850
851 instance = client_Inst(current->name, len, current, Fn);
852 } else if (*len <= current->len) {
853 instance = (oid *)xmalloc(sizeof(name) * ( *len + 1));
854 xmemcpy(instance, name, (sizeof(name) * *len));
855 instance[*len] = 1 ;
856 *len += 1;
857 } else {
858 int no = name[current->len] ;
859 int i ; // Note: This works because the Confifg.peers
860 // keep its index acording to its position.
861 for ( i=0 ; peers && (i < no) ; peers = peers->next , i++ ) ;
862
863 if (peers) {
864 instance = (oid *)xmalloc(sizeof(name) * (current->len + 1 ));
865 xmemcpy(instance, name, (sizeof(name) * current->len ));
866 instance[current->len] = no + 1 ; // i.e. the next index on cache_peeer table.
867 } else {
868 return (instance);
869 }
870 }
871 *Fn = current->parsefunction;
872 return (instance);
873 }
874
875 static oid *
876 client_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn)
877 {
878 oid *instance = NULL;
879 IPAddress laddr;
880 IPAddress *aux;
881 int size = 0;
882 int newshift = 0;
883
884 if(*len <= current->len) {
885 aux = client_entry(NULL);
886 if(aux)
887 laddr = *aux;
888 else
889 laddr.SetAnyAddr();
890
891 if(laddr.IsIPv4())
892 size = sizeof(in_addr);
893 #if USE_IPV6
894 else
895 size = sizeof(in6_addr);
896 #endif
897
898 instance = (oid *)xmalloc(sizeof(name) * (*len + size ));
899 xmemcpy(instance, name, (sizeof(name) * (*len)));
900
901 if ( !laddr.IsAnyAddr() ) {
902 addr2oid(laddr, &instance[ *len]); // the addr
903 *len += size ;
904 }
905 } else {
906 int shift = *len - current->len ; // i.e 4 or 16
907 oid2addr(&name[*len - shift], laddr,shift);
908 aux = client_entry(&laddr);
909 if(aux)
910 laddr = *aux;
911 else
912 laddr.SetAnyAddr();
913
914 if(!laddr.IsAnyAddr()) {
915 if(laddr.IsIPv4())
916 newshift = sizeof(in_addr);
917 #if USE_IPV6
918 else
919 newshift = sizeof(in6_addr);
920 #endif
921 instance = (oid *)xmalloc(sizeof(name) * (current->len + newshift));
922 xmemcpy(instance, name, (sizeof(name) * (current->len)));
923 addr2oid(laddr, &instance[current->len]); // the addr.
924 *len = current->len + newshift ;
925 }
926 }
927
928 *Fn = current->parsefunction;
929 return (instance);
930 }
931
932
933 /*
934 * Utility functions
935 */
936
937 /*
938 * Tree utility functions.
939 */
940
941 /*
942 * Returns a sibling object for the requested child object or NULL
943 * if it does not exit
944 */
945 static mib_tree_entry *
946 snmpTreeSiblingEntry(oid entry, snint len, mib_tree_entry * current)
947 {
948 mib_tree_entry *next = NULL;
949 int count = 0;
950
951 while ((!next) && (count < current->children)) {
952 if (current->leaves[count]->name[len] == entry) {
953 next = current->leaves[count];
954 }
955
956 count++;
957 }
958
959 /* Exactly the sibling on rigth */
960 if (count < current->children) {
961 next = current->leaves[count];
962 } else {
963 next = NULL;
964 }
965
966 return (next);
967 }
968
969 /*
970 * Returns the requested child object or NULL if it does not exist
971 */
972 static mib_tree_entry *
973 snmpTreeEntry(oid entry, snint len, mib_tree_entry * current)
974 {
975 mib_tree_entry *next = NULL;
976 int count = 0;
977
978 while ((!next) && (count < current->children)) {
979 if (current->leaves[count]->name[len] == entry) {
980 next = current->leaves[count];
981 }
982
983 count++;
984 }
985
986 return (next);
987 }
988
989 /*
990 * Adds a node to the MIB tree structure and adds the appropriate children
991 */
992 static mib_tree_entry *
993 #if STDC_HEADERS
994 snmpAddNode(oid * name, int len, oid_ParseFn * parsefunction, instance_Fn * instancefunction, int children,...)
995 #else
996 snmpAddNode(va_alist)
997 va_dcl
998 #endif
999 {
1000 #if STDC_HEADERS
1001 va_list args;
1002 int loop;
1003 mib_tree_entry *entry = NULL;
1004 va_start(args, children);
1005 #else
1006
1007 va_list args;
1008 oid *name = NULL;
1009 int len = 0, children = 0, loop;
1010 oid_ParseFn *parsefunction = NULL;
1011 instance_Fn *instancefunction = NULL;
1012 mib_tree_entry *entry = NULL;
1013 va_start(args);
1014 name = va_arg(args, oid *);
1015 len = va_arg(args, int);
1016 parsefunction = va_arg(args, oid_ParseFn *);
1017 instancefunction = va_arg(args, instance_Fn *);
1018 children = va_arg(args, int);
1019 #endif
1020
1021 debugs(49, 6, "snmpAddNode: Children : " << children << ", Oid : ");
1022 snmpDebugOid(6, name, len);
1023
1024 va_start(args, children);
1025 entry = (mib_tree_entry *)xmalloc(sizeof(mib_tree_entry));
1026 entry->name = name;
1027 entry->len = len;
1028 entry->parsefunction = parsefunction;
1029 entry->instancefunction = instancefunction;
1030 entry->children = children;
1031
1032 if (children > 0)
1033 {
1034 entry->leaves = (mib_tree_entry **)xmalloc(sizeof(mib_tree_entry *) * children);
1035
1036 for (loop = 0; loop < children; loop++) {
1037 entry->leaves[loop] = va_arg(args, mib_tree_entry *);
1038 entry->leaves[loop]->parent = entry;
1039 }
1040 }
1041
1042 return (entry);
1043 }
1044 /* End of tree utility functions */
1045
1046 /*
1047 * Returns the list of parameters in an oid
1048 */
1049 static oid *
1050 #if STDC_HEADERS
1051 snmpCreateOid(int length,...)
1052 #else
1053 snmpCreateOid(va_alist)
1054 va_dcl
1055 #endif
1056 {
1057 #if STDC_HEADERS
1058 va_list args;
1059 oid *new_oid;
1060 int loop;
1061 va_start(args, length);
1062 #else
1063
1064 va_list args;
1065 int length = 0, loop;
1066 oid *new_oid;
1067 va_start(args);
1068 length va_arg(args, int);
1069 #endif
1070
1071 new_oid = (oid *)xmalloc(sizeof(oid) * length);
1072
1073 if (length > 0)
1074 {
1075 for (loop = 0; loop < length; loop++) {
1076 new_oid[loop] = va_arg(args, int);
1077 }
1078 }
1079
1080 return (new_oid);
1081 }
1082
1083 /*
1084 * Debug calls, prints out the OID for debugging purposes.
1085 */
1086 void
1087 snmpDebugOid(int lvl, oid * Name, snint Len)
1088 {
1089 char mbuf[16], objid[1024];
1090 int x;
1091 objid[0] = '\0';
1092
1093 for (x = 0; x < Len; x++) {
1094 snprintf(mbuf, sizeof(mbuf), ".%u", (unsigned int) Name[x]);
1095 strncat(objid, mbuf, sizeof(objid) - strlen(objid) - 1);
1096 }
1097
1098 debugs(49, lvl, " oid = " << objid);
1099 }
1100
1101 static void
1102 snmpSnmplibDebug(int lvl, char *buf)
1103 {
1104 debug(49, lvl) ("%s", buf);
1105 }
1106
1107
1108
1109 /*
1110 IPv4 address: 10.10.0.9 ==>
1111 oid == 10.10.0.9
1112 IPv6 adress : 20:01:32:ef:a2:21:fb:32:00:00:00:00:00:00:00:00:OO:01 ==>
1113 oid == 32.1.50.239.162.33.251.20.50.0.0.0.0.0.0.0.0.0.1
1114 */
1115 void
1116 addr2oid(IPAddress &addr, oid * Dest)
1117 {
1118 u_int i ;
1119 u_char *cp = NULL;
1120 struct in_addr iaddr;
1121 #if USE_IPV6
1122 struct in6_addr i6addr;
1123 oid code = addr.IsIPv4()? INETADDRESSTYPE_IPV4 : INETADDRESSTYPE_IPV6 ;
1124 u_int size = (code == INETADDRESSTYPE_IPV4) ? sizeof(struct in_addr):sizeof(struct in6_addr);
1125 #else
1126 oid code = INETADDRESSTYPE_IPV4 ;
1127 u_int size = sizeof(struct in_addr) ;
1128 #endif /* USE_IPV6 */
1129 // Dest[0] = code ;
1130 if ( code == INETADDRESSTYPE_IPV4 ) {
1131 addr.GetInAddr(iaddr);
1132 cp = (u_char *) &(iaddr.s_addr);
1133 }
1134 #if USE_IPV6
1135 else
1136 {
1137 addr.GetInAddr(i6addr);
1138 cp = (u_char *) &i6addr;
1139 }
1140 #endif
1141 for ( i=0 ; i < size ; i++)
1142 {
1143 // OID's are in network order
1144 Dest[i] = *cp++;
1145 }
1146 debugs(49, 7, "addr2oid: Dest : ");
1147 snmpDebugOid(7, Dest, size );
1148
1149 }
1150
1151 /*
1152 oid == 10.10.0.9 ==>
1153 IPv4 address: 10.10.0.9
1154 oid == 32.1.50.239.162.33.251.20.50.0.0.0.0.0.0.0.0.0.1 ==>
1155 IPv6 adress : 20:01:32:ef:a2:21:fb:32:00:00:00:00:00:00:00:00:OO:01
1156 */
1157 void
1158 oid2addr(oid * id, IPAddress &addr, u_int size)
1159 {
1160 struct in_addr iaddr;
1161 u_int i;
1162 u_char *cp;
1163 #if USE_IPV6
1164 struct in6_addr i6addr;
1165 if ( size == sizeof(struct in_addr) )
1166 #endif /* USE_IPV6 */
1167 cp = (u_char *) &(iaddr.s_addr);
1168 #if USE_IPV6
1169 else
1170 cp = (u_char *) &(i6addr);
1171 #endif /* USE_IPV6 */
1172 debugs(49, 7, "oid2addr: id : ");
1173 snmpDebugOid(7, id, size );
1174 for(i=0 ; i<size; i++)
1175 {
1176 cp[i] = id[i];
1177 }
1178 #if USE_IPV6
1179 if ( size == sizeof(struct in_addr) )
1180 #endif
1181 addr = iaddr;
1182 #if USE_IPV6
1183 else
1184 addr = i6addr;
1185 #endif
1186
1187 }
1188
1189 /* SNMP checklists */
1190 #include "ACLStrategy.h"
1191 #include "ACLStrategised.h"
1192 #include "ACLStringData.h"
1193
1194 class ACLSNMPCommunityStrategy : public ACLStrategy<char const *>
1195 {
1196
1197 public:
1198 virtual int match (ACLData<MatchType> * &, ACLChecklist *);
1199 static ACLSNMPCommunityStrategy *Instance();
1200 /* Not implemented to prevent copies of the instance. */
1201 /* Not private to prevent brain dead g+++ warnings about
1202 * private constructors with no friends */
1203 ACLSNMPCommunityStrategy(ACLSNMPCommunityStrategy const &);
1204
1205 private:
1206 static ACLSNMPCommunityStrategy Instance_;
1207 ACLSNMPCommunityStrategy(){}
1208
1209 ACLSNMPCommunityStrategy&operator=(ACLSNMPCommunityStrategy const &);
1210 };
1211
1212 class ACLSNMPCommunity
1213 {
1214
1215 private:
1216 static ACL::Prototype RegistryProtoype;
1217 static ACLStrategised<char const *> RegistryEntry_;
1218 };
1219
1220 ACL::Prototype ACLSNMPCommunity::RegistryProtoype(&ACLSNMPCommunity::RegistryEntry_, "snmp_community");
1221 ACLStrategised<char const *> ACLSNMPCommunity::RegistryEntry_(new ACLStringData, ACLSNMPCommunityStrategy::Instance(), "snmp_community");
1222
1223 int
1224 ACLSNMPCommunityStrategy::match (ACLData<MatchType> * &data, ACLChecklist *checklist)
1225 {
1226 return data->match (checklist->snmp_community);
1227 }
1228
1229 ACLSNMPCommunityStrategy *
1230 ACLSNMPCommunityStrategy::Instance()
1231 {
1232 return &Instance_;
1233 }
1234
1235 ACLSNMPCommunityStrategy ACLSNMPCommunityStrategy::Instance_;