3 * $Id: snmp_core.cc,v 1.81 2007/12/18 23:24:25 amosjeffries Exp $
5 * DEBUG: section 49 SNMP support
6 * AUTHOR: Glenn Chisholm
8 * SQUID Web Proxy Cache http://www.squid-cache.org/
9 * ----------------------------------------------------------
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.
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.
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.
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
37 #include "cache_snmp.h"
38 #include "ACLChecklist.h"
40 #define SNMP_REQUEST_SIZE 4096
41 #define MAX_PROTOSTAT 5
43 typedef struct _mib_tree_entry mib_tree_entry
;
44 typedef oid
*(instance_Fn
) (oid
* name
, snint
* len
, mib_tree_entry
* current
, oid_ParseFn
** Fn
);
46 struct _mib_tree_entry
50 oid_ParseFn
*parsefunction
;
51 instance_Fn
*instancefunction
;
54 struct _mib_tree_entry
**leaves
;
56 struct _mib_tree_entry
*parent
;
59 mib_tree_entry
*mib_tree_head
;
60 mib_tree_entry
*mib_tree_last
;
63 static mib_tree_entry
*snmpAddNode(oid
* name
, int len
, oid_ParseFn
* parsefunction
, instance_Fn
* instancefunction
, int children
,...);
64 static oid
*snmpCreateOid(int length
,...);
66 static mib_tree_entry
*snmpAddNode();
67 static oid
*snmpCreateOid();
69 SQUIDCEXTERN
void (*snmplib_debug_hook
) (int, char *);
70 static oid
*static_Inst(oid
* name
, snint
* len
, mib_tree_entry
* current
, oid_ParseFn
** Fn
);
71 static oid
*time_Inst(oid
* name
, snint
* len
, mib_tree_entry
* current
, oid_ParseFn
** Fn
);
72 static oid
*peer_Inst(oid
* name
, snint
* len
, mib_tree_entry
* current
, oid_ParseFn
** Fn
);
73 static oid
*client_Inst(oid
* name
, snint
* len
, mib_tree_entry
* current
, oid_ParseFn
** Fn
);
74 static void snmpDecodePacket(snmp_request_t
* rq
);
75 static void snmpConstructReponse(snmp_request_t
* rq
);
77 static struct snmp_pdu
*snmpAgentResponse(struct snmp_pdu
*PDU
);
78 static oid_ParseFn
*snmpTreeNext(oid
* Current
, snint CurrentLen
, oid
** Next
, snint
* NextLen
);
79 static oid_ParseFn
*snmpTreeGet(oid
* Current
, snint CurrentLen
);
80 static mib_tree_entry
*snmpTreeEntry(oid entry
, snint len
, mib_tree_entry
* current
);
81 static mib_tree_entry
*snmpTreeSiblingEntry(oid entry
, snint len
, mib_tree_entry
* current
);
82 static void snmpSnmplibDebug(int lvl
, char *buf
);
85 * The functions used during startup:
88 * snmpConnectionShutdown
93 * Turns the MIB into a Tree structure. Called during the startup process.
98 debugs(49, 5, "snmpInit: Building SNMP mib tree structure");
100 snmplib_debug_hook
= snmpSnmplibDebug
;
102 mib_tree_head
= snmpAddNode(snmpCreateOid(1, 1),
104 snmpAddNode(snmpCreateOid(2, 1, 3),
106 snmpAddNode(snmpCreateOid(3, 1, 3, 6),
108 snmpAddNode(snmpCreateOid(4, 1, 3, 6, 1),
110 snmpAddNode(snmpCreateOid(5, 1, 3, 6, 1, 4),
112 snmpAddNode(snmpCreateOid(6, 1, 3, 6, 1, 4, 1),
114 snmpAddNode(snmpCreateOid(7, 1, 3, 6, 1, 4, 1, 3495),
116 snmpAddNode(snmpCreateOid(LEN_SQUIDMIB
, SQUIDMIB
),
118 snmpAddNode(snmpCreateOid(LEN_SQ_SYS
, SQ_SYS
),
119 LEN_SQ_SYS
, NULL
, NULL
, 3,
120 snmpAddNode(snmpCreateOid(LEN_SYS
, SQ_SYS
, SYSVMSIZ
),
121 LEN_SYS
, snmp_sysFn
, static_Inst
, 0),
122 snmpAddNode(snmpCreateOid(LEN_SYS
, SQ_SYS
, SYSSTOR
),
123 LEN_SYS
, snmp_sysFn
, static_Inst
, 0),
124 snmpAddNode(snmpCreateOid(LEN_SYS
, SQ_SYS
, SYS_UPTIME
),
125 LEN_SYS
, snmp_sysFn
, static_Inst
, 0)),
126 snmpAddNode(snmpCreateOid(LEN_SQ_CONF
, SQ_CONF
),
127 LEN_SQ_CONF
, NULL
, NULL
, 6,
128 snmpAddNode(snmpCreateOid(LEN_SYS
, SQ_CONF
, CONF_ADMIN
),
129 LEN_SYS
, snmp_confFn
, static_Inst
, 0),
130 snmpAddNode(snmpCreateOid(LEN_SYS
, SQ_CONF
, CONF_VERSION
),
131 LEN_SYS
, snmp_confFn
, static_Inst
, 0),
132 snmpAddNode(snmpCreateOid(LEN_SYS
, SQ_CONF
, CONF_VERSION_ID
),
133 LEN_SYS
, snmp_confFn
, static_Inst
, 0),
134 snmpAddNode(snmpCreateOid(LEN_SYS
, SQ_CONF
, CONF_LOG_FAC
),
135 LEN_SYS
, snmp_confFn
, static_Inst
, 0),
136 snmpAddNode(snmpCreateOid(LEN_SYS
, SQ_CONF
, CONF_STORAGE
),
137 LEN_SYS
, NULL
, NULL
, 4,
138 snmpAddNode(snmpCreateOid(LEN_CONF_ST
, SQ_CONF
, CONF_STORAGE
, CONF_ST_MMAXSZ
),
139 LEN_CONF_ST
, snmp_confFn
, static_Inst
, 0),
140 snmpAddNode(snmpCreateOid(LEN_CONF_ST
, SQ_CONF
, CONF_STORAGE
, CONF_ST_SWMAXSZ
),
141 LEN_CONF_ST
, snmp_confFn
, static_Inst
, 0),
142 snmpAddNode(snmpCreateOid(LEN_CONF_ST
, SQ_CONF
, CONF_STORAGE
, CONF_ST_SWHIWM
),
143 LEN_CONF_ST
, snmp_confFn
, static_Inst
, 0),
144 snmpAddNode(snmpCreateOid(LEN_CONF_ST
, SQ_CONF
, CONF_STORAGE
, CONF_ST_SWLOWM
),
145 LEN_CONF_ST
, snmp_confFn
, static_Inst
, 0)),
146 snmpAddNode(snmpCreateOid(LEN_SYS
, SQ_CONF
, CONF_UNIQNAME
),
147 LEN_SYS
, snmp_confFn
, static_Inst
, 0)),
148 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
, SQ_PRF
),
149 LEN_SQ_PRF
, NULL
, NULL
, 2,
150 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 1, SQ_PRF
, PERF_SYS
),
151 LEN_SQ_PRF
+ 1, NULL
, NULL
, 13,
152 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 2, SQ_PRF
, PERF_SYS
, PERF_SYS_PF
),
153 LEN_SQ_PRF
+ 2, snmp_prfSysFn
, static_Inst
, 0),
154 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 2, SQ_PRF
, PERF_SYS
, PERF_SYS_NUMR
),
155 LEN_SQ_PRF
+ 2, snmp_prfSysFn
, static_Inst
, 0),
156 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 2, SQ_PRF
, PERF_SYS
, PERF_SYS_MEMUSAGE
),
157 LEN_SQ_PRF
+ 2, snmp_prfSysFn
, static_Inst
, 0),
158 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 2, SQ_PRF
, PERF_SYS
, PERF_SYS_CPUTIME
),
159 LEN_SQ_PRF
+ 2, snmp_prfSysFn
, static_Inst
, 0),
160 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 2, SQ_PRF
, PERF_SYS
, PERF_SYS_CPUUSAGE
),
161 LEN_SQ_PRF
+ 2, snmp_prfSysFn
, static_Inst
, 0),
162 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 2, SQ_PRF
, PERF_SYS
, PERF_SYS_MAXRESSZ
),
163 LEN_SQ_PRF
+ 2, snmp_prfSysFn
, static_Inst
, 0),
164 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 2, SQ_PRF
, PERF_SYS
, PERF_SYS_NUMOBJCNT
),
165 LEN_SQ_PRF
+ 2, snmp_prfSysFn
, static_Inst
, 0),
166 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 2, SQ_PRF
, PERF_SYS
, PERF_SYS_CURLRUEXP
),
167 LEN_SQ_PRF
+ 2, snmp_prfSysFn
, static_Inst
, 0),
168 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 2, SQ_PRF
, PERF_SYS
, PERF_SYS_CURUNLREQ
),
169 LEN_SQ_PRF
+ 2, snmp_prfSysFn
, static_Inst
, 0),
170 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 2, SQ_PRF
, PERF_SYS
, PERF_SYS_CURUNUSED_FD
),
171 LEN_SQ_PRF
+ 2, snmp_prfSysFn
, static_Inst
, 0),
172 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 2, SQ_PRF
, PERF_SYS
, PERF_SYS_CURRESERVED_FD
),
173 LEN_SQ_PRF
+ 2, snmp_prfSysFn
, static_Inst
, 0),
174 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 2, SQ_PRF
, PERF_SYS
, PERF_SYS_CURUSED_FD
),
175 LEN_SQ_PRF
+ 2, snmp_prfSysFn
, static_Inst
, 0),
176 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 2, SQ_PRF
, PERF_SYS
, PERF_SYS_CURMAX_FD
),
177 LEN_SQ_PRF
+ 2, snmp_prfSysFn
, static_Inst
, 0)),
178 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 1, SQ_PRF
, PERF_PROTO
),
179 LEN_SQ_PRF
+ 1, NULL
, NULL
, 2,
180 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 2, SQ_PRF
, PERF_PROTO
, PERF_PROTOSTAT_AGGR
),
181 LEN_SQ_PRF
+ 2, NULL
, NULL
, 15,
182 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 3, SQ_PRF
, PERF_PROTO
, PERF_PROTOSTAT_AGGR
, PERF_PROTOSTAT_AGGR_HTTP_REQ
),
183 LEN_SQ_PRF
+ 3, snmp_prfProtoFn
, static_Inst
, 0),
184 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 3, SQ_PRF
, PERF_PROTO
, PERF_PROTOSTAT_AGGR
, PERF_PROTOSTAT_AGGR_HTTP_HITS
),
185 LEN_SQ_PRF
+ 3, snmp_prfProtoFn
, static_Inst
, 0),
186 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 3, SQ_PRF
, PERF_PROTO
, PERF_PROTOSTAT_AGGR
, PERF_PROTOSTAT_AGGR_HTTP_ERRORS
),
187 LEN_SQ_PRF
+ 3, snmp_prfProtoFn
, static_Inst
, 0),
188 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 3, SQ_PRF
, PERF_PROTO
, PERF_PROTOSTAT_AGGR
, PERF_PROTOSTAT_AGGR_HTTP_KBYTES_IN
),
189 LEN_SQ_PRF
+ 3, snmp_prfProtoFn
, static_Inst
, 0),
190 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 3, SQ_PRF
, PERF_PROTO
, PERF_PROTOSTAT_AGGR
, PERF_PROTOSTAT_AGGR_HTTP_KBYTES_OUT
),
191 LEN_SQ_PRF
+ 3, snmp_prfProtoFn
, static_Inst
, 0),
192 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 3, SQ_PRF
, PERF_PROTO
, PERF_PROTOSTAT_AGGR
, PERF_PROTOSTAT_AGGR_ICP_S
),
193 LEN_SQ_PRF
+ 3, snmp_prfProtoFn
, static_Inst
, 0),
194 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 3, SQ_PRF
, PERF_PROTO
, PERF_PROTOSTAT_AGGR
, PERF_PROTOSTAT_AGGR_ICP_R
),
195 LEN_SQ_PRF
+ 3, snmp_prfProtoFn
, static_Inst
, 0),
196 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 3, SQ_PRF
, PERF_PROTO
, PERF_PROTOSTAT_AGGR
, PERF_PROTOSTAT_AGGR_ICP_SKB
),
197 LEN_SQ_PRF
+ 3, snmp_prfProtoFn
, static_Inst
, 0),
198 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 3, SQ_PRF
, PERF_PROTO
, PERF_PROTOSTAT_AGGR
, PERF_PROTOSTAT_AGGR_ICP_RKB
),
199 LEN_SQ_PRF
+ 3, snmp_prfProtoFn
, static_Inst
, 0),
200 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 3, SQ_PRF
, PERF_PROTO
, PERF_PROTOSTAT_AGGR
, PERF_PROTOSTAT_AGGR_REQ
),
201 LEN_SQ_PRF
+ 3, snmp_prfProtoFn
, static_Inst
, 0),
202 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 3, SQ_PRF
, PERF_PROTO
, PERF_PROTOSTAT_AGGR
, PERF_PROTOSTAT_AGGR_ERRORS
),
203 LEN_SQ_PRF
+ 3, snmp_prfProtoFn
, static_Inst
, 0),
204 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 3, SQ_PRF
, PERF_PROTO
, PERF_PROTOSTAT_AGGR
, PERF_PROTOSTAT_AGGR_KBYTES_IN
),
205 LEN_SQ_PRF
+ 3, snmp_prfProtoFn
, static_Inst
, 0),
206 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 3, SQ_PRF
, PERF_PROTO
, PERF_PROTOSTAT_AGGR
, PERF_PROTOSTAT_AGGR_KBYTES_OUT
),
207 LEN_SQ_PRF
+ 3, snmp_prfProtoFn
, static_Inst
, 0),
208 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 3, SQ_PRF
, PERF_PROTO
, PERF_PROTOSTAT_AGGR
, PERF_PROTOSTAT_AGGR_CURSWAP
),
209 LEN_SQ_PRF
+ 3, snmp_prfProtoFn
, static_Inst
, 0),
210 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 3, SQ_PRF
, PERF_PROTO
, PERF_PROTOSTAT_AGGR
, PERF_PROTOSTAT_AGGR_CLIENTS
),
211 LEN_SQ_PRF
+ 3, snmp_prfProtoFn
, static_Inst
, 0)),
212 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 2, SQ_PRF
, PERF_PROTO
, 2),
213 LEN_SQ_PRF
+ 2, NULL
, NULL
, 1,
214 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 3, SQ_PRF
, PERF_PROTO
, PERF_PROTOSTAT_MEDIAN
, 1),
215 LEN_SQ_PRF
+ 3, NULL
, NULL
, 11,
216 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 4, SQ_PRF
, PERF_PROTO
, PERF_PROTOSTAT_MEDIAN
, 1, PERF_MEDIAN_TIME
),
217 LEN_SQ_PRF
+ 4, snmp_prfProtoFn
, time_Inst
, 0),
218 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 4, SQ_PRF
, PERF_PROTO
, PERF_PROTOSTAT_MEDIAN
, 1, PERF_MEDIAN_HTTP_ALL
),
219 LEN_SQ_PRF
+ 4, snmp_prfProtoFn
, time_Inst
, 0),
220 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 4, SQ_PRF
, PERF_PROTO
, PERF_PROTOSTAT_MEDIAN
, 1, PERF_MEDIAN_HTTP_MISS
),
221 LEN_SQ_PRF
+ 4, snmp_prfProtoFn
, time_Inst
, 0),
222 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 4, SQ_PRF
, PERF_PROTO
, PERF_PROTOSTAT_MEDIAN
, 1, PERF_MEDIAN_HTTP_NM
),
223 LEN_SQ_PRF
+ 4, snmp_prfProtoFn
, time_Inst
, 0),
224 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 4, SQ_PRF
, PERF_PROTO
, PERF_PROTOSTAT_MEDIAN
, 1, PERF_MEDIAN_HTTP_HIT
),
225 LEN_SQ_PRF
+ 4, snmp_prfProtoFn
, time_Inst
, 0),
226 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 4, SQ_PRF
, PERF_PROTO
, PERF_PROTOSTAT_MEDIAN
, 1, PERF_MEDIAN_ICP_QUERY
),
227 LEN_SQ_PRF
+ 4, snmp_prfProtoFn
, time_Inst
, 0),
228 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 4, SQ_PRF
, PERF_PROTO
, PERF_PROTOSTAT_MEDIAN
, 1, PERF_MEDIAN_ICP_REPLY
),
229 LEN_SQ_PRF
+ 4, snmp_prfProtoFn
, time_Inst
, 0),
230 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 4, SQ_PRF
, PERF_PROTO
, PERF_PROTOSTAT_MEDIAN
, 1, PERF_MEDIAN_DNS
),
231 LEN_SQ_PRF
+ 4, snmp_prfProtoFn
, time_Inst
, 0),
232 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 4, SQ_PRF
, PERF_PROTO
, PERF_PROTOSTAT_MEDIAN
, 1, PERF_MEDIAN_RHR
),
233 LEN_SQ_PRF
+ 4, snmp_prfProtoFn
, time_Inst
, 0),
234 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 4, SQ_PRF
, PERF_PROTO
, PERF_PROTOSTAT_MEDIAN
, 1, PERF_MEDIAN_BHR
),
235 LEN_SQ_PRF
+ 4, snmp_prfProtoFn
, time_Inst
, 0),
236 snmpAddNode(snmpCreateOid(LEN_SQ_PRF
+ 4, SQ_PRF
, PERF_PROTO
, PERF_PROTOSTAT_MEDIAN
, 1, PERF_MEDIAN_HTTP_NH
),
237 LEN_SQ_PRF
+ 4, snmp_prfProtoFn
, time_Inst
, 0))))),
238 snmpAddNode(snmpCreateOid(LEN_SQ_NET
, SQ_NET
),
239 LEN_SQ_NET
, NULL
, NULL
, 3,
240 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 1, SQ_NET
, NET_IP_CACHE
),
241 LEN_SQ_NET
+ 1, NULL
, NULL
, 8,
242 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 2, SQ_NET
, NET_IP_CACHE
, IP_ENT
),
243 LEN_SQ_NET
+ 2, snmp_netIpFn
, static_Inst
, 0),
244 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 2, SQ_NET
, NET_IP_CACHE
, IP_REQ
),
245 LEN_SQ_NET
+ 2, snmp_netIpFn
, static_Inst
, 0),
246 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 2, SQ_NET
, NET_IP_CACHE
, IP_HITS
),
247 LEN_SQ_NET
+ 2, snmp_netIpFn
, static_Inst
, 0),
248 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 2, SQ_NET
, NET_IP_CACHE
, IP_PENDHIT
),
249 LEN_SQ_NET
+ 2, snmp_netIpFn
, static_Inst
, 0),
250 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 2, SQ_NET
, NET_IP_CACHE
, IP_NEGHIT
),
251 LEN_SQ_NET
+ 2, snmp_netIpFn
, static_Inst
, 0),
252 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 2, SQ_NET
, NET_IP_CACHE
, IP_MISS
),
253 LEN_SQ_NET
+ 2, snmp_netIpFn
, static_Inst
, 0),
254 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 2, SQ_NET
, NET_IP_CACHE
, IP_GHBN
),
255 LEN_SQ_NET
+ 2, snmp_netIpFn
, static_Inst
, 0),
256 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 2, SQ_NET
, NET_IP_CACHE
, IP_LOC
),
257 LEN_SQ_NET
+ 2, snmp_netIpFn
, static_Inst
, 0)),
258 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 1, SQ_NET
, NET_FQDN_CACHE
),
259 LEN_SQ_NET
+ 1, NULL
, NULL
, 7,
260 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 2, SQ_NET
, NET_FQDN_CACHE
, FQDN_ENT
),
261 LEN_SQ_NET
+ 2, snmp_netFqdnFn
, static_Inst
, 0),
262 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 2, SQ_NET
, NET_FQDN_CACHE
, FQDN_REQ
),
263 LEN_SQ_NET
+ 2, snmp_netFqdnFn
, static_Inst
, 0),
264 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 2, SQ_NET
, NET_FQDN_CACHE
, FQDN_HITS
),
265 LEN_SQ_NET
+ 2, snmp_netFqdnFn
, static_Inst
, 0),
266 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 2, SQ_NET
, NET_FQDN_CACHE
, FQDN_PENDHIT
),
267 LEN_SQ_NET
+ 2, snmp_netFqdnFn
, static_Inst
, 0),
268 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 2, SQ_NET
, NET_FQDN_CACHE
, FQDN_NEGHIT
),
269 LEN_SQ_NET
+ 2, snmp_netFqdnFn
, static_Inst
, 0),
270 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 2, SQ_NET
, NET_FQDN_CACHE
, FQDN_MISS
),
271 LEN_SQ_NET
+ 2, snmp_netFqdnFn
, static_Inst
, 0),
272 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 2, SQ_NET
, NET_FQDN_CACHE
, FQDN_GHBN
),
273 LEN_SQ_NET
+ 2, snmp_netFqdnFn
, static_Inst
, 0)),
274 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 1, SQ_NET
, NET_DNS_CACHE
),
275 LEN_SQ_NET
+ 1, NULL
, NULL
, 3,
277 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 2, SQ_NET
, NET_DNS_CACHE
, DNS_REQ
),
278 LEN_SQ_NET
+ 2, snmp_netDnsFn
, static_Inst
, 0),
279 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 2, SQ_NET
, NET_DNS_CACHE
, DNS_REP
),
280 LEN_SQ_NET
+ 2, snmp_netDnsFn
, static_Inst
, 0),
281 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 2, SQ_NET
, NET_DNS_CACHE
, DNS_SERVERS
),
282 LEN_SQ_NET
+ 2, snmp_netDnsFn
, static_Inst
, 0))),
284 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 2, SQ_NET
, NET_DNS_CACHE
, DNS_REQ
),
285 LEN_SQ_NET
+ 2, snmp_netIdnsFn
, static_Inst
, 0),
286 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 2, SQ_NET
, NET_DNS_CACHE
, DNS_REP
),
287 LEN_SQ_NET
+ 2, snmp_netIdnsFn
, static_Inst
, 0),
288 snmpAddNode(snmpCreateOid(LEN_SQ_NET
+ 2, SQ_NET
, NET_DNS_CACHE
, DNS_SERVERS
),
289 LEN_SQ_NET
+ 2, snmp_netIdnsFn
, static_Inst
, 0))),
291 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
, SQ_MESH
),
292 LEN_SQ_MESH
, NULL
, NULL
, 2,
293 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 1, SQ_MESH
, MESH_PTBL
),
294 LEN_SQ_MESH
+ 1, NULL
, NULL
, 1,
295 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 2, SQ_MESH
, 1, 1),
296 LEN_SQ_MESH
+ 2, NULL
, NULL
, 15,
297 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, MESH_PTBL
, 1, MESH_PTBL_INDEX
),
298 LEN_SQ_MESH
+ 3, snmp_meshPtblFn
, peer_Inst
, 0),
299 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, MESH_PTBL
, 1, MESH_PTBL_NAME
),
300 LEN_SQ_MESH
+ 3, snmp_meshPtblFn
, peer_Inst
, 0),
301 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, MESH_PTBL
, 1, MESH_PTBL_ADDR_TYPE
),
302 LEN_SQ_MESH
+ 3, snmp_meshPtblFn
, peer_Inst
, 0),
303 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, MESH_PTBL
, 1, MESH_PTBL_ADDR
),
304 LEN_SQ_MESH
+ 3, snmp_meshPtblFn
, peer_Inst
, 0),
305 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, MESH_PTBL
, 1, MESH_PTBL_HTTP
),
306 LEN_SQ_MESH
+ 3, snmp_meshPtblFn
, peer_Inst
, 0),
307 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, MESH_PTBL
, 1, MESH_PTBL_ICP
),
308 LEN_SQ_MESH
+ 3, snmp_meshPtblFn
, peer_Inst
, 0),
309 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, MESH_PTBL
, 1, MESH_PTBL_TYPE
),
310 LEN_SQ_MESH
+ 3, snmp_meshPtblFn
, peer_Inst
, 0),
311 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, MESH_PTBL
, 1, MESH_PTBL_STATE
),
312 LEN_SQ_MESH
+ 3, snmp_meshPtblFn
, peer_Inst
, 0),
313 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, MESH_PTBL
, 1, MESH_PTBL_SENT
),
314 LEN_SQ_MESH
+ 3, snmp_meshPtblFn
, peer_Inst
, 0),
315 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, MESH_PTBL
, 1, MESH_PTBL_PACKED
),
316 LEN_SQ_MESH
+ 3, snmp_meshPtblFn
, peer_Inst
, 0),
317 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, MESH_PTBL
, 1, MESH_PTBL_FETCHES
),
318 LEN_SQ_MESH
+ 3, snmp_meshPtblFn
, peer_Inst
, 0),
319 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, MESH_PTBL
, 1, MESH_PTBL_RTT
),
320 LEN_SQ_MESH
+ 3, snmp_meshPtblFn
, peer_Inst
, 0),
321 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, MESH_PTBL
, 1, MESH_PTBL_IGN
),
322 LEN_SQ_MESH
+ 3, snmp_meshPtblFn
, peer_Inst
, 0),
323 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, MESH_PTBL
, 1, MESH_PTBL_KEEPAL_S
),
324 LEN_SQ_MESH
+ 3, snmp_meshPtblFn
, peer_Inst
, 0),
325 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, MESH_PTBL
, 1, MESH_PTBL_KEEPAL_R
),
326 LEN_SQ_MESH
+ 3, snmp_meshPtblFn
, peer_Inst
, 0))),
327 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 1, SQ_MESH
, MESH_CTBL
),
328 LEN_SQ_MESH
+ 1, NULL
, NULL
, 1,
329 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 2, SQ_MESH
, MESH_CTBL
, 1),
330 LEN_SQ_MESH
+ 2, NULL
, NULL
, 10,
331 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, MESH_CTBL
, 1, MESH_CTBL_ADDR_TYPE
),
332 LEN_SQ_MESH
+ 3, snmp_meshCtblFn
, client_Inst
, 0),
333 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, MESH_CTBL
, 1, MESH_CTBL_ADDR
),
334 LEN_SQ_MESH
+ 3, snmp_meshCtblFn
, client_Inst
, 0),
335 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, MESH_CTBL
, 1, MESH_CTBL_HTREQ
),
336 LEN_SQ_MESH
+ 3, snmp_meshCtblFn
, client_Inst
, 0),
337 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, MESH_CTBL
, 1, MESH_CTBL_HTBYTES
),
338 LEN_SQ_MESH
+ 3, snmp_meshCtblFn
, client_Inst
, 0),
339 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, MESH_CTBL
, 1, MESH_CTBL_HTHITS
),
340 LEN_SQ_MESH
+ 3, snmp_meshCtblFn
, client_Inst
, 0),
341 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, MESH_CTBL
, 1, MESH_CTBL_HTHITBYTES
),
342 LEN_SQ_MESH
+ 3, snmp_meshCtblFn
, client_Inst
, 0),
343 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, MESH_CTBL
, 1, MESH_CTBL_ICPREQ
),
344 LEN_SQ_MESH
+ 3, snmp_meshCtblFn
, client_Inst
, 0),
345 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, MESH_CTBL
, 1, MESH_CTBL_ICPBYTES
),
346 LEN_SQ_MESH
+ 3, snmp_meshCtblFn
, client_Inst
, 0),
347 snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, MESH_CTBL
, 1, MESH_CTBL_ICPHITS
),
348 LEN_SQ_MESH
+ 3, snmp_meshCtblFn
, client_Inst
, 0),
349 (mib_tree_last
= snmpAddNode(snmpCreateOid(LEN_SQ_MESH
+ 3, SQ_MESH
, MESH_CTBL
, 1, MESH_CTBL_ICPHITBYTES
),
350 LEN_SQ_MESH
+ 3, snmp_meshCtblFn
, client_Inst
, 0)))))
360 debugs(49, 9, "snmpInit: Completed SNMP mib tree structure");
364 snmpConnectionOpen(void)
366 struct addrinfo
*xaddr
= NULL
;
369 debugs(49, 5, "snmpConnectionOpen: Called");
371 if (Config
.Port
.snmp
> 0) {
372 Config
.Addrs
.snmp_incoming
.SetPort(Config
.Port
.snmp
);
374 theInSnmpConnection
= comm_open(SOCK_DGRAM
,
376 Config
.Addrs
.snmp_incoming
,
381 if (theInSnmpConnection
< 0)
382 fatal("Cannot open snmp Port");
384 commSetSelect(theInSnmpConnection
, COMM_SELECT_READ
, snmpHandleUdp
, NULL
, 0);
386 debugs(1, 1, "Accepting SNMP messages on " << Config
.Addrs
.snmp_incoming
<< ", FD " << theInSnmpConnection
<< ".");
388 if (!Config
.Addrs
.snmp_outgoing
.IsNoAddr()) {
389 Config
.Addrs
.snmp_outgoing
.SetPort(Config
.Port
.snmp
);
391 theOutSnmpConnection
= comm_open(SOCK_DGRAM
,
393 Config
.Addrs
.snmp_outgoing
,
398 if (theOutSnmpConnection
< 0)
399 fatal("Cannot open Outgoing SNMP Port");
401 commSetSelect(theOutSnmpConnection
,
406 debugs(1, 1, "Outgoing SNMP messages on " << Config
.Addrs
.snmp_outgoing
<< ", FD " << theOutSnmpConnection
<< ".");
408 fd_note(theOutSnmpConnection
, "Outgoing SNMP socket");
410 fd_note(theInSnmpConnection
, "Incoming SNMP socket");
412 theOutSnmpConnection
= theInSnmpConnection
;
415 theOutSNMPAddr
.SetEmpty();
417 theOutSNMPAddr
.InitAddrInfo(xaddr
);
419 x
= getsockname(theOutSnmpConnection
, xaddr
->ai_addr
, &xaddr
->ai_addrlen
);
422 debugs(51, 1, "theOutSnmpConnection FD " << theOutSnmpConnection
<< ": getsockname: " << xstrerror());
424 theOutSNMPAddr
= *xaddr
;
426 theOutSNMPAddr
.FreeAddrInfo(xaddr
);
431 snmpConnectionShutdown(void)
433 if (theInSnmpConnection
< 0)
436 if (theInSnmpConnection
!= theOutSnmpConnection
) {
437 debugs(49, 1, "FD " << theInSnmpConnection
<< " Closing SNMP socket");
438 comm_close(theInSnmpConnection
);
442 * Here we set 'theInSnmpConnection' to -1 even though the SNMP 'in'
443 * and 'out' sockets might be just one FD. This prevents this
444 * function from executing repeatedly. When we are really ready to
445 * exit or restart, main will comm_close the 'out' descriptor.
446 */ theInSnmpConnection
= -1;
449 * Normally we only write to the outgoing SNMP socket, but we
450 * also have a read handler there to catch messages sent to that
451 * specific interface. During shutdown, we must disable reading
452 * on the outgoing socket.
454 assert(theOutSnmpConnection
> -1);
456 commSetSelect(theOutSnmpConnection
, COMM_SELECT_READ
, NULL
, NULL
, 0);
460 snmpConnectionClose(void)
462 snmpConnectionShutdown();
464 if (theOutSnmpConnection
> -1) {
465 debugs(49, 1, "FD " << theOutSnmpConnection
<< " Closing SNMP socket");
466 comm_close(theOutSnmpConnection
);
471 * Functions for handling the requests.
475 * Accept the UDP packet
478 snmpHandleUdp(int sock
, void *not_used
)
480 LOCAL_ARRAY(char, buf
, SNMP_REQUEST_SIZE
);
482 snmp_request_t
*snmp_rq
;
485 debugs(49, 5, "snmpHandleUdp: Called.");
487 commSetSelect(sock
, COMM_SELECT_READ
, snmpHandleUdp
, NULL
, 0);
489 memset(buf
, '\0', SNMP_REQUEST_SIZE
);
491 len
= comm_udp_recvfrom(sock
,
499 debugs(49, 3, "snmpHandleUdp: FD " << sock
<< ": received " << len
<< " bytes from " << from
<< ".");
501 snmp_rq
= (snmp_request_t
*)xcalloc(1, sizeof(snmp_request_t
));
502 snmp_rq
->buf
= (u_char
*) buf
;
504 snmp_rq
->sock
= sock
;
505 snmp_rq
->outbuf
= (unsigned char *)xmalloc(snmp_rq
->outlen
= SNMP_REQUEST_SIZE
);
506 snmp_rq
->from
= from
;
507 snmpDecodePacket(snmp_rq
);
508 xfree(snmp_rq
->outbuf
);
511 debugs(49, 1, "snmpHandleUdp: FD " << sock
<< " recvfrom: " << xstrerror());
516 * Turn SNMP packet into a PDU, check available ACL's
519 snmpDecodePacket(snmp_request_t
* rq
)
521 struct snmp_pdu
*PDU
;
523 u_char
*buf
= rq
->buf
;
527 debugs(49, 5, HERE
<< "Called.");
528 PDU
= snmp_pdu_create(0);
529 /* Allways answer on SNMPv1 */
530 rq
->session
.Version
= SNMP_VERSION_1
;
531 Community
= snmp_parse(&rq
->session
, PDU
, buf
, len
);
534 ACLChecklist checklist
;
535 checklist
.accessList
= cbdataReference(Config
.accessList
.snmp
);
536 checklist
.src_addr
= rq
->from
;
537 checklist
.snmp_community
= (char *) Community
;
538 /* cbdataReferenceDone() happens in either fastCheck() or ~ACLCheckList */
539 allow
= checklist
.fastCheck();
542 if ((snmp_coexist_V2toV1(PDU
)) && (Community
) && (allow
)) {
543 rq
->community
= Community
;
545 debugs(49, 5, "snmpAgentParse: reqid=[" << PDU
->reqid
<< "]");
546 snmpConstructReponse(rq
);
548 debugs(49, 1, HERE
<< "Failed SNMP agent query from : " << rq
->from
);
557 * Packet OK, ACL Check OK, Create reponse.
560 snmpConstructReponse(snmp_request_t
* rq
)
563 struct snmp_pdu
*RespPDU
;
565 debugs(49, 5, "snmpConstructReponse: Called.");
566 RespPDU
= snmpAgentResponse(rq
->PDU
);
567 snmp_free_pdu(rq
->PDU
);
569 if (RespPDU
!= NULL
) {
570 snmp_build(&rq
->session
, RespPDU
, rq
->outbuf
, &rq
->outlen
);
571 comm_udp_sendto(rq
->sock
, rq
->from
, rq
->outbuf
, rq
->outlen
);
572 snmp_free_pdu(RespPDU
);
577 * Decide how to respond to the request, construct a response and
578 * return the response to the requester.
581 static struct snmp_pdu
*
583 snmpAgentResponse(struct snmp_pdu
*PDU
)
586 struct snmp_pdu
*Answer
= NULL
;
588 debugs(49, 5, "snmpAgentResponse: Called.");
590 if ((Answer
= snmp_pdu_create(SNMP_PDU_RESPONSE
)))
592 Answer
->reqid
= PDU
->reqid
;
593 Answer
->errindex
= 0;
595 if (PDU
->command
== SNMP_PDU_GET
|| PDU
->command
== SNMP_PDU_GETNEXT
) {
597 int get_next
= (PDU
->command
== SNMP_PDU_GETNEXT
);
598 variable_list
*VarPtr_
;
599 variable_list
**RespVars
= &(Answer
->variables
);
600 oid_ParseFn
*ParseFn
;
602 /* Loop through all variables */
604 for (VarPtr_
= PDU
->variables
; VarPtr_
; VarPtr_
= VarPtr_
->next_variable
) {
605 variable_list
*VarPtr
= VarPtr_
;
606 variable_list
*VarNew
= NULL
;
607 oid
*NextOidName
= NULL
;
608 snint NextOidNameLen
= 0;
613 ParseFn
= snmpTreeNext(VarPtr
->name
, VarPtr
->name_length
, &NextOidName
, &NextOidNameLen
);
615 ParseFn
= snmpTreeGet(VarPtr
->name
, VarPtr
->name_length
);
617 if (ParseFn
== NULL
) {
618 Answer
->errstat
= SNMP_ERR_NOSUCHNAME
;
619 debugs(49, 5, "snmpAgentResponse: No such oid. ");
622 VarPtr
= snmp_var_new(NextOidName
, NextOidNameLen
);
626 int * errstatTmp
= &(Answer
->errstat
);
628 VarNew
= (*ParseFn
) (VarPtr
, (snint
*) errstatTmp
);
631 snmp_var_free(VarPtr
);
634 if ((Answer
->errstat
!= SNMP_ERR_NOERROR
) || (VarNew
== NULL
)) {
635 Answer
->errindex
= index
;
636 debugs(49, 5, "snmpAgentResponse: error.");
639 snmp_var_free(VarNew
);
641 while ((VarPtr
= Answer
->variables
) != NULL
) {
642 Answer
->variables
= VarPtr
->next_variable
;
643 snmp_var_free(VarPtr
);
646 /* Steal the original PDU list of variables for the error response */
647 Answer
->variables
= PDU
->variables
;
649 PDU
->variables
= NULL
;
654 /* No error. Insert this var at the end, and move on to the next.
658 RespVars
= &(VarNew
->next_variable
);
667 snmpTreeGet(oid
* Current
, snint CurrentLen
)
669 oid_ParseFn
*Fn
= NULL
;
670 mib_tree_entry
*mibTreeEntry
= NULL
;
673 debugs(49, 5, "snmpTreeGet: Called");
675 debugs(49, 6, "snmpTreeGet: Current : ");
676 snmpDebugOid(6, Current
, CurrentLen
);
678 mibTreeEntry
= mib_tree_head
;
680 if (Current
[count
] == mibTreeEntry
->name
[count
]) {
683 while ((mibTreeEntry
) && (count
< CurrentLen
) && (!mibTreeEntry
->parsefunction
)) {
684 mibTreeEntry
= snmpTreeEntry(Current
[count
], count
, mibTreeEntry
);
689 if (mibTreeEntry
&& mibTreeEntry
->parsefunction
)
690 Fn
= mibTreeEntry
->parsefunction
;
692 debugs(49, 5, "snmpTreeGet: return");
698 snmpTreeNext(oid
* Current
, snint CurrentLen
, oid
** Next
, snint
* NextLen
)
700 oid_ParseFn
*Fn
= NULL
;
701 mib_tree_entry
*mibTreeEntry
= NULL
, *nextoid
= NULL
;
704 debugs(49, 5, "snmpTreeNext: Called");
706 debugs(49, 6, "snmpTreeNext: Current : ");
707 snmpDebugOid(6, Current
, CurrentLen
);
709 mibTreeEntry
= mib_tree_head
;
711 if (Current
[count
] == mibTreeEntry
->name
[count
]) {
714 while ((mibTreeEntry
) && (count
< CurrentLen
) && (!mibTreeEntry
->parsefunction
)) {
715 mib_tree_entry
*nextmibTreeEntry
= snmpTreeEntry(Current
[count
], count
, mibTreeEntry
);
717 if (!nextmibTreeEntry
)
720 mibTreeEntry
= nextmibTreeEntry
;
724 debugs(49, 5, "snmpTreeNext: Recursed down to requested object");
729 if (mibTreeEntry
== mib_tree_last
)
733 if ((mibTreeEntry
) && (mibTreeEntry
->parsefunction
)) {
734 *NextLen
= CurrentLen
;
735 *Next
= (*mibTreeEntry
->instancefunction
) (Current
, NextLen
, mibTreeEntry
, &Fn
);
738 debugs(49, 6, "snmpTreeNext: Next : ");
739 snmpDebugOid(6, *Next
, *NextLen
);
744 if ((mibTreeEntry
) && (mibTreeEntry
->parsefunction
)) {
746 nextoid
= snmpTreeSiblingEntry(Current
[count
], count
, mibTreeEntry
->parent
);
748 debugs(49, 5, "snmpTreeNext: Next OID found for sibling" << nextoid
);
749 mibTreeEntry
= nextoid
;
752 debugs(49, 5, "snmpTreeNext: Attempting to recurse up for next object");
757 if (mibTreeEntry
->parent
->parent
) {
758 nextoid
= mibTreeEntry
->parent
;
759 mibTreeEntry
= snmpTreeEntry(Current
[count
] + 1, count
, nextoid
->parent
);
762 mibTreeEntry
= nextoid
;
766 nextoid
= mibTreeEntry
;
772 while ((mibTreeEntry
) && (!mibTreeEntry
->parsefunction
)) {
773 mibTreeEntry
= mibTreeEntry
->leaves
[0];
777 *NextLen
= mibTreeEntry
->len
;
778 *Next
= (*mibTreeEntry
->instancefunction
) (mibTreeEntry
->name
, NextLen
, mibTreeEntry
, &Fn
);
783 debugs(49, 6, "snmpTreeNext: Next : ");
784 snmpDebugOid(6, *Next
, *NextLen
);
792 static_Inst(oid
* name
, snint
* len
, mib_tree_entry
* current
, oid_ParseFn
** Fn
)
794 oid
*instance
= NULL
;
795 if (*len
<= current
->len
) {
796 instance
= (oid
*)xmalloc(sizeof(name
) * (*len
+ 1));
797 xmemcpy(instance
, name
, (sizeof(name
) * *len
));
801 *Fn
= current
->parsefunction
;
806 time_Inst(oid
* name
, snint
* len
, mib_tree_entry
* current
, oid_ParseFn
** Fn
)
808 oid
*instance
= NULL
;
809 int identifier
= 0, loop
= 0;
810 int index
[TIME_INDEX_LEN
] = {TIME_INDEX
};
812 if (*len
<= current
->len
) {
813 instance
= (oid
*)xmalloc(sizeof(name
) * (*len
+ 1));
814 xmemcpy(instance
, name
, (sizeof(name
) * *len
));
815 instance
[*len
] = *index
;
818 identifier
= name
[*len
- 1];
820 while ((loop
< TIME_INDEX_LEN
) && (identifier
!= index
[loop
]))
823 if (loop
< (TIME_INDEX_LEN
- 1)) {
824 instance
= (oid
*)xmalloc(sizeof(name
) * (*len
));
825 xmemcpy(instance
, name
, (sizeof(name
) * *len
));
826 instance
[*len
- 1] = index
[++loop
];
830 *Fn
= current
->parsefunction
;
836 peer_Inst(oid
* name
, snint
* len
, mib_tree_entry
* current
, oid_ParseFn
** Fn
)
838 oid
*instance
= NULL
;
839 peer
*peers
= Config
.peers
;
842 current
= current
->parent
->parent
->parent
->leaves
[1];
843 while ((current
) && (!current
->parsefunction
))
844 current
= current
->leaves
[0];
846 instance
= client_Inst(current
->name
, len
, current
, Fn
);
847 } else if (*len
<= current
->len
) {
848 instance
= (oid
*)xmalloc(sizeof(name
) * ( *len
+ 1));
849 xmemcpy(instance
, name
, (sizeof(name
) * *len
));
853 int no
= name
[current
->len
] ;
854 int i
; // Note: This works because the Confifg.peers
855 // keep its index acording to its position.
856 for ( i
=0 ; peers
&& (i
< no
) ; peers
= peers
->next
, i
++ ) ;
859 instance
= (oid
*)xmalloc(sizeof(name
) * (current
->len
+ 1 ));
860 xmemcpy(instance
, name
, (sizeof(name
) * current
->len
));
861 instance
[current
->len
] = no
+ 1 ; // i.e. the next index on cache_peeer table.
866 *Fn
= current
->parsefunction
;
871 client_Inst(oid
* name
, snint
* len
, mib_tree_entry
* current
, oid_ParseFn
** Fn
)
873 oid
*instance
= NULL
;
879 if(*len
<= current
->len
) {
880 aux
= client_entry(NULL
);
887 size
= sizeof(in_addr
);
890 size
= sizeof(in6_addr
);
893 instance
= (oid
*)xmalloc(sizeof(name
) * (*len
+ size
));
894 xmemcpy(instance
, name
, (sizeof(name
) * (*len
)));
896 if ( !laddr
.IsAnyAddr() ) {
897 addr2oid(laddr
, &instance
[ *len
]); // the addr
901 int shift
= *len
- current
->len
; // i.e 4 or 16
902 oid2addr(&name
[*len
- shift
], laddr
,shift
);
903 aux
= client_entry(&laddr
);
909 if(!laddr
.IsAnyAddr()) {
911 newshift
= sizeof(in_addr
);
914 newshift
= sizeof(in6_addr
);
916 instance
= (oid
*)xmalloc(sizeof(name
) * (current
->len
+ newshift
));
917 xmemcpy(instance
, name
, (sizeof(name
) * (current
->len
)));
918 addr2oid(laddr
, &instance
[current
->len
]); // the addr.
919 *len
= current
->len
+ newshift
;
923 *Fn
= current
->parsefunction
;
933 * Tree utility functions.
937 * Returns a sibling object for the requested child object or NULL
938 * if it does not exit
940 static mib_tree_entry
*
941 snmpTreeSiblingEntry(oid entry
, snint len
, mib_tree_entry
* current
)
943 mib_tree_entry
*next
= NULL
;
946 while ((!next
) && (count
< current
->children
)) {
947 if (current
->leaves
[count
]->name
[len
] == entry
) {
948 next
= current
->leaves
[count
];
954 /* Exactly the sibling on rigth */
955 if (count
< current
->children
) {
956 next
= current
->leaves
[count
];
965 * Returns the requested child object or NULL if it does not exist
967 static mib_tree_entry
*
968 snmpTreeEntry(oid entry
, snint len
, mib_tree_entry
* current
)
970 mib_tree_entry
*next
= NULL
;
973 while ((!next
) && (count
< current
->children
)) {
974 if (current
->leaves
[count
]->name
[len
] == entry
) {
975 next
= current
->leaves
[count
];
985 * Adds a node to the MIB tree structure and adds the appropriate children
987 static mib_tree_entry
*
989 snmpAddNode(oid
* name
, int len
, oid_ParseFn
* parsefunction
, instance_Fn
* instancefunction
, int children
,...)
991 snmpAddNode(va_alist
)
998 mib_tree_entry
*entry
= NULL
;
999 va_start(args
, children
);
1004 int len
= 0, children
= 0, loop
;
1005 oid_ParseFn
*parsefunction
= NULL
;
1006 instance_Fn
*instancefunction
= NULL
;
1007 mib_tree_entry
*entry
= NULL
;
1009 name
= va_arg(args
, oid
*);
1010 len
= va_arg(args
, int);
1011 parsefunction
= va_arg(args
, oid_ParseFn
*);
1012 instancefunction
= va_arg(args
, instance_Fn
*);
1013 children
= va_arg(args
, int);
1016 debugs(49, 6, "snmpAddNode: Children : " << children
<< ", Oid : ");
1017 snmpDebugOid(6, name
, len
);
1019 va_start(args
, children
);
1020 entry
= (mib_tree_entry
*)xmalloc(sizeof(mib_tree_entry
));
1023 entry
->parsefunction
= parsefunction
;
1024 entry
->instancefunction
= instancefunction
;
1025 entry
->children
= children
;
1029 entry
->leaves
= (mib_tree_entry
**)xmalloc(sizeof(mib_tree_entry
*) * children
);
1031 for (loop
= 0; loop
< children
; loop
++) {
1032 entry
->leaves
[loop
] = va_arg(args
, mib_tree_entry
*);
1033 entry
->leaves
[loop
]->parent
= entry
;
1039 /* End of tree utility functions */
1042 * Returns the list of parameters in an oid
1046 snmpCreateOid(int length
,...)
1048 snmpCreateOid(va_alist
)
1056 va_start(args
, length
);
1060 int length
= 0, loop
;
1063 length
va_arg(args
, int);
1066 new_oid
= (oid
*)xmalloc(sizeof(oid
) * length
);
1070 for (loop
= 0; loop
< length
; loop
++) {
1071 new_oid
[loop
] = va_arg(args
, int);
1079 * Debug calls, prints out the OID for debugging purposes.
1082 snmpDebugOid(int lvl
, oid
* Name
, snint Len
)
1084 char mbuf
[16], objid
[1024];
1088 for (x
= 0; x
< Len
; x
++) {
1089 snprintf(mbuf
, sizeof(mbuf
), ".%u", (unsigned int) Name
[x
]);
1090 strncat(objid
, mbuf
, sizeof(objid
));
1093 debugs(49, lvl
, " oid = " << objid
);
1097 snmpSnmplibDebug(int lvl
, char *buf
)
1099 debug(49, lvl
) ("%s", buf
);
1105 IPv4 address: 10.10.0.9 ==>
1107 IPv6 adress : 20:01:32:ef:a2:21:fb:32:00:00:00:00:00:00:00:00:OO:01 ==>
1108 oid == 32.1.50.239.162.33.251.20.50.0.0.0.0.0.0.0.0.0.1
1111 addr2oid(IPAddress
&addr
, oid
* Dest
)
1115 struct in_addr iaddr
;
1117 struct in6_addr i6addr
;
1118 oid code
= addr
.IsIPv4()? INETADDRESSTYPE_IPV4
: INETADDRESSTYPE_IPV6
;
1119 u_int size
= (code
== INETADDRESSTYPE_IPV4
) ? sizeof(struct in_addr
):sizeof(struct in6_addr
);
1121 oid code
= INETADDRESSTYPE_IPV4
;
1122 u_int size
= sizeof(struct in_addr
) ;
1123 #endif /* USE_IPV6 */
1125 if ( code
== INETADDRESSTYPE_IPV4
) {
1126 addr
.GetInAddr(iaddr
);
1127 cp
= (u_char
*) &(iaddr
.s_addr
);
1132 addr
.GetInAddr(i6addr
);
1133 cp
= (u_char
*) &i6addr
;
1136 for ( i
=0 ; i
< size
; i
++)
1138 // OID's are in network order
1141 debugs(49, 7, "addr2oid: Dest : ");
1142 snmpDebugOid(7, Dest
, size
);
1147 oid == 10.10.0.9 ==>
1148 IPv4 address: 10.10.0.9
1149 oid == 32.1.50.239.162.33.251.20.50.0.0.0.0.0.0.0.0.0.1 ==>
1150 IPv6 adress : 20:01:32:ef:a2:21:fb:32:00:00:00:00:00:00:00:00:OO:01
1153 oid2addr(oid
* id
, IPAddress
&addr
, u_int size
)
1155 struct in_addr iaddr
;
1159 struct in6_addr i6addr
;
1160 if ( size
== sizeof(struct in_addr
) )
1161 #endif /* USE_IPV6 */
1162 cp
= (u_char
*) &(iaddr
.s_addr
);
1165 cp
= (u_char
*) &(i6addr
);
1166 #endif /* USE_IPV6 */
1167 debugs(49, 7, "oid2addr: id : ");
1168 snmpDebugOid(7, id
, size
);
1169 for(i
=0 ; i
<size
; i
++)
1174 if ( size
== sizeof(struct in_addr
) )
1184 /* SNMP checklists */
1185 #include "ACLStrategy.h"
1186 #include "ACLStrategised.h"
1187 #include "ACLStringData.h"
1189 class ACLSNMPCommunityStrategy
: public ACLStrategy
<char const *>
1193 virtual int match (ACLData
<MatchType
> * &, ACLChecklist
*);
1194 static ACLSNMPCommunityStrategy
*Instance();
1195 /* Not implemented to prevent copies of the instance. */
1196 /* Not private to prevent brain dead g+++ warnings about
1197 * private constructors with no friends */
1198 ACLSNMPCommunityStrategy(ACLSNMPCommunityStrategy
const &);
1201 static ACLSNMPCommunityStrategy Instance_
;
1202 ACLSNMPCommunityStrategy(){}
1204 ACLSNMPCommunityStrategy
&operator=(ACLSNMPCommunityStrategy
const &);
1207 class ACLSNMPCommunity
1211 static ACL::Prototype RegistryProtoype
;
1212 static ACLStrategised
<char const *> RegistryEntry_
;
1215 ACL::Prototype
ACLSNMPCommunity::RegistryProtoype(&ACLSNMPCommunity::RegistryEntry_
, "snmp_community");
1216 ACLStrategised
<char const *> ACLSNMPCommunity::RegistryEntry_(new ACLStringData
, ACLSNMPCommunityStrategy::Instance(), "snmp_community");
1219 ACLSNMPCommunityStrategy::match (ACLData
<MatchType
> * &data
, ACLChecklist
*checklist
)
1221 return data
->match (checklist
->snmp_community
);
1224 ACLSNMPCommunityStrategy
*
1225 ACLSNMPCommunityStrategy::Instance()
1230 ACLSNMPCommunityStrategy
ACLSNMPCommunityStrategy::Instance_
;