SNMP Agent http://mbed.org/users/okini3939/notebook/agentbed-library/
Dependents: WeatherPlatform_20110408 WeatherPlatform WeatherStation
Agentbed.cpp
- Committer:
- okini3939
- Date:
- 2011-01-28
- Revision:
- 2:9e4369522e03
- Parent:
- 0:bb21da73024a
File content as of revision 2:9e4369522e03:
/* Agentbed library Modified for mbed, 2010 Suga. Agentuino.cpp - An Arduino library for a lightweight SNMP Agent. Copyright (C) 2010 Eric C. Gionet <lavco_eg@hotmail.com> All rights reserved. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ // // sketch_aug23a // #include "Agentbed.h" SNMP_API_STAT_CODES AgentbedClass::begin(EthernetNetIf *eth) { // set community names _getCommName = "public"; _setCommName = "private"; // // set community name set/get sizes _setSize = strlen(_setCommName); _getSize = strlen(_getCommName); // // init UDP socket udpsock = new UDPSocket; udpsock->setOnEvent(this, &AgentbedClass::listen); udpsock->bind(Host(eth->getIp(), SNMP_DEFAULT_PORT)); // return SNMP_API_STAT_SUCCESS; } SNMP_API_STAT_CODES AgentbedClass::begin(char *getCommName, char *setCommName, uint16_t port, EthernetNetIf *eth) { // set community name set/get sizes _setSize = strlen(setCommName); _getSize = strlen(getCommName); // // validate get/set community name sizes if ( _setSize > SNMP_MAX_NAME_LEN + 1 || _getSize > SNMP_MAX_NAME_LEN + 1 ) { return SNMP_API_STAT_NAME_TOO_BIG; } // // set community names _getCommName = getCommName; _setCommName = setCommName; // // validate session port number if ( port == NULL || port == 0 ) port = SNMP_DEFAULT_PORT; // // init UDP socket udpsock = new UDPSocket; udpsock->setOnEvent(this, &AgentbedClass::listen); udpsock->bind(Host(eth->getIp(), port)); // return SNMP_API_STAT_SUCCESS; } void AgentbedClass::listen (UDPSocketEvent e) { // if bytes available in receive buffer // and pointer to a function (delegate function) // isn't null, trigger the function if (e == UDPSOCKET_READABLE && _callback != NULL ) { (*_callback)(); } } SNMP_API_STAT_CODES AgentbedClass::requestPdu(SNMP_PDU *pdu) { char *community; // sequence length byte __attribute__((__unused__)) seqLen; // version byte verLen, verEnd; // community string byte comLen, comEnd; // pdu byte __attribute__((__unused__)) pduTyp, pduLen; byte ridLen, ridEnd; byte errLen, errEnd; byte eriLen, eriEnd; byte __attribute__((__unused__)) vblTyp, vblLen; byte __attribute__((__unused__)) vbiTyp, vbiLen; byte obiLen, obiEnd; byte __attribute__((__unused__)) valTyp, valLen, valEnd; byte i; Host dest; // // set packet packet size (skip UDP header) // _packetSize = Udp.available()-8; // memset(_packet, 0, SNMP_MAX_PACKET_LEN); // // get UDP packet _packetSize = udpsock->recvfrom((char*)_packet, SNMP_MAX_PACKET_LEN, &_dst); // // validate packet if ( _packetSize != 0 && _packetSize > SNMP_MAX_PACKET_LEN ) { // //SNMP_FREE(_packet); return SNMP_API_STAT_PACKET_TOO_BIG; } // // allocate byte array based on packet size //if ( (_packet = (byte *)malloc(sizeof(byte)*_packetSize)) == NULL ) { // //SNMP_FREE(_packet); // return SNMP_API_STAT_MALLOC_ERR; //} // // packet check 1 if ( _packet[0] != 0x30 ) { // //SNMP_FREE(_packet); return SNMP_API_STAT_PACKET_INVALID; } // // sequence length seqLen = _packet[1]; // version verLen = _packet[3]; verEnd = 3 + verLen; // community string comLen = _packet[verEnd + 2]; comEnd = verEnd + 2 + comLen; // pdu pduTyp = _packet[comEnd + 1]; pduLen = _packet[comEnd + 2]; ridLen = _packet[comEnd + 4]; ridEnd = comEnd + 4 + ridLen; errLen = _packet[ridEnd + 2]; errEnd = ridEnd + 2 + errLen; eriLen = _packet[errEnd + 2]; eriEnd = errEnd + 2 + eriLen; vblTyp = _packet[eriEnd + 1]; vblLen = _packet[eriEnd + 2]; vbiTyp = _packet[eriEnd + 3]; vbiLen = _packet[eriEnd + 4]; obiLen = _packet[eriEnd + 6]; obiEnd = eriEnd + obiLen + 6; valTyp = _packet[obiEnd + 1]; valLen = _packet[obiEnd + 2]; valEnd = obiEnd + 2 + valLen; // // extract version pdu->version = 0; for ( i = 0; i < verLen; i++ ) { pdu->version = (pdu->version << 8) | _packet[5 + i]; } // // pdu-type pdu->type = (SNMP_PDU_TYPES)pduTyp; _dstType = pdu->type; // // validate community size if ( comLen > SNMP_MAX_NAME_LEN ) { // set pdu error pdu->error = SNMP_ERR_TOO_BIG; // //SNMP_FREE(_packet); return SNMP_API_STAT_NAME_TOO_BIG; } // // extract and compare community name // allocate char array based on community size if ( (community = (char *)malloc(sizeof(char)*comLen)) == NULL ) { // //SNMP_FREE(_packet); return SNMP_API_STAT_MALLOC_ERR; } // for ( i = 0; i < comLen; i++ ) { community[i] = _packet[verEnd + 3 + i]; } // terminate as a string community[comLen] = '\0'; // // validate community name if ( pdu->type == SNMP_PDU_SET ) { if ( strcmp(_setCommName, community) != 0 ) // set pdu error pdu->error = SNMP_ERR_NO_SUCH_NAME; } else { if ( strcmp(_getCommName, community) != 0 ) // set pdu error pdu->error = SNMP_ERR_NO_SUCH_NAME; } // // free community buffer SNMP_FREE(community); // // extract reqiest-id 0x00 0x00 0x00 0x01 (4-byte int aka int32) pdu->requestId = 0; for ( i = 0; i < ridLen; i++ ) { pdu->requestId = (pdu->requestId << 8) | _packet[comEnd + 5 + i]; } // // extract error pdu->error = SNMP_ERR_NO_ERROR; int32_t err = 0; for ( i = 0; i < errLen; i++ ) { err = (err << 8) | _packet[ridEnd + 3 + i]; } pdu->error = (SNMP_ERR_CODES)err; // // extract error-index pdu->errorIndex = 0; for ( i = 0; i < eriLen; i++ ) { pdu->errorIndex = (pdu->errorIndex << 8) | _packet[errEnd + 3 + i]; } // // // validate object-identifier size if ( obiLen > SNMP_MAX_OID_LEN ) { // set pdu error pdu->error = SNMP_ERR_TOO_BIG; // //SNMP_FREE(_packet); return SNMP_API_STAT_OID_TOO_BIG; } // // extract and contruct object-identifier /* if ( (pdu->OID.oid = (byte *)malloc(sizeof(byte)*obiLen)) == NULL ) { // free DPU receive buffer _socket.readSkip(_socket.available()); // SNMP_FREE(_packet); return SNMP_API_STAT_MALLOC_ERR; } */ memset(pdu->OID.data, 0, SNMP_MAX_OID_LEN); pdu->OID.size = obiLen; for ( i = 0; i < obiLen; i++ ) { pdu->OID.data[i] = _packet[eriEnd + 7 + i]; } // // value-type pdu->VALUE.syntax = (SNMP_SYNTAXES)valTyp; // // validate value size if ( obiLen > SNMP_MAX_VALUE_LEN ) { // set pdu error pdu->error = SNMP_ERR_TOO_BIG; // //SNMP_FREE(_packet); return SNMP_API_STAT_VALUE_TOO_BIG; } // // value-size pdu->VALUE.size = valLen; // // extract value // allocate char array based on oid size /* if( (pdu->VALUE.value = (byte *)malloc(sizeof(byte)*valLen)) == NULL ) { // free DPU receive buffer _socket.readSkip(_socket.available()); // SNMP_FREE(_packet); return SNMP_API_STAT_MALLOC_ERR; } */ memset(pdu->VALUE.data, 0, SNMP_MAX_VALUE_LEN); for ( i = 0; i < valLen; i++ ) { pdu->VALUE.data[i] = _packet[obiEnd + 3 + i]; } // //SNMP_FREE(_packet); // return SNMP_API_STAT_SUCCESS; } SNMP_API_STAT_CODES AgentbedClass::responsePdu(SNMP_PDU *pdu) { int32_u u; byte i; // // Length of entire SNMP packet _packetPos = 0; // 23 _packetSize = 25 - 1 + sizeof(pdu->requestId) + sizeof(pdu->error) + sizeof(pdu->errorIndex) + pdu->OID.size + pdu->VALUE.size; // memset(_packet, 0, SNMP_MAX_PACKET_LEN); // if ( _dstType == SNMP_PDU_SET ) { _packetSize += _setSize; } else { _packetSize += _getSize; } // // allocate byte array based on packet size //if ( (_packet = (byte *)malloc(sizeof(byte)*_packetSize)) == NULL ) { // //SNMP_FREE(_packet); // return SNMP_API_STAT_MALLOC_ERR; //} // _packet[_packetPos++] = (byte)SNMP_SYNTAX_SEQUENCE; // type _packet[_packetPos++] = (byte)_packetSize; // length // // SNMP version _packet[_packetPos++] = (byte)SNMP_SYNTAX_INT; // type _packet[_packetPos++] = 0x01; // length _packet[_packetPos++] = 0x00; // value // // SNMP community string _packet[_packetPos++] = (byte)SNMP_SYNTAX_OCTETS; // type if ( _dstType == SNMP_PDU_SET ) { _packet[_packetPos++] = (byte)_setSize; // length for ( i = 0; i < _setSize; i++ ) { _packet[_packetPos++] = (byte)_setCommName[i]; } } else { _packet[_packetPos++] = (byte)_getSize; // length for ( i = 0; i < _getSize; i++ ) { _packet[_packetPos++] = (byte)_getCommName[i]; } } // // SNMP PDU _packet[_packetPos++] = (byte)pdu->type; _packet[_packetPos++] = (byte)( sizeof(pdu->requestId) + sizeof((int32_t)pdu->error) + sizeof(pdu->errorIndex) + pdu->OID.size + pdu->VALUE.size + 14 ); // // Request ID (size always 4 e.g. 4-byte int) _packet[_packetPos++] = (byte)SNMP_SYNTAX_INT; // type _packet[_packetPos++] = (byte)sizeof(pdu->requestId); u.int32 = pdu->requestId; _packet[_packetPos++] = u.data[3]; _packet[_packetPos++] = u.data[2]; _packet[_packetPos++] = u.data[1]; _packet[_packetPos++] = u.data[0]; // // Error (size always 4 e.g. 4-byte int) _packet[_packetPos++] = (byte)SNMP_SYNTAX_INT; // type _packet[_packetPos++] = (byte)sizeof((int32_t)pdu->error); u.int32 = pdu->error; _packet[_packetPos++] = u.data[3]; _packet[_packetPos++] = u.data[2]; _packet[_packetPos++] = u.data[1]; _packet[_packetPos++] = u.data[0]; // // Error Index (size always 4 e.g. 4-byte int) _packet[_packetPos++] = (byte)SNMP_SYNTAX_INT; // type _packet[_packetPos++] = (byte)sizeof(pdu->errorIndex); u.int32 = pdu->errorIndex; _packet[_packetPos++] = u.data[3]; _packet[_packetPos++] = u.data[2]; _packet[_packetPos++] = u.data[1]; _packet[_packetPos++] = u.data[0]; // // Varbind List _packet[_packetPos++] = (byte)SNMP_SYNTAX_SEQUENCE; // type _packet[_packetPos++] = (byte)( pdu->OID.size + pdu->VALUE.size + 6 ); //4 // // Varbind _packet[_packetPos++] = (byte)SNMP_SYNTAX_SEQUENCE; // type _packet[_packetPos++] = (byte)( pdu->OID.size + pdu->VALUE.size + 4 ); //2 // // ObjectIdentifier _packet[_packetPos++] = (byte)SNMP_SYNTAX_OID; // type _packet[_packetPos++] = (byte)(pdu->OID.size); for ( i = 0; i < pdu->OID.size; i++ ) { _packet[_packetPos++] = pdu->OID.data[i]; } // // Value _packet[_packetPos++] = (byte)pdu->VALUE.syntax; // type _packet[_packetPos++] = (byte)(pdu->VALUE.size); for ( i = 0; i < pdu->VALUE.size; i++ ) { _packet[_packetPos++] = pdu->VALUE.data[i]; } // udpsock->sendto((char*)_packet, _packetPos, &_dst); // //SNMP_FREE(_packet); // return SNMP_API_STAT_SUCCESS; } void AgentbedClass::onPduReceive(onPduReceiveCallback pduReceived) { _callback = pduReceived; } void AgentbedClass::freePdu(SNMP_PDU *pdu) { //SNMP_FREE(pdu->OID.oid); //SNMP_FREE(pdu->VALUE.value); memset(pdu->OID.data, 0, SNMP_MAX_OID_LEN); memset(pdu->VALUE.data, 0, SNMP_MAX_VALUE_LEN); //free((char *) pdu); } // Create one global object //AgentbedClass Agentbed;