2 * $Id: snmp_core.cc,v 1.14 1998/11/12 06:28:23 wessels Exp $
4 * DEBUG: section 49 SNMP support
5 * AUTHOR: Glenn Chisholm
7 * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
8 * ----------------------------------------------------------
10 * Squid is the result of efforts by numerous individuals from the
11 * Internet community. Development is led by Duane Wessels of the
12 * National Laboratory for Applied Network Research and funded by the
13 * National Science Foundation. Squid is Copyrighted (C) 1998 by
14 * Duane Wessels and the University of California San Diego. Please
15 * see the COPYRIGHT file for full details. Squid incorporates
16 * software developed and/or copyrighted by other sources. Please see
17 * the CREDITS file for full details.
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2 of the License, or
22 * (at your option) any later version.
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
35 #include "cache_snmp.h"
37 #define SNMP_REQUEST_SIZE 4096
38 #define MAX_PROTOSTAT 5
40 struct _mib_tree_entry
{
43 oid_ParseFn
*parsefunction
;
45 struct _mib_tree_entry
**leaves
;
46 struct _mib_tree_entry
*parent
;
50 struct sockaddr_in address
;
53 struct _snmpUdpData
*next
;
56 typedef struct _snmpUdpData snmpUdpData
;
57 typedef struct _mib_tree_entry mib_tree_entry
;
59 mib_tree_entry
*mib_tree_head
;
60 snmpUdpData
*snmpUdpHead
= NULL
;
61 snmpUdpData
*snmpUdpTail
= NULL
;
63 extern void (*snmplib_debug_hook
) (int, char *);
65 static void snmpDecodePacket(snmp_request_t
* rq
);
66 static void snmpConstructReponse(snmp_request_t
* rq
, struct snmp_session
*Session
);
67 static struct snmp_pdu
*snmpAgentResponse(struct snmp_pdu
*PDU
);
69 static void snmpUdpSend(int, const struct sockaddr_in
*, void *, int);
70 static void snmpUdpReply(int, void *);
71 static void snmpAppendUdp(snmpUdpData
*);
74 static mib_tree_entry
*snmpAddNode(oid
* name
, int len
, oid_ParseFn
* parsefunction
, int children
,...);
75 static oid_ParseFn
*snmpTreeNext(oid
* Current
, snint CurrentLen
, oid
** Next
, snint
* NextLen
);
76 static mib_tree_entry
*snmpTreeEntry(oid entry
, snint len
, mib_tree_entry
* current
);
78 static oid
*snmpCreateOid(int length
,...);
79 static oid
*snmpOidDup(oid
* A
, snint ALen
);
80 static void snmpSnmplibDebug(int lvl
, char *buf
);
84 * The functions used during startup:
87 * snmpConnectionShutdown
92 * Turns the MIB into a Tree structure. Called during the startup process.
97 debug(49, 5) ("snmpInit: Called.\n");
99 debug(49, 5) ("snmpInit: Building SNMP mib tree structure\n");
101 snmplib_debug_hook
= snmpSnmplibDebug
;
103 mib_tree_head
= snmpAddNode(snmpCreateOid(1, 1),
105 snmpAddNode(snmpCreateOid(2, 1, 3),
107 snmpAddNode(snmpCreateOid(3, 1, 3, 6),
109 snmpAddNode(snmpCreateOid(4, 1, 3, 6, 1),
111 snmpAddNode(snmpCreateOid(5, 1, 3, 6, 1, 4),
113 snmpAddNode(snmpCreateOid(6, 1, 3, 6, 1, 4, 1),
115 snmpAddNode(snmpCreateOid(7, 1, 3, 6, 1, 4, 1, 3495),
117 snmpAddNode(snmpCreateOid(LEN_SQUIDMIB
, SQUIDMIB
),
119 snmpAddNode(snmpCreateOid(LEN_SQ_SYS
, SQ_SYS
),
121 snmpAddNode(snmpCreateOid(LEN_SQ_SYS
+ 1, SQ_SYS
, 1),
122 LEN_SQ_SYS
+ 1, snmp_sysFn
, 0),
123 snmpAddNode(snmpCreateOid(LEN_SQ_SYS
+ 1, SQ_SYS
, 2),
124 LEN_SQ_SYS
+ 1, snmp_sysFn
, 0),
125 snmpAddNode(snmpCreateOid(LEN_SQ_SYS
+ 1, SQ_SYS
, 3),
126 LEN_SQ_SYS
+ 1, snmp_sysFn
, 0)),
127 snmpAddNode(snmpCreateOid(LEN_SQ_CONF
, SQ_CONF
),
128 LEN_SQ_CONF
, NULL
, 5,
129 snmpAddNode(snmpCreateOid(LEN_SQ_CONF
+ 1, SQ_CONF
, 1),
130 LEN_SQ_CONF
+ 1, snmp_confFn
, 0),
131 snmpAddNode(snmpCreateOid(LEN_SQ_CONF
+ 1, SQ_CONF
, 2),
132 LEN_SQ_CONF
+ 1, snmp_confFn
, 0),
133 snmpAddNode(snmpCreateOid(LEN_SQ_CONF
+ 1, SQ_CONF
, 3),
134 LEN_SQ_CONF
+ 1, snmp_confFn
, 0),
135 snmpAddNode(snmpCreateOid(LEN_SQ_CONF
+ 1, SQ_CONF
, 4),
136 LEN_SQ_CONF
+ 1, snmp_confFn
, 0),
137 snmpAddNode(snmpCreateOid(LEN_SQ_CONF
+ 1, SQ_CONF
, 5),
138 LEN_SQ_CONF
+ 1, NULL
, 6,
139 snmpAddNode(snmpCreateOid(LEN_SQ_CONF
+ 2, SQ_CONF
, 5, 1),
140 LEN_SQ_CONF
+ 2, snmp_confFn
, 0),
141 snmpAddNode(snmpCreateOid(LEN_SQ_CONF
+ 2, SQ_CONF
, 5, 2),
142 LEN_SQ_CONF
+ 2, snmp_confFn
, 0),
143 snmpAddNode(snmpCreateOid(LEN_SQ_CONF
+ 2, SQ_CONF
, 5, 3),
144 LEN_SQ_CONF
+ 2, snmp_confFn
, 0),
145 snmpAddNode(snmpCreateOid(LEN_SQ_CONF
+ 2, SQ_CONF
, 5, 4),
146 LEN_SQ_CONF
+ 2, snmp_confFn
, 0),
147 snmpAddNode(snmpCreateOid(LEN_SQ_CONF
+ 2, SQ_CONF
, 5, 5),
148 LEN_SQ_CONF
+ 2, snmp_confFn
, 0),
149 snmpAddNode(snmpCreateOid(LEN_SQ_CONF
+ 2, SQ_CONF
, 5, 6),
150 LEN_SQ_CONF
+ 2, snmp_confFn
, 0))),
151 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
, SQ_PRF
),
152 LEN_SQ_PRF
, snmp_confFn
, 2,
153 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 1, SQ_PRF
, 1),
154 LEN_SQ_PRF
+ 1, snmp_sysFn
, 11,
155 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 2, SQ_PRF
, 1, 1),
156 LEN_SQ_PRF
+ 2, snmp_sysFn
, 0),
157 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 2, SQ_PRF
, 1, 2),
158 LEN_SQ_PRF
+ 2, snmp_sysFn
, 0),
159 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 2, SQ_PRF
, 1, 3),
160 LEN_SQ_PRF
+ 2, snmp_sysFn
, 0),
161 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 2, SQ_PRF
, 1, 4),
162 LEN_SQ_PRF
+ 2, snmp_sysFn
, 0),
163 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 2, SQ_PRF
, 1, 5),
164 LEN_SQ_PRF
+ 2, snmp_sysFn
, 0),
165 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 2, SQ_PRF
, 1, 6),
166 LEN_SQ_PRF
+ 2, snmp_sysFn
, 0),
167 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 2, SQ_PRF
, 1, 7),
168 LEN_SQ_PRF
+ 2, snmp_sysFn
, 0),
169 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 2, SQ_PRF
, 1, 8),
170 LEN_SQ_PRF
+ 2, snmp_sysFn
, 0),
171 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 2, SQ_PRF
, 1, 9),
172 LEN_SQ_PRF
+ 2, snmp_sysFn
, 0),
173 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 2, SQ_PRF
, 1, 10),
174 LEN_SQ_PRF
+ 2, snmp_sysFn
, 0),
175 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 2, SQ_PRF
, 1, 11),
176 LEN_SQ_PRF
+ 2, snmp_sysFn
, 0)),
177 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 1, SQ_PRF
, 2),
178 LEN_SQ_PRF
+ 1, snmp_sysFn
, 2,
179 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 2, SQ_PRF
, 2, 1),
180 LEN_SQ_PRF
+ 2, snmp_sysFn
, 14,
181 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 3, SQ_PRF
, 2, 1, 1),
182 LEN_SQ_PRF
+ 3, snmp_sysFn
, 0),
183 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 3, SQ_PRF
, 2, 1, 2),
184 LEN_SQ_PRF
+ 3, snmp_sysFn
, 0),
185 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 3, SQ_PRF
, 2, 1, 3),
186 LEN_SQ_PRF
+ 3, snmp_sysFn
, 0),
187 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 3, SQ_PRF
, 2, 1, 4),
188 LEN_SQ_PRF
+ 3, snmp_sysFn
, 0),
189 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 3, SQ_PRF
, 2, 1, 5),
190 LEN_SQ_PRF
+ 3, snmp_sysFn
, 0),
191 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 3, SQ_PRF
, 2, 1, 6),
192 LEN_SQ_PRF
+ 3, snmp_sysFn
, 0),
193 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 3, SQ_PRF
, 2, 1, 7),
194 LEN_SQ_PRF
+ 3, snmp_sysFn
, 0),
195 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 3, SQ_PRF
, 2, 1, 8),
196 LEN_SQ_PRF
+ 3, snmp_sysFn
, 0),
197 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 3, SQ_PRF
, 2, 1, 9),
198 LEN_SQ_PRF
+ 3, snmp_sysFn
, 0),
199 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 3, SQ_PRF
, 2, 1, 10),
200 LEN_SQ_PRF
+ 3, snmp_sysFn
, 0),
201 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 3, SQ_PRF
, 2, 1, 11),
202 LEN_SQ_PRF
+ 3, snmp_sysFn
, 0),
203 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 3, SQ_PRF
, 2, 1, 12),
204 LEN_SQ_PRF
+ 3, snmp_sysFn
, 0),
205 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 3, SQ_PRF
, 2, 1, 13),
206 LEN_SQ_PRF
+ 3, snmp_sysFn
, 0),
207 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 3, SQ_PRF
, 2, 1, 14),
208 LEN_SQ_PRF
+ 3, snmp_sysFn
, 0)),
209 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 2, SQ_PRF
, 2, 2),
210 LEN_SQ_PRF
+ 2, snmp_sysFn
, 1,
211 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 3, SQ_PRF
, 2, 2, 1),
212 LEN_SQ_PRF
+ 3, snmp_sysFn
, 8,
213 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 4, SQ_PRF
, 2, 2, 1, 1),
214 LEN_SQ_PRF
+ 4, snmp_sysFn
, 0),
215 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 4, SQ_PRF
, 2, 2, 1, 2),
216 LEN_SQ_PRF
+ 4, snmp_sysFn
, 0),
217 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 4, SQ_PRF
, 2, 2, 1, 3),
218 LEN_SQ_PRF
+ 4, snmp_sysFn
, 0),
219 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 4, SQ_PRF
, 2, 2, 1, 4),
220 LEN_SQ_PRF
+ 4, snmp_sysFn
, 0),
221 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 4, SQ_PRF
, 2, 2, 1, 5),
222 LEN_SQ_PRF
+ 4, snmp_sysFn
, 0),
223 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 4, SQ_PRF
, 2, 2, 1, 6),
224 LEN_SQ_PRF
+ 4, snmp_sysFn
, 0),
225 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 4, SQ_PRF
, 2, 2, 1, 7),
226 LEN_SQ_PRF
+ 4, snmp_sysFn
, 0),
227 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 4, SQ_PRF
, 2, 2, 1, 8),
228 LEN_SQ_PRF
+ 4, snmp_sysFn
, 0))))),
229 snmpAddNode(snmpCreateOid(LEN_SQ_NET
, SQ_NET
),
230 LEN_SQ_NET
, snmp_confFn
, 3,
231 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 1, SQ_NET
, 1),
232 LEN_SQ_NET
+ 1, snmp_sysFn
, 9,
233 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 2, SQ_NET
, 1, 1),
234 LEN_SQ_NET
+ 2, snmp_sysFn
, 0),
235 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 2, SQ_NET
, 1, 2),
236 LEN_SQ_NET
+ 2, snmp_sysFn
, 0),
237 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 2, SQ_NET
, 1, 3),
238 LEN_SQ_NET
+ 2, snmp_sysFn
, 0),
239 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 2, SQ_NET
, 1, 4),
240 LEN_SQ_NET
+ 2, snmp_sysFn
, 0),
241 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 2, SQ_NET
, 1, 5),
242 LEN_SQ_NET
+ 2, snmp_sysFn
, 0),
243 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 2, SQ_NET
, 1, 6),
244 LEN_SQ_NET
+ 2, snmp_sysFn
, 0),
245 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 2, SQ_NET
, 1, 7),
246 LEN_SQ_NET
+ 2, snmp_sysFn
, 0),
247 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 2, SQ_NET
, 1, 8),
248 LEN_SQ_NET
+ 2, snmp_sysFn
, 0),
249 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 2, SQ_NET
, 1, 9),
250 LEN_SQ_NET
+ 2, snmp_sysFn
, 0)),
251 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 1, SQ_NET
, 2),
252 LEN_SQ_NET
+ 1, snmp_sysFn
, 8,
253 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 2, SQ_NET
, 2, 1),
254 LEN_SQ_NET
+ 2, snmp_sysFn
, 0),
255 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 2, SQ_NET
, 2, 2),
256 LEN_SQ_NET
+ 2, snmp_sysFn
, 0),
257 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 2, SQ_NET
, 2, 3),
258 LEN_SQ_NET
+ 2, snmp_sysFn
, 0),
259 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 2, SQ_NET
, 2, 4),
260 LEN_SQ_NET
+ 2, snmp_sysFn
, 0),
261 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 2, SQ_NET
, 2, 5),
262 LEN_SQ_NET
+ 2, snmp_sysFn
, 0),
263 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 2, SQ_NET
, 2, 6),
264 LEN_SQ_NET
+ 2, snmp_sysFn
, 0),
265 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 2, SQ_NET
, 2, 7),
266 LEN_SQ_NET
+ 2, snmp_sysFn
, 0),
267 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 2, SQ_NET
, 2, 8),
268 LEN_SQ_NET
+ 2, snmp_sysFn
, 0)),
269 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 1, SQ_NET
, 3),
270 LEN_SQ_NET
+ 1, snmp_sysFn
, 3,
271 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 2, SQ_NET
, 3, 1),
272 LEN_SQ_NET
+ 2, snmp_sysFn
, 0),
273 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 2, SQ_NET
, 3, 2),
274 LEN_SQ_NET
+ 2, snmp_sysFn
, 0),
275 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 2, SQ_NET
, 3, 3),
276 LEN_SQ_NET
+ 2, snmp_sysFn
, 0))),
277 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
, SQ_MESH
),
278 LEN_SQ_MESH
, snmp_confFn
, 2,
279 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 1, SQ_MESH
, 1),
280 LEN_SQ_MESH
+ 1, snmp_sysFn
, 1,
281 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 2, SQ_MESH
, 1, 1),
282 LEN_SQ_MESH
+ 2, snmp_sysFn
, 13,
283 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, 1, 1, 1),
284 LEN_SQ_MESH
+ 3, snmp_sysFn
, 0),
285 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, 1, 1, 2),
286 LEN_SQ_MESH
+ 3, snmp_sysFn
, 0),
287 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, 1, 1, 3),
288 LEN_SQ_MESH
+ 3, snmp_sysFn
, 0),
289 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, 1, 1, 4),
290 LEN_SQ_MESH
+ 3, snmp_sysFn
, 0),
291 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, 1, 1, 5),
292 LEN_SQ_MESH
+ 3, snmp_sysFn
, 0),
293 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, 1, 1, 6),
294 LEN_SQ_MESH
+ 3, snmp_sysFn
, 0),
295 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, 1, 1, 7),
296 LEN_SQ_MESH
+ 3, snmp_sysFn
, 0),
297 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, 1, 1, 8),
298 LEN_SQ_MESH
+ 3, snmp_sysFn
, 0),
299 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, 1, 1, 9),
300 LEN_SQ_MESH
+ 3, snmp_sysFn
, 0),
301 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, 1, 1, 10),
302 LEN_SQ_MESH
+ 3, snmp_sysFn
, 0),
303 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, 1, 1, 11),
304 LEN_SQ_MESH
+ 3, snmp_sysFn
, 0),
305 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, 1, 1, 12),
306 LEN_SQ_MESH
+ 3, snmp_sysFn
, 0),
307 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, 1, 1, 13),
308 LEN_SQ_MESH
+ 3, snmp_sysFn
, 0))),
309 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 1, SQ_MESH
, 2),
310 LEN_SQ_MESH
+ 1, snmp_sysFn
, 1,
311 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 2, SQ_MESH
, 2, 1),
312 LEN_SQ_MESH
+ 2, snmp_sysFn
, 9,
313 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, 2, 1, 1),
314 LEN_SQ_MESH
+ 3, snmp_sysFn
, 0),
315 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, 2, 1, 2),
316 LEN_SQ_MESH
+ 3, snmp_sysFn
, 0),
317 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, 2, 1, 3),
318 LEN_SQ_MESH
+ 3, snmp_sysFn
, 0),
319 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, 2, 1, 4),
320 LEN_SQ_MESH
+ 3, snmp_sysFn
, 0),
321 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, 2, 1, 5),
322 LEN_SQ_MESH
+ 3, snmp_sysFn
, 0),
323 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, 2, 1, 6),
324 LEN_SQ_MESH
+ 3, snmp_sysFn
, 0),
325 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, 2, 1, 7),
326 LEN_SQ_MESH
+ 3, snmp_sysFn
, 0),
327 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, 2, 1, 8),
328 LEN_SQ_MESH
+ 3, snmp_sysFn
, 0),
329 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, 2, 1, 9),
330 LEN_SQ_MESH
+ 3, snmp_sysFn
, 0))))
340 debug(49, 9) ("snmpInit: Completed SNMP mib tree structure\n");
344 snmpConnectionOpen(void)
347 struct sockaddr_in xaddr
;
351 debug(49, 5) ("snmpConnectionOpen: Called\n");
352 if ((port
= Config
.Port
.snmp
) > (u_short
) 0) {
354 theInSnmpConnection
= comm_open(SOCK_DGRAM
,
356 Config
.Addrs
.snmp_incoming
,
361 if (theInSnmpConnection
< 0)
362 fatal("Cannot open snmp Port");
363 commSetSelect(theInSnmpConnection
, COMM_SELECT_READ
, snmpHandleUdp
, NULL
, 0);
364 debug(1, 1) ("Accepting SNMP messages on port %d, FD %d.\n",
365 (int) port
, theInSnmpConnection
);
366 if (Config
.Addrs
.snmp_outgoing
.s_addr
!= no_addr
.s_addr
) {
368 theOutSnmpConnection
= comm_open(SOCK_DGRAM
,
370 Config
.Addrs
.snmp_outgoing
,
375 if (theOutSnmpConnection
< 0)
376 fatal("Cannot open Outgoing SNMP Port");
377 commSetSelect(theOutSnmpConnection
,
381 debug(1, 1) ("Outgoing SNMP messages on port %d, FD %d.\n",
382 (int) port
, theOutSnmpConnection
);
383 fd_note(theOutSnmpConnection
, "Outgoing SNMP socket");
384 fd_note(theInSnmpConnection
, "Incoming SNMP socket");
386 theOutSnmpConnection
= theInSnmpConnection
;
388 memset(&theOutSNMPAddr
, '\0', sizeof(struct in_addr
));
389 len
= sizeof(struct sockaddr_in
);
390 memset(&xaddr
, '\0', len
);
391 x
= getsockname(theOutSnmpConnection
,
392 (struct sockaddr
*) &xaddr
, &len
);
394 debug(51, 1) ("theOutSnmpConnection FD %d: getsockname: %s\n",
395 theOutSnmpConnection
, xstrerror());
397 theOutSNMPAddr
= xaddr
.sin_addr
;
402 snmpConnectionShutdown(void)
404 if (theInSnmpConnection
< 0)
406 if (theInSnmpConnection
!= theOutSnmpConnection
) {
407 debug(49, 1) ("FD %d Closing SNMP socket\n", theInSnmpConnection
);
408 comm_close(theInSnmpConnection
);
411 * Here we set 'theInSnmpConnection' to -1 even though the SNMP 'in'
412 * and 'out' sockets might be just one FD. This prevents this
413 * function from executing repeatedly. When we are really ready to
414 * exit or restart, main will comm_close the 'out' descriptor.
415 */ theInSnmpConnection
= -1;
417 * Normally we only write to the outgoing SNMP socket, but we
418 * also have a read handler there to catch messages sent to that
419 * specific interface. During shutdown, we must disable reading
420 * on the outgoing socket.
422 assert(theOutSnmpConnection
> -1);
423 commSetSelect(theOutSnmpConnection
, COMM_SELECT_READ
, NULL
, NULL
, 0);
427 snmpConnectionClose(void)
429 snmpConnectionShutdown();
430 if (theOutSnmpConnection
> -1) {
431 debug(49, 1) ("FD %d Closing SNMP socket\n", theOutSnmpConnection
);
432 comm_close(theOutSnmpConnection
);
437 * Functions for handling the requests.
441 * Accept the UDP packet
444 snmpHandleUdp(int sock
, void *not_used
)
446 LOCAL_ARRAY(char, buf
, SNMP_REQUEST_SIZE
);
447 struct sockaddr_in from
;
449 snmp_request_t
*snmp_rq
;
452 debug(49, 5) ("snmpHandleUdp: Called.\n");
454 commSetSelect(sock
, COMM_SELECT_READ
, snmpHandleUdp
, NULL
, 0);
455 from_len
= sizeof(struct sockaddr_in
);
456 memset(&from
, '\0', from_len
);
458 Counter
.syscalls
.sock
.recvfroms
++;
464 (struct sockaddr
*) &from
,
469 debug(49, 3) ("snmpHandleUdp: FD %d: received %d bytes from %s.\n",
472 inet_ntoa(from
.sin_addr
));
474 snmp_rq
= xcalloc(1, sizeof(snmp_request_t
));
475 snmp_rq
->buf
= (u_char
*) buf
;
477 snmp_rq
->sock
= sock
;
478 snmp_rq
->outbuf
= xmalloc(snmp_rq
->outlen
= SNMP_REQUEST_SIZE
);
479 memcpy(&snmp_rq
->from
, &from
, sizeof(struct sockaddr_in
));
480 snmpDecodePacket(snmp_rq
);
482 debug(49, 1) ("snmpHandleUdp: FD %d recvfrom: %s\n", sock
, xstrerror());
487 * Turn SNMP packet into a PDU, check available ACL's
490 snmpDecodePacket(snmp_request_t
* rq
)
492 struct snmp_pdu
*PDU
;
493 struct snmp_session
*Session
;
494 aclCheck_t checklist
;
496 u_char
*buf
= rq
->buf
;
500 debug(49, 5) ("snmpDecodePacket: Called.\n");
501 /* Now that we have the data, turn it into a PDU */
502 Session
= (struct snmp_session
*) xmalloc(sizeof(struct snmp_session
));
503 Session
->Version
= SNMP_VERSION_1
;
504 Session
->authenticator
= NULL
;
505 Session
->community
= (u_char
*) xstrdup("public");
506 Session
->community_len
= 6;
507 cbdataAdd(rq
, MEM_NONE
);
508 PDU
= snmp_pdu_create(0);
509 Community
= snmp_parse(Session
, PDU
, buf
, len
);
511 checklist
.src_addr
= rq
->from
.sin_addr
;
512 checklist
.snmp_community
= Community
;
514 allow
= aclCheckFast(Config
.accessList
.snmp
, &checklist
);
515 if ((snmp_coexist_V2toV1(PDU
)) && (Community
) && (allow
)) {
516 rq
->community
= Community
;
518 debug(49, 5) ("snmpAgentParse: reqid=[%d]\n", PDU
->reqid
);
519 snmpConstructReponse(rq
, Session
);
526 * Packet OK, ACL Check OK, Create reponse.
529 snmpConstructReponse(snmp_request_t
* rq
, struct snmp_session
*Session
)
531 struct snmp_pdu
*RespPDU
;
534 debug(49, 5) ("snmpConstructReponse: Called.\n");
536 Session
->community
= rq
->community
;
537 Session
->community_len
= strlen((char *) rq
->community
);
539 RespPDU
= snmpAgentResponse(rq
->PDU
);
540 snmp_free_pdu(rq
->PDU
);
542 if (RespPDU
== NULL
) {
544 ret
= snmp_build(Session
, RespPDU
, rq
->outbuf
, &rq
->outlen
);
545 snmpUdpSend(rq
->sock
, &rq
->from
, rq
->outbuf
, rq
->outlen
);
546 snmp_free_pdu(RespPDU
);
551 * Decide how to respond to the request, construct a response and
552 * return the response to the requester.
554 * If configured forward any reponses which are not for this agent.
557 snmpAgentResponse(struct snmp_pdu
*PDU
)
559 struct snmp_pdu
*Answer
= NULL
;
560 oid_ParseFn
*ParseFn
= NULL
;
561 variable_list
*VarNew
= NULL
;
563 debug(49, 5) ("snmpAgentResponse: Called.\n");
565 if ((Answer
= snmp_pdu_create(SNMP_PDU_RESPONSE
))) {
566 Answer
->reqid
= PDU
->reqid
;
567 Answer
->errindex
= 0;
568 if (PDU
->command
== SNMP_PDU_GET
) {
570 } else if (PDU
->command
== SNMP_PDU_GETNEXT
) {
571 oid
*NextOidName
= NULL
;
572 int NextOidNameLen
= 0;
574 ParseFn
= snmpTreeNext(PDU
->variables
->name
, PDU
->variables
->name_length
,
575 &(NextOidName
), (snint
*) & NextOidNameLen
);
577 if (ParseFn
== NULL
) {
578 Answer
->errstat
= SNMP_ERR_NOSUCHNAME
;
579 debug(49, 5) ("snmpAgentResponse: No such oid: ");
580 snmpDebugOid(5, PDU
->variables
->name
, PDU
->variables
->name_length
);
582 xfree(PDU
->variables
->name
);
583 PDU
->variables
->name
= NextOidName
;
584 PDU
->variables
->name_length
= NextOidNameLen
;
585 VarNew
= (*ParseFn
) (PDU
->variables
, (snint
*) & Answer
->errstat
);
588 /* Was there an error? */
589 if (Answer
->errstat
!= SNMP_ERR_NOERROR
) {
590 Answer
->errindex
= 1;
592 /* Just copy this variable */
593 Answer
->variables
= PDU
->variables
;
594 PDU
->variables
= NULL
;
596 Answer
->variables
= VarNew
;
600 snmp_free_pdu(Answer
);
608 snmpTreeNext(oid
* Current
, snint CurrentLen
, oid
** Next
, snint
* NextLen
)
610 oid_ParseFn
*Fn
= NULL
;
611 mib_tree_entry
*mibTreeEntry
= NULL
, *new_oid
= NULL
;
614 debug(49, 5) ("snmpTreeNext: Called\n");
616 debug(49, 6) ("snmpTreeNext: Current : \n");
617 snmpDebugOid(6, Current
, CurrentLen
);
619 mibTreeEntry
= mib_tree_head
;
620 if (Current
[count
] == mibTreeEntry
->name
[count
]) {
622 while ((mibTreeEntry
) && (count
< CurrentLen
)) {
623 mibTreeEntry
= snmpTreeEntry(Current
[count
], count
, mibTreeEntry
);
626 debug(49, 5) ("snmpTreeNext: Past first\n");
628 if (mibTreeEntry
->parsefunction
) {
630 new_oid
= snmpTreeEntry(Current
[count
] + 1, count
, mibTreeEntry
->parent
);
632 mibTreeEntry
= mibTreeEntry
->parent
;
637 debug(49, 5) ("snmpTreeNext: Past Second\n");
639 if ((!mibTreeEntry
->parsefunction
) && (mibTreeEntry
)) {
640 while (!mibTreeEntry
->parsefunction
) {
641 mibTreeEntry
= snmpTreeEntry(1, count
, mibTreeEntry
);
645 debug(49, 5) ("snmpTreeNext: Past Third\n");
648 *Next
= snmpOidDup(mibTreeEntry
->name
, mibTreeEntry
->len
);
649 *NextLen
= mibTreeEntry
->len
;
650 Fn
= mibTreeEntry
->parsefunction
;
652 debug(49, 5) ("snmpTreeNext: return\n");
657 snmpTreeEntry(oid entry
, snint len
, mib_tree_entry
* current
)
659 mib_tree_entry
*next
= NULL
;
662 debug(49, 5) ("snmpTreeEntry: Called\n");
664 debug(49, 6) ("snmpTreeEntry: Oid: %d, Len: %d, Current : \n", entry
, len
);
665 snmpDebugOid(6, current
->name
, current
->len
);
667 while ((!next
) && (count
< current
->children
)) {
668 debug(49, 6) ("snmpTreeEntry: While loop count: %d, children: %d \n", count
, current
->children
);
669 snmpDebugOid(6, current
->leaves
[count
]->name
, current
->leaves
[count
]->len
);
670 if (current
->leaves
[count
]->name
[len
] == entry
) {
671 next
= current
->leaves
[count
];
676 debug(49, 6) ("snmpTreeEntry: Returned : \n");
677 snmpDebugOid(6, next
->name
, next
->len
);
683 * Send the UDP reply.
686 snmpUdpSend(int fd
, const struct sockaddr_in
*to
, void *msg
, int len
)
688 snmpUdpData
*data
= xcalloc(1, sizeof(snmpUdpData
));
689 debug(49, 5) ("snmpUdpSend: Queueing response for %s\n",
690 inet_ntoa(to
->sin_addr
));
695 commSetSelect(fd
, COMM_SELECT_WRITE
, snmpUdpReply
, snmpUdpHead
, 0);
700 snmpUdpReply(int fd
, void *data
)
702 snmpUdpData
*queue
= data
;
704 /* Disable handler, in case of errors. */
705 commSetSelect(fd
, COMM_SELECT_WRITE
, NULL
, NULL
, 0);
706 while ((queue
= snmpUdpHead
) != NULL
) {
707 debug(49, 5) ("snmpUdpReply: FD %d sending %d bytes to %s port %d\n",
710 inet_ntoa(queue
->address
.sin_addr
),
711 ntohs(queue
->address
.sin_port
));
712 x
= comm_udp_sendto(fd
,
714 sizeof(struct sockaddr_in
),
718 if (ignoreErrno(errno
))
719 break; /* don't de-queue */
721 snmpUdpHead
= queue
->next
;
722 debug(49, 3) ("snmpUdpReply: freeing %p\n", queue
->msg
);
723 safe_free(queue
->msg
);
724 debug(49, 3) ("snmpUdpReply: freeing %p\n", queue
);
727 /* Reinstate handler if needed */
729 commSetSelect(fd
, COMM_SELECT_WRITE
, snmpUdpReply
, snmpUdpHead
, 0);
734 snmpAppendUdp(snmpUdpData
* item
)
737 if (snmpUdpHead
== NULL
) {
740 } else if (snmpUdpTail
== snmpUdpHead
) {
742 snmpUdpHead
->next
= item
;
744 snmpUdpTail
->next
= item
;
755 * Tree utility functions.
759 * Adds a node to the MIB tree structure and adds the appropriate children
762 snmpAddNode(oid
* name
, int len
, oid_ParseFn
* parsefunction
, int children
,...)
766 mib_tree_entry
*entry
= NULL
;
768 debug(49, 6) ("snmpAddNode: Children : %d, Oid : \n", children
);
769 snmpDebugOid(6, name
, len
);
771 va_start(args
, children
);
772 entry
= xmalloc(sizeof(mib_tree_entry
));
773 entry
->name
= snmpOidDup(name
, len
);
775 entry
->parsefunction
= parsefunction
;
776 entry
->children
= children
;
779 entry
->leaves
= xmalloc(sizeof(mib_tree_entry
*) * children
);
780 for (loop
= 0; loop
< children
; loop
++) {
781 entry
->leaves
[loop
] = va_arg(args
, mib_tree_entry
*);
782 entry
->leaves
[loop
]->parent
= entry
;
787 /* End of tree utility functions */
790 * Returns the list of parameters in an oid[]
793 snmpCreateOid(int length
,...)
799 va_start(args
, length
);
800 new_oid
= xmalloc(sizeof(oid
) * length
);
803 for (loop
= 0; loop
< length
; loop
++) {
804 new_oid
[loop
] = va_arg(args
, int);
811 * Allocate space for, and copy, an OID. Returns new oid, or NULL.
814 snmpOidDup(oid
* A
, snint ALen
)
818 Ans
= (oid
*) xmalloc(sizeof(oid
) * ALen
);
820 memcpy(Ans
, A
, (sizeof(oid
) * ALen
));
825 * Debug calls, prints out the OID for debugging purposes.
828 snmpDebugOid(int lvl
, oid
* Name
, snint Len
)
830 char mbuf
[16], objid
[1024];
834 for (x
= 0; x
< Len
; x
++) {
835 snprintf(mbuf
, sizeof(mbuf
), ".%u", (unsigned int) Name
[x
]);
836 strncat(objid
, mbuf
, sizeof(objid
));
839 debug(49, lvl
) (" oid = %s\n", objid
);
843 snmpSnmplibDebug(int lvl
, char *buf
)
845 debug(49, lvl
) ("%s", buf
);