]> git.ipfire.org Git - thirdparty/squid.git/blob - src/snmp_core.cc
Bug 1298: Multiple OIDs in SNMP GETNEXT not processed
[thirdparty/squid.git] / src / snmp_core.cc
1
2 /*
3 * $Id: snmp_core.cc,v 1.67 2005/05/05 15:44:45 serassio 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 /*
86 * The functions used during startup:
87 * snmpInit
88 * snmpConnectionOpen
89 * snmpConnectionShutdown
90 * snmpConnectionClose
91 */
92
93 /*
94 * Turns the MIB into a Tree structure. Called during the startup process.
95 */
96 void
97 snmpInit(void)
98 {
99 debug(49, 5) ("snmpInit: Called.\n");
100
101 debug(49, 5) ("snmpInit: Building SNMP mib tree structure\n");
102
103 snmplib_debug_hook = snmpSnmplibDebug;
104
105 mib_tree_head = snmpAddNode(snmpCreateOid(1, 1),
106 1, NULL, NULL, 1,
107 snmpAddNode(snmpCreateOid(2, 1, 3),
108 2, NULL, NULL, 1,
109 snmpAddNode(snmpCreateOid(3, 1, 3, 6),
110 3, NULL, NULL, 1,
111 snmpAddNode(snmpCreateOid(4, 1, 3, 6, 1),
112 4, NULL, NULL, 1,
113 snmpAddNode(snmpCreateOid(5, 1, 3, 6, 1, 4),
114 5, NULL, NULL, 1,
115 snmpAddNode(snmpCreateOid(6, 1, 3, 6, 1, 4, 1),
116 6, NULL, NULL, 1,
117 snmpAddNode(snmpCreateOid(7, 1, 3, 6, 1, 4, 1, 3495),
118 7, NULL, NULL, 1,
119 snmpAddNode(snmpCreateOid(LEN_SQUIDMIB, SQUIDMIB),
120 8, NULL, NULL, 5,
121 snmpAddNode(snmpCreateOid(LEN_SQ_SYS, SQ_SYS),
122 LEN_SQ_SYS, NULL, NULL, 3,
123 snmpAddNode(snmpCreateOid(LEN_SYS, SQ_SYS, SYSVMSIZ),
124 LEN_SYS, snmp_sysFn, static_Inst, 0),
125 snmpAddNode(snmpCreateOid(LEN_SYS, SQ_SYS, SYSSTOR),
126 LEN_SYS, snmp_sysFn, static_Inst, 0),
127 snmpAddNode(snmpCreateOid(LEN_SYS, SQ_SYS, SYS_UPTIME),
128 LEN_SYS, snmp_sysFn, static_Inst, 0)),
129 snmpAddNode(snmpCreateOid(LEN_SQ_CONF, SQ_CONF),
130 LEN_SQ_CONF, NULL, NULL, 5,
131 snmpAddNode(snmpCreateOid(LEN_SYS, SQ_CONF, CONF_ADMIN),
132 LEN_SYS, snmp_confFn, static_Inst, 0),
133 snmpAddNode(snmpCreateOid(LEN_SYS, SQ_CONF, CONF_VERSION),
134 LEN_SYS, snmp_confFn, static_Inst, 0),
135 snmpAddNode(snmpCreateOid(LEN_SYS, SQ_CONF, CONF_VERSION_ID),
136 LEN_SYS, snmp_confFn, static_Inst, 0),
137 snmpAddNode(snmpCreateOid(LEN_SYS, SQ_CONF, CONF_LOG_FAC),
138 LEN_SYS, snmp_confFn, static_Inst, 0),
139 snmpAddNode(snmpCreateOid(LEN_SYS, SQ_CONF, CONF_STORAGE),
140 LEN_SYS, NULL, NULL, 4,
141 snmpAddNode(snmpCreateOid(LEN_CONF_ST, SQ_CONF, CONF_STORAGE, CONF_ST_MMAXSZ),
142 LEN_CONF_ST, snmp_confFn, static_Inst, 0),
143 snmpAddNode(snmpCreateOid(LEN_CONF_ST, SQ_CONF, CONF_STORAGE, CONF_ST_SWMAXSZ),
144 LEN_CONF_ST, snmp_confFn, static_Inst, 0),
145 snmpAddNode(snmpCreateOid(LEN_CONF_ST, SQ_CONF, CONF_STORAGE, CONF_ST_SWHIWM),
146 LEN_CONF_ST, snmp_confFn, static_Inst, 0),
147 snmpAddNode(snmpCreateOid(LEN_CONF_ST, SQ_CONF, CONF_STORAGE, CONF_ST_SWLOWM),
148 LEN_CONF_ST, snmp_confFn, static_Inst, 0))),
149 snmpAddNode(snmpCreateOid(LEN_SQ_PRF, SQ_PRF),
150 LEN_SQ_PRF, NULL, NULL, 2,
151 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 1, SQ_PRF, PERF_SYS),
152 LEN_SQ_PRF + 1, NULL, NULL, 11,
153 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 1),
154 LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
155 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 2),
156 LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
157 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 3),
158 LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
159 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 4),
160 LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
161 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 5),
162 LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
163 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 6),
164 LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
165 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 7),
166 LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
167 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 8),
168 LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
169 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 9),
170 LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
171 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 10),
172 LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
173 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 11),
174 LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0)),
175 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 1, SQ_PRF, PERF_PROTO),
176 LEN_SQ_PRF + 1, NULL, NULL, 2,
177 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_PROTO, 1),
178 LEN_SQ_PRF + 2, NULL, NULL, 15,
179 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 1),
180 LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
181 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 2),
182 LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
183 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 3),
184 LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
185 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 4),
186 LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
187 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 5),
188 LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
189 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 6),
190 LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
191 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 7),
192 LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
193 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 8),
194 LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
195 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 9),
196 LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
197 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 10),
198 LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
199 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 11),
200 LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
201 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 12),
202 LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
203 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 13),
204 LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
205 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 14),
206 LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
207 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 15),
208 LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0)),
209 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_PROTO, 2),
210 LEN_SQ_PRF + 2, NULL, NULL, 1,
211 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 2, 1),
212 LEN_SQ_PRF + 3, NULL, NULL, 10,
213 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 1),
214 LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
215 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 2),
216 LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
217 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 3),
218 LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
219 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 4),
220 LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
221 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 5),
222 LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
223 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 6),
224 LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
225 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 7),
226 LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
227 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 8),
228 LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
229 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 9),
230 LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
231 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 10),
232 LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0))))),
233 snmpAddNode(snmpCreateOid(LEN_SQ_NET, SQ_NET),
234 LEN_SQ_NET, NULL, NULL, 3,
235 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 1, SQ_NET, NET_IP_CACHE),
236 LEN_SQ_NET + 1, NULL, NULL, 8,
237 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_ENT),
238 LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0),
239 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_REQ),
240 LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0),
241 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_HITS),
242 LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0),
243 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_PENDHIT),
244 LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0),
245 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_NEGHIT),
246 LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0),
247 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_MISS),
248 LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0),
249 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_GHBN),
250 LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0),
251 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_LOC),
252 LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0)),
253 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 1, SQ_NET, NET_FQDN_CACHE),
254 LEN_SQ_NET + 1, NULL, NULL, 7,
255 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_FQDN_CACHE, FQDN_ENT),
256 LEN_SQ_NET + 2, snmp_netFqdnFn, static_Inst, 0),
257 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_FQDN_CACHE, FQDN_REQ),
258 LEN_SQ_NET + 2, snmp_netFqdnFn, static_Inst, 0),
259 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_FQDN_CACHE, FQDN_HITS),
260 LEN_SQ_NET + 2, snmp_netFqdnFn, static_Inst, 0),
261 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_FQDN_CACHE, FQDN_PENDHIT),
262 LEN_SQ_NET + 2, snmp_netFqdnFn, static_Inst, 0),
263 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_FQDN_CACHE, FQDN_NEGHIT),
264 LEN_SQ_NET + 2, snmp_netFqdnFn, static_Inst, 0),
265 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_FQDN_CACHE, FQDN_MISS),
266 LEN_SQ_NET + 2, snmp_netFqdnFn, static_Inst, 0),
267 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_FQDN_CACHE, FQDN_GHBN),
268 LEN_SQ_NET + 2, snmp_netFqdnFn, static_Inst, 0)),
269 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 1, SQ_NET, NET_DNS_CACHE),
270 LEN_SQ_NET + 1, NULL, NULL, 3,
271 #if USE_DNSSERVERS
272 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_DNS_CACHE, DNS_REQ),
273 LEN_SQ_NET + 2, snmp_netDnsFn, static_Inst, 0),
274 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_DNS_CACHE, DNS_REP),
275 LEN_SQ_NET + 2, snmp_netDnsFn, static_Inst, 0),
276 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_DNS_CACHE, DNS_SERVERS),
277 LEN_SQ_NET + 2, snmp_netDnsFn, static_Inst, 0))),
278 #else
279 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_DNS_CACHE, DNS_REQ),
280 LEN_SQ_NET + 2, snmp_netIdnsFn, static_Inst, 0),
281 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_DNS_CACHE, DNS_REP),
282 LEN_SQ_NET + 2, snmp_netIdnsFn, static_Inst, 0),
283 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_DNS_CACHE, DNS_SERVERS),
284 LEN_SQ_NET + 2, snmp_netIdnsFn, static_Inst, 0))),
285 #endif
286 snmpAddNode(snmpCreateOid(LEN_SQ_MESH, SQ_MESH),
287 LEN_SQ_MESH, NULL, NULL, 2,
288 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 1, SQ_MESH, 1),
289 LEN_SQ_MESH + 1, NULL, NULL, 1,
290 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 2, SQ_MESH, 1, 1),
291 LEN_SQ_MESH + 2, NULL, NULL, 13,
292 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 1),
293 LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
294 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 2),
295 LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
296 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 3),
297 LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
298 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 4),
299 LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
300 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 5),
301 LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
302 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 6),
303 LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
304 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 7),
305 LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
306 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 8),
307 LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
308 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 9),
309 LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
310 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 10),
311 LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
312 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 11),
313 LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
314 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 12),
315 LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
316 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 13),
317 LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0))),
318 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 1, SQ_MESH, 2),
319 LEN_SQ_MESH + 1, NULL, NULL, 1,
320 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 2, SQ_MESH, 2, 1),
321 LEN_SQ_MESH + 2, NULL, NULL, 9,
322 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 1),
323 LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0),
324 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 2),
325 LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0),
326 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 3),
327 LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0),
328 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 4),
329 LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0),
330 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 5),
331 LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0),
332 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 6),
333 LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0),
334 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 7),
335 LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0),
336 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 8),
337 LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0),
338 (mib_tree_last = snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 9),
339 LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0)))))
340 )
341 )
342 )
343 )
344 )
345 )
346 )
347 );
348
349 debug(49, 9) ("snmpInit: Completed SNMP mib tree structure\n");
350 }
351
352 void
353 snmpConnectionOpen(void)
354 {
355 u_short port;
356
357 struct sockaddr_in xaddr;
358 socklen_t len;
359 int x;
360
361 debug(49, 5) ("snmpConnectionOpen: Called\n");
362
363 if ((port = Config.Port.snmp) > (u_short) 0) {
364 enter_suid();
365 theInSnmpConnection = comm_open(SOCK_DGRAM,
366 IPPROTO_UDP,
367 Config.Addrs.snmp_incoming,
368 port,
369 COMM_NONBLOCKING,
370 "SNMP Port");
371 leave_suid();
372
373 if (theInSnmpConnection < 0)
374 fatal("Cannot open snmp Port");
375
376 commSetSelect(theInSnmpConnection, COMM_SELECT_READ, snmpHandleUdp, NULL, 0);
377
378 debug(1, 1) ("Accepting SNMP messages on port %d, FD %d.\n",
379 (int) port, theInSnmpConnection);
380
381 if (Config.Addrs.snmp_outgoing.s_addr != no_addr.s_addr) {
382 enter_suid();
383 theOutSnmpConnection = comm_open(SOCK_DGRAM,
384 IPPROTO_UDP,
385 Config.Addrs.snmp_outgoing,
386 port,
387 COMM_NONBLOCKING,
388 "SNMP Port");
389 leave_suid();
390
391 if (theOutSnmpConnection < 0)
392 fatal("Cannot open Outgoing SNMP Port");
393
394 commSetSelect(theOutSnmpConnection,
395 COMM_SELECT_READ,
396 snmpHandleUdp,
397 NULL, 0);
398
399 debug(1, 1) ("Outgoing SNMP messages on port %d, FD %d.\n",
400 (int) port, theOutSnmpConnection);
401
402 fd_note(theOutSnmpConnection, "Outgoing SNMP socket");
403
404 fd_note(theInSnmpConnection, "Incoming SNMP socket");
405 } else {
406 theOutSnmpConnection = theInSnmpConnection;
407 }
408
409 memset(&theOutSNMPAddr, '\0', sizeof(struct IN_ADDR));
410
411 len = sizeof(struct sockaddr_in);
412 memset(&xaddr, '\0', len);
413 x = getsockname(theOutSnmpConnection,
414
415 (struct sockaddr *) &xaddr, &len);
416
417 if (x < 0)
418 debug(51, 1) ("theOutSnmpConnection FD %d: getsockname: %s\n",
419 theOutSnmpConnection, xstrerror());
420 else
421 theOutSNMPAddr = xaddr.sin_addr;
422 }
423 }
424
425 void
426 snmpConnectionShutdown(void)
427 {
428 if (theInSnmpConnection < 0)
429 return;
430
431 if (theInSnmpConnection != theOutSnmpConnection) {
432 debug(49, 1) ("FD %d Closing SNMP socket\n", theInSnmpConnection);
433 comm_close(theInSnmpConnection);
434 }
435
436 /*
437 * Here we set 'theInSnmpConnection' to -1 even though the SNMP 'in'
438 * and 'out' sockets might be just one FD. This prevents this
439 * function from executing repeatedly. When we are really ready to
440 * exit or restart, main will comm_close the 'out' descriptor.
441 */ theInSnmpConnection = -1;
442
443 /*
444 * Normally we only write to the outgoing SNMP socket, but we
445 * also have a read handler there to catch messages sent to that
446 * specific interface. During shutdown, we must disable reading
447 * on the outgoing socket.
448 */
449 assert(theOutSnmpConnection > -1);
450
451 commSetSelect(theOutSnmpConnection, COMM_SELECT_READ, NULL, NULL, 0);
452 }
453
454 void
455 snmpConnectionClose(void)
456 {
457 snmpConnectionShutdown();
458
459 if (theOutSnmpConnection > -1) {
460 debug(49, 1) ("FD %d Closing SNMP socket\n", theOutSnmpConnection);
461 comm_close(theOutSnmpConnection);
462 }
463 }
464
465 /*
466 * Functions for handling the requests.
467 */
468
469 /*
470 * Accept the UDP packet
471 */
472 void
473 snmpHandleUdp(int sock, void *not_used)
474 {
475 LOCAL_ARRAY(char, buf, SNMP_REQUEST_SIZE);
476
477 struct sockaddr_in from;
478 socklen_t from_len;
479 snmp_request_t *snmp_rq;
480 int len;
481
482 debug(49, 5) ("snmpHandleUdp: Called.\n");
483
484 commSetSelect(sock, COMM_SELECT_READ, snmpHandleUdp, NULL, 0);
485
486 from_len = sizeof(struct sockaddr_in);
487 memset(&from, '\0', from_len);
488 memset(buf, '\0', SNMP_REQUEST_SIZE);
489
490 len = comm_udp_recvfrom(sock,
491 buf,
492 SNMP_REQUEST_SIZE,
493 0,
494
495 (struct sockaddr *) &from,
496 &from_len);
497
498 if (len > 0) {
499 buf[len] = '\0';
500 debug(49, 3) ("snmpHandleUdp: FD %d: received %d bytes from %s.\n",
501 sock,
502 len,
503 inet_ntoa(from.sin_addr));
504
505 snmp_rq = (snmp_request_t *)xcalloc(1, sizeof(snmp_request_t));
506 snmp_rq->buf = (u_char *) buf;
507 snmp_rq->len = len;
508 snmp_rq->sock = sock;
509 snmp_rq->outbuf = (unsigned char *)xmalloc(snmp_rq->outlen = SNMP_REQUEST_SIZE);
510
511 xmemcpy(&snmp_rq->from, &from, sizeof(struct sockaddr_in));
512 snmpDecodePacket(snmp_rq);
513 xfree(snmp_rq->outbuf);
514 xfree(snmp_rq);
515 } else {
516 debug(49, 1) ("snmpHandleUdp: FD %d recvfrom: %s\n", sock, 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
527 struct snmp_pdu *PDU;
528
529 u_char *Community;
530 u_char *buf = rq->buf;
531 int len = rq->len;
532 int allow = 0;
533
534 debug(49, 5) ("snmpDecodePacket: Called.\n");
535 /* Now that we have the data, turn it into a PDU */
536 PDU = snmp_pdu_create(0);
537 rq->session.Version = SNMP_VERSION_1;
538 Community = snmp_parse(&rq->session, PDU, buf, len);
539 ACLChecklist checklist;
540 checklist.src_addr = rq->from.sin_addr;
541 checklist.snmp_community = (char *) Community;
542 checklist.accessList = Config.accessList.snmp;
543
544 if (Community)
545 allow = checklist.fastCheck();
546
547 checklist.accessList = NULL;
548
549 if ((snmp_coexist_V2toV1(PDU)) && (Community) && (allow)) {
550 rq->community = Community;
551 rq->PDU = PDU;
552 debug(49, 5) ("snmpAgentParse: reqid=[%d]\n", PDU->reqid);
553 snmpConstructReponse(rq);
554 } else {
555 debug(49, 1) ("Failed SNMP agent query from : %s.\n",
556 inet_ntoa(rq->from.sin_addr));
557 snmp_free_pdu(PDU);
558 }
559
560 if (Community)
561 xfree(Community);
562 }
563
564 /*
565 * Packet OK, ACL Check OK, Create reponse.
566 */
567 static void
568 snmpConstructReponse(snmp_request_t * rq)
569 {
570
571 struct snmp_pdu *RespPDU;
572
573 debug(49, 5) ("snmpConstructReponse: Called.\n");
574 RespPDU = snmpAgentResponse(rq->PDU);
575 snmp_free_pdu(rq->PDU);
576
577 if (RespPDU != NULL) {
578 snmp_build(&rq->session, RespPDU, rq->outbuf, &rq->outlen);
579 comm_udp_sendto(rq->sock, &rq->from, sizeof(rq->from), rq->outbuf, rq->outlen);
580 snmp_free_pdu(RespPDU);
581 }
582 }
583
584 /*
585 * Decide how to respond to the request, construct a response and
586 * return the response to the requester.
587 */
588
589 static struct snmp_pdu *
590
591 snmpAgentResponse(struct snmp_pdu *PDU)
592 {
593
594 struct snmp_pdu *Answer = NULL;
595
596 debug(49, 5) ("snmpAgentResponse: Called.\n");
597
598 if ((Answer = snmp_pdu_create(SNMP_PDU_RESPONSE)))
599 {
600 Answer->reqid = PDU->reqid;
601 Answer->errindex = 0;
602
603 if (PDU->command == SNMP_PDU_GET || PDU->command == SNMP_PDU_GETNEXT) {
604 int get_next = (PDU->command == SNMP_PDU_GETNEXT);
605 variable_list *VarPtr_;
606 variable_list **RespVars = &(Answer->variables);
607 oid_ParseFn *ParseFn;
608 int index = 0;
609 /* Loop through all variables */
610
611 for (VarPtr_ = PDU->variables; VarPtr_; VarPtr_ = VarPtr_->next_variable) {
612 variable_list *VarPtr = VarPtr_;
613 variable_list *VarNew = NULL;
614 oid *NextOidName = NULL;
615 snint NextOidNameLen = 0;
616
617 index++;
618
619 /* Find the parsing function for this variable */
620
621 if (get_next)
622 ParseFn = snmpTreeNext(VarPtr->name, VarPtr->name_length, &NextOidName, &NextOidNameLen);
623 else
624 ParseFn = snmpTreeGet(VarPtr->name, VarPtr->name_length);
625
626 if (ParseFn == NULL) {
627 Answer->errstat = SNMP_ERR_NOSUCHNAME;
628 debug(49, 5) ("snmpAgentResponse: No such oid. ");
629 } else {
630 if (get_next) {
631 VarPtr = snmp_var_new(NextOidName, NextOidNameLen);
632 xfree(NextOidName);
633 }
634
635 VarNew = (*ParseFn) (VarPtr, (snint *) & (Answer->errstat));
636
637 if (get_next)
638 snmp_var_free(VarPtr);
639 }
640
641 /* Was there an error? */
642 if ((Answer->errstat != SNMP_ERR_NOERROR) || (VarNew == NULL)) {
643 Answer->errindex = index;
644 debug(49, 5) ("snmpAgentResponse: error.\n");
645
646 if (VarNew)
647 snmp_var_free(VarNew);
648
649 /* Free the already processed results, if any */
650 while ((VarPtr = Answer->variables) != NULL) {
651 Answer->variables = VarPtr->next_variable;
652 snmp_var_free(VarPtr);
653 }
654
655 /* Steal the original PDU list of variables for the error response */
656 Answer->variables = PDU->variables;
657
658 PDU->variables = NULL;
659
660 return (Answer);
661 }
662
663 /* No error. Insert this var at the end, and move on to the next.
664 */
665 *RespVars = VarNew;
666
667 RespVars = &(VarNew->next_variable);
668 }
669 }
670 }
671
672 return (Answer);
673 }
674
675 static oid_ParseFn *
676 snmpTreeGet(oid * Current, snint CurrentLen)
677 {
678 oid_ParseFn *Fn = NULL;
679 mib_tree_entry *mibTreeEntry = NULL;
680 int count = 0;
681
682 debug(49, 5) ("snmpTreeGet: Called\n");
683
684 debug(49, 6) ("snmpTreeGet: Current : \n");
685 snmpDebugOid(6, Current, CurrentLen);
686
687 mibTreeEntry = mib_tree_head;
688
689 if (Current[count] == mibTreeEntry->name[count]) {
690 count++;
691
692 while ((mibTreeEntry) && (count < CurrentLen) && (!mibTreeEntry->parsefunction)) {
693 mibTreeEntry = snmpTreeEntry(Current[count], count, mibTreeEntry);
694 count++;
695 }
696 }
697
698 if (mibTreeEntry && mibTreeEntry->parsefunction)
699 Fn = mibTreeEntry->parsefunction;
700
701 debug(49, 5) ("snmpTreeGet: return\n");
702
703 return (Fn);
704 }
705
706 static oid_ParseFn *
707 snmpTreeNext(oid * Current, snint CurrentLen, oid ** Next, snint * NextLen)
708 {
709 oid_ParseFn *Fn = NULL;
710 mib_tree_entry *mibTreeEntry = NULL, *nextoid = NULL;
711 int count = 0;
712
713 debug(49, 5) ("snmpTreeNext: Called\n");
714
715 debug(49, 6) ("snmpTreeNext: Current : \n");
716 snmpDebugOid(6, Current, CurrentLen);
717
718 mibTreeEntry = mib_tree_head;
719
720 if (Current[count] == mibTreeEntry->name[count]) {
721 count++;
722
723 while ((mibTreeEntry) && (count < CurrentLen) && (!mibTreeEntry->parsefunction)) {
724 mibTreeEntry = snmpTreeEntry(Current[count], count, mibTreeEntry);
725 count++;
726 }
727
728 debug(49, 5) ("snmpTreeNext: Recursed down to requested object\n");
729 } else {
730 return NULL;
731 }
732
733 if (mibTreeEntry == mib_tree_last)
734 return (Fn);
735
736 if ((mibTreeEntry) && (mibTreeEntry->parsefunction)) {
737 *NextLen = CurrentLen;
738 *Next = (*mibTreeEntry->instancefunction) (Current, NextLen, mibTreeEntry, &Fn);
739
740 if (*Next)
741 return (Fn);
742 }
743
744 if ((mibTreeEntry) && (mibTreeEntry->parsefunction)) {
745 count--;
746 nextoid = snmpTreeSiblingEntry(Current[count], count, mibTreeEntry->parent);
747
748 if (nextoid) {
749 debug(49, 5) ("snmpTreeNext: Next OID found for sibling\n");
750 mibTreeEntry = nextoid;
751 count++;
752 } else {
753 debug(49, 5) ("snmpTreeNext: Attempting to recurse up for next object\n");
754
755 while (!nextoid) {
756 count--;
757
758 if (mibTreeEntry->parent->parent) {
759 nextoid = mibTreeEntry->parent;
760 mibTreeEntry = snmpTreeEntry(Current[count] + 1, count, nextoid->parent);
761
762 if (!mibTreeEntry) {
763 mibTreeEntry = nextoid;
764 nextoid = NULL;
765 }
766 } else {
767 nextoid = mibTreeEntry;
768 mibTreeEntry = NULL;
769 }
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 return (Fn);
785 else
786 return NULL;
787 }
788
789 static oid *
790 static_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn)
791 {
792 oid *instance = NULL;
793
794 if (*len <= current->len) {
795 instance = (oid *)xmalloc(sizeof(name) * (*len + 1));
796 xmemcpy(instance, name, (sizeof(name) * *len));
797 instance[*len] = 0;
798 *len += 1;
799 }
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] =
811 {TIME_INDEX};
812
813 if (*len <= current->len) {
814 instance = (oid *)xmalloc(sizeof(name) * (*len + 1));
815 xmemcpy(instance, name, (sizeof(name) * *len));
816 instance[*len] = *index;
817 *len += 1;
818 } else {
819 identifier = name[*len - 1];
820
821 while ((identifier != index[loop]) && (loop < TIME_INDEX_LEN))
822 loop++;
823
824 if (loop < TIME_INDEX_LEN - 1) {
825 instance = (oid *)xmalloc(sizeof(name) * (*len));
826 xmemcpy(instance, name, (sizeof(name) * *len));
827 instance[*len - 1] = index[++loop];
828 }
829 }
830
831 *Fn = current->parsefunction;
832 return (instance);
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 u_char *cp = NULL;
840 peer *peers = Config.peers;
841
842 struct IN_ADDR *laddr = NULL;
843 char *host_addr = NULL, *current_addr = NULL, *last_addr = NULL;
844
845 if (peers == NULL) {
846 current = current->parent->parent->parent->leaves[1];
847
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 + 4));
854 xmemcpy(instance, name, (sizeof(name) * *len));
855 cp = (u_char *) & (peers->in_addr.sin_addr.s_addr);
856 instance[*len] = *cp++;
857 instance[*len + 1] = *cp++;
858 instance[*len + 2] = *cp++;
859 instance[*len + 3] = *cp++;
860 *len += 4;
861 } else {
862 laddr = oid2addr(&name[*len - 4]);
863 host_addr = inet_ntoa(*laddr);
864 last_addr = (char *)xmalloc(strlen(host_addr));
865 strncpy(last_addr, host_addr, strlen(host_addr));
866 current_addr = inet_ntoa(peers->in_addr.sin_addr);
867
868 while ((peers) && (strncmp(last_addr, current_addr, strlen(current_addr)))) {
869 if (peers->next) {
870 peers = peers->next;
871 current_addr = inet_ntoa(peers->in_addr.sin_addr);
872 } else {
873 peers = NULL;
874 }
875 }
876
877 xfree(last_addr);
878
879 if (peers) {
880 if (peers->next) {
881 peers = peers->next;
882 instance = (oid *)xmalloc(sizeof(name) * (*len));
883 xmemcpy(instance, name, (sizeof(name) * *len));
884 cp = (u_char *) & (peers->in_addr.sin_addr.s_addr);
885 instance[*len - 4] = *cp++;
886 instance[*len - 3] = *cp++;
887 instance[*len - 2] = *cp++;
888 instance[*len - 1] = *cp++;
889 } else {
890 return (instance);
891 }
892 } else {
893 return (instance);
894 }
895 }
896
897 *Fn = current->parsefunction;
898 return (instance);
899 }
900
901 static oid *
902 client_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn)
903 {
904 oid *instance = NULL;
905 u_char *cp = NULL;
906
907 struct IN_ADDR *laddr = NULL;
908
909 if (*len <= current->len) {
910 instance = (oid *)xmalloc(sizeof(name) * (*len + 4));
911 xmemcpy(instance, name, (sizeof(name) * *len));
912 laddr = client_entry(NULL);
913
914 if (laddr) {
915 cp = (u_char *) & (laddr->s_addr);
916 instance[*len] = *cp++;
917 instance[*len + 1] = *cp++;
918 instance[*len + 2] = *cp++;
919 instance[*len + 3] = *cp++;
920 *len += 4;
921 }
922 } else {
923 laddr = oid2addr(&name[*len - 4]);
924 laddr = client_entry(laddr);
925
926 if (laddr) {
927 instance = (oid *)xmalloc(sizeof(name) * (*len));
928 xmemcpy(instance, name, (sizeof(name) * *len));
929 cp = (u_char *) & (laddr->s_addr);
930 instance[*len - 4] = *cp++;
931 instance[*len - 3] = *cp++;
932 instance[*len - 2] = *cp++;
933 instance[*len - 1] = *cp++;
934 }
935 }
936
937 *Fn = current->parsefunction;
938 return (instance);
939 }
940
941
942 /*
943 * Utility functions
944 */
945
946 /*
947 * Tree utility functions.
948 */
949
950 /*
951 * Returns a the sibling object in the tree
952 */
953 static mib_tree_entry *
954 snmpTreeSiblingEntry(oid entry, snint len, mib_tree_entry * current)
955 {
956 mib_tree_entry *next = NULL;
957 int count = 0;
958
959 while ((!next) && (count < current->children)) {
960 if (current->leaves[count]->name[len] == entry) {
961 next = current->leaves[count];
962 }
963
964 count++;
965 }
966
967 if (count < current->children) {
968 next = current->leaves[count];
969 } else {
970 next = NULL;
971 }
972
973 return (next);
974 }
975
976 /*
977 * Returns the requested child object or NULL if it does not exist
978 */
979 static mib_tree_entry *
980 snmpTreeEntry(oid entry, snint len, mib_tree_entry * current)
981 {
982 mib_tree_entry *next = NULL;
983 int count = 0;
984
985 while ((!next) && (count < current->children)) {
986 if (current->leaves[count]->name[len] == entry) {
987 next = current->leaves[count];
988 }
989
990 count++;
991 }
992
993 return (next);
994 }
995
996 /*
997 * Adds a node to the MIB tree structure and adds the appropriate children
998 */
999 static mib_tree_entry *
1000 #if STDC_HEADERS
1001 snmpAddNode(oid * name, int len, oid_ParseFn * parsefunction, instance_Fn * instancefunction, int children,...)
1002 #else
1003 snmpAddNode(va_alist)
1004 va_dcl
1005 #endif
1006 {
1007 #if STDC_HEADERS
1008 va_list args;
1009 int loop;
1010 mib_tree_entry *entry = NULL;
1011 va_start(args, children);
1012 #else
1013
1014 va_list args;
1015 oid *name = NULL;
1016 int len = 0, children = 0, loop;
1017 oid_ParseFn *parsefunction = NULL;
1018 instance_Fn *instancefunction = NULL;
1019 mib_tree_entry *entry = NULL;
1020 va_start(args);
1021 name = va_arg(args, oid *);
1022 len = va_arg(args, int);
1023 parsefunction = va_arg(args, oid_ParseFn *);
1024 instancefunction = va_arg(args, instance_Fn *);
1025 children = va_arg(args, int);
1026 #endif
1027
1028 debug(49, 6) ("snmpAddNode: Children : %d, Oid : \n", children);
1029 snmpDebugOid(6, name, len);
1030
1031 va_start(args, children);
1032 entry = (mib_tree_entry *)xmalloc(sizeof(mib_tree_entry));
1033 entry->name = name;
1034 entry->len = len;
1035 entry->parsefunction = parsefunction;
1036 entry->instancefunction = instancefunction;
1037 entry->children = children;
1038
1039 if (children > 0)
1040 {
1041 entry->leaves = (mib_tree_entry **)xmalloc(sizeof(mib_tree_entry *) * children);
1042
1043 for (loop = 0; loop < children; loop++) {
1044 entry->leaves[loop] = va_arg(args, mib_tree_entry *);
1045 entry->leaves[loop]->parent = entry;
1046 }
1047 }
1048
1049 return (entry);
1050 }
1051 /* End of tree utility functions */
1052
1053 /*
1054 * Returns the list of parameters in an oid
1055 */
1056 static oid *
1057 #if STDC_HEADERS
1058 snmpCreateOid(int length,...)
1059 #else
1060 snmpCreateOid(va_alist)
1061 va_dcl
1062 #endif
1063 {
1064 #if STDC_HEADERS
1065 va_list args;
1066 oid *new_oid;
1067 int loop;
1068 va_start(args, length);
1069 #else
1070
1071 va_list args;
1072 int length = 0, loop;
1073 oid *new_oid;
1074 va_start(args);
1075 length va_arg(args, int);
1076 #endif
1077
1078 new_oid = (oid *)xmalloc(sizeof(oid) * length);
1079
1080 if (length > 0)
1081 {
1082 for (loop = 0; loop < length; loop++) {
1083 new_oid[loop] = va_arg(args, int);
1084 }
1085 }
1086
1087 return (new_oid);
1088 }
1089
1090 #if UNUSED_CODE
1091 /*
1092 * Allocate space for, and copy, an OID. Returns new oid.
1093 */
1094 static oid *
1095 snmpOidDup(oid * A, snint ALen)
1096 {
1097 oid *Ans = xmalloc(sizeof(oid) * ALen);
1098 xmemcpy(Ans, A, (sizeof(oid) * ALen));
1099 return Ans;
1100 }
1101
1102 #endif
1103
1104 /*
1105 * Debug calls, prints out the OID for debugging purposes.
1106 */
1107 void
1108 snmpDebugOid(int lvl, oid * Name, snint Len)
1109 {
1110 char mbuf[16], objid[1024];
1111 int x;
1112 objid[0] = '\0';
1113
1114 for (x = 0; x < Len; x++) {
1115 snprintf(mbuf, sizeof(mbuf), ".%u", (unsigned int) Name[x]);
1116 strncat(objid, mbuf, sizeof(objid));
1117 }
1118
1119 debug(49, lvl) (" oid = %s\n", objid);
1120 }
1121
1122 static void
1123 snmpSnmplibDebug(int lvl, char *buf)
1124 {
1125 debug(49, lvl) ("%s", buf);
1126 }
1127
1128 void
1129
1130 addr2oid(struct IN_ADDR addr, oid * Dest)
1131 {
1132 u_char *cp;
1133 cp = (u_char *) & (addr.s_addr);
1134 Dest[0] = *cp++;
1135 Dest[1] = *cp++;
1136 Dest[2] = *cp++;
1137 Dest[3] = *cp++;
1138 }
1139
1140 struct IN_ADDR
1141 *
1142 oid2addr(oid * id)
1143 {
1144
1145 static struct IN_ADDR laddr;
1146 u_char *cp = (u_char *) & (laddr.s_addr);
1147 cp[0] = id[0];
1148 cp[1] = id[1];
1149 cp[2] = id[2];
1150 cp[3] = id[3];
1151 return &laddr;
1152 }
1153
1154 /* SNMP checklists */
1155 #include "ACLStrategy.h"
1156 #include "ACLStrategised.h"
1157 #include "ACLStringData.h"
1158
1159 class ACLSNMPCommunityStrategy : public ACLStrategy<char const *>
1160 {
1161
1162 public:
1163 virtual int match (ACLData<MatchType> * &, ACLChecklist *);
1164 static ACLSNMPCommunityStrategy *Instance();
1165 /* Not implemented to prevent copies of the instance. */
1166 /* Not private to prevent brain dead g+++ warnings about
1167 * private constructors with no friends */
1168 ACLSNMPCommunityStrategy(ACLSNMPCommunityStrategy const &);
1169
1170 private:
1171 static ACLSNMPCommunityStrategy Instance_;
1172 ACLSNMPCommunityStrategy(){}
1173
1174 ACLSNMPCommunityStrategy&operator=(ACLSNMPCommunityStrategy const &);
1175 };
1176
1177 class ACLSNMPCommunity
1178 {
1179
1180 private:
1181 static ACL::Prototype RegistryProtoype;
1182 static ACLStrategised<char const *> RegistryEntry_;
1183 };
1184
1185 ACL::Prototype ACLSNMPCommunity::RegistryProtoype(&ACLSNMPCommunity::RegistryEntry_, "snmp_community");
1186 ACLStrategised<char const *> ACLSNMPCommunity::RegistryEntry_(new ACLStringData, ACLSNMPCommunityStrategy::Instance(), "snmp_community");
1187
1188 int
1189 ACLSNMPCommunityStrategy::match (ACLData<MatchType> * &data, ACLChecklist *checklist)
1190 {
1191 return data->match (checklist->snmp_community);
1192 ;
1193 }
1194
1195 ACLSNMPCommunityStrategy *
1196 ACLSNMPCommunityStrategy::Instance()
1197 {
1198 return &Instance_;
1199 }
1200
1201 ACLSNMPCommunityStrategy ACLSNMPCommunityStrategy::Instance_;