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