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