-
Notifications
You must be signed in to change notification settings - Fork 37
Expand file tree
/
Copy pathSNMP_Agent.cpp
More file actions
246 lines (196 loc) · 8.49 KB
/
SNMP_Agent.cpp
File metadata and controls
246 lines (196 loc) · 8.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
#include "SNMP_Agent.h"
const char* SNMP_TAG = "SNMP";
void SNMPAgent::setUDP(UDP* udp){
this->_udp.push_back(udp);
this->begin();
}
void SNMPAgent::begin(){
this->restartUDP();
}
void SNMPAgent::begin(const char* prefix){
this->oidPrefix = prefix;
this->begin();
}
void SNMPAgent::stop(){
for(auto udp : _udp){
udp->stop();
}
}
SNMP_ERROR_RESPONSE SNMPAgent::loop(){
for(auto udp : _udp){
int packetLength = udp->parsePacket();
if(packetLength > 0){
SNMP_LOGD("Received packet from: %s, of size: %d", udp->remoteIP().toString().c_str(), packetLength);
if(packetLength < 0 || packetLength > MAX_SNMP_PACKET_LENGTH){
SNMP_LOGW("Incoming packet too large: %d\n", packetLength);
return SNMP_REQUEST_TOO_LARGE;
}
memset(_packetBuffer, 0, MAX_SNMP_PACKET_LENGTH);
int readBytes = udp->read(_packetBuffer, packetLength);
if(readBytes != packetLength){
SNMP_LOGW("Packet length mismatch: expected: %d, actual: %d\n", packetLength, readBytes);
return SNMP_REQUEST_INVALID;
}
int responseLength = 0;
SNMP_ERROR_RESPONSE response = handlePacket(_packetBuffer, packetLength, &responseLength, MAX_SNMP_PACKET_LENGTH, callbacks, _community, _readOnlyCommunity, informCallback, (void*)this);
if(response > 0 && response != SNMP_INFORM_RESPONSE_OCCURRED){
// send it
SNMP_LOGD("Built packet, sending back response to: %s, %d\n", udp->remoteIP().toString().c_str(), udp->remotePort());
udp->beginPacket(udp->remoteIP(), udp->remotePort());
udp->write(_packetBuffer, responseLength);
if(!udp->endPacket()){
SNMP_LOGW("Failed to send response packet\n");
}
}
if(response == SNMP_SET_OCCURRED){
setOccurred = true;
}
this->handleInformQueue();
return response;
}
}
this->handleInformQueue();
return SNMP_NO_PACKET;
}
SortableOIDType* SNMPAgent::buildOIDWithPrefix(const char *oid, bool overwritePrefix){
SortableOIDType* newOid;
if(!this->oidPrefix.empty() && !overwritePrefix){
std::string temp;
temp.append(this->oidPrefix);
temp.append(oid);
newOid = new SortableOIDType(temp);
} else {
newOid = new SortableOIDType(oid);
}
if(newOid->valid){
return newOid;
}
delete newOid;
return nullptr;
}
ValueCallback* SNMPAgent::addReadWriteStringHandler(const char *oid, char** value, size_t max_len, bool isSettable, bool overwritePrefix){
if(!value || !*value) return nullptr;
SortableOIDType* oidType = buildOIDWithPrefix(oid, overwritePrefix);
if(!oidType) return nullptr;
return addHandler(new StringCallback(oidType, value, max_len), isSettable);
}
ValueCallback *SNMPAgent::addReadOnlyStaticStringHandler(const char *oid, const std::string& value, bool overwritePrefix) {
SortableOIDType* oidType = buildOIDWithPrefix(oid, overwritePrefix);
if(!oidType) return nullptr;
return addHandler(new ReadOnlyStringCallback(oidType, value), false);
}
ValueCallback* SNMPAgent::addOpaqueHandler(const char *oid, uint8_t* value, size_t data_len, bool isSettable, bool overwritePrefix){
if(!value) return nullptr;
SortableOIDType* oidType = buildOIDWithPrefix(oid, overwritePrefix);
if(!oidType) return nullptr;
return addHandler(new OpaqueCallback(oidType, value, data_len), isSettable);
}
ValueCallback* SNMPAgent::addIntegerHandler(const char *oid, int* value, bool isSettable, bool overwritePrefix){
if(!value) return nullptr;
SortableOIDType* oidType = buildOIDWithPrefix(oid, overwritePrefix);
if(!oidType) return nullptr;
return addHandler(new IntegerCallback(oidType, value), isSettable);
}
ValueCallback* SNMPAgent::addReadOnlyIntegerHandler(const char *oid, int value, bool overwritePrefix){
SortableOIDType* oidType = buildOIDWithPrefix(oid, overwritePrefix);
if(!oidType) {
return nullptr;
}
return addHandler(new StaticIntegerCallback(oidType, value), false);
}
ValueCallback* SNMPAgent::addDynamicIntegerHandler(const char *oid, GETINT_FUNC callback_func, bool overwritePrefix){
if(!callback_func) {
return nullptr;
}
SortableOIDType* oidType = buildOIDWithPrefix(oid, overwritePrefix);
if(!oidType) {
return nullptr;
}
return addHandler(new DynamicIntegerCallback(oidType, callback_func), false);
}
ValueCallback* SNMPAgent::addTimestampHandler(const char *oid, uint32_t* value, bool isSettable, bool overwritePrefix){
if(!value) return nullptr;
SortableOIDType* oidType = buildOIDWithPrefix(oid, overwritePrefix);
if(!oidType) return nullptr;
return addHandler(new TimestampCallback(oidType, value), isSettable);
}
ValueCallback* SNMPAgent::addDynamicReadOnlyTimestampHandler(const char *oid, GETUINT_FUNC callback_func, bool overwritePrefix){
SortableOIDType* oidType = buildOIDWithPrefix(oid, overwritePrefix);
if(!oidType) {
return nullptr;
}
return addHandler(new DynamicTimestampCallback(oidType, callback_func), false);
}
ValueCallback* SNMPAgent::addDynamicReadOnlyStringHandler(const char *oid, GETSTRING_FUNC callback_func, bool overwritePrefix){
SortableOIDType* oidType = buildOIDWithPrefix(oid, overwritePrefix);
if(!oidType) {
return nullptr;
}
return addHandler(new DynamicStringCallback(oidType, callback_func), false);
}
ValueCallback* SNMPAgent::addOIDHandler(const char *oid, const std::string& value, bool overwritePrefix){
SortableOIDType* oidType = buildOIDWithPrefix(oid, overwritePrefix);
if(!oidType) return nullptr;
return addHandler(new OIDCallback(oidType, value), false);
}
ValueCallback* SNMPAgent::addCounter64Handler(const char *oid, uint64_t* value, bool overwritePrefix){
if(!value) return nullptr;
SortableOIDType* oidType = buildOIDWithPrefix(oid, overwritePrefix);
if(!oidType) return nullptr;
return addHandler(new Counter64Callback(oidType, value), false);
}
ValueCallback* SNMPAgent::addCounter32Handler(const char *oid, uint32_t* value, bool overwritePrefix){
if(!value) return nullptr;
SortableOIDType* oidType = buildOIDWithPrefix(oid, overwritePrefix);
if(!oidType) return nullptr;
return addHandler(new Counter32Callback(oidType, value), false);
}
ValueCallback* SNMPAgent::addGaugeHandler(const char *oid, uint32_t* value, bool overwritePrefix){
if(!value) return nullptr;
SortableOIDType* oidType = buildOIDWithPrefix(oid, overwritePrefix);
if(!oidType) return nullptr;
return addHandler(new Gauge32Callback(oidType, value), false);
}
ValueCallback* addIPAddressHandler(const char *oid, IPAddress* value, bool isSettable, bool overwritePrefix){
if(!value) return nullptr;
SortableOIDType* oidType = buildOIDWithPrefix(oid, overwritePrefix);
if(!oidType) return nullptr;
return addHandler(new NetworkAddressCallback(oidType, value), false);
}
ValueCallback * SNMPAgent::addHandler(ValueCallback *callback, bool isSettable) {
callback->isSettable = isSettable;
this->callbacks.push_back(callback);
return callback;
}
bool SNMPAgent::removeHandler(ValueCallback* callback){ // this will remove the callback from the list and shift everything in the list back so there are no gaps, this will not delete the actual callback
remove_handler(this->callbacks, callback);
return true;
}
bool SNMPAgent::sortHandlers(){
sort_handlers(this->callbacks);
return true;
}
snmp_request_id_t SNMPAgent::sendTrapTo(SNMPTrap* trap, const IPAddress& ip, bool replaceQueuedRequests, int retries, int delay_ms){
return queue_and_send_trap(this->informList, trap, ip, replaceQueuedRequests, retries, delay_ms);
}
void SNMPAgent::informCallback(void* ctx, snmp_request_id_t requestID, bool responseReceiveSuccess){
if(!ctx) return;
SNMPAgent* agent = static_cast<SNMPAgent*>(ctx);
return inform_callback(agent->informList, requestID, responseReceiveSuccess);
}
void SNMPAgent::handleInformQueue(){
handle_inform_queue(this->informList);
}
void SNMPAgent::markTrapDeleted(SNMPTrap* trap){
for(auto agent : SNMPAgent::agents){
mark_trap_deleted(agent->informList, trap);
}
}
std::list<SNMPAgent*> SNMPAgent::agents = std::list<SNMPAgent*>();
bool SNMPAgent::restartUDP() {
for(auto udp : _udp){
udp->stop();
udp->begin(AgentUDPport);
}
return true;
}