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