]> git.ipfire.org Git - thirdparty/squid.git/blame - src/snmp_core.cc
Squid SNMP code rewrite
[thirdparty/squid.git] / src / snmp_core.cc
CommitLineData
43d4303e 1/*
dba79ac5 2 * $Id: snmp_core.cc,v 1.13 1998/11/11 20:04:19 glenn Exp $
43d4303e 3 *
4 * DEBUG: section 49 SNMP support
dba79ac5 5 * AUTHOR: Glenn Chisholm
43d4303e 6 *
7 * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
e25c139f 8 * ----------------------------------------------------------
43d4303e 9 *
10 * Squid is the result of efforts by numerous individuals from the
11 * Internet community. Development is led by Duane Wessels of the
e25c139f 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.
43d4303e 18 *
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2 of the License, or
22 * (at your option) any later version.
dba79ac5 23 *
43d4303e 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.
dba79ac5 28 *
43d4303e 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
cbdec147 31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
e25c139f 32 *
43d4303e 33 */
43d4303e 34#include "squid.h"
43d4303e 35#include "cache_snmp.h"
43d4303e 36
37#define SNMP_REQUEST_SIZE 4096
38#define MAX_PROTOSTAT 5
39
dba79ac5 40struct _mib_tree_entry {
41 oid *name;
42 int len;
43 oid_ParseFn *parsefunction;
44 int children;
45 struct _mib_tree_entry **leaves;
46 struct _mib_tree_entry *parent;
47};
43d4303e 48
dba79ac5 49struct _snmpUdpData {
43d4303e 50 struct sockaddr_in address;
51 void *msg;
52 int len;
dba79ac5 53 struct _snmpUdpData *next;
43d4303e 54};
55
dba79ac5 56typedef struct _snmpUdpData snmpUdpData;
57typedef struct _mib_tree_entry mib_tree_entry;
43d4303e 58
dba79ac5 59mib_tree_entry *mib_tree_head;
60snmpUdpData *snmpUdpHead = NULL;
61snmpUdpData *snmpUdpTail = NULL;
43d4303e 62
dba79ac5 63extern void (*snmplib_debug_hook) (int, char *);
43d4303e 64
dba79ac5 65static void snmpDecodePacket(snmp_request_t * rq);
66static void snmpConstructReponse(snmp_request_t * rq, struct snmp_session *Session);
67static struct snmp_pdu* snmpAgentResponse(struct snmp_pdu *PDU);
43d4303e 68
dba79ac5 69static void snmpUdpSend(int, const struct sockaddr_in *, void *, int);
70static void snmpUdpReply(int, void *);
71static void snmpAppendUdp(snmpUdpData *);
43d4303e 72
43d4303e 73
dba79ac5 74static mib_tree_entry* snmpAddNode(oid *name, int len, oid_ParseFn *parsefunction, int children, ...);
75static oid_ParseFn *snmpTreeNext(oid *Current, snint CurrentLen, oid **Next, snint *NextLen);
76static mib_tree_entry* snmpTreeEntry(oid entry, snint len, mib_tree_entry *current);
43d4303e 77
dba79ac5 78static oid* snmpCreateOid(int length, ...);
79static oid* snmpOidDup(oid * A, snint ALen);
80static void snmpSnmplibDebug(int lvl, char *buf);
43d4303e 81
43d4303e 82
dba79ac5 83/*
84 * The functions used during startup:
85 * snmpInit
86 * snmpConnectionOpen
87 * snmpConnectionShutdown
88 * snmpConnectionClose
89 */
43d4303e 90
dba79ac5 91/*
92 Turns the MIB into a Tree structure. Called during the startup process.
93*/
43d4303e 94void
95snmpInit(void)
96{
dba79ac5 97 debug(49, 5) ("snmpInit: Called.\n");
98
99 debug(49, 5) ("snmpInit: Building SNMP mib tree structure\n");
100
43d4303e 101 snmplib_debug_hook = snmpSnmplibDebug;
102
dba79ac5 103 mib_tree_head = snmpAddNode(snmpCreateOid(1, 1),
104 1, NULL, 1,
105 snmpAddNode(snmpCreateOid(2, 1, 3),
106 2, NULL, 1,
107 snmpAddNode(snmpCreateOid(3, 1, 3, 6),
108 3, NULL, 1,
109 snmpAddNode(snmpCreateOid(4, 1, 3, 6, 1),
110 4, NULL, 1,
111 snmpAddNode(snmpCreateOid(5, 1, 3, 6, 1, 4),
112 5, NULL, 1,
113 snmpAddNode(snmpCreateOid(6, 1, 3, 6, 1, 4, 1),
114 6, NULL, 1,
115 snmpAddNode(snmpCreateOid(7, 1, 3, 6, 1, 4, 1, 3495),
116 7, NULL, 1,
117 snmpAddNode(snmpCreateOid(LEN_SQUIDMIB, SQUIDMIB),
118 8, NULL, 5,
119 snmpAddNode(snmpCreateOid(LEN_SQ_SYS, SQ_SYS),
120 LEN_SQ_SYS, NULL, 3,
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))))
331 )
332 )
333 )
334 )
335 )
336 )
337 )
338 );
339
340 debug(49, 9) ("snmpInit: Completed SNMP mib tree structure\n");
43d4303e 341}
342
343void
344snmpConnectionOpen(void)
345{
346 u_short port;
43d4303e 347 struct sockaddr_in xaddr;
6637e3a5 348 socklen_t len;
43d4303e 349 int x;
350
dba79ac5 351 debug(49, 5) ("snmpConnectionOpen: Called\n");
43d4303e 352 if ((port = Config.Port.snmp) > (u_short) 0) {
dba79ac5 353 enter_suid();
354 theInSnmpConnection = comm_open(SOCK_DGRAM,
355 0,
356 Config.Addrs.snmp_incoming,
357 port,
358 COMM_NONBLOCKING,
359 "SNMP Port");
360 leave_suid();
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) {
367 enter_suid();
368 theOutSnmpConnection = comm_open(SOCK_DGRAM,
369 0,
370 Config.Addrs.snmp_outgoing,
371 port,
372 COMM_NONBLOCKING,
373 "SNMP Port");
374 leave_suid();
375 if (theOutSnmpConnection < 0)
376 fatal("Cannot open Outgoing SNMP Port");
377 commSetSelect(theOutSnmpConnection,
378 COMM_SELECT_READ,
379 snmpHandleUdp,
380 NULL, 0);
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");
385 } else {
386 theOutSnmpConnection = theInSnmpConnection;
387 }
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);
393 if (x < 0)
394 debug(51, 1) ("theOutSnmpConnection FD %d: getsockname: %s\n",
395 theOutSnmpConnection, xstrerror());
396 else
397 theOutSNMPAddr = xaddr.sin_addr;
43d4303e 398 }
399}
400
43d4303e 401void
402snmpConnectionShutdown(void)
403{
404 if (theInSnmpConnection < 0)
dba79ac5 405 return;
43d4303e 406 if (theInSnmpConnection != theOutSnmpConnection) {
dba79ac5 407 debug(49, 1) ("FD %d Closing SNMP socket\n", theInSnmpConnection);
408 comm_close(theInSnmpConnection);
43d4303e 409 }
410 /*
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;
dba79ac5 416 /*
43d4303e 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.
421 */
422 assert(theOutSnmpConnection > -1);
423 commSetSelect(theOutSnmpConnection, COMM_SELECT_READ, NULL, NULL, 0);
424}
425
426void
427snmpConnectionClose(void)
428{
429 snmpConnectionShutdown();
430 if (theOutSnmpConnection > -1) {
dba79ac5 431 debug(49, 1) ("FD %d Closing SNMP socket\n", theOutSnmpConnection);
432 comm_close(theOutSnmpConnection);
43d4303e 433 }
434}
435
dba79ac5 436/*
437 Functions for handling the requests.
438*/
43d4303e 439
dba79ac5 440/*
441 * Accept the UDP packet
442 */
43d4303e 443void
dba79ac5 444snmpHandleUdp(int sock, void *not_used)
43d4303e 445{
dba79ac5 446 LOCAL_ARRAY(char, buf, SNMP_REQUEST_SIZE);
447 struct sockaddr_in from;
448 socklen_t from_len;
449 snmp_request_t *snmp_rq;
450 int len;
451
452 debug(49, 5) ("snmpHandleUdp: Called.\n");
453
454 commSetSelect(sock, COMM_SELECT_READ, snmpHandleUdp, NULL, 0);
455 from_len = sizeof(struct sockaddr_in);
456 memset(&from, '\0', from_len);
457
458 Counter.syscalls.sock.recvfroms++;
459
460 len = recvfrom(sock,
461 buf,
462 SNMP_REQUEST_SIZE,
463 0,
464 (struct sockaddr *) &from,
465 &from_len);
466
467 if (len > 0) {
468 buf[len] = '\0';
469 debug(49, 3) ("snmpHandleUdp: FD %d: received %d bytes from %s.\n",
470 sock,
471 len,
472 inet_ntoa(from.sin_addr));
473
474 snmp_rq = xcalloc(1, sizeof(snmp_request_t));
475 snmp_rq->buf = (u_char *) buf;
476 snmp_rq->len = len;
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);
481 } else {
482 debug(49, 1) ("snmpHandleUdp: FD %d recvfrom: %s\n", sock, xstrerror());
483 }
484}
43d4303e 485
dba79ac5 486/*
487 * Turn SNMP packet into a PDU, check available ACL's
488 */
489void
490snmpDecodePacket(snmp_request_t * rq)
491{
43d4303e 492 struct snmp_pdu *PDU;
dba79ac5 493 struct snmp_session *Session;
494 aclCheck_t checklist;
43d4303e 495 u_char *Community;
dba79ac5 496 u_char *buf = rq->buf;
497 int len = rq->len;
498 int allow = 0;
43d4303e 499
dba79ac5 500 debug(49, 5) ("snmpDecodePacket: Called.\n");
43d4303e 501 /* Now that we have the data, turn it into a PDU */
dba79ac5 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;
43d4303e 507 cbdataAdd(rq, MEM_NONE);
508 PDU = snmp_pdu_create(0);
509 Community = snmp_parse(Session, PDU, buf, len);
510
dba79ac5 511 checklist.src_addr = rq->from.sin_addr;
512 checklist.snmp_community = Community;
513
514 allow = aclCheckFast(Config.accessList.snmp, &checklist);
515 if ((snmp_coexist_V2toV1(PDU)) && (Community) && (allow)) {
516 rq->community = Community;
517 rq->PDU = PDU;
518 debug(49, 5) ("snmpAgentParse: reqid=[%d]\n", PDU->reqid);
519 snmpConstructReponse(rq, Session);
520 } else {
b644367b 521 snmp_free_pdu(PDU);
43d4303e 522 }
dba79ac5 523}
43d4303e 524
dba79ac5 525/*
526 * Packet OK, ACL Check OK, Create reponse.
527 */
528void
529snmpConstructReponse(snmp_request_t * rq, struct snmp_session *Session)
530{
531 struct snmp_pdu *RespPDU;
532 int ret;
43d4303e 533
dba79ac5 534 debug(49, 5) ("snmpConstructReponse: Called.\n");
535
536 Session->community = rq->community;
537 Session->community_len = strlen((char *) rq->community);
538
539 RespPDU = snmpAgentResponse(rq->PDU);
540 snmp_free_pdu(rq->PDU);
541 xfree(Session);
542 if (RespPDU == NULL) {
543 } else {
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);
43d4303e 547 }
43d4303e 548}
549
dba79ac5 550/*
551 * Decide how to respond to the request, construct a response and
552 * return the response to the requester.
553 *
554 * If configured forward any reponses which are not for this agent.
555 */
43d4303e 556struct snmp_pdu *
557snmpAgentResponse(struct snmp_pdu *PDU)
558{
559 struct snmp_pdu *Answer = NULL;
dba79ac5 560 oid_ParseFn *ParseFn = NULL;
561 variable_list *VarNew = NULL;
43d4303e 562
dba79ac5 563 debug(49, 5) ("snmpAgentResponse: Called.\n");
43d4303e 564
dba79ac5 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) {
43d4303e 569
dba79ac5 570 } else if (PDU->command == SNMP_PDU_GETNEXT) {
571 oid *NextOidName = NULL;
572 int NextOidNameLen = 0;
b644367b 573
dba79ac5 574 ParseFn = snmpTreeNext(PDU->variables->name, PDU->variables->name_length,
575 &(NextOidName), (snint *) &NextOidNameLen);
b644367b 576
577 if (ParseFn == NULL) {
578 Answer->errstat = SNMP_ERR_NOSUCHNAME;
dba79ac5 579 debug(49, 5) ("snmpAgentResponse: No such oid: ");
580 snmpDebugOid(5, PDU->variables->name, PDU->variables->name_length);
581 } else {
582 xfree(PDU->variables->name);
583 PDU->variables->name = NextOidName;
584 PDU->variables->name_length = NextOidNameLen;
585 VarNew = (*ParseFn) (PDU->variables, (snint *) &Answer->errstat);
586 }
b644367b 587
588 /* Was there an error? */
dba79ac5 589 if (Answer->errstat != SNMP_ERR_NOERROR) {
590 Answer->errindex = 1;
591
592 /* Just copy this variable */
593 Answer->variables = PDU->variables;
594 PDU->variables = NULL;
595 } else {
596 Answer->variables = VarNew;
b644367b 597 }
dba79ac5 598
599 }else{
600 snmp_free_pdu(Answer);
601 Answer = NULL;
b644367b 602 }
dba79ac5 603 }
604 return (Answer);
605}
b644367b 606
dba79ac5 607oid_ParseFn *
608snmpTreeNext(oid * Current, snint CurrentLen, oid ** Next, snint * NextLen)
609{
610 oid_ParseFn *Fn = NULL;
611 mib_tree_entry *mibTreeEntry = NULL, *new_oid = NULL;
612 int count = 0;
613
614 debug(49, 5) ("snmpTreeNext: Called\n");
615
616 debug(49, 6) ("snmpTreeNext: Current : \n");
617 snmpDebugOid(6, Current, CurrentLen);
b644367b 618
dba79ac5 619 mibTreeEntry = mib_tree_head;
620 if (Current[count] == mibTreeEntry->name[count]) {
621 count++;
622 while ((mibTreeEntry) && (count < CurrentLen)) {
623 mibTreeEntry = snmpTreeEntry(Current[count], count , mibTreeEntry);
624 count++;
b644367b 625 }
dba79ac5 626 debug(49, 5) ("snmpTreeNext: Past first\n");
627
628 if (mibTreeEntry->parsefunction) {
629 while(!new_oid){
630 new_oid = snmpTreeEntry(Current[count]+1, count , mibTreeEntry->parent);
631 if(!new_oid){
632 mibTreeEntry = mibTreeEntry->parent;
633 count--;
634 }
635 }
636 }
637 debug(49, 5) ("snmpTreeNext: Past Second\n");
b644367b 638
dba79ac5 639 if ((!mibTreeEntry->parsefunction) && (mibTreeEntry)) {
640 while (!mibTreeEntry->parsefunction) {
641 mibTreeEntry = snmpTreeEntry(1, count , mibTreeEntry);
642 count++;
643 }
644 }
645 debug(49, 5) ("snmpTreeNext: Past Third\n");
646 }
647 if(mibTreeEntry){
648 *Next = snmpOidDup(mibTreeEntry->name, mibTreeEntry->len);
649 *NextLen = mibTreeEntry->len;
650 Fn = mibTreeEntry->parsefunction;
651 }
652 debug(49, 5) ("snmpTreeNext: return\n");
653 return (Fn);
43d4303e 654}
655
dba79ac5 656mib_tree_entry *
657snmpTreeEntry(oid entry, snint len, mib_tree_entry * current)
43d4303e 658{
dba79ac5 659 mib_tree_entry *next = NULL;
660 int count = 0;
665bc266 661
dba79ac5 662 debug(49, 5) ("snmpTreeEntry: Called\n");
665bc266 663
dba79ac5 664 debug(49, 6) ("snmpTreeEntry: Oid: %d, Len: %d, Current : \n",entry, len);
665 snmpDebugOid(6, current->name, current->len);
43d4303e 666
dba79ac5 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];
672 }
673 count++;
43d4303e 674 }
dba79ac5 675 if(next){
676 debug(49, 6) ("snmpTreeEntry: Returned : \n");
677 snmpDebugOid(6, next->name, next->len);
678 }
679 return (next);
680}
43d4303e 681
dba79ac5 682/*
683 Send the UDP reply.
684*/
685void
686snmpUdpSend(int fd, const struct sockaddr_in *to, void *msg, int len)
687{
688 snmpUdpData *data = xcalloc(1, sizeof(snmpUdpData));
689 debug(49, 5) ("snmpUdpSend: Queueing response for %s\n",
690 inet_ntoa(to->sin_addr));
691 data->address = *to;
692 data->msg = msg;
693 data->len = len;
694 snmpAppendUdp(data);
695 commSetSelect(fd, COMM_SELECT_WRITE, snmpUdpReply, snmpUdpHead, 0);
43d4303e 696
dba79ac5 697}
43d4303e 698
dba79ac5 699void
700snmpUdpReply(int fd, void *data)
701{
702 snmpUdpData *queue = data;
703 int x;
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",
708 fd,
709 queue->len,
710 inet_ntoa(queue->address.sin_addr),
711 ntohs(queue->address.sin_port));
712 x = comm_udp_sendto(fd,
713 &queue->address,
714 sizeof(struct sockaddr_in),
715 queue->msg,
716 queue->len);
717 if (x < 0) {
718 if (ignoreErrno(errno))
719 break; /* don't de-queue */
720 }
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);
725 safe_free(queue);
726 }
727 /* Reinstate handler if needed */
728 if (snmpUdpHead) {
729 commSetSelect(fd, COMM_SELECT_WRITE, snmpUdpReply, snmpUdpHead, 0);
730 }
43d4303e 731}
732
dba79ac5 733void
734snmpAppendUdp(snmpUdpData * item)
43d4303e 735{
dba79ac5 736 item->next = NULL;
737 if (snmpUdpHead == NULL) {
738 snmpUdpHead = item;
739 snmpUdpTail = item;
740 } else if (snmpUdpTail == snmpUdpHead) {
741 snmpUdpTail = item;
742 snmpUdpHead->next = item;
743 } else {
744 snmpUdpTail->next = item;
745 snmpUdpTail = item;
43d4303e 746 }
747
dba79ac5 748}
43d4303e 749
dba79ac5 750/*
751 Utility functions
752*/
43d4303e 753
dba79ac5 754/*
755 Tree utility functions.
756*/
43d4303e 757
dba79ac5 758/*
759 Adds a node to the MIB tree structure and adds the appropriate children
760*/
761mib_tree_entry*
762snmpAddNode(oid *name, int len, oid_ParseFn *parsefunction, int children, ...)
763{
764 va_list args;
765 int loop;
766 mib_tree_entry *entry = NULL;
767
768 debug(49, 6) ("snmpAddNode: Children : %d, Oid : \n", children);
769 snmpDebugOid(6, name, len);
770
771 va_start(args, children);
772 entry = xmalloc(sizeof(mib_tree_entry));
773 entry->name = snmpOidDup(name, len);
774 entry->len = len;
775 entry->parsefunction = parsefunction;
776 entry->children = children;
777
778 if(children > 0){
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;
783 }
784 }
785 return(entry);
786}
787/* End of tree utility functions */
43d4303e 788
dba79ac5 789/*
790 Returns the list of parameters in an oid[]
791*/
792oid*
793snmpCreateOid(int length, ...)
794{
795 va_list args;
796 oid *new_oid;
797 int loop;
798
799 va_start(args, length);
800 new_oid = xmalloc(sizeof(oid)*length);
801
802 if(length > 0){
803 for(loop = 0;loop < length;loop++){
804 new_oid[loop] = va_arg(args, int);
805 }
806 }
807 return(new_oid);
43d4303e 808}
809
dba79ac5 810/*
811 Allocate space for, and copy, an OID. Returns new oid, or NULL.
43d4303e 812 */
813oid *
dba79ac5 814snmpOidDup(oid * A, snint ALen)
43d4303e 815{
816 oid *Ans;
dba79ac5 817
818 Ans = (oid *) xmalloc(sizeof(oid) * ALen);
43d4303e 819 if (Ans)
dba79ac5 820 memcpy(Ans, A, (sizeof(oid) * ALen));
43d4303e 821 return (Ans);
822}
823
dba79ac5 824/*
825 Debug calls, prints out the OID for debugging purposes.
826*/
827void
828snmpDebugOid(int lvl, oid * Name, snint Len)
829{
830 char mbuf[16], objid[1024];
831 int x;
832 objid[0] = '\0';
43d4303e 833
dba79ac5 834 for (x = 0; x < Len; x++) {
835 snprintf(mbuf, sizeof(mbuf), ".%u", (unsigned int) Name[x]);
836 strncat(objid, mbuf, sizeof(objid));
43d4303e 837 }
dba79ac5 838
839 debug(49, lvl) (" oid = %s\n", objid);
43d4303e 840}
b644367b 841
dba79ac5 842static void
843snmpSnmplibDebug(int lvl, char *buf)
844{
845 debug(49, lvl) ("%s", buf);
846}
43d4303e 847
43d4303e 848