]> git.ipfire.org Git - thirdparty/squid.git/blob - src/snmp_core.cc
Summary: More Windows Merges.
[thirdparty/squid.git] / src / snmp_core.cc
1
2 /*
3 * $Id: snmp_core.cc,v 1.63 2003/02/23 00:08:04 robertc 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 struct snmp_session Session;
530 u_char *Community;
531 u_char *buf = rq->buf;
532 int len = rq->len;
533 int allow = 0;
534
535 debug(49, 5) ("snmpDecodePacket: Called.\n");
536 /* Now that we have the data, turn it into a PDU */
537 PDU = snmp_pdu_create(0);
538 Session.Version = SNMP_VERSION_1;
539 Community = snmp_parse(&Session, PDU, buf, len);
540 ACLChecklist checklist;
541 checklist.src_addr = rq->from.sin_addr;
542 checklist.snmp_community = (char *) Community;
543
544 if (Community)
545 allow = aclCheckFast(Config.accessList.snmp, &checklist);
546
547 if ((snmp_coexist_V2toV1(PDU)) && (Community) && (allow)) {
548 rq->community = Community;
549 rq->PDU = PDU;
550 debug(49, 5) ("snmpAgentParse: reqid=[%d]\n", PDU->reqid);
551 snmpConstructReponse(rq);
552 } else {
553 debug(49, 1) ("Failed SNMP agent query from : %s.\n",
554 inet_ntoa(rq->from.sin_addr));
555 snmp_free_pdu(PDU);
556 }
557
558 if (Community)
559 xfree(Community);
560 }
561
562 /*
563 * Packet OK, ACL Check OK, Create reponse.
564 */
565 static void
566 snmpConstructReponse(snmp_request_t * rq)
567 {
568
569 struct snmp_session Session;
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 Session.Version = SNMP_VERSION_1;
579 Session.community = rq->community;
580 Session.community_len = strlen((char *) rq->community);
581 snmp_build(&Session, RespPDU, rq->outbuf, &rq->outlen);
582 comm_udp_sendto(rq->sock, &rq->from, sizeof(rq->from), rq->outbuf, rq->outlen);
583 snmp_free_pdu(RespPDU);
584 }
585 }
586
587 /*
588 * Decide how to respond to the request, construct a response and
589 * return the response to the requester.
590 */
591
592 static struct snmp_pdu *
593
594 snmpAgentResponse(struct snmp_pdu *PDU)
595 {
596
597 struct snmp_pdu *Answer = NULL;
598 oid_ParseFn *ParseFn = NULL;
599
600 variable_list *VarPtr, *VarNew = NULL, **VarPtrP;
601 int index = 0;
602
603 debug(49, 5) ("snmpAgentResponse: Called.\n");
604
605 if ((Answer = snmp_pdu_create(SNMP_PDU_RESPONSE)))
606 {
607 Answer->reqid = PDU->reqid;
608 Answer->errindex = 0;
609
610 if (PDU->command == SNMP_PDU_GET) {
611 variable_list **RespVars;
612
613 RespVars = &(Answer->variables);
614 /* Loop through all variables */
615
616 for (VarPtrP = &(PDU->variables);
617 *VarPtrP;
618 VarPtrP = &((*VarPtrP)->next_variable)) {
619 VarPtr = *VarPtrP;
620
621 index++;
622
623 /* Find the parsing function for this variable */
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 VarNew = (*ParseFn) (VarPtr, (snint *) & (Answer->errstat));
631
632 /* Was there an error? */
633 if ((Answer->errstat != SNMP_ERR_NOERROR) ||
634 (VarNew == NULL)) {
635 Answer->errindex = index;
636 debug(49, 5) ("snmpAgentParse: successful.\n");
637 /* Just copy the rest of the variables. Quickly. */
638 *RespVars = VarPtr;
639 *VarPtrP = NULL;
640 return (Answer);
641 }
642
643 /* No error. Insert this var at the end, and move on to the next.
644 */
645 *RespVars = VarNew;
646
647 RespVars = &(VarNew->next_variable);
648 }
649
650 return (Answer);
651 } else if (PDU->command == SNMP_PDU_GETNEXT) {
652 oid *NextOidName = NULL;
653 int NextOidNameLen = 0;
654
655 ParseFn = snmpTreeNext(PDU->variables->name, PDU->variables->name_length,
656 &(NextOidName), (snint *) & NextOidNameLen);
657
658 if (ParseFn == NULL) {
659 Answer->errstat = SNMP_ERR_NOSUCHNAME;
660 debug(49, 5) ("snmpAgentResponse: No such oid: ");
661 snmpDebugOid(5, PDU->variables->name, PDU->variables->name_length);
662 } else {
663 xfree(PDU->variables->name);
664 PDU->variables->name = NextOidName;
665 PDU->variables->name_length = NextOidNameLen;
666 VarNew = (*ParseFn) (PDU->variables, (snint *) & Answer->errstat);
667 }
668
669 /* Was there an error? */
670 if (Answer->errstat != SNMP_ERR_NOERROR) {
671 Answer->errindex = 1;
672 Answer->variables = PDU->variables;
673 PDU->variables = NULL;
674 } else {
675 Answer->variables = VarNew;
676 }
677
678 } else {
679 snmp_free_pdu(Answer);
680 Answer = NULL;
681 }
682 }
683
684 return (Answer);
685 }
686
687 static oid_ParseFn *
688 snmpTreeGet(oid * Current, snint CurrentLen)
689 {
690 oid_ParseFn *Fn = NULL;
691 mib_tree_entry *mibTreeEntry = NULL;
692 int count = 0;
693
694 debug(49, 5) ("snmpTreeGet: Called\n");
695
696 debug(49, 6) ("snmpTreeGet: Current : \n");
697 snmpDebugOid(6, Current, CurrentLen);
698
699 mibTreeEntry = mib_tree_head;
700
701 if (Current[count] == mibTreeEntry->name[count]) {
702 count++;
703
704 while ((mibTreeEntry) && (count < CurrentLen) && (!mibTreeEntry->parsefunction)) {
705 mibTreeEntry = snmpTreeEntry(Current[count], count, mibTreeEntry);
706 count++;
707 }
708 }
709
710 if (mibTreeEntry && mibTreeEntry->parsefunction)
711 Fn = mibTreeEntry->parsefunction;
712
713 debug(49, 5) ("snmpTreeGet: return\n");
714
715 return (Fn);
716 }
717
718 static oid_ParseFn *
719 snmpTreeNext(oid * Current, snint CurrentLen, oid ** Next, snint * NextLen)
720 {
721 oid_ParseFn *Fn = NULL;
722 mib_tree_entry *mibTreeEntry = NULL, *nextoid = NULL;
723 int count = 0;
724
725 debug(49, 5) ("snmpTreeNext: Called\n");
726
727 debug(49, 6) ("snmpTreeNext: Current : \n");
728 snmpDebugOid(6, Current, CurrentLen);
729
730 mibTreeEntry = mib_tree_head;
731
732 if (Current[count] == mibTreeEntry->name[count]) {
733 count++;
734
735 while ((mibTreeEntry) && (count < CurrentLen) && (!mibTreeEntry->parsefunction)) {
736 mibTreeEntry = snmpTreeEntry(Current[count], count, mibTreeEntry);
737 count++;
738 }
739
740 debug(49, 5) ("snmpTreeNext: Recursed down to requested object\n");
741 } else {
742 return NULL;
743 }
744
745 if (mibTreeEntry == mib_tree_last)
746 return (Fn);
747
748 if ((mibTreeEntry) && (mibTreeEntry->parsefunction)) {
749 *NextLen = CurrentLen;
750 *Next = (*mibTreeEntry->instancefunction) (Current, NextLen, mibTreeEntry, &Fn);
751
752 if (*Next)
753 return (Fn);
754 }
755
756 if ((mibTreeEntry) && (mibTreeEntry->parsefunction)) {
757 count--;
758 nextoid = snmpTreeSiblingEntry(Current[count], count, mibTreeEntry->parent);
759
760 if (nextoid) {
761 debug(49, 5) ("snmpTreeNext: Next OID found for sibling\n");
762 mibTreeEntry = nextoid;
763 count++;
764 } else {
765 debug(49, 5) ("snmpTreeNext: Attempting to recurse up for next object\n");
766
767 while (!nextoid) {
768 count--;
769
770 if (mibTreeEntry->parent->parent) {
771 nextoid = mibTreeEntry->parent;
772 mibTreeEntry = snmpTreeEntry(Current[count] + 1, count, nextoid->parent);
773
774 if (!mibTreeEntry) {
775 mibTreeEntry = nextoid;
776 nextoid = NULL;
777 }
778 } else {
779 nextoid = mibTreeEntry;
780 mibTreeEntry = NULL;
781 }
782 }
783 }
784 }
785
786 while ((mibTreeEntry) && (!mibTreeEntry->parsefunction)) {
787 mibTreeEntry = mibTreeEntry->leaves[0];
788 }
789
790 if (mibTreeEntry) {
791 *NextLen = mibTreeEntry->len;
792 *Next = (*mibTreeEntry->instancefunction) (mibTreeEntry->name, NextLen, mibTreeEntry, &Fn);
793 }
794
795 if (*Next)
796 return (Fn);
797 else
798 return NULL;
799 }
800
801 static oid *
802 static_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn)
803 {
804 oid *instance = NULL;
805
806 if (*len <= current->len) {
807 instance = (oid *)xmalloc(sizeof(name) * (*len + 1));
808 xmemcpy(instance, name, (sizeof(name) * *len));
809 instance[*len] = 0;
810 *len += 1;
811 }
812
813 *Fn = current->parsefunction;
814 return (instance);
815 }
816
817 static oid *
818 time_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn)
819 {
820 oid *instance = NULL;
821 int identifier = 0, loop = 0;
822 int index[TIME_INDEX_LEN] =
823 {TIME_INDEX};
824
825 if (*len <= current->len) {
826 instance = (oid *)xmalloc(sizeof(name) * (*len + 1));
827 xmemcpy(instance, name, (sizeof(name) * *len));
828 instance[*len] = *index;
829 *len += 1;
830 } else {
831 identifier = name[*len - 1];
832
833 while ((identifier != index[loop]) && (loop < TIME_INDEX_LEN))
834 loop++;
835
836 if (loop < TIME_INDEX_LEN - 1) {
837 instance = (oid *)xmalloc(sizeof(name) * (*len));
838 xmemcpy(instance, name, (sizeof(name) * *len));
839 instance[*len - 1] = index[++loop];
840 }
841 }
842
843 *Fn = current->parsefunction;
844 return (instance);
845 }
846
847 static oid *
848 peer_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn)
849 {
850 oid *instance = NULL;
851 u_char *cp = NULL;
852 peer *peers = Config.peers;
853
854 struct in_addr *laddr = NULL;
855 char *host_addr = NULL, *current_addr = NULL, *last_addr = NULL;
856
857 if (peers == NULL) {
858 current = current->parent->parent->parent->leaves[1];
859
860 while ((current) && (!current->parsefunction))
861 current = current->leaves[0];
862
863 instance = client_Inst(current->name, len, current, Fn);
864 } else if (*len <= current->len) {
865 instance = (oid *)xmalloc(sizeof(name) * (*len + 4));
866 xmemcpy(instance, name, (sizeof(name) * *len));
867 cp = (u_char *) & (peers->in_addr.sin_addr.s_addr);
868 instance[*len] = *cp++;
869 instance[*len + 1] = *cp++;
870 instance[*len + 2] = *cp++;
871 instance[*len + 3] = *cp++;
872 *len += 4;
873 } else {
874 laddr = oid2addr(&name[*len - 4]);
875 host_addr = inet_ntoa(*laddr);
876 last_addr = (char *)xmalloc(strlen(host_addr));
877 strncpy(last_addr, host_addr, strlen(host_addr));
878 current_addr = inet_ntoa(peers->in_addr.sin_addr);
879
880 while ((peers) && (strncmp(last_addr, current_addr, strlen(current_addr)))) {
881 if (peers->next) {
882 peers = peers->next;
883 current_addr = inet_ntoa(peers->in_addr.sin_addr);
884 } else {
885 peers = NULL;
886 }
887 }
888
889 xfree(last_addr);
890
891 if (peers) {
892 if (peers->next) {
893 peers = peers->next;
894 instance = (oid *)xmalloc(sizeof(name) * (*len));
895 xmemcpy(instance, name, (sizeof(name) * *len));
896 cp = (u_char *) & (peers->in_addr.sin_addr.s_addr);
897 instance[*len - 4] = *cp++;
898 instance[*len - 3] = *cp++;
899 instance[*len - 2] = *cp++;
900 instance[*len - 1] = *cp++;
901 } else {
902 return (instance);
903 }
904 } else {
905 return (instance);
906 }
907 }
908
909 *Fn = current->parsefunction;
910 return (instance);
911 }
912
913 static oid *
914 client_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn)
915 {
916 oid *instance = NULL;
917 u_char *cp = NULL;
918
919 struct in_addr *laddr = NULL;
920
921 if (*len <= current->len) {
922 instance = (oid *)xmalloc(sizeof(name) * (*len + 4));
923 xmemcpy(instance, name, (sizeof(name) * *len));
924 laddr = client_entry(NULL);
925
926 if (laddr) {
927 cp = (u_char *) & (laddr->s_addr);
928 instance[*len] = *cp++;
929 instance[*len + 1] = *cp++;
930 instance[*len + 2] = *cp++;
931 instance[*len + 3] = *cp++;
932 *len += 4;
933 }
934 } else {
935 laddr = oid2addr(&name[*len - 4]);
936 laddr = client_entry(laddr);
937
938 if (laddr) {
939 instance = (oid *)xmalloc(sizeof(name) * (*len));
940 xmemcpy(instance, name, (sizeof(name) * *len));
941 cp = (u_char *) & (laddr->s_addr);
942 instance[*len - 4] = *cp++;
943 instance[*len - 3] = *cp++;
944 instance[*len - 2] = *cp++;
945 instance[*len - 1] = *cp++;
946 }
947 }
948
949 *Fn = current->parsefunction;
950 return (instance);
951 }
952
953
954 /*
955 * Utility functions
956 */
957
958 /*
959 * Tree utility functions.
960 */
961
962 /*
963 * Returns a the sibling object in the tree
964 */
965 static mib_tree_entry *
966 snmpTreeSiblingEntry(oid entry, snint len, mib_tree_entry * current)
967 {
968 mib_tree_entry *next = NULL;
969 int count = 0;
970
971 while ((!next) && (count < current->children)) {
972 if (current->leaves[count]->name[len] == entry) {
973 next = current->leaves[count];
974 }
975
976 count++;
977 }
978
979 if (count < current->children) {
980 next = current->leaves[count];
981 } else {
982 next = NULL;
983 }
984
985 return (next);
986 }
987
988 /*
989 * Returns the requested child object or NULL if it does not exist
990 */
991 static mib_tree_entry *
992 snmpTreeEntry(oid entry, snint len, mib_tree_entry * current)
993 {
994 mib_tree_entry *next = NULL;
995 int count = 0;
996
997 while ((!next) && (count < current->children)) {
998 if (current->leaves[count]->name[len] == entry) {
999 next = current->leaves[count];
1000 }
1001
1002 count++;
1003 }
1004
1005 return (next);
1006 }
1007
1008 /*
1009 * Adds a node to the MIB tree structure and adds the appropriate children
1010 */
1011 static mib_tree_entry *
1012 #if STDC_HEADERS
1013 snmpAddNode(oid * name, int len, oid_ParseFn * parsefunction, instance_Fn * instancefunction, int children,...)
1014 #else
1015 snmpAddNode(va_alist)
1016 va_dcl
1017 #endif
1018 {
1019 #if STDC_HEADERS
1020 va_list args;
1021 int loop;
1022 mib_tree_entry *entry = NULL;
1023 va_start(args, children);
1024 #else
1025
1026 va_list args;
1027 oid *name = NULL;
1028 int len = 0, children = 0, loop;
1029 oid_ParseFn *parsefunction = NULL;
1030 instance_Fn *instancefunction = NULL;
1031 mib_tree_entry *entry = NULL;
1032 va_start(args);
1033 name = va_arg(args, oid *);
1034 len = va_arg(args, int);
1035 parsefunction = va_arg(args, oid_ParseFn *);
1036 instancefunction = va_arg(args, instance_Fn *);
1037 children = va_arg(args, int);
1038 #endif
1039
1040 debug(49, 6) ("snmpAddNode: Children : %d, Oid : \n", children);
1041 snmpDebugOid(6, name, len);
1042
1043 va_start(args, children);
1044 entry = (mib_tree_entry *)xmalloc(sizeof(mib_tree_entry));
1045 entry->name = name;
1046 entry->len = len;
1047 entry->parsefunction = parsefunction;
1048 entry->instancefunction = instancefunction;
1049 entry->children = children;
1050
1051 if (children > 0)
1052 {
1053 entry->leaves = (mib_tree_entry **)xmalloc(sizeof(mib_tree_entry *) * children);
1054
1055 for (loop = 0; loop < children; loop++) {
1056 entry->leaves[loop] = va_arg(args, mib_tree_entry *);
1057 entry->leaves[loop]->parent = entry;
1058 }
1059 }
1060
1061 return (entry);
1062 }
1063 /* End of tree utility functions */
1064
1065 /*
1066 * Returns the list of parameters in an oid
1067 */
1068 static oid *
1069 #if STDC_HEADERS
1070 snmpCreateOid(int length,...)
1071 #else
1072 snmpCreateOid(va_alist)
1073 va_dcl
1074 #endif
1075 {
1076 #if STDC_HEADERS
1077 va_list args;
1078 oid *new_oid;
1079 int loop;
1080 va_start(args, length);
1081 #else
1082
1083 va_list args;
1084 int length = 0, loop;
1085 oid *new_oid;
1086 va_start(args);
1087 length va_arg(args, int);
1088 #endif
1089
1090 new_oid = (oid *)xmalloc(sizeof(oid) * length);
1091
1092 if (length > 0)
1093 {
1094 for (loop = 0; loop < length; loop++) {
1095 new_oid[loop] = va_arg(args, int);
1096 }
1097 }
1098
1099 return (new_oid);
1100 }
1101
1102 #if UNUSED_CODE
1103 /*
1104 * Allocate space for, and copy, an OID. Returns new oid.
1105 */
1106 static oid *
1107 snmpOidDup(oid * A, snint ALen)
1108 {
1109 oid *Ans = xmalloc(sizeof(oid) * ALen);
1110 xmemcpy(Ans, A, (sizeof(oid) * ALen));
1111 return Ans;
1112 }
1113
1114 #endif
1115
1116 /*
1117 * Debug calls, prints out the OID for debugging purposes.
1118 */
1119 void
1120 snmpDebugOid(int lvl, oid * Name, snint Len)
1121 {
1122 char mbuf[16], objid[1024];
1123 int x;
1124 objid[0] = '\0';
1125
1126 for (x = 0; x < Len; x++) {
1127 snprintf(mbuf, sizeof(mbuf), ".%u", (unsigned int) Name[x]);
1128 strncat(objid, mbuf, sizeof(objid));
1129 }
1130
1131 debug(49, lvl) (" oid = %s\n", objid);
1132 }
1133
1134 static void
1135 snmpSnmplibDebug(int lvl, char *buf)
1136 {
1137 debug(49, lvl) ("%s", buf);
1138 }
1139
1140 void
1141
1142 addr2oid(struct in_addr addr, oid * Dest)
1143 {
1144 u_char *cp;
1145 cp = (u_char *) & (addr.s_addr);
1146 Dest[0] = *cp++;
1147 Dest[1] = *cp++;
1148 Dest[2] = *cp++;
1149 Dest[3] = *cp++;
1150 }
1151
1152 struct in_addr
1153 *
1154 oid2addr(oid * id)
1155 {
1156
1157 static struct in_addr laddr;
1158 u_char *cp = (u_char *) & (laddr.s_addr);
1159 cp[0] = id[0];
1160 cp[1] = id[1];
1161 cp[2] = id[2];
1162 cp[3] = id[3];
1163 return &laddr;
1164 }