]>
Commit | Line | Data |
---|---|---|
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 |
43 | IPAddress theOutSNMPAddr; |
44 | ||
b6a2f15e | 45 | typedef struct _mib_tree_entry mib_tree_entry; |
46 | typedef oid *(instance_Fn) (oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn); | |
47 | ||
62e76326 | 48 | struct _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 | 61 | mib_tree_entry *mib_tree_head; |
b6a2f15e | 62 | mib_tree_entry *mib_tree_last; |
43d4303e | 63 | |
6de2df60 | 64 | #if STDC_HEADERS |
b6a2f15e | 65 | static mib_tree_entry *snmpAddNode(oid * name, int len, oid_ParseFn * parsefunction, instance_Fn * instancefunction, int children,...); |
853dead1 | 66 | static oid *snmpCreateOid(int length,...); |
8a6218c6 | 67 | #else |
853dead1 | 68 | static mib_tree_entry *snmpAddNode(); |
69 | static oid *snmpCreateOid(); | |
8a6218c6 | 70 | #endif |
8fd63c35 | 71 | SQUIDCEXTERN void (*snmplib_debug_hook) (int, char *); |
b6a2f15e | 72 | static oid *static_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn); |
73 | static oid *time_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn); | |
74 | static oid *peer_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn); | |
75 | static oid *client_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn); | |
8a6218c6 | 76 | static void snmpDecodePacket(snmp_request_t * rq); |
74c161ea | 77 | static void snmpConstructReponse(snmp_request_t * rq); |
62e76326 | 78 | |
897029fd | 79 | static struct snmp_pdu *snmpAgentResponse(struct snmp_pdu *PDU); |
c68e9c6b | 80 | static oid_ParseFn *snmpTreeNext(oid * Current, snint CurrentLen, oid ** Next, snint * NextLen); |
d439f213 | 81 | static oid_ParseFn *snmpTreeGet(oid * Current, snint CurrentLen); |
c68e9c6b | 82 | static mib_tree_entry *snmpTreeEntry(oid entry, snint len, mib_tree_entry * current); |
897029fd | 83 | static mib_tree_entry *snmpTreeSiblingEntry(oid entry, snint len, mib_tree_entry * current); |
dba79ac5 | 84 | static 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 | 97 | void |
98 | snmpInit(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 | ||
365 | void | |
366 | snmpConnectionOpen(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 | 432 | void |
433 | snmpConnectionShutdown(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 | ||
462 | void | |
463 | snmpConnectionClose(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 | 482 | void |
dba79ac5 | 483 | snmpHandleUdp(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 | 523 | static void |
dba79ac5 | 524 | snmpDecodePacket(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 | 564 | static void |
74c161ea | 565 | snmpConstructReponse(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 | 586 | static 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 | 671 | static oid_ParseFn * |
d439f213 | 672 | snmpTreeGet(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 | 702 | static oid_ParseFn * |
dba79ac5 | 703 | snmpTreeNext(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 | 796 | static oid * |
b6a2f15e | 797 | static_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 | 810 | static oid * |
b6a2f15e | 811 | time_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 | 840 | static oid * |
b6a2f15e | 841 | peer_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 | 875 | static oid * |
b6a2f15e | 876 | client_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 | 945 | static mib_tree_entry * |
897029fd | 946 | snmpTreeSiblingEntry(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 | 972 | static mib_tree_entry * |
897029fd | 973 | snmpTreeEntry(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 | 992 | static mib_tree_entry * |
1952717f | 993 | #if STDC_HEADERS |
b6a2f15e | 994 | snmpAddNode(oid * name, int len, oid_ParseFn * parsefunction, instance_Fn * instancefunction, int children,...) |
1952717f | 995 | #else |
996 | snmpAddNode(va_alist) | |
62e76326 | 997 | va_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 | 1049 | static oid * |
1952717f | 1050 | #if STDC_HEADERS |
c68e9c6b | 1051 | snmpCreateOid(int length,...) |
1952717f | 1052 | #else |
1053 | snmpCreateOid(va_alist) | |
62e76326 | 1054 | va_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 | 1086 | void |
1087 | snmpDebugOid(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 | 1101 | static void |
dba79ac5 | 1102 | snmpSnmplibDebug(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 | */ | |
1115 | void | |
1116 | addr2oid(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 | */ | |
1157 | void | |
1158 | oid2addr(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 | ||
1194 | class ACLSNMPCommunityStrategy : public ACLStrategy<char const *> | |
1195 | { | |
1196 | ||
1197 | public: | |
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 | ||
1205 | private: | |
1206 | static ACLSNMPCommunityStrategy Instance_; | |
1207 | ACLSNMPCommunityStrategy(){} | |
1208 | ||
1209 | ACLSNMPCommunityStrategy&operator=(ACLSNMPCommunityStrategy const &); | |
1210 | }; | |
1211 | ||
1212 | class ACLSNMPCommunity | |
1213 | { | |
1214 | ||
1215 | private: | |
1216 | static ACL::Prototype RegistryProtoype; | |
1217 | static ACLStrategised<char const *> RegistryEntry_; | |
1218 | }; | |
1219 | ||
1220 | ACL::Prototype ACLSNMPCommunity::RegistryProtoype(&ACLSNMPCommunity::RegistryEntry_, "snmp_community"); | |
1221 | ACLStrategised<char const *> ACLSNMPCommunity::RegistryEntry_(new ACLStringData, ACLSNMPCommunityStrategy::Instance(), "snmp_community"); | |
1222 | ||
1223 | int | |
1224 | ACLSNMPCommunityStrategy::match (ACLData<MatchType> * &data, ACLChecklist *checklist) | |
1225 | { | |
1226 | return data->match (checklist->snmp_community); | |
b0dd28ba | 1227 | } |
1228 | ||
1229 | ACLSNMPCommunityStrategy * | |
1230 | ACLSNMPCommunityStrategy::Instance() | |
1231 | { | |
1232 | return &Instance_; | |
1233 | } | |
1234 | ||
1235 | ACLSNMPCommunityStrategy ACLSNMPCommunityStrategy::Instance_; |