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