]> git.ipfire.org Git - thirdparty/squid.git/blame - src/snmp_core.cc
NO_CACHE_DIGEST_DIRECT is unused
[thirdparty/squid.git] / src / snmp_core.cc
CommitLineData
43d4303e 1/*
1d5b6d43 2 * $Id: snmp_core.cc,v 1.18 1998/11/18 00:16:39 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 {
c68e9c6b 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;
dba79ac5 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
853dead1 63#ifdef __STDC__
c68e9c6b 64static mib_tree_entry *snmpAddNode(oid * name, int len, oid_ParseFn * parsefunction, int children,...);
853dead1 65static oid *snmpCreateOid(int length,...);
66#else
67static mib_tree_entry *snmpAddNode();
68static oid *snmpCreateOid();
69#endif
897029fd 70extern void (*snmplib_debug_hook) (int, char *);
71static void snmpDecodePacket(snmp_request_t * rq);
72static void snmpConstructReponse(snmp_request_t * rq, struct snmp_session *Session);
73static struct snmp_pdu *snmpAgentResponse(struct snmp_pdu *PDU);
74static void snmpUdpSend(int, const struct sockaddr_in *, void *, int);
75static void snmpUdpReply(int, void *);
76static void snmpAppendUdp(snmpUdpData *);
c68e9c6b 77static oid_ParseFn *snmpTreeNext(oid * Current, snint CurrentLen, oid ** Next, snint * NextLen);
d439f213 78static oid_ParseFn *snmpTreeGet(oid * Current, snint CurrentLen);
c68e9c6b 79static mib_tree_entry *snmpTreeEntry(oid entry, snint len, mib_tree_entry * current);
897029fd 80static mib_tree_entry *snmpTreeSiblingEntry(oid entry, snint len, mib_tree_entry * current);
c68e9c6b 81static oid *snmpOidDup(oid * A, snint ALen);
dba79ac5 82static void snmpSnmplibDebug(int lvl, char *buf);
43d4303e 83
43d4303e 84
dba79ac5 85/*
86 * The functions used during startup:
87 * snmpInit
88 * snmpConnectionOpen
89 * snmpConnectionShutdown
90 * snmpConnectionClose
91 */
43d4303e 92
dba79ac5 93/*
c68e9c6b 94 * Turns the MIB into a Tree structure. Called during the startup process.
95 */
43d4303e 96void
97snmpInit(void)
98{
dba79ac5 99 debug(49, 5) ("snmpInit: Called.\n");
100
101 debug(49, 5) ("snmpInit: Building SNMP mib tree structure\n");
102
43d4303e 103 snmplib_debug_hook = snmpSnmplibDebug;
104
dba79ac5 105 mib_tree_head = snmpAddNode(snmpCreateOid(1, 1),
106 1, NULL, 1,
107 snmpAddNode(snmpCreateOid(2, 1, 3),
108 2, NULL, 1,
109 snmpAddNode(snmpCreateOid(3, 1, 3, 6),
110 3, NULL, 1,
111 snmpAddNode(snmpCreateOid(4, 1, 3, 6, 1),
112 4, NULL, 1,
113 snmpAddNode(snmpCreateOid(5, 1, 3, 6, 1, 4),
114 5, NULL, 1,
115 snmpAddNode(snmpCreateOid(6, 1, 3, 6, 1, 4, 1),
116 6, NULL, 1,
117 snmpAddNode(snmpCreateOid(7, 1, 3, 6, 1, 4, 1, 3495),
118 7, NULL, 1,
119 snmpAddNode(snmpCreateOid(LEN_SQUIDMIB, SQUIDMIB),
120 8, NULL, 5,
121 snmpAddNode(snmpCreateOid(LEN_SQ_SYS, SQ_SYS),
122 LEN_SQ_SYS, NULL, 3,
123 snmpAddNode(snmpCreateOid(LEN_SQ_SYS + 1, SQ_SYS, 1),
124 LEN_SQ_SYS + 1, snmp_sysFn, 0),
125 snmpAddNode(snmpCreateOid(LEN_SQ_SYS + 1, SQ_SYS, 2),
126 LEN_SQ_SYS + 1, snmp_sysFn, 0),
127 snmpAddNode(snmpCreateOid(LEN_SQ_SYS + 1, SQ_SYS, 3),
128 LEN_SQ_SYS + 1, snmp_sysFn, 0)),
129 snmpAddNode(snmpCreateOid(LEN_SQ_CONF, SQ_CONF),
130 LEN_SQ_CONF, NULL, 5,
131 snmpAddNode(snmpCreateOid(LEN_SQ_CONF + 1, SQ_CONF, 1),
132 LEN_SQ_CONF + 1, snmp_confFn, 0),
133 snmpAddNode(snmpCreateOid(LEN_SQ_CONF + 1, SQ_CONF, 2),
134 LEN_SQ_CONF + 1, snmp_confFn, 0),
135 snmpAddNode(snmpCreateOid(LEN_SQ_CONF + 1, SQ_CONF, 3),
136 LEN_SQ_CONF + 1, snmp_confFn, 0),
137 snmpAddNode(snmpCreateOid(LEN_SQ_CONF + 1, SQ_CONF, 4),
138 LEN_SQ_CONF + 1, snmp_confFn, 0),
139 snmpAddNode(snmpCreateOid(LEN_SQ_CONF + 1, SQ_CONF, 5),
140 LEN_SQ_CONF + 1, NULL, 6,
141 snmpAddNode(snmpCreateOid(LEN_SQ_CONF + 2, SQ_CONF, 5, 1),
142 LEN_SQ_CONF + 2, snmp_confFn, 0),
143 snmpAddNode(snmpCreateOid(LEN_SQ_CONF + 2, SQ_CONF, 5, 2),
144 LEN_SQ_CONF + 2, snmp_confFn, 0),
145 snmpAddNode(snmpCreateOid(LEN_SQ_CONF + 2, SQ_CONF, 5, 3),
146 LEN_SQ_CONF + 2, snmp_confFn, 0),
147 snmpAddNode(snmpCreateOid(LEN_SQ_CONF + 2, SQ_CONF, 5, 4),
148 LEN_SQ_CONF + 2, snmp_confFn, 0),
149 snmpAddNode(snmpCreateOid(LEN_SQ_CONF + 2, SQ_CONF, 5, 5),
150 LEN_SQ_CONF + 2, snmp_confFn, 0),
151 snmpAddNode(snmpCreateOid(LEN_SQ_CONF + 2, SQ_CONF, 5, 6),
152 LEN_SQ_CONF + 2, snmp_confFn, 0))),
153 snmpAddNode(snmpCreateOid(LEN_SQ_PRF, SQ_PRF),
d439f213 154 LEN_SQ_PRF, NULL, 2,
dba79ac5 155 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 1, SQ_PRF, 1),
d439f213 156 LEN_SQ_PRF + 1, NULL, 11,
dba79ac5 157 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, 1, 1),
d439f213 158 LEN_SQ_PRF + 2, snmp_prfSysFn, 0),
dba79ac5 159 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, 1, 2),
d439f213 160 LEN_SQ_PRF + 2, snmp_prfSysFn, 0),
dba79ac5 161 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, 1, 3),
d439f213 162 LEN_SQ_PRF + 2, snmp_prfSysFn, 0),
dba79ac5 163 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, 1, 4),
d439f213 164 LEN_SQ_PRF + 2, snmp_prfSysFn, 0),
dba79ac5 165 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, 1, 5),
d439f213 166 LEN_SQ_PRF + 2, snmp_prfSysFn, 0),
dba79ac5 167 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, 1, 6),
d439f213 168 LEN_SQ_PRF + 2, snmp_prfSysFn, 0),
dba79ac5 169 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, 1, 7),
d439f213 170 LEN_SQ_PRF + 2, snmp_prfSysFn, 0),
dba79ac5 171 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, 1, 8),
d439f213 172 LEN_SQ_PRF + 2, snmp_prfSysFn, 0),
dba79ac5 173 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, 1, 9),
d439f213 174 LEN_SQ_PRF + 2, snmp_prfSysFn, 0),
dba79ac5 175 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, 1, 10),
d439f213 176 LEN_SQ_PRF + 2, snmp_prfSysFn, 0),
dba79ac5 177 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, 1, 11),
d439f213 178 LEN_SQ_PRF + 2, snmp_prfSysFn, 0)),
dba79ac5 179 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 1, SQ_PRF, 2),
d439f213 180 LEN_SQ_PRF + 1, NULL, 2,
dba79ac5 181 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, 2, 1),
1d5b6d43 182 LEN_SQ_PRF + 2, NULL, 15,
dba79ac5 183 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, 2, 1, 1),
d439f213 184 LEN_SQ_PRF + 3, snmp_prfProtoFn, 0),
dba79ac5 185 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, 2, 1, 2),
d439f213 186 LEN_SQ_PRF + 3, snmp_prfProtoFn, 0),
dba79ac5 187 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, 2, 1, 3),
d439f213 188 LEN_SQ_PRF + 3, snmp_prfProtoFn, 0),
dba79ac5 189 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, 2, 1, 4),
d439f213 190 LEN_SQ_PRF + 3, snmp_prfProtoFn, 0),
dba79ac5 191 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, 2, 1, 5),
d439f213 192 LEN_SQ_PRF + 3, snmp_prfProtoFn, 0),
dba79ac5 193 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, 2, 1, 6),
d439f213 194 LEN_SQ_PRF + 3, snmp_prfProtoFn, 0),
dba79ac5 195 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, 2, 1, 7),
d439f213 196 LEN_SQ_PRF + 3, snmp_prfProtoFn, 0),
dba79ac5 197 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, 2, 1, 8),
d439f213 198 LEN_SQ_PRF + 3, snmp_prfProtoFn, 0),
dba79ac5 199 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, 2, 1, 9),
d439f213 200 LEN_SQ_PRF + 3, snmp_prfProtoFn, 0),
dba79ac5 201 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, 2, 1, 10),
d439f213 202 LEN_SQ_PRF + 3, snmp_prfProtoFn, 0),
dba79ac5 203 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, 2, 1, 11),
d439f213 204 LEN_SQ_PRF + 3, snmp_prfProtoFn, 0),
dba79ac5 205 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, 2, 1, 12),
d439f213 206 LEN_SQ_PRF + 3, snmp_prfProtoFn, 0),
dba79ac5 207 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, 2, 1, 13),
d439f213 208 LEN_SQ_PRF + 3, snmp_prfProtoFn, 0),
1d5b6d43 209 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, 2, 1, 14),
210 LEN_SQ_PRF + 3, snmp_prfProtoFn, 0),
211 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, 2, 1, 15),
d439f213 212 LEN_SQ_PRF + 3, snmp_prfProtoFn, 0)),
dba79ac5 213 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, 2, 2),
d439f213 214 LEN_SQ_PRF + 2, NULL, 1,
dba79ac5 215 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, 2, 2, 1),
1d5b6d43 216 LEN_SQ_PRF + 3, NULL, 10,
dba79ac5 217 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, 2, 2, 1, 1),
897029fd 218 LEN_SQ_PRF + 4, NULL, 3,
219 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 5, SQ_PRF, 2, 2, 1, 1, 1),
220 LEN_SQ_PRF + 5, snmp_prfProtoFn, 0),
221 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 5, SQ_PRF, 2, 2, 1, 1, 5),
222 LEN_SQ_PRF + 5, snmp_prfProtoFn, 0),
223 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 5, SQ_PRF, 2, 2, 1, 1, 60),
224 LEN_SQ_PRF + 5, snmp_prfProtoFn, 0)),
dba79ac5 225 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, 2, 2, 1, 2),
897029fd 226 LEN_SQ_PRF + 4, NULL, 3,
227 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 5, SQ_PRF, 2, 2, 1, 2, 1),
228 LEN_SQ_PRF + 5, snmp_prfProtoFn, 0),
229 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 5, SQ_PRF, 2, 2, 1, 2, 5),
230 LEN_SQ_PRF + 5, snmp_prfProtoFn, 0),
231 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 5, SQ_PRF, 2, 2, 1, 2, 60),
232 LEN_SQ_PRF + 5, snmp_prfProtoFn, 0)),
dba79ac5 233 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, 2, 2, 1, 3),
897029fd 234 LEN_SQ_PRF + 4, NULL, 3,
235 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 5, SQ_PRF, 2, 2, 1, 3, 1),
236 LEN_SQ_PRF + 5, snmp_prfProtoFn, 0),
237 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 5, SQ_PRF, 2, 2, 1, 3, 5),
238 LEN_SQ_PRF + 5, snmp_prfProtoFn, 0),
239 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 5, SQ_PRF, 2, 2, 1, 3, 60),
240 LEN_SQ_PRF + 5, snmp_prfProtoFn, 0)),
dba79ac5 241 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, 2, 2, 1, 4),
897029fd 242 LEN_SQ_PRF + 4, NULL, 3,
243 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 5, SQ_PRF, 2, 2, 1, 4, 1),
244 LEN_SQ_PRF + 5, snmp_prfProtoFn, 0),
245 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 5, SQ_PRF, 2, 2, 1, 4, 5),
246 LEN_SQ_PRF + 5, snmp_prfProtoFn, 0),
247 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 5, SQ_PRF, 2, 2, 1, 4, 60),
248 LEN_SQ_PRF + 5, snmp_prfProtoFn, 0)),
dba79ac5 249 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, 2, 2, 1, 5),
897029fd 250 LEN_SQ_PRF + 4, NULL, 3,
251 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 5, SQ_PRF, 2, 2, 1, 5, 1),
252 LEN_SQ_PRF + 5, snmp_prfProtoFn, 0),
253 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 5, SQ_PRF, 2, 2, 1, 5, 5),
254 LEN_SQ_PRF + 5, snmp_prfProtoFn, 0),
255 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 5, SQ_PRF, 2, 2, 1, 5, 60),
256 LEN_SQ_PRF + 5, snmp_prfProtoFn, 0)),
dba79ac5 257 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, 2, 2, 1, 6),
897029fd 258 LEN_SQ_PRF + 4, NULL, 3,
259 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 5, SQ_PRF, 2, 2, 1, 6, 1),
260 LEN_SQ_PRF + 5, snmp_prfProtoFn, 0),
261 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 5, SQ_PRF, 2, 2, 1, 6, 5),
262 LEN_SQ_PRF + 5, snmp_prfProtoFn, 0),
263 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 5, SQ_PRF, 2, 2, 1, 6, 60),
264 LEN_SQ_PRF + 5, snmp_prfProtoFn, 0)),
dba79ac5 265 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, 2, 2, 1, 7),
897029fd 266 LEN_SQ_PRF + 4, NULL, 3,
267 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 5, SQ_PRF, 2, 2, 1, 7, 1),
268 LEN_SQ_PRF + 5, snmp_prfProtoFn, 0),
269 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 5, SQ_PRF, 2, 2, 1, 7, 5),
270 LEN_SQ_PRF + 5, snmp_prfProtoFn, 0),
271 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 5, SQ_PRF, 2, 2, 1, 7, 60),
272 LEN_SQ_PRF + 5, snmp_prfProtoFn, 0)),
1d5b6d43 273 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, 2, 2, 1, 8),
274 LEN_SQ_PRF + 4, NULL, 3,
897029fd 275 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 5, SQ_PRF, 2, 2, 1, 8, 1),
276 LEN_SQ_PRF + 5, snmp_prfProtoFn, 0),
277 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 5, SQ_PRF, 2, 2, 1, 8, 5),
1d5b6d43 278 LEN_SQ_PRF + 5, snmp_prfProtoFn, 0),
279 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 5, SQ_PRF, 2, 2, 1, 8, 60),
280 LEN_SQ_PRF + 5, snmp_prfProtoFn, 0)),
281 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, 2, 2, 1, 9),
282 LEN_SQ_PRF + 4, NULL, 3,
283 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 5, SQ_PRF, 2, 2, 1, 9, 1),
284 LEN_SQ_PRF + 5, snmp_prfProtoFn, 0),
285 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 5, SQ_PRF, 2, 2, 1, 9, 5),
286 LEN_SQ_PRF + 5, snmp_prfProtoFn, 0),
287 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 5, SQ_PRF, 2, 2, 1, 9, 60),
288 LEN_SQ_PRF + 5, snmp_prfProtoFn, 0)),
289 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, 2, 2, 1, 10),
290 LEN_SQ_PRF + 4, NULL, 3,
291 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 5, SQ_PRF, 2, 2, 1, 10, 1),
292 LEN_SQ_PRF + 5, snmp_prfProtoFn, 0),
293 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 5, SQ_PRF, 2, 2, 1, 10, 5),
294 LEN_SQ_PRF + 5, snmp_prfProtoFn, 0),
295 snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 5, SQ_PRF, 2, 2, 1, 10, 60),
897029fd 296 LEN_SQ_PRF + 5, snmp_prfProtoFn, 0)))))),
dba79ac5 297 snmpAddNode(snmpCreateOid(LEN_SQ_NET, SQ_NET),
d439f213 298 LEN_SQ_NET, NULL, 3,
dba79ac5 299 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 1, SQ_NET, 1),
897029fd 300 LEN_SQ_NET + 1, NULL, 8,
dba79ac5 301 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, 1, 1),
d439f213 302 LEN_SQ_NET + 2, snmp_netIpFn, 0),
dba79ac5 303 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, 1, 2),
d439f213 304 LEN_SQ_NET + 2, snmp_netIpFn, 0),
dba79ac5 305 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, 1, 3),
d439f213 306 LEN_SQ_NET + 2, snmp_netIpFn, 0),
dba79ac5 307 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, 1, 4),
d439f213 308 LEN_SQ_NET + 2, snmp_netIpFn, 0),
dba79ac5 309 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, 1, 5),
d439f213 310 LEN_SQ_NET + 2, snmp_netIpFn, 0),
dba79ac5 311 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, 1, 6),
d439f213 312 LEN_SQ_NET + 2, snmp_netIpFn, 0),
dba79ac5 313 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, 1, 7),
d439f213 314 LEN_SQ_NET + 2, snmp_netIpFn, 0),
dba79ac5 315 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, 1, 8),
d439f213 316 LEN_SQ_NET + 2, snmp_netIpFn, 0)),
dba79ac5 317 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 1, SQ_NET, 2),
897029fd 318 LEN_SQ_NET + 1, NULL, 7,
dba79ac5 319 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, 2, 1),
d439f213 320 LEN_SQ_NET + 2, snmp_netFqdnFn, 0),
dba79ac5 321 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, 2, 2),
d439f213 322 LEN_SQ_NET + 2, snmp_netFqdnFn, 0),
dba79ac5 323 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, 2, 3),
d439f213 324 LEN_SQ_NET + 2, snmp_netFqdnFn, 0),
dba79ac5 325 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, 2, 4),
d439f213 326 LEN_SQ_NET + 2, snmp_netFqdnFn, 0),
dba79ac5 327 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, 2, 5),
d439f213 328 LEN_SQ_NET + 2, snmp_netFqdnFn, 0),
dba79ac5 329 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, 2, 6),
d439f213 330 LEN_SQ_NET + 2, snmp_netFqdnFn, 0),
dba79ac5 331 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, 2, 7),
d439f213 332 LEN_SQ_NET + 2, snmp_netFqdnFn, 0)),
dba79ac5 333 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 1, SQ_NET, 3),
d439f213 334 LEN_SQ_NET + 1, NULL, 3,
dba79ac5 335 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, 3, 1),
d439f213 336 LEN_SQ_NET + 2, snmp_netDnsFn, 0),
dba79ac5 337 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, 3, 2),
d439f213 338 LEN_SQ_NET + 2, snmp_netDnsFn, 0),
dba79ac5 339 snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, 3, 3),
d439f213 340 LEN_SQ_NET + 2, snmp_netDnsFn, 0))),
dba79ac5 341 snmpAddNode(snmpCreateOid(LEN_SQ_MESH, SQ_MESH),
d439f213 342 LEN_SQ_MESH, NULL, 2,
dba79ac5 343 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 1, SQ_MESH, 1),
d439f213 344 LEN_SQ_MESH + 1, NULL, 1,
dba79ac5 345 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 2, SQ_MESH, 1, 1),
d439f213 346 LEN_SQ_MESH + 2, NULL, 13,
dba79ac5 347 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 1),
d439f213 348 LEN_SQ_MESH + 3, snmp_meshPtblFn, 0),
dba79ac5 349 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 2),
d439f213 350 LEN_SQ_MESH + 3, snmp_meshPtblFn, 0),
dba79ac5 351 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 3),
d439f213 352 LEN_SQ_MESH + 3, snmp_meshPtblFn, 0),
dba79ac5 353 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 4),
d439f213 354 LEN_SQ_MESH + 3, snmp_meshPtblFn, 0),
dba79ac5 355 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 5),
d439f213 356 LEN_SQ_MESH + 3, snmp_meshPtblFn, 0),
dba79ac5 357 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 6),
d439f213 358 LEN_SQ_MESH + 3, snmp_meshPtblFn, 0),
dba79ac5 359 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 7),
d439f213 360 LEN_SQ_MESH + 3, snmp_meshPtblFn, 0),
dba79ac5 361 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 8),
d439f213 362 LEN_SQ_MESH + 3, snmp_meshPtblFn, 0),
dba79ac5 363 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 9),
d439f213 364 LEN_SQ_MESH + 3, snmp_meshPtblFn, 0),
dba79ac5 365 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 10),
d439f213 366 LEN_SQ_MESH + 3, snmp_meshPtblFn, 0),
dba79ac5 367 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 11),
d439f213 368 LEN_SQ_MESH + 3, snmp_meshPtblFn, 0),
dba79ac5 369 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 12),
d439f213 370 LEN_SQ_MESH + 3, snmp_meshPtblFn, 0),
dba79ac5 371 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 13),
d439f213 372 LEN_SQ_MESH + 3, snmp_meshPtblFn, 0))),
dba79ac5 373 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 1, SQ_MESH, 2),
d439f213 374 LEN_SQ_MESH + 1, NULL, 1,
dba79ac5 375 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 2, SQ_MESH, 2, 1),
d439f213 376 LEN_SQ_MESH + 2, NULL, 9,
dba79ac5 377 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 1),
d439f213 378 LEN_SQ_MESH + 3, snmp_meshCtblFn, 0),
dba79ac5 379 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 2),
d439f213 380 LEN_SQ_MESH + 3, snmp_meshCtblFn, 0),
dba79ac5 381 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 3),
d439f213 382 LEN_SQ_MESH + 3, snmp_meshCtblFn, 0),
dba79ac5 383 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 4),
d439f213 384 LEN_SQ_MESH + 3, snmp_meshCtblFn, 0),
dba79ac5 385 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 5),
d439f213 386 LEN_SQ_MESH + 3, snmp_meshCtblFn, 0),
dba79ac5 387 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 6),
d439f213 388 LEN_SQ_MESH + 3, snmp_meshCtblFn, 0),
dba79ac5 389 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 7),
d439f213 390 LEN_SQ_MESH + 3, snmp_meshCtblFn, 0),
dba79ac5 391 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 8),
d439f213 392 LEN_SQ_MESH + 3, snmp_meshCtblFn, 0),
dba79ac5 393 snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 9),
d439f213 394 LEN_SQ_MESH + 3, snmp_meshCtblFn, 0))))
dba79ac5 395 )
396 )
397 )
398 )
399 )
400 )
401 )
402 );
403
404 debug(49, 9) ("snmpInit: Completed SNMP mib tree structure\n");
43d4303e 405}
406
407void
408snmpConnectionOpen(void)
409{
410 u_short port;
43d4303e 411 struct sockaddr_in xaddr;
6637e3a5 412 socklen_t len;
43d4303e 413 int x;
414
c68e9c6b 415 debug(49, 5) ("snmpConnectionOpen: Called\n");
43d4303e 416 if ((port = Config.Port.snmp) > (u_short) 0) {
c68e9c6b 417 enter_suid();
418 theInSnmpConnection = comm_open(SOCK_DGRAM,
419 0,
420 Config.Addrs.snmp_incoming,
421 port,
422 COMM_NONBLOCKING,
423 "SNMP Port");
424 leave_suid();
425 if (theInSnmpConnection < 0)
426 fatal("Cannot open snmp Port");
427 commSetSelect(theInSnmpConnection, COMM_SELECT_READ, snmpHandleUdp, NULL, 0);
428 debug(1, 1) ("Accepting SNMP messages on port %d, FD %d.\n",
429 (int) port, theInSnmpConnection);
430 if (Config.Addrs.snmp_outgoing.s_addr != no_addr.s_addr) {
431 enter_suid();
432 theOutSnmpConnection = comm_open(SOCK_DGRAM,
433 0,
434 Config.Addrs.snmp_outgoing,
435 port,
436 COMM_NONBLOCKING,
437 "SNMP Port");
438 leave_suid();
439 if (theOutSnmpConnection < 0)
440 fatal("Cannot open Outgoing SNMP Port");
441 commSetSelect(theOutSnmpConnection,
442 COMM_SELECT_READ,
443 snmpHandleUdp,
444 NULL, 0);
445 debug(1, 1) ("Outgoing SNMP messages on port %d, FD %d.\n",
446 (int) port, theOutSnmpConnection);
447 fd_note(theOutSnmpConnection, "Outgoing SNMP socket");
448 fd_note(theInSnmpConnection, "Incoming SNMP socket");
449 } else {
450 theOutSnmpConnection = theInSnmpConnection;
451 }
452 memset(&theOutSNMPAddr, '\0', sizeof(struct in_addr));
453 len = sizeof(struct sockaddr_in);
454 memset(&xaddr, '\0', len);
455 x = getsockname(theOutSnmpConnection,
456 (struct sockaddr *) &xaddr, &len);
457 if (x < 0)
458 debug(51, 1) ("theOutSnmpConnection FD %d: getsockname: %s\n",
459 theOutSnmpConnection, xstrerror());
460 else
461 theOutSNMPAddr = xaddr.sin_addr;
43d4303e 462 }
463}
464
43d4303e 465void
466snmpConnectionShutdown(void)
467{
468 if (theInSnmpConnection < 0)
c68e9c6b 469 return;
43d4303e 470 if (theInSnmpConnection != theOutSnmpConnection) {
c68e9c6b 471 debug(49, 1) ("FD %d Closing SNMP socket\n", theInSnmpConnection);
472 comm_close(theInSnmpConnection);
43d4303e 473 }
474 /*
475 * Here we set 'theInSnmpConnection' to -1 even though the SNMP 'in'
476 * and 'out' sockets might be just one FD. This prevents this
477 * function from executing repeatedly. When we are really ready to
478 * exit or restart, main will comm_close the 'out' descriptor.
479 */ theInSnmpConnection = -1;
dba79ac5 480 /*
43d4303e 481 * Normally we only write to the outgoing SNMP socket, but we
482 * also have a read handler there to catch messages sent to that
483 * specific interface. During shutdown, we must disable reading
484 * on the outgoing socket.
485 */
486 assert(theOutSnmpConnection > -1);
487 commSetSelect(theOutSnmpConnection, COMM_SELECT_READ, NULL, NULL, 0);
488}
489
490void
491snmpConnectionClose(void)
492{
493 snmpConnectionShutdown();
494 if (theOutSnmpConnection > -1) {
c68e9c6b 495 debug(49, 1) ("FD %d Closing SNMP socket\n", theOutSnmpConnection);
496 comm_close(theOutSnmpConnection);
43d4303e 497 }
498}
499
dba79ac5 500/*
c68e9c6b 501 * Functions for handling the requests.
502 */
43d4303e 503
dba79ac5 504/*
505 * Accept the UDP packet
506 */
43d4303e 507void
dba79ac5 508snmpHandleUdp(int sock, void *not_used)
43d4303e 509{
dba79ac5 510 LOCAL_ARRAY(char, buf, SNMP_REQUEST_SIZE);
511 struct sockaddr_in from;
512 socklen_t from_len;
513 snmp_request_t *snmp_rq;
514 int len;
515
516 debug(49, 5) ("snmpHandleUdp: Called.\n");
517
518 commSetSelect(sock, COMM_SELECT_READ, snmpHandleUdp, NULL, 0);
519 from_len = sizeof(struct sockaddr_in);
520 memset(&from, '\0', from_len);
521
522 Counter.syscalls.sock.recvfroms++;
523
524 len = recvfrom(sock,
525 buf,
526 SNMP_REQUEST_SIZE,
527 0,
528 (struct sockaddr *) &from,
529 &from_len);
530
531 if (len > 0) {
532 buf[len] = '\0';
533 debug(49, 3) ("snmpHandleUdp: FD %d: received %d bytes from %s.\n",
534 sock,
535 len,
536 inet_ntoa(from.sin_addr));
537
538 snmp_rq = xcalloc(1, sizeof(snmp_request_t));
539 snmp_rq->buf = (u_char *) buf;
540 snmp_rq->len = len;
541 snmp_rq->sock = sock;
542 snmp_rq->outbuf = xmalloc(snmp_rq->outlen = SNMP_REQUEST_SIZE);
543 memcpy(&snmp_rq->from, &from, sizeof(struct sockaddr_in));
544 snmpDecodePacket(snmp_rq);
545 } else {
546 debug(49, 1) ("snmpHandleUdp: FD %d recvfrom: %s\n", sock, xstrerror());
547 }
548}
43d4303e 549
dba79ac5 550/*
551 * Turn SNMP packet into a PDU, check available ACL's
552 */
553void
554snmpDecodePacket(snmp_request_t * rq)
555{
43d4303e 556 struct snmp_pdu *PDU;
dba79ac5 557 struct snmp_session *Session;
558 aclCheck_t checklist;
43d4303e 559 u_char *Community;
dba79ac5 560 u_char *buf = rq->buf;
561 int len = rq->len;
562 int allow = 0;
43d4303e 563
dba79ac5 564 debug(49, 5) ("snmpDecodePacket: Called.\n");
43d4303e 565 /* Now that we have the data, turn it into a PDU */
dba79ac5 566 Session = (struct snmp_session *) xmalloc(sizeof(struct snmp_session));
567 Session->Version = SNMP_VERSION_1;
568 Session->authenticator = NULL;
569 Session->community = (u_char *) xstrdup("public");
570 Session->community_len = 6;
43d4303e 571 cbdataAdd(rq, MEM_NONE);
572 PDU = snmp_pdu_create(0);
573 Community = snmp_parse(Session, PDU, buf, len);
574
dba79ac5 575 checklist.src_addr = rq->from.sin_addr;
576 checklist.snmp_community = Community;
577
578 allow = aclCheckFast(Config.accessList.snmp, &checklist);
579 if ((snmp_coexist_V2toV1(PDU)) && (Community) && (allow)) {
580 rq->community = Community;
581 rq->PDU = PDU;
582 debug(49, 5) ("snmpAgentParse: reqid=[%d]\n", PDU->reqid);
583 snmpConstructReponse(rq, Session);
584 } else {
b644367b 585 snmp_free_pdu(PDU);
43d4303e 586 }
dba79ac5 587}
43d4303e 588
dba79ac5 589/*
590 * Packet OK, ACL Check OK, Create reponse.
591 */
592void
593snmpConstructReponse(snmp_request_t * rq, struct snmp_session *Session)
594{
595 struct snmp_pdu *RespPDU;
596 int ret;
43d4303e 597
dba79ac5 598 debug(49, 5) ("snmpConstructReponse: Called.\n");
599
600 Session->community = rq->community;
601 Session->community_len = strlen((char *) rq->community);
602
603 RespPDU = snmpAgentResponse(rq->PDU);
604 snmp_free_pdu(rq->PDU);
605 xfree(Session);
606 if (RespPDU == NULL) {
607 } else {
608 ret = snmp_build(Session, RespPDU, rq->outbuf, &rq->outlen);
609 snmpUdpSend(rq->sock, &rq->from, rq->outbuf, rq->outlen);
610 snmp_free_pdu(RespPDU);
43d4303e 611 }
43d4303e 612}
613
dba79ac5 614/*
615 * Decide how to respond to the request, construct a response and
616 * return the response to the requester.
617 *
618 * If configured forward any reponses which are not for this agent.
619 */
43d4303e 620struct snmp_pdu *
621snmpAgentResponse(struct snmp_pdu *PDU)
622{
623 struct snmp_pdu *Answer = NULL;
dba79ac5 624 oid_ParseFn *ParseFn = NULL;
d439f213 625
626 variable_list *VarPtr, *VarNew = NULL, **VarPtrP;
627 int index = 0;
43d4303e 628
dba79ac5 629 debug(49, 5) ("snmpAgentResponse: Called.\n");
43d4303e 630
dba79ac5 631 if ((Answer = snmp_pdu_create(SNMP_PDU_RESPONSE))) {
632 Answer->reqid = PDU->reqid;
633 Answer->errindex = 0;
634 if (PDU->command == SNMP_PDU_GET) {
d439f213 635 variable_list **RespVars;
636
637 RespVars = &(Answer->variables);
638 /* Loop through all variables */
639 for (VarPtrP = &(PDU->variables);
640 *VarPtrP;
641 VarPtrP = &((*VarPtrP)->next_variable)) {
642 VarPtr = *VarPtrP;
643
644 index++;
645
646 /* Find the parsing function for this variable */
647 ParseFn = snmpTreeGet(VarPtr->name, VarPtr->name_length);
648
649 if (ParseFn == NULL) {
650 Answer->errstat = SNMP_ERR_NOSUCHNAME;
651 debug(49, 5) ("snmpAgentResponse: No such oid. ");
652 } else
653 VarNew = (*ParseFn) (VarPtr, (snint *) & (Answer->errstat));
654
655 /* Was there an error? */
656 if ((Answer->errstat != SNMP_ERR_NOERROR) ||
657 (VarNew == NULL)) {
658 Answer->errindex = index;
659 debug(49, 5) ("snmpAgentParse: successful.\n");
660 /* Just copy the rest of the variables. Quickly. */
661 *RespVars = VarPtr;
662 *VarPtrP = NULL;
663 return (Answer);
664 }
665 /* No error. Insert this var at the end, and move on to the next.
666 */
667 *RespVars = VarNew;
668 RespVars = &(VarNew->next_variable);
669 }
670 return (Answer);
dba79ac5 671 } else if (PDU->command == SNMP_PDU_GETNEXT) {
672 oid *NextOidName = NULL;
673 int NextOidNameLen = 0;
b644367b 674
dba79ac5 675 ParseFn = snmpTreeNext(PDU->variables->name, PDU->variables->name_length,
c68e9c6b 676 &(NextOidName), (snint *) & NextOidNameLen);
b644367b 677
678 if (ParseFn == NULL) {
679 Answer->errstat = SNMP_ERR_NOSUCHNAME;
dba79ac5 680 debug(49, 5) ("snmpAgentResponse: No such oid: ");
681 snmpDebugOid(5, PDU->variables->name, PDU->variables->name_length);
682 } else {
683 xfree(PDU->variables->name);
684 PDU->variables->name = NextOidName;
685 PDU->variables->name_length = NextOidNameLen;
c68e9c6b 686 VarNew = (*ParseFn) (PDU->variables, (snint *) & Answer->errstat);
dba79ac5 687 }
b644367b 688
689 /* Was there an error? */
dba79ac5 690 if (Answer->errstat != SNMP_ERR_NOERROR) {
691 Answer->errindex = 1;
dba79ac5 692 Answer->variables = PDU->variables;
693 PDU->variables = NULL;
694 } else {
695 Answer->variables = VarNew;
b644367b 696 }
dba79ac5 697
c68e9c6b 698 } else {
699 snmp_free_pdu(Answer);
700 Answer = NULL;
b644367b 701 }
dba79ac5 702 }
703 return (Answer);
704}
b644367b 705
d439f213 706oid_ParseFn *
707snmpTreeGet(oid * Current, snint CurrentLen)
708{
709 oid_ParseFn *Fn = NULL;
710 mib_tree_entry *mibTreeEntry = NULL;
711 int count = 0;
712
713 debug(49, 5) ("snmpTreeGet: Called\n");
714
715 debug(49, 6) ("snmpTreeGet: Current : \n");
716 snmpDebugOid(6, Current, CurrentLen);
717
718 mibTreeEntry = mib_tree_head;
719 if (Current[count] == mibTreeEntry->name[count]) {
720 count++;
721 while ((mibTreeEntry) && (count < CurrentLen)) {
722 mibTreeEntry = snmpTreeEntry(Current[count], count, mibTreeEntry);
723 count++;
724 }
725 }
726 if (mibTreeEntry) {
727 Fn = mibTreeEntry->parsefunction;
728 }
729 debug(49, 5) ("snmpTreeGet: return\n");
730 return (Fn);
731}
732
dba79ac5 733oid_ParseFn *
734snmpTreeNext(oid * Current, snint CurrentLen, oid ** Next, snint * NextLen)
735{
736 oid_ParseFn *Fn = NULL;
897029fd 737 mib_tree_entry *mibTreeEntry = NULL, *nextoid = NULL;
dba79ac5 738 int count = 0;
739
740 debug(49, 5) ("snmpTreeNext: Called\n");
741
742 debug(49, 6) ("snmpTreeNext: Current : \n");
743 snmpDebugOid(6, Current, CurrentLen);
b644367b 744
dba79ac5 745 mibTreeEntry = mib_tree_head;
746 if (Current[count] == mibTreeEntry->name[count]) {
747 count++;
748 while ((mibTreeEntry) && (count < CurrentLen)) {
c68e9c6b 749 mibTreeEntry = snmpTreeEntry(Current[count], count, mibTreeEntry);
dba79ac5 750 count++;
b644367b 751 }
897029fd 752 debug(49, 5) ("snmpTreeNext: Recursed down to requested object\n");
dba79ac5 753
d439f213 754 if ((mibTreeEntry) && (mibTreeEntry->parsefunction)) {
755 count--;
897029fd 756 nextoid = snmpTreeSiblingEntry(Current[count], count, mibTreeEntry->parent);
757 if(nextoid){
758 mibTreeEntry = nextoid;
759 count++;
760 }else{
761 debug(49, 5) ("snmpTreeNext: Attempting to recurse up for next object\n");
762 while(!nextoid){
763 count--;
764 nextoid = mibTreeEntry->parent;
765 mibTreeEntry = snmpTreeEntry(Current[count] + 1, count, nextoid->parent);
766 if(!mibTreeEntry){
767 mibTreeEntry = nextoid;
768 nextoid = NULL;
769 }
770 }
771 }
c68e9c6b 772 }
dba79ac5 773 debug(49, 5) ("snmpTreeNext: Past Second\n");
b644367b 774
d439f213 775 while ((mibTreeEntry) && (!mibTreeEntry->parsefunction)) {
897029fd 776 mibTreeEntry = mibTreeEntry->leaves[0];
dba79ac5 777 }
dba79ac5 778 }
c68e9c6b 779 if (mibTreeEntry) {
780 *Next = snmpOidDup(mibTreeEntry->name, mibTreeEntry->len);
781 *NextLen = mibTreeEntry->len;
dba79ac5 782 Fn = mibTreeEntry->parsefunction;
783 }
784 debug(49, 5) ("snmpTreeNext: return\n");
785 return (Fn);
43d4303e 786}
787
dba79ac5 788mib_tree_entry *
897029fd 789snmpTreeSiblingEntry(oid entry, snint len, mib_tree_entry * current)
43d4303e 790{
dba79ac5 791 mib_tree_entry *next = NULL;
792 int count = 0;
897029fd 793
794 while ((!next) && (count < current->children)) {
795 if (current->leaves[count]->name[len] == entry) {
796 next = current->leaves[count];
797 }
798 count++;
799 }
800 if(count < current->children){
801 next = current->leaves[count];
802 }else{
803 next = NULL;
804 }
805 return (next);
806}
665bc266 807
897029fd 808mib_tree_entry *
809snmpTreeEntry(oid entry, snint len, mib_tree_entry * current)
810{
811 mib_tree_entry *next = NULL;
812 int count = 0;
43d4303e 813
dba79ac5 814 while ((!next) && (count < current->children)) {
dba79ac5 815 if (current->leaves[count]->name[len] == entry) {
816 next = current->leaves[count];
817 }
818 count++;
43d4303e 819 }
dba79ac5 820 return (next);
821}
43d4303e 822
d439f213 823/*
824 * Utility functions
825 */
826
827/*
828 * Tree utility functions.
829 */
830
831/*
832 * Adds a node to the MIB tree structure and adds the appropriate children
833 */
853dead1 834#ifdef __STDC__
d439f213 835mib_tree_entry *
836snmpAddNode(oid * name, int len, oid_ParseFn * parsefunction, int children,...)
837{
838 va_list args;
839 int loop;
840 mib_tree_entry *entry = NULL;
853dead1 841 va_start(args, children);
842
843#else
844mib_tree_entry *
845snmpAddNode(va_alist)
846 va_dcl
847{
848 va_list args;
849 oid *name = NULL;
850 int len = 0, children = 0, loop;
851 oid_ParseFn *parsefunction = NULL;
852 mib_tree_entry *entry = NULL;
853
854 va_start(args);
855 name = va_arg(args, oid *);
856 len = va_arg(args, int);
857 parsefunction = va_arg(args, oid_ParseFn *);
858 children = va_arg(args, int);
859#endif
d439f213 860
861 debug(49, 6) ("snmpAddNode: Children : %d, Oid : \n", children);
862 snmpDebugOid(6, name, len);
863
864 va_start(args, children);
865 entry = xmalloc(sizeof(mib_tree_entry));
866 entry->name = snmpOidDup(name, len);
867 entry->len = len;
868 entry->parsefunction = parsefunction;
869 entry->children = children;
870
871 if (children > 0) {
872 entry->leaves = xmalloc(sizeof(mib_tree_entry *) * children);
873 for (loop = 0; loop < children; loop++) {
874 entry->leaves[loop] = va_arg(args, mib_tree_entry *);
875 entry->leaves[loop]->parent = entry;
876 }
877 }
878 return (entry);
879}
880/* End of tree utility functions */
881
dba79ac5 882/*
c68e9c6b 883 * Send the UDP reply.
884 */
dba79ac5 885void
886snmpUdpSend(int fd, const struct sockaddr_in *to, void *msg, int len)
887{
888 snmpUdpData *data = xcalloc(1, sizeof(snmpUdpData));
889 debug(49, 5) ("snmpUdpSend: Queueing response for %s\n",
c68e9c6b 890 inet_ntoa(to->sin_addr));
dba79ac5 891 data->address = *to;
892 data->msg = msg;
893 data->len = len;
894 snmpAppendUdp(data);
895 commSetSelect(fd, COMM_SELECT_WRITE, snmpUdpReply, snmpUdpHead, 0);
43d4303e 896
dba79ac5 897}
43d4303e 898
dba79ac5 899void
900snmpUdpReply(int fd, void *data)
901{
902 snmpUdpData *queue = data;
903 int x;
904 /* Disable handler, in case of errors. */
905 commSetSelect(fd, COMM_SELECT_WRITE, NULL, NULL, 0);
906 while ((queue = snmpUdpHead) != NULL) {
c68e9c6b 907 debug(49, 5) ("snmpUdpReply: FD %d sending %d bytes to %s port %d\n",
908 fd,
909 queue->len,
910 inet_ntoa(queue->address.sin_addr),
911 ntohs(queue->address.sin_port));
912 x = comm_udp_sendto(fd,
913 &queue->address,
914 sizeof(struct sockaddr_in),
915 queue->msg,
916 queue->len);
917 if (x < 0) {
918 if (ignoreErrno(errno))
919 break; /* don't de-queue */
920 }
921 snmpUdpHead = queue->next;
922 debug(49, 3) ("snmpUdpReply: freeing %p\n", queue->msg);
923 safe_free(queue->msg);
924 debug(49, 3) ("snmpUdpReply: freeing %p\n", queue);
925 safe_free(queue);
dba79ac5 926 }
927 /* Reinstate handler if needed */
928 if (snmpUdpHead) {
c68e9c6b 929 commSetSelect(fd, COMM_SELECT_WRITE, snmpUdpReply, snmpUdpHead, 0);
dba79ac5 930 }
43d4303e 931}
932
dba79ac5 933void
934snmpAppendUdp(snmpUdpData * item)
43d4303e 935{
dba79ac5 936 item->next = NULL;
937 if (snmpUdpHead == NULL) {
c68e9c6b 938 snmpUdpHead = item;
939 snmpUdpTail = item;
dba79ac5 940 } else if (snmpUdpTail == snmpUdpHead) {
c68e9c6b 941 snmpUdpTail = item;
942 snmpUdpHead->next = item;
dba79ac5 943 } else {
c68e9c6b 944 snmpUdpTail->next = item;
945 snmpUdpTail = item;
43d4303e 946 }
947
dba79ac5 948}
43d4303e 949
dba79ac5 950/*
c68e9c6b 951 * Returns the list of parameters in an oid[]
952 */
853dead1 953#ifdef __STDC__
c68e9c6b 954oid *
955snmpCreateOid(int length,...)
dba79ac5 956{
c68e9c6b 957 va_list args;
958 oid *new_oid;
959 int loop;
960
961 va_start(args, length);
853dead1 962#else
963oid *
964snmpCreateOid(va_alist)
965 va_dcl
966{
967 va_list args;
968 int length = 0, loop;
969 oid *new_oid;
970
971 va_start(args);
972 length va_arg(args, int);
973#endif
974
c68e9c6b 975 new_oid = xmalloc(sizeof(oid) * length);
976
977 if (length > 0) {
978 for (loop = 0; loop < length; loop++) {
979 new_oid[loop] = va_arg(args, int);
980 }
981 }
982 return (new_oid);
43d4303e 983}
984
dba79ac5 985/*
c68e9c6b 986 * Allocate space for, and copy, an OID. Returns new oid, or NULL.
43d4303e 987 */
988oid *
dba79ac5 989snmpOidDup(oid * A, snint ALen)
43d4303e 990{
991 oid *Ans;
c68e9c6b 992
993 Ans = (oid *) xmalloc(sizeof(oid) * ALen);
43d4303e 994 if (Ans)
c68e9c6b 995 memcpy(Ans, A, (sizeof(oid) * ALen));
43d4303e 996 return (Ans);
997}
998
dba79ac5 999/*
c68e9c6b 1000 * Debug calls, prints out the OID for debugging purposes.
1001 */
dba79ac5 1002void
1003snmpDebugOid(int lvl, oid * Name, snint Len)
c68e9c6b 1004{
dba79ac5 1005 char mbuf[16], objid[1024];
1006 int x;
1007 objid[0] = '\0';
43d4303e 1008
dba79ac5 1009 for (x = 0; x < Len; x++) {
c68e9c6b 1010 snprintf(mbuf, sizeof(mbuf), ".%u", (unsigned int) Name[x]);
1011 strncat(objid, mbuf, sizeof(objid));
43d4303e 1012 }
c68e9c6b 1013
dba79ac5 1014 debug(49, lvl) (" oid = %s\n", objid);
43d4303e 1015}
b644367b 1016
c68e9c6b 1017static void
dba79ac5 1018snmpSnmplibDebug(int lvl, char *buf)
c68e9c6b 1019{
dba79ac5 1020 debug(49, lvl) ("%s", buf);
c68e9c6b 1021}