From 4a6a61ca53bd4260373812ce83c166d0cbb65ad8 Mon Sep 17 00:00:00 2001 From: Nicholas Boone Date: Sun, 20 May 2018 11:13:53 +0100 Subject: [PATCH 1/3] Initial commit --- Arduino_SNMP.h | 560 ++++++++++++++++++++++++++++------------------ BER.h | 101 ++++++++- README.md | 16 +- SNMPGet.h | 175 +++++++++++++++ SNMPGetResponse.h | 221 ++++++++++++++++++ SNMPRequest.h | 13 ++ SNMPTrap.h | 5 +- VarBinds.h | 10 +- 8 files changed, 867 insertions(+), 234 deletions(-) create mode 100644 SNMPGet.h create mode 100644 SNMPGetResponse.h diff --git a/Arduino_SNMP.h b/Arduino_SNMP.h index e5e039e..013c748 100644 --- a/Arduino_SNMP.h +++ b/Arduino_SNMP.h @@ -27,7 +27,7 @@ class ValueCallback { class IntegerCallback: public ValueCallback { public: IntegerCallback(): ValueCallback(INTEGER){}; - int* value; + unsigned int* value; bool isFloat = false; }; @@ -43,6 +43,7 @@ class StringCallback: public ValueCallback { char** value; }; + typedef struct ValueCallbackList { ~ValueCallbackList(){ delete next; @@ -51,7 +52,10 @@ typedef struct ValueCallbackList { struct ValueCallbackList* next = 0; } ValueCallbacks; + #include "SNMPTrap.h" +#include "SNMPGet.h" +#include "SNMPGetResponse.h" class SNMPAgent { public: @@ -63,11 +67,12 @@ class SNMPAgent { ValueCallback* findCallback(char* oid, bool next); ValueCallback* addFloatHandler(char* oid, float* value, bool isSettable = false); // this obv just adds integer but with the *0.1 set ValueCallback* addStringHandler(char*, char**, bool isSettable = false); // passing in a pointer to a char* - ValueCallback* addIntegerHandler(char* oid, int* value, bool isSettable = false); + ValueCallback* addIntegerHandler(char* oid, unsigned int* value, bool isSettable = false); ValueCallback* addTimestampHandler(char* oid, int* value, bool isSettable = false); bool setUDP(UDP* udp); bool begin(); + bool beginMaster(); bool begin(char*); bool loop(); char oidPrefix[40]; @@ -78,11 +83,12 @@ class SNMPAgent { } UDP* _udp; bool removeHandler(ValueCallback* callback); + private: void addHandler(ValueCallback* callback); - unsigned char _packetBuffer[SNMP_PACKET_LENGTH]; - bool inline receivePacket(int length); + unsigned char _packetBuffer[SNMP_PACKET_LENGTH]; // create and array of unsigned char that is 256 long + bool inline receivePacket(int length); SNMPOIDResponse* generateErrorResponse(ERROR_STATUS error, char* oid){ SNMPOIDResponse* errorResponse = new SNMPOIDResponse(); errorResponse->oid = new OIDType(oid); @@ -106,6 +112,11 @@ bool SNMPAgent::begin(){ _udp->begin(161); } +bool SNMPAgent::beginMaster() { + if (!_udp) return false; + _udp->begin(162); +} + bool SNMPAgent::begin(char* prefix){ strncpy(oidPrefix, prefix, 40); return this->begin(); @@ -115,185 +126,304 @@ bool SNMPAgent::loop(){ if(!_udp){ return false; } - receivePacket(_udp->parsePacket()); + receivePacket(_udp->parsePacket()); // get the lenght of the packet is bytes and then run the recivePacket function + } -bool inline SNMPAgent::receivePacket(int packetLength){ - if(!packetLength) return false; -// Serial.print("Received from: ");Serial.print(packetLength);Serial.print(" ");Serial.println(_udp->remoteIP()); - memset(_packetBuffer, 0, SNMP_PACKET_LENGTH); - int len = packetLength; -// int len = _udp->read(_packetBuffer, SNMP_PACKET_LENGTH); - for(int i = 0; i < len; i++){ - _packetBuffer[i] = _udp->read(); -// Serial.print(_packetBuffer[i], HEX); -// Serial.print(" "); - } - Serial.println(); - _udp->flush(); - _packetBuffer[len] = 0; -// Serial.println(_packetBuffer); - SNMPRequest* snmprequest = new SNMPRequest(); - if(snmprequest->parseFrom(_packetBuffer)){ - - // check version and community - if(snmprequest->version != 1 || strcmp(_community, snmprequest->communityString) != 0) { - Serial.println(F("Invalid community or version")); - delete snmprequest; - return false; - } - - SNMPResponse* response = new SNMPResponse(); - response->requestID = snmprequest->requestID; - strncpy(response->communityString, snmprequest->communityString, 15); - int varBindIndex = 1; - snmprequest->varBindsCursor = snmprequest->varBinds; - while(true){ - delay(1); - //Serial.print("OID: ");//Serial.println(snmprequest->varBindsCursor->value->oid->_value); - - // Deal with OID request here: - bool walk = false; - if(snmprequest->requestType == GetNextRequestPDU){ - walk = true; - } - ValueCallback* callback = findCallback(snmprequest->varBindsCursor->value->oid->_value, walk); - if(callback){ // this is where we deal with the response varbind - SNMPOIDResponse* OIDResponse = new SNMPOIDResponse(); - OIDResponse->errorStatus = (ERROR_STATUS)0; - - memset(OIDBuf, 0, 50); - strcat(OIDBuf, oidPrefix); - strcat(OIDBuf, callback->OID); - - OIDResponse->oid = new OIDType(OIDBuf); - OIDResponse->type = callback->type; - - // TODO: this whole thing needs better flow: proper checking for errors etc. - - if(snmprequest->requestType == SetRequestPDU){ - // settable data.. - if(callback->isSettable){ - if(callback->type != snmprequest->varBindsCursor->value->type){ - // wrong data type to set.. - // BAD_VALUE - Serial.println(F("VALUE-TYPE DOES NOT MATCH")); - SNMPOIDResponse* errorResponse = generateErrorResponse(BAD_VALUE, snmprequest->varBindsCursor->value->oid->_value); - response->addErrorResponse(errorResponse, varBindIndex); - } else { - // actually set it - switch(callback->type){ - case STRING: - { - memcpy(*((StringCallback*)callback)->value, String(((OctetType*)snmprequest->varBindsCursor->value->value)->_value).c_str(), 25);// FIXME: this is VERY dangerous, i'm assuming the length of the source char*, this needs to change. for some reason strncpy didnd't work, need to look into this. the '25' also needs to be defined somewhere so this won't break; - *(*((StringCallback*)callback)->value + 24) = 0x0; // close off the dest string, temporary - OctetType* value = new OctetType(*((StringCallback*)callback)->value); - OIDResponse->value = value; - setOccurred = true; - } - break; - case INTEGER: - { - IntegerType* value = new IntegerType(); - if(!((IntegerCallback*)callback)->isFloat){ - *(((IntegerCallback*)callback)->value) = ((IntegerType*)snmprequest->varBindsCursor->value->value)->_value; - value->_value = *(((IntegerCallback*)callback)->value); - } else { - *(((IntegerCallback*)callback)->value) = (float)(((IntegerType*)snmprequest->varBindsCursor->value->value)->_value / 10); - value->_value = *(float*)(((IntegerCallback*)callback)->value) * 10; - } - OIDResponse->value = value; - setOccurred = true; - } - break; - } - response->addResponse(OIDResponse); - } - } else { - // not settable, send error - Serial.println(F("OID NOT SETTABLE")); - SNMPOIDResponse* errorResponse = generateErrorResponse(READ_ONLY, snmprequest->varBindsCursor->value->oid->_value); - response->addErrorResponse(errorResponse, varBindIndex); - } - } else if(snmprequest->requestType == GetRequestPDU || snmprequest->requestType == GetNextRequestPDU){ - - if(callback->type == INTEGER){ - IntegerType* value = new IntegerType(); - if(!((IntegerCallback*)callback)->isFloat){ - value->_value = *(((IntegerCallback*)callback)->value); - } else { - value->_value = *(float*)(((IntegerCallback*)callback)->value) * 10; - } - OIDResponse->value = value; - } else if(callback->type == STRING){ - OctetType* value = new OctetType(*((StringCallback*)callback)->value); - OIDResponse->value = value; - } else if(callback->type == TIMESTAMP){ - TimestampType* value = new TimestampType(*(((TimestampCallback*)callback)->value)); - OIDResponse->value = value; - } - response->addResponse(OIDResponse); - } - } else { - // inject a NoSuchObject error - Serial.println(F("OID NOT FOUND")); - SNMPOIDResponse* errorResponse = generateErrorResponse(NO_SUCH_NAME, snmprequest->varBindsCursor->value->oid->_value); - response->addErrorResponse(errorResponse, varBindIndex); - - } - // ------------------------- - - snmprequest->varBindsCursor = snmprequest->varBindsCursor->next; - if(!snmprequest->varBindsCursor->value){ - break; - } - varBindIndex++; - } -// Serial.println("Sending UDP"); - memset(_packetBuffer, 0, SNMP_PACKET_LENGTH); - delay(1); - int length = response->serialise(_packetBuffer); - //Serial.print("Serialised into length: ");//Serial.println(length); - delay(1); - _udp->beginPacket(_udp->remoteIP(), _udp->remotePort()); - _udp->write(_packetBuffer, length); - if(!_udp->endPacket()){ - Serial.println(F("COULDN'T SEND PACKET")); - for(int i = 0; i < length; i++){ - Serial.print(_packetBuffer[i], HEX); - } - Serial.print(F("Length: "));Serial.println(length); - Serial.print(F("Length of incoming: "));Serial.println(len); - } - delay(1); - //Serial.println("Packet Sent"); -// -// //Serial.print("Length of response: ");//Serial.println(length); -// //Serial.print("Response: "); -// char* buff = buf; -// while(length != 0){ -// //Serial.print(*buff, HEX); -// //Serial.print(" "); -// buff++; -// length--; -// } -// //Serial.println(); -// Serial.print(F("freeMemory before delete=")); -// Serial.println(freeMemory()); - delete response; - } else { - Serial.println(F("CORRUPT PACKET")); - VarBindList* tempList = snmprequest->varBinds; - while(tempList->next){ - delete tempList->value->oid; - delete tempList->value->value; - tempList = tempList->next; - } - delete tempList->value->oid; - delete tempList->value->value; - } - delete snmprequest; -// //Serial.printf("Current heap size: %u\n", ESP.getFreeHeap()); +bool inline SNMPAgent::receivePacket(int packetLength) { + if (!packetLength) return false; + // Serial.print("Received from: ");Serial.print(packetLength);Serial.print(" ");Serial.println(_udp->remoteIP()); + memset(_packetBuffer, 0, SNMP_PACKET_LENGTH); + int len = packetLength; + // int len = _udp->read(_packetBuffer, SNMP_PACKET_LENGTH); + for (int i = 0; i < len; i++) { + _packetBuffer[i] = _udp->read(); + // Serial.print(_packetBuffer[i]); + // Serial.print(" "); + + + } + + _udp->flush(); + _packetBuffer[len] = 0; + + //Serial.println(); + if (_packetBuffer[13] == GetResponsePDU) { + + + SNMPGetRespose* snmpgetresponse = new SNMPGetRespose(); + + if (snmpgetresponse->parseFrom(_packetBuffer)) { + + // check version and community + if (snmpgetresponse->version != 1 || strcmp(_community, snmpgetresponse->communityString) != 0) { + Serial.println(F("Invalid community or version")); + + } + int varBindIndex = 1; + snmpgetresponse->varBindsCursor = snmpgetresponse->varBinds; + while (true) { + //Serial.print("OID: ");Serial.println(snmpgetresponse->varBindsCursor->value->oid->_value); + + ValueCallback* callback = findCallback(snmpgetresponse->varBindsCursor->value->oid->_value, false); + //Serial.println(callback->OID); + if (callback->isSettable) { + //Serial.println("isSettable"); + if (callback->type != snmpgetresponse->varBindsCursor->value->type) { + // wrong data type to set.. + // BAD_VALUE + Serial.println(F("VALUE-TYPE DOES NOT MATCH")); + + } + + switch (callback->type) { + case STRING: + { + memcpy(*((StringCallback*)callback)->value, String(((OctetType*)snmpgetresponse->varBindsCursor->value->value)->_value).c_str(), 25);// FIXME: this is VERY dangerous, i'm assuming the length of the source char*, this needs to change. for some reason strncpy didnd't work, need to look into this. the '25' also needs to be defined somewhere so this won't break; + *(*((StringCallback*)callback)->value + 24) = 0x0; // close off the dest string, temporary + OctetType* value = new OctetType(*((StringCallback*)callback)->value); + Serial.print("STR value: "); + // Serial.println(value); + delete value; + setOccurred = true; + } + break; + case INTEGER: + { + IntegerType* value = new IntegerType(); + if (!((IntegerCallback*)callback)->isFloat) { + //Serial.println(*(((IntegerCallback*)callback)->value)); + *(((IntegerCallback*)callback)->value) = ((IntegerType*)snmpgetresponse->varBindsCursor->value->value)->_value; + value->_value = *(((IntegerCallback*)callback)->value); + } + else { + + *(((IntegerCallback*)callback)->value) = (float)(((IntegerType*)snmpgetresponse->varBindsCursor->value->value)->_value / 10); + value->_value = *(float*)(((IntegerCallback*)callback)->value) * 10; + } + delete value; + setOccurred = true; + } + break; + } + + } + else { + // not settable, send error + Serial.println(F("OID NOT SETTABLE")); + } + snmpgetresponse->varBindsCursor = snmpgetresponse->varBindsCursor->next; + if (!snmpgetresponse->varBindsCursor->value) { + break; + } + varBindIndex++; + } + } + else { + + Serial.println(F("CORRUPT PACKET")); + VarBindList* tempList = snmpgetresponse->varBinds; + while (tempList->next) { + delete tempList->value->oid; + delete tempList->value->value; + tempList = tempList->next; + } + delete tempList->value->oid; + delete tempList->value->value; + + } + + + + delete snmpgetresponse; + + return true; + + } + + else if ((_packetBuffer[13] == GetRequestPDU) || (_packetBuffer[13] == SetRequestPDU)) { + + + // Serial.println(_packetBuffer); + SNMPRequest* snmprequest = new SNMPRequest(); + if (snmprequest->parseFrom(_packetBuffer)) { + + // check version and community + if (snmprequest->version != 1 || strcmp(_community, snmprequest->communityString) != 0) { + Serial.println(F("Invalid community or version")); + delete snmprequest; + return false; + } + + SNMPResponse* response = new SNMPResponse(); + response->requestID = snmprequest->requestID; + strncpy(response->communityString, snmprequest->communityString, 15); + int varBindIndex = 1; + snmprequest->varBindsCursor = snmprequest->varBinds; + while (true) { + delay(1); + //Serial.print("OID: ");//Serial.println(snmprequest->varBindsCursor->value->oid->_value); + + // Deal with OID request here: + bool walk = false; + if (snmprequest->requestType == GetNextRequestPDU) { + walk = true; + } + ValueCallback* callback = findCallback(snmprequest->varBindsCursor->value->oid->_value, walk); + if (callback) { // this is where we deal with the response varbind + SNMPOIDResponse* OIDResponse = new SNMPOIDResponse(); + OIDResponse->errorStatus = (ERROR_STATUS)0; + + memset(OIDBuf, 0, 50); + strcat(OIDBuf, oidPrefix); + strcat(OIDBuf, callback->OID); + + OIDResponse->oid = new OIDType(OIDBuf); + OIDResponse->type = callback->type; + + // TODO: this whole thing needs better flow: proper checking for errors etc. + + if (snmprequest->requestType == SetRequestPDU) { + // settable data.. + if (callback->isSettable) { + if (callback->type != snmprequest->varBindsCursor->value->type) { + // wrong data type to set.. + // BAD_VALUE + Serial.println(F("VALUE-TYPE DOES NOT MATCH")); + SNMPOIDResponse* errorResponse = generateErrorResponse(BAD_VALUE, snmprequest->varBindsCursor->value->oid->_value); + response->addErrorResponse(errorResponse, varBindIndex); + } + else { + // actually set it + switch (callback->type) { + case STRING: + { + memcpy(*((StringCallback*)callback)->value, String(((OctetType*)snmprequest->varBindsCursor->value->value)->_value).c_str(), 25);// FIXME: this is VERY dangerous, i'm assuming the length of the source char*, this needs to change. for some reason strncpy didnd't work, need to look into this. the '25' also needs to be defined somewhere so this won't break; + *(*((StringCallback*)callback)->value + 24) = 0x0; // close off the dest string, temporary + OctetType* value = new OctetType(*((StringCallback*)callback)->value); + OIDResponse->value = value; + setOccurred = true; + } + break; + case INTEGER: + { + IntegerType* value = new IntegerType(); + if (!((IntegerCallback*)callback)->isFloat) { + *(((IntegerCallback*)callback)->value) = ((IntegerType*)snmprequest->varBindsCursor->value->value)->_value; + value->_value = *(((IntegerCallback*)callback)->value); + } + else { + *(((IntegerCallback*)callback)->value) = (float)(((IntegerType*)snmprequest->varBindsCursor->value->value)->_value / 10); + value->_value = *(float*)(((IntegerCallback*)callback)->value) * 10; + } + OIDResponse->value = value; + setOccurred = true; + } + break; + } + response->addResponse(OIDResponse); + } + } + else { + // not settable, send error + Serial.println(F("OID NOT SETTABLE")); + SNMPOIDResponse* errorResponse = generateErrorResponse(READ_ONLY, snmprequest->varBindsCursor->value->oid->_value); + response->addErrorResponse(errorResponse, varBindIndex); + } + } + else if (snmprequest->requestType == GetRequestPDU || snmprequest->requestType == GetNextRequestPDU) { + + if (callback->type == INTEGER) { + IntegerType* value = new IntegerType(); + if (!((IntegerCallback*)callback)->isFloat) { + value->_value = *(((IntegerCallback*)callback)->value); + } + else { + value->_value = *(float*)(((IntegerCallback*)callback)->value) * 10; + } + OIDResponse->value = value; + } + else if (callback->type == STRING) { + OctetType* value = new OctetType(*((StringCallback*)callback)->value); + OIDResponse->value = value; + } + else if (callback->type == TIMESTAMP) { + TimestampType* value = new TimestampType(*(((TimestampCallback*)callback)->value)); + OIDResponse->value = value; + } + response->addResponse(OIDResponse); + } + } + else { + // inject a NoSuchObject error + Serial.println(F("OID NOT FOUND")); + SNMPOIDResponse* errorResponse = generateErrorResponse(NO_SUCH_NAME, snmprequest->varBindsCursor->value->oid->_value); + response->addErrorResponse(errorResponse, varBindIndex); + + } + // ------------------------- + + snmprequest->varBindsCursor = snmprequest->varBindsCursor->next; + if (!snmprequest->varBindsCursor->value) { + break; + } + varBindIndex++; + } + // Serial.println("Sending UDP"); + memset(_packetBuffer, 0, SNMP_PACKET_LENGTH); + delay(1); + int length = response->serialise(_packetBuffer); + //Serial.print("Serialised into length: ");//Serial.println(length); + delay(1); + _udp->beginPacket(_udp->remoteIP(), _udp->remotePort()); + _udp->write(_packetBuffer, length); + if (!_udp->endPacket()) { + Serial.println(F("COULDN'T SEND PACKET")); + for (int i = 0; i < length; i++) { + Serial.print(_packetBuffer[i], HEX); + } + Serial.print(F("Length: ")); Serial.println(length); + Serial.print(F("Length of incoming: ")); Serial.println(len); + } + delay(1); + //Serial.println("Packet Sent"); + // + // //Serial.print("Length of response: ");//Serial.println(length); + // //Serial.print("Response: "); + // char* buff = buf; + // while(length != 0){ + // //Serial.print(*buff, HEX); + // //Serial.print(" "); + // buff++; + // length--; + // } + // //Serial.println(); + // Serial.print(F("freeMemory before delete=")); + // Serial.println(freeMemory()); + delete response; + } + else { + Serial.println(F("CORRUPT PACKET")); + VarBindList* tempList = snmprequest->varBinds; + while (tempList->next) { + delete tempList->value->oid; + delete tempList->value->value; + tempList = tempList->next; + } + delete tempList->value->oid; + delete tempList->value->value; + } + delete snmprequest; + // //Serial.printf("Current heap size: %u\n", ESP.getFreeHeap()); + + + } + + else { + Serial.println("Could not determine PDU type"); + } + + } ValueCallback* SNMPAgent::findCallback(char* oid, bool next){ @@ -303,12 +433,12 @@ ValueCallback* SNMPAgent::findCallback(char* oid, bool next){ if(callbacksCursor->value){ while(true){ if(!useNext){ - memset(OIDBuf, 0, 50); - strcat(OIDBuf, oidPrefix); + memset(OIDBuf, 0, 50); + strcat(OIDBuf, oidPrefix); strcat(OIDBuf, callbacksCursor->value->OID); if(strcmp(OIDBuf, oid) == 0){ // found - if(next){ + if(next){ useNext = true; } else { return callbacksCursor->value; @@ -321,7 +451,7 @@ ValueCallback* SNMPAgent::findCallback(char* oid, bool next){ } } else { return callbacksCursor->value; - } + } if(callbacksCursor->next){ callbacksCursor = callbacksCursor->next; @@ -329,8 +459,10 @@ ValueCallback* SNMPAgent::findCallback(char* oid, bool next){ break; } } + + } - + return 0; } @@ -344,7 +476,7 @@ ValueCallback* SNMPAgent::addStringHandler(char* oid, char** value, bool isSetta return callback; } -ValueCallback* SNMPAgent::addIntegerHandler(char* oid, int* value, bool isSettable){ +ValueCallback* SNMPAgent::addIntegerHandler(char* oid, unsigned int* value, bool isSettable){ ValueCallback* callback = new IntegerCallback(); if(isSettable) callback->isSettable = true; callback->OID = (char*)malloc((sizeof(char) * strlen(oid)) + 1); @@ -360,7 +492,7 @@ ValueCallback* SNMPAgent::addFloatHandler(char* oid, float* value, bool isSettab if(isSettable) callback->isSettable = true; callback->OID = (char*)malloc((sizeof(char) * strlen(oid)) + 1); strcpy(callback->OID, oid); - ((IntegerCallback*)callback)->value = (int*)value; + ((IntegerCallback*)callback)->value = (unsigned int*)value; ((IntegerCallback*)callback)->isFloat = true; addHandler(callback); return callback; @@ -391,32 +523,32 @@ void SNMPAgent::addHandler(ValueCallback* callback){ } bool SNMPAgent::removeHandler(ValueCallback* callback){ // this will remove the callback and shift everything in the list back so there are no gaps, this will not delete the actual callback -// callbacksCursor = callbacks; -// Serial.println("Entering hell..."); -// if(!callbacksCursor->value){ -// return false; -// } -// bool shifting = false; -// do { -// if(callbacksCursor->value == callback){ -// // found -// while(callbacksCursor->next != 0){ -// callbacksCursor->value = callbacksCursor->next->value; -// callbacksCursor = callbacksCursor->next; -// if(callbacksCursor->next == 0){ -// // this was last in line, move it to here then break; -// break; -// } -// -// } -// delete callbacksCursor; -// shifting = true; -// break; -// } -// callbacksCursor = callbacksCursor->next; -// } while(callbacksCursor->next != 0); -// -// return shifting; + callbacksCursor = callbacks; + Serial.println("Entering hell..."); + if(!callbacksCursor->value){ + return false; + } + bool shifting = false; + do { + if(callbacksCursor->value == callback){ + // found + while(callbacksCursor->next != 0){ + callbacksCursor->value = callbacksCursor->next->value; + callbacksCursor = callbacksCursor->next; + if(callbacksCursor->next == 0){ + // this was last in line, move it to here then break; + break; + } + + } + delete callbacksCursor; + shifting = true; + break; + } + callbacksCursor = callbacksCursor->next; + } while(callbacksCursor->next != 0); + + return shifting; return false; } diff --git a/BER.h b/BER.h index da90f4f..d9772e2 100644 --- a/BER.h +++ b/BER.h @@ -16,6 +16,7 @@ typedef enum ASN_TYPE_WITH_VALUE { // Complex STRUCTURE = 0x30, NETWORK_ADDRESS = 0x40, + COUNTER32 = 0x41, TIMESTAMP = 0x43, GetRequestPDU = 0xA0, @@ -94,6 +95,8 @@ class IntegerType: public BER_CONTAINER { *ptr = _type; ptr++; unsigned char* lengthPtr = ptr++; + //Serial.print("INTEGER length: "); + //Serial.println(*lengthPtr); if(_value != 0){ _length = 4; // FIXME: need to give this dynamic length // while(_length > 1){ @@ -120,15 +123,19 @@ class IntegerType: public BER_CONTAINER { bool fromBuffer(unsigned char* buf){ buf++;// skip Type _length = *buf; - buf++; + + buf++; + unsigned short tempLength = _length; -// _value = *buf; // TODO: make work for integers more than 255 + _value = *buf; // TODO: make work for integers more than 255 + _value = 0; while(tempLength > 0){ _value = _value << 8; _value = _value | *buf++; tempLength--; } + //Serial.print("Counter Value: "); Serial.println(_value); return true; } int getLength(){ @@ -136,6 +143,67 @@ class IntegerType: public BER_CONTAINER { } }; +class Counter32 : public BER_CONTAINER { +public: + Counter32() : BER_CONTAINER(true, INTEGER) {}; + Counter32(unsigned long value) : _value(value), BER_CONTAINER(true, INTEGER) {}; + ~Counter32() {}; + unsigned long _value; + int serialise(unsigned char* buf) { + // here we print out the BER encoded ASN.1 bytes, which includes type, length and value. we return the length of the entire block (TL&V) ni bytes; + unsigned char* ptr = buf; + *ptr = _type; + ptr++; + unsigned char* lengthPtr = ptr++; + Serial.print("INTEGER length: "); + Serial.println(*lengthPtr); + if (_value != 0) { + _length = 4; // FIXME: need to give this dynamic length + // while(_length > 1){ + // if(_value >> 24 == 0){ + // _length--; + // _value = _value << 8; + // } else { + // break; + // } + // } + *ptr++ = _value >> 24 & 0xFF; + *ptr++ = _value >> 16 & 0xFF; + *ptr++ = _value >> 8 & 0xFF; + *ptr++ = _value & 0xFF; + + + } + else { + _length = 1; + *ptr = 0; + } + *lengthPtr = _length; + return _length + 2; + } + bool fromBuffer(unsigned char* buf) { + buf++;// skip Type + _length = *buf; + + buf++; + + unsigned short tempLength = _length; + _value = *buf; // TODO: make work for integers more than 255 + + _value = 0; + while (tempLength > 0) { + _value = _value << 8; + _value = _value | *buf++; + tempLength--; + } + //Serial.print("Counter Value: "); Serial.println(_value); + return true; + } + int getLength() { + return _length; + } +}; + class TimestampType: public IntegerType { public: TimestampType(): IntegerType(){ @@ -270,11 +338,10 @@ class OIDType: public BER_CONTAINER { } delay(1); } - Serial.print("OID: " );Serial.println(_value); + //Serial.print("OID: " );Serial.println(_value); // memcpy(_value, buf, _length); return true; } - int getLength(){ return _length; } @@ -318,9 +385,13 @@ class ComplexType: public BER_CONTAINER { ComplexType(ASN_TYPE type): BER_CONTAINER(false, type){}; ~ComplexType(){ delete _values; + } ValuesList* _values = 0; + + // buf is an unsigned char pointer to an array that lists the bytes we got from the UDP packet bool fromBuffer(unsigned char* buf){ + // the buffer we get passed in is the complete ASN Container, including the type header. buf++; // Skip our own type _length = *buf; @@ -334,7 +405,10 @@ class ComplexType: public BER_CONTAINER { // now we are at the front of a list of one or many other types, lets do our loop unsigned char i = 0; while(i < _length){ - ASN_TYPE valueType = (ASN_TYPE)*buf; + + + + ASN_TYPE valueType = (ASN_TYPE)*buf; buf++; i++; unsigned short valueLength = *buf; if(valueLength > 127){ @@ -346,7 +420,7 @@ class ComplexType: public BER_CONTAINER { } buf++; i++; // Serial.println("SUP"); -// char* newValue = (char*)malloc(sizeof(char) * valueLength + 2); +// char* Value = (char*)malloc(sizeof(char) * valueLength + 2); // memset(newValue, 0, valueLength + 2); // memcpy(newValue, buf - 2, valueLength + 2); // buf += valueLength; i+= valueLength; @@ -363,12 +437,17 @@ class ComplexType: public BER_CONTAINER { break; // primitive case INTEGER: - newObj = new IntegerType(); + newObj = new IntegerType(); break; case STRING: newObj = new OctetType(); break; + case COUNTER32: + //Serial.println("valueType is counter32"); + newObj = new Counter32(); + break; case OID: +// Serial.println("valueType is OID"); newObj = new OIDType(); break; case NULLTYPE: @@ -381,14 +460,17 @@ class ComplexType: public BER_CONTAINER { case TIMESTAMP: newObj = new TimestampType(); break; + } + newObj->fromBuffer(buf - 2); buf += valueLength; i+= valueLength; //newObj->fromBuffer(newValue); // free(newValue); addValueToList(newObj); + } - return true; + return true; } int serialise(unsigned char* buf){ @@ -400,7 +482,7 @@ class ComplexType: public BER_CONTAINER { *lengthPtr = 0; ValuesList* conductor = _values; while(conductor){ -// Serial.print("about to serialise something of type: ");Serial.println(conductor->value->_type, HEX); + //Serial.print("about to serialise something of type: ");Serial.println(conductor->value->_type, HEX); delay(0); int length = conductor->value->serialise(ptr); @@ -425,6 +507,7 @@ class ComplexType: public BER_CONTAINER { } else { *lengthPtr = actualLength; } + delete conductor; return actualLength + 2; } diff --git a/README.md b/README.md index deef3fa..28f3989 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,12 @@ -# Arduino_SNMP -SNMP Agent built with Arduino +# Arduino_SNMP_manager +This adds some SNMP manager functions. Allowing you to send get requests and parse the response. -This is a very rough-around-the-edges SNMP Agent library I created for personal use. -Originally designed on the ESP8266 Arduino Core, it is very Heap-Intensive and is not nice to memory. -Not sure how it will work on basic Arduinos. +This is my first time programing so the code is probably a disaster but it works for the task I needed. -It does let you pass in any UDP Client though, so it theoretically will work in any network environment. +I have only tested it for my use case. + +generate and send get-requests. +parse response formated in int32. + +Other response types like Char and Counter should would but I have not tested any of them. -Pull requests/comments are welcome diff --git a/SNMPGet.h b/SNMPGet.h new file mode 100644 index 0000000..9c04bc5 --- /dev/null +++ b/SNMPGet.h @@ -0,0 +1,175 @@ +#ifndef SNMPGet_h +#define SNMPGet_h + +class SNMPGet { +public: + SNMPGet(const char* community, short version) : _community(community), _version(version) { + if (version == 0) { + version1 = true; + } + if (version == 1) { + version2 = true; + } + }; + short _version; + const char* _community; + IPAddress agentIP; + //OIDType* getOID; + //TimestampCallback* uptimeCallback; + short requestID; + short errorID = 0; + short errorIndex = 0; + + // the setters that need to be configured for each Get. + void addOIDPointer(ValueCallback* callback); + + + ValueCallbacks* callbacks = new ValueCallbacks(); + ValueCallbacks* callbacksCursor = callbacks; + + + UDP* _udp = 0; +/* void setGetOID(OIDType* oid) { + getOID = oid; + } +*/ + void setRequestID(short request) { + requestID = request; + } + + void setIP(IPAddress ip) { + agentIP = ip; + } + + void setUDP(UDP* udp) { + _udp = udp; + } + +/* void setUptimeCallback(TimestampCallback* uptime) { + uptimeCallback = uptime; + } +*/ + + + + ComplexType* packet = 0; + bool build(); + + bool version1 = false; + bool version2 = false; + + bool sendTo(IPAddress ip) { + if (!_udp) { + return false; + } + if (!build()) { + Serial.println("Failed Building packet.."); + delete packet; + return false; + } + unsigned char _packetBuffer[SNMP_PACKET_LENGTH]; + memset(_packetBuffer, 0, SNMP_PACKET_LENGTH); + int length = packet->serialise(_packetBuffer); + delete packet; + _udp->beginPacket(ip, 161); + _udp->write(_packetBuffer, length); + return _udp->endPacket(); + + + } + + void clearOIDList() { // this just removes the list, does not kill the values in the list + callbacksCursor = callbacks; + delete callbacksCursor; + callbacks = new ValueCallbacks(); + callbacksCursor = callbacks; + } + +}; + +bool SNMPGet::build() { + if (packet) { packet = 0; } + packet = new ComplexType(STRUCTURE); + packet->addValueToList(new IntegerType((int)_version)); + packet->addValueToList(new OctetType((char*)_community)); + ComplexType* getPDU; + getPDU = new ComplexType(GetRequestPDU); + + getPDU->addValueToList(new IntegerType(requestID)); + getPDU->addValueToList(new IntegerType(errorID)); + getPDU->addValueToList(new IntegerType(errorIndex)); + ComplexType* varBindList = new ComplexType(STRUCTURE); +/* getPDU->addValueToList(new TimestampType(*(uptimeCallback->value))); + getPDU->addValueToList(new OIDType(getOID->_value)); + getPDU->addValueToList(new NetworkAddress(agentIP)); +*/ + + //getPDU->addValueToList(new TimestampType(*(uptimeCallback->value))); + + + callbacksCursor = callbacks; + if (callbacksCursor->value) { + while (true) { + ComplexType* varBind = new ComplexType(STRUCTURE); + varBind->addValueToList(new OIDType(callbacksCursor->value->OID)); + BER_CONTAINER* value; + //value = new NullType(); + + switch (callbacksCursor->value->type) { + case INTEGER: + { + value = new IntegerType(0);//*((IntegerCallback*)callbacksCursor->value)->value); + + } + break; + case TIMESTAMP: + { + value = new TimestampType(*((TimestampCallback*)callbacksCursor->value)->value); + } + break; + case STRING: + { + value = new OctetType(*((StringCallback*)callbacksCursor->value)->value); + } + case COUNTER32: { + + value = new IntegerType(0); + + } + break; + } + + varBind->addValueToList(value); + varBindList->addValueToList(varBind); + + if (callbacksCursor->next) { + callbacksCursor = callbacksCursor->next; + } + else { + break; + } + } + } + + getPDU->addValueToList(varBindList); + packet->addValueToList(getPDU); + return true; +} + +void SNMPGet::addOIDPointer(ValueCallback* callback) { + callbacksCursor = callbacks; + if (callbacksCursor->value) { + while (callbacksCursor->next != 0) { + callbacksCursor = callbacksCursor->next; + } + callbacksCursor->next = new ValueCallbacks(); + callbacksCursor = callbacksCursor->next; + callbacksCursor->value = callback; + callbacksCursor->next = 0; + } + else + callbacks->value = callback; +} + + +#endif \ No newline at end of file diff --git a/SNMPGetResponse.h b/SNMPGetResponse.h new file mode 100644 index 0000000..33b7a31 --- /dev/null +++ b/SNMPGetResponse.h @@ -0,0 +1,221 @@ +#ifndef SNMPGetResponse_h +#define SNMPGetResponse_h + + +class SNMPGetRespose { + +public: + SNMPGetRespose() {}; + ~SNMPGetRespose() { + delete varBinds; + delete SNMPPacket; + //delete varBindsCursor; + }; + char* communityString; + int version; + ASN_TYPE requestType; + unsigned long requestID; + int errorStatus; + int errorIndex; + VarBindList* varBinds = 0; + VarBindList* varBindsCursor = 0; + + ComplexType* SNMPPacket; + bool parseFrom(unsigned char* buf); + bool serialise(char* buf); + enum SNMPExpect EXPECTING = SNMPVERSION; + bool isCorrupt = false; +}; + +bool SNMPGetRespose::parseFrom(unsigned char* buf) { + + SNMPPacket = new ComplexType(STRUCTURE); + + // confirm that the packet is a STRUCTURE + if (buf[0] != 0x30) { + isCorrupt = true; + return false; + } + + SNMPPacket->fromBuffer(buf); + + if (SNMPPacket->getLength()>30) { + // we now have a full ASN.1 packet in SNMPPacket + ValuesList* cursor = SNMPPacket->_values; + ValuesList* tempCursor; + + + + while (EXPECTING != DONE) { + switch (EXPECTING) { + case SNMPVERSION: + if (cursor->value->_type == INTEGER) { + version = ((IntegerType*)cursor->value)->_value + 1; + + if (!cursor->next) { + isCorrupt = true; + return false; + } + + cursor = cursor->next; + EXPECTING = COMMUNITY; + + } + else { + + isCorrupt = true; + return false; + } + break; + case COMMUNITY: + if (cursor->value->_type == STRING) { + communityString = ((OctetType*)cursor->value)->_value; + + if (!cursor->next) { + isCorrupt = true; + return false; + } + cursor = cursor->next; + EXPECTING = PDU; // temp + } + else { + + isCorrupt = true; + return false; + } + break; + case PDU: + switch (cursor->value->_type) { + case GetRequestPDU: + case GetNextRequestPDU: + case GetResponsePDU: + case SetRequestPDU: + requestType = cursor->value->_type; + break; + default: + + isCorrupt = true; + return false; + break; + } + cursor = ((ComplexType*)cursor->value)->_values; + EXPECTING = REQUESTID; + break; + case REQUESTID: + if (cursor->value->_type == INTEGER) { + requestID = ((IntegerType*)cursor->value)->_value; + if (!cursor->next) { + isCorrupt = true; + return false; + } + cursor = cursor->next; + EXPECTING = ERRORSTATUS; + } + else { + + isCorrupt = true; + return false; + } + break; + case ERRORSTATUS: + if (cursor->value->_type == INTEGER) { + errorStatus = ((IntegerType*)cursor->value)->_value; + if (!cursor->next) { + isCorrupt = true; + return false; + } + + cursor = cursor->next; + EXPECTING = ERRORID; + } + else { + + isCorrupt = true; + return false; + } + break; + case ERRORID: + if (cursor->value->_type == INTEGER) { + errorIndex = ((IntegerType*)cursor->value)->_value; + if (!cursor->next) { + isCorrupt = true; + return false; + } + + cursor = cursor->next; + EXPECTING = VARBINDS; + } + else { + + isCorrupt = true; + return false; + } + break; + case VARBINDS: // we have a varbind structure, lets dive into it. + if (cursor->value->_type == STRUCTURE) { + + + varBinds = new VarBindList(); + + varBindsCursor = varBinds; + + tempCursor = ((ComplexType*)cursor->value)->_values; + + EXPECTING = VARBIND; + } + else { + + isCorrupt = true; + return false; + } + break; + case VARBIND: + // we need to keep the cursor outside the varbindlist itself so we always have access to the list + if (tempCursor->value->_type == STRUCTURE && ((ComplexType*)tempCursor->value)->_values->value->_type == OID) { + + VarBind* varbind = new VarBind(); + + varbind->oid = ((OIDType*)((ComplexType*)tempCursor->value)->_values->value); + + //Serial.print("OID: "); Serial.println(varbind->oid->_value); + varbind->type = ((ComplexType*)tempCursor->value)->_values->next->value->_type; + + varbind->value = ((ComplexType*)tempCursor->value)->_values->next->value; + + varBindsCursor->value = varbind; + + varBindsCursor->next = new VarBindList(); + + if (!tempCursor->next) { + + EXPECTING = DONE; + } + else { + // tempCursor = ((ComplexType*)cursor->next->value)->_values; + + tempCursor = tempCursor->next; + varBindsCursor = varBindsCursor->next; + } + } + else { + + isCorrupt = true; + return false; + } + + break; + } + } + //Serial.print("Free Heap Size SNMPRequest::parseFrom: "); + //Serial.println(xPortGetFreeHeapSize()); + + return true; + } + else { + Serial.println("packet short"); + return false; + + } +} + +#endif diff --git a/SNMPRequest.h b/SNMPRequest.h index 5952c8a..356b22f 100644 --- a/SNMPRequest.h +++ b/SNMPRequest.h @@ -40,20 +40,27 @@ class SNMPRequest { bool SNMPRequest::parseFrom(unsigned char* buf){ SNMPPacket = new ComplexType(STRUCTURE); + + // confirm that the packet is a STRUCTURE if(buf[0] != 0x30) { isCorrupt = true; return false; } + SNMPPacket->fromBuffer(buf); + + // we now have a full ASN.1 packet in SNMPPacket ValuesList* cursor = SNMPPacket->_values; ValuesList* tempCursor; + while(EXPECTING != DONE){ switch(EXPECTING){ case SNMPVERSION: if(cursor->value->_type == INTEGER){ version = ((IntegerType*)cursor->value)->_value + 1; + if(!cursor->next){ isCorrupt = true; return false; @@ -68,6 +75,7 @@ bool SNMPRequest::parseFrom(unsigned char* buf){ case COMMUNITY: if(cursor->value->_type == STRING){ communityString = ((OctetType*)cursor->value)->_value; + if(!cursor->next){ isCorrupt = true; return false; @@ -93,6 +101,8 @@ bool SNMPRequest::parseFrom(unsigned char* buf){ break; } cursor = ((ComplexType*)cursor->value)->_values; + //Serial.print("PDU: "); + //Serial.println(cursor); EXPECTING = REQUESTID; break; case REQUESTID: @@ -170,9 +180,12 @@ bool SNMPRequest::parseFrom(unsigned char* buf){ isCorrupt = true; return false; } + break; } } + //Serial.print("Free Heap Size SNMPRequest::parseFrom: "); + //Serial.println(xPortGetFreeHeapSize()); return true; } diff --git a/SNMPTrap.h b/SNMPTrap.h index d4d1a1b..b2f5fae 100644 --- a/SNMPTrap.h +++ b/SNMPTrap.h @@ -44,14 +44,15 @@ class SNMPTrap { } void addOIDPointer(ValueCallback* callback); - - + + ValueCallbacks* callbacks = new ValueCallbacks(); ValueCallbacks* callbacksCursor = callbacks; UDP* _udp = 0; bool sendTo(IPAddress ip){ + //Serial.println("Trying to Send Packet"); if(!_udp){ return false; } diff --git a/VarBinds.h b/VarBinds.h index 53e5d6c..a0fe2f4 100644 --- a/VarBinds.h +++ b/VarBinds.h @@ -3,8 +3,14 @@ typedef struct VarBindStruct { ~VarBindStruct(){ -// if(value) delete value; -// if(oid) delete oid; + // if (value) { + // delete value; + // + // } + // if (oid) { + // delete oid; + // + // } }; OIDType* oid = 0; ASN_TYPE type; From 55efeab194d4f5005f7d8d1f7df324b57dc113e0 Mon Sep 17 00:00:00 2001 From: Nicholas Boone Date: Sun, 20 May 2018 13:25:48 +0100 Subject: [PATCH 2/3] Example of Get-request This example show how to use the get functions to request information from another device. The OID's will probably need to be replaced to work with your device. --- examples/ESP_SNMP/SNMP_Get_Example.ino | 102 +++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 examples/ESP_SNMP/SNMP_Get_Example.ino diff --git a/examples/ESP_SNMP/SNMP_Get_Example.ino b/examples/ESP_SNMP/SNMP_Get_Example.ino new file mode 100644 index 0000000..2e78c20 --- /dev/null +++ b/examples/ESP_SNMP/SNMP_Get_Example.ino @@ -0,0 +1,102 @@ +#include +#include +#include + +//************************************ +//* update this with your WiFi info * +//************************************ +const char* ssid = "networkName"; +const char* password = "P@ssword"; +//************************************ + +unsigned int byteUp = 0; //value in octets (we are counting them as bytes) +unsigned int byteDown = 0; +unsigned long timeLast = 0; +int timeDelay = 2000; // delay in milliseconds + +// initialise objects needed for SNMP +WiFiUDP udp; // UDP object used to send and recieve packets + +SNMPAgent snmp = SNMPAgent("public"); // Starts an SMMPAgent instance with the community string 'public' +SNMPGet GetRequestUp = SNMPGet("public", 0); // Starts an SMMPGet instance with the community string 'public' +SNMPGet GetRequestDown = SNMPGet("public", 0); // Starts an SMMPGet instance with the community string 'public' +ValueCallback* callbackDownLoad;//blank callback pointer. every OID that you want to send a Get-request for needs one +ValueCallback* callbackUpLoad; + +IPAddress netAdd = IPAddress(192,168,1,1); // IP address object of the device you want to get info from + +void setup() +{ + // put your setup code here, to run once: + Serial.begin(115200); + WiFi.begin(ssid, password); + Serial.println(""); + // Wait for connection + while (WiFi.status() != WL_CONNECTED) + { + delay(500); + Serial.print("."); + } + Serial.println(""); + Serial.print("Connected to "); + Serial.println(ssid); + Serial.print("my IP address: "); + Serial.println(WiFi.localIP()); + + snmp.setUDP(&udp);// give snmp a pointer to the UDP object + snmp.begin();// start the SNMP listener + snmp.beginMaster(); // start the SNMP sender + + // OID for download + snmp.addIntegerHandler(".1.3.6.1.2.1.2.2.1.16.3", &byteUp, true); + + // OID for upload + snmp.addIntegerHandler(".1.3.6.1.2.1.2.2.1.10.3", &byteDown, true); + + //Create the call back ID's you will need to pass to the SNMP function + callbackDownLoad = snmp.findCallback(".1.3.6.1.2.1.2.2.1.16.3", false); + callbackUpLoad = snmp.findCallback(".1.3.6.1.2.1.2.2.1.10.3", false); + +} + +void loop() { + // put your main code here, to run repeatedly: + snmp.loop(); + getSNMP(); +} + +void getSNMP(){ + //check to see if it is time to send an SNMP request. + //if you send requests to often it seens to cause some issues + if((timeLast + timeDelay) <= millis()){ + + //see the results of the get-request in the serial monitor + Serial.print("byte Up: "); + Serial.print(byteUp); + Serial.println(); + Serial.print("byte Down: "); + Serial.print(byteDown); + Serial.println(); + Serial.println("----------------------"); + + //build a SNMP get-request + GetRequestDown.addOIDPointer(callbackDownLoad); + GetRequestDown.setIP(WiFi.localIP()); //IP of the arduino + GetRequestDown.setUDP(&udp); + GetRequestDown.setRequestID(rand() % 5555); + GetRequestDown.sendTo(netAdd); //IP of the remote client + GetRequestDown.clearOIDList(); + snmp.resetSetOccurred(); + + GetRequestUp.addOIDPointer(callbackUpLoad); + GetRequestUp.setIP(WiFi.localIP()); + GetRequestUp.setUDP(&udp); + GetRequestUp.setRequestID(rand() % 5555); + GetRequestUp.sendTo(netAdd); + GetRequestUp.clearOIDList(); + snmp.resetSetOccurred(); + + timeLast = millis(); + } + +} From 3725152f25ba0359a471ce7b09a7c33d132ca5c7 Mon Sep 17 00:00:00 2001 From: Niich <38820650+Niich@users.noreply.github.com> Date: Fri, 14 Jun 2019 00:15:57 +0100 Subject: [PATCH 3/3] Updated example for SNMP Strings --- Arduino_SNMP.h | 2 +- examples/ESP_SNMP/SNMP_Get_Example.ino | 21 ++++++++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/Arduino_SNMP.h b/Arduino_SNMP.h index 013c748..e257a99 100644 --- a/Arduino_SNMP.h +++ b/Arduino_SNMP.h @@ -182,7 +182,7 @@ bool inline SNMPAgent::receivePacket(int packetLength) { memcpy(*((StringCallback*)callback)->value, String(((OctetType*)snmpgetresponse->varBindsCursor->value->value)->_value).c_str(), 25);// FIXME: this is VERY dangerous, i'm assuming the length of the source char*, this needs to change. for some reason strncpy didnd't work, need to look into this. the '25' also needs to be defined somewhere so this won't break; *(*((StringCallback*)callback)->value + 24) = 0x0; // close off the dest string, temporary OctetType* value = new OctetType(*((StringCallback*)callback)->value); - Serial.print("STR value: "); + //Serial.print("STR value: "); // Serial.println(value); delete value; setOccurred = true; diff --git a/examples/ESP_SNMP/SNMP_Get_Example.ino b/examples/ESP_SNMP/SNMP_Get_Example.ino index 2e78c20..11384c9 100644 --- a/examples/ESP_SNMP/SNMP_Get_Example.ino +++ b/examples/ESP_SNMP/SNMP_Get_Example.ino @@ -12,6 +12,8 @@ const char* password = "P@ssword"; unsigned int byteUp = 0; //value in octets (we are counting them as bytes) unsigned int byteDown = 0; unsigned long timeLast = 0; +char string[25]; //string we will use to store the result of the request. Set it to a lenght at least as long and the result of your SNMP get request +char * chars = string; //char pointer used to referance the string int timeDelay = 2000; // delay in milliseconds // initialise objects needed for SNMP @@ -19,9 +21,11 @@ WiFiUDP udp; // UDP object used to send and recieve packets SNMPAgent snmp = SNMPAgent("public"); // Starts an SMMPAgent instance with the community string 'public' SNMPGet GetRequestUp = SNMPGet("public", 0); // Starts an SMMPGet instance with the community string 'public' -SNMPGet GetRequestDown = SNMPGet("public", 0); // Starts an SMMPGet instance with the community string 'public' +SNMPGet GetRequestDown = SNMPGet("public", 0); +SNMPGet GetRequestString = SNMPGet("public", 0); ValueCallback* callbackDownLoad;//blank callback pointer. every OID that you want to send a Get-request for needs one ValueCallback* callbackUpLoad; +ValueCallback* callbackString; IPAddress netAdd = IPAddress(192,168,1,1); // IP address object of the device you want to get info from @@ -53,9 +57,13 @@ void setup() // OID for upload snmp.addIntegerHandler(".1.3.6.1.2.1.2.2.1.10.3", &byteDown, true); + // OID for string + snmp.addStringHandler(".1.3.6.1.2.1.31.1.1.1.18.3", &chars, true); + //Create the call back ID's you will need to pass to the SNMP function callbackDownLoad = snmp.findCallback(".1.3.6.1.2.1.2.2.1.16.3", false); callbackUpLoad = snmp.findCallback(".1.3.6.1.2.1.2.2.1.10.3", false); + callbackString = snmp.findCallback(".1.3.6.1.2.1.31.1.1.1.18.3", false); } @@ -77,6 +85,9 @@ void getSNMP(){ Serial.print("byte Down: "); Serial.print(byteDown); Serial.println(); + Serial.print("String is: "); + Serial.print(string); + Serial.println(); Serial.println("----------------------"); //build a SNMP get-request @@ -95,6 +106,14 @@ void getSNMP(){ GetRequestUp.sendTo(netAdd); GetRequestUp.clearOIDList(); snmp.resetSetOccurred(); + + GetRequestString.addOIDPointer(callbackString); + GetRequestString.setIP(WiFi.localIP()); + GetRequestString.setUDP(&udp); + GetRequestString.setRequestID(rand() % 5555); + GetRequestString.sendTo(netAdd); + GetRequestString.clearOIDList(); + snmp.resetSetOccurred(); timeLast = millis(); }