fork allowing use of the latest official mbed networking library

Dependents:   SNMPv1UDPExmaple

Fork of Agentbed by Suga koubou

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Agentbed.cpp Source File

Agentbed.cpp

00001 /*
00002   Agentbed library
00003   Modified for mbed, 2010 Suga.
00004  
00005  
00006   Agentuino.cpp - An Arduino library for a lightweight SNMP Agent.
00007   Copyright (C) 2010 Eric C. Gionet <lavco_eg@hotmail.com>
00008   All rights reserved.
00009 
00010   This library is free software; you can redistribute it and/or
00011   modify it under the terms of the GNU Lesser General Public
00012   License as published by the Free Software Foundation; either
00013   version 2.1 of the License, or (at your option) any later version.
00014 
00015   This library is distributed in the hope that it will be useful,
00016   but WITHOUT ANY WARRANTY; without even the implied warranty of
00017   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018   Lesser General Public License for more details.
00019 
00020   You should have received a copy of the GNU Lesser General Public
00021   License along with this library; if not, write to the Free Software
00022   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00023 */
00024 
00025 //
00026 // sketch_aug23a
00027 //
00028 
00029 #include "Agentbed.h"
00030 
00031 SNMP_API_STAT_CODES SNMP::init()
00032 {
00033     // set community names
00034     _getCommName = "public";
00035     _setCommName = "private";
00036     //
00037     // set community name set/get sizes
00038     _setSize = strlen(_setCommName);
00039     _getSize = strlen(_getCommName);
00040     //
00041     return SNMP_API_STAT_SUCCESS;
00042 }
00043 
00044 SNMP_API_STAT_CODES SNMP::init(char *getCommName, char *setCommName)
00045 {
00046     // set community name set/get sizes
00047     _setSize = strlen(setCommName);
00048     _getSize = strlen(getCommName);
00049     //
00050     // validate get/set community name sizes
00051     if ( _setSize > SNMP_MAX_NAME_LEN + 1 || _getSize > SNMP_MAX_NAME_LEN + 1 ) {
00052         return SNMP_API_STAT_NAME_TOO_BIG;
00053     }
00054     //
00055     // set community names
00056     _getCommName = getCommName;
00057     _setCommName = setCommName;
00058     //
00059     
00060     return SNMP_API_STAT_SUCCESS;
00061 }
00062 
00063 SNMP_API_STAT_CODES SNMP::toPdu(SNMP_PDU *pdu,char *_packet,uint16_t _packetSize)
00064 {
00065     char *community;
00066     // sequence length
00067     byte __attribute__((__unused__)) seqLen;
00068     // version
00069     byte verLen, verEnd;
00070     // community string
00071     byte comLen, comEnd;
00072     // pdu
00073     byte __attribute__((__unused__)) pduTyp, pduLen;
00074     byte ridLen, ridEnd;
00075     byte errLen, errEnd;
00076     byte eriLen, eriEnd;
00077     byte __attribute__((__unused__)) vblTyp, vblLen;
00078     byte __attribute__((__unused__)) vbiTyp, vbiLen;
00079     byte obiLen, obiEnd;
00080     byte __attribute__((__unused__)) valTyp, valLen, valEnd;
00081     byte i;
00082     //
00083     // set packet packet size (skip UDP header)
00084 //    _packetSize = Udp.available()-8;
00085     //
00086  //   memset(_packet, 0, SNMP_MAX_PACKET_LEN);
00087     //
00088     // get UDP packet
00089  ///  _packetSize = udpsock->recvfrom((char*)_packet, SNMP_MAX_PACKET_LEN, &_dst);
00090     //
00091     // validate packet
00092     if ( _packetSize != 0 && _packetSize > SNMP_MAX_PACKET_LEN ) {
00093         //
00094         //SNMP_FREE(_packet);
00095 
00096         return SNMP_API_STAT_PACKET_TOO_BIG;
00097     }
00098     //
00099     // allocate byte array based on packet size
00100     //if ( (_packet = (byte *)malloc(sizeof(byte)*_packetSize)) == NULL ) {
00101         //
00102         //SNMP_FREE(_packet);
00103 
00104     //    return SNMP_API_STAT_MALLOC_ERR;
00105     //}
00106     //
00107     // packet check 1
00108     if ( _packet[0] != 0x30 ) {
00109         //
00110         //SNMP_FREE(_packet);
00111 
00112         return SNMP_API_STAT_PACKET_INVALID;
00113     }
00114     //
00115     // sequence length
00116     seqLen = _packet[1];
00117     // version
00118     verLen = _packet[3];
00119     verEnd = 3 + verLen;
00120     // community string
00121     comLen = _packet[verEnd + 2];
00122     comEnd = verEnd + 2 + comLen;
00123     // pdu
00124     pduTyp = _packet[comEnd + 1];
00125     pduLen = _packet[comEnd + 2];
00126     ridLen = _packet[comEnd + 4];
00127     ridEnd = comEnd + 4 + ridLen;
00128     errLen = _packet[ridEnd + 2];
00129     errEnd = ridEnd + 2 + errLen;
00130     eriLen = _packet[errEnd + 2];
00131     eriEnd = errEnd + 2 + eriLen;
00132     vblTyp = _packet[eriEnd + 1];
00133     vblLen = _packet[eriEnd + 2];
00134     vbiTyp = _packet[eriEnd + 3];
00135     vbiLen = _packet[eriEnd + 4];
00136     obiLen = _packet[eriEnd + 6];
00137     obiEnd = eriEnd + obiLen + 6;
00138     valTyp = _packet[obiEnd + 1];
00139     valLen = _packet[obiEnd + 2];
00140     valEnd = obiEnd + 2 + valLen;
00141     //
00142     // extract version
00143     pdu->version = 0;
00144     for ( i = 0; i < verLen; i++ ) {
00145         pdu->version = (pdu->version << 8) | _packet[5 + i];
00146     }
00147     //
00148     // pdu-type
00149     pdu->type = (SNMP_PDU_TYPES)pduTyp;
00150     _dstType = pdu->type;
00151     //
00152     // validate community size
00153     if ( comLen > SNMP_MAX_NAME_LEN ) {
00154         // set pdu error
00155         pdu->error = SNMP_ERR_TOO_BIG;
00156         //
00157         //SNMP_FREE(_packet);
00158 
00159         return SNMP_API_STAT_NAME_TOO_BIG;
00160     }
00161     //
00162     // extract and compare community name
00163     // allocate char array based on community size
00164     if ( (community = (char *)malloc(sizeof(char)*comLen)) == NULL ) {
00165         //
00166         //SNMP_FREE(_packet);
00167 
00168         return SNMP_API_STAT_MALLOC_ERR;
00169     }
00170     //
00171     for ( i = 0; i < comLen; i++ ) {
00172         community[i] = _packet[verEnd + 3 + i];
00173     }
00174     // terminate as a string
00175     community[comLen] = '\0';
00176     //
00177     // validate community name
00178     if ( pdu->type == SNMP_PDU_SET ) {
00179         if ( strcmp(_setCommName, community) != 0 )
00180             // set pdu error
00181             pdu->error = SNMP_ERR_NO_SUCH_NAME;
00182     } else {
00183         if ( strcmp(_getCommName, community) != 0 )
00184             // set pdu error
00185             pdu->error = SNMP_ERR_NO_SUCH_NAME;
00186     }
00187     //
00188     // free community buffer
00189     SNMP_FREE(community);
00190     //
00191     // extract reqiest-id 0x00 0x00 0x00 0x01 (4-byte int aka int32)
00192     pdu->requestId = 0;
00193     for ( i = 0; i < ridLen; i++ ) {
00194         pdu->requestId = (pdu->requestId << 8) | _packet[comEnd + 5 + i];
00195     }
00196     //
00197     // extract error 
00198     pdu->error = SNMP_ERR_NO_ERROR;
00199     int32_t err = 0;
00200     for ( i = 0; i < errLen; i++ ) {
00201         err = (err << 8) | _packet[ridEnd + 3 + i];
00202     }
00203     pdu->error = (SNMP_ERR_CODES)err;
00204     //
00205     // extract error-index 
00206     pdu->errorIndex = 0;
00207     for ( i = 0; i < eriLen; i++ ) {
00208         pdu->errorIndex = (pdu->errorIndex << 8) | _packet[errEnd + 3 + i];
00209     }
00210     //
00211     //
00212     // validate object-identifier size
00213     if ( obiLen > SNMP_MAX_OID_LEN ) {
00214         // set pdu error
00215         pdu->error = SNMP_ERR_TOO_BIG;
00216         //
00217         //SNMP_FREE(_packet);
00218 
00219         return SNMP_API_STAT_OID_TOO_BIG;
00220     }
00221     //
00222     // extract and contruct object-identifier
00223     /*
00224     if ( (pdu->OID.oid = (byte *)malloc(sizeof(byte)*obiLen)) == NULL ) {
00225         // free DPU receive buffer
00226         _socket.readSkip(_socket.available());
00227         //
00228         SNMP_FREE(_packet);
00229 
00230         return SNMP_API_STAT_MALLOC_ERR;
00231     }
00232     */
00233     memset(pdu->OID.data, 0, SNMP_MAX_OID_LEN);
00234     pdu->OID.size = obiLen;
00235     for ( i = 0; i < obiLen; i++ ) {
00236         pdu->OID.data[i] = _packet[eriEnd + 7 + i];
00237     }
00238     //
00239     // value-type
00240     pdu->VALUE.syntax = (SNMP_SYNTAXES)valTyp;
00241     //
00242     // validate value size
00243     if ( obiLen > SNMP_MAX_VALUE_LEN ) {
00244         // set pdu error
00245         pdu->error = SNMP_ERR_TOO_BIG;
00246         //
00247         //SNMP_FREE(_packet);
00248 
00249         return SNMP_API_STAT_VALUE_TOO_BIG;
00250     }
00251     //
00252     // value-size
00253     pdu->VALUE.size = valLen;
00254     //
00255     // extract value
00256     // allocate char array based on oid size
00257     /*
00258     if( (pdu->VALUE.value = (byte *)malloc(sizeof(byte)*valLen)) == NULL ) {
00259         // free DPU receive buffer
00260         _socket.readSkip(_socket.available());
00261         //
00262         SNMP_FREE(_packet);
00263 
00264         return SNMP_API_STAT_MALLOC_ERR;
00265     }
00266     */
00267     memset(pdu->VALUE.data, 0, SNMP_MAX_VALUE_LEN);
00268     for ( i = 0; i < valLen; i++ ) {
00269         pdu->VALUE.data[i] = _packet[obiEnd + 3 + i];
00270     }
00271     //
00272     //SNMP_FREE(_packet);
00273     //
00274     return SNMP_API_STAT_SUCCESS;
00275 }
00276 
00277 uint16_t SNMP::fromPdu(SNMP_PDU *pdu,char *_packet)
00278 {
00279     int32_u u;
00280     uint16_t _packetSize;
00281     byte i;
00282     //
00283     // Length of entire SNMP packet
00284     _packetPos = 0;  // 23
00285     _packetSize = 25 - 1 + sizeof(pdu->requestId) + sizeof(pdu->error) + sizeof(pdu->errorIndex) + pdu->OID.size + pdu->VALUE.size;
00286     //
00287     memset(_packet, 0, SNMP_MAX_PACKET_LEN);
00288     //
00289     if ( _dstType == SNMP_PDU_SET ) {
00290         _packetSize += _setSize;
00291     } else {
00292         _packetSize += _getSize;
00293     }
00294     //
00295     // allocate byte array based on packet size
00296     //if ( (_packet = (byte *)malloc(sizeof(byte)*_packetSize)) == NULL ) {
00297         //
00298         //SNMP_FREE(_packet);
00299 
00300     //    return SNMP_API_STAT_MALLOC_ERR;
00301     //}
00302     //
00303     _packet[_packetPos++] = (byte)SNMP_SYNTAX_SEQUENCE;    // type
00304     _packet[_packetPos++] = (byte)_packetSize;        // length
00305     //
00306 
00307     // SNMP version
00308     _packet[_packetPos++] = (byte)SNMP_SYNTAX_INT;    // type
00309     _packet[_packetPos++] = 0x01;            // length
00310     _packet[_packetPos++] = 0x00;            // value
00311     //
00312     // SNMP community string
00313     _packet[_packetPos++] = (byte)SNMP_SYNTAX_OCTETS;    // type
00314     if ( _dstType == SNMP_PDU_SET ) {
00315         _packet[_packetPos++] = (byte)_setSize;    // length
00316         for ( i = 0; i < _setSize; i++ ) {
00317             _packet[_packetPos++] = (byte)_setCommName[i];
00318         }
00319     } else {
00320         _packet[_packetPos++] = (byte)_getSize;    // length
00321         for ( i = 0; i < _getSize; i++ ) {
00322             _packet[_packetPos++] = (byte)_getCommName[i];
00323         }
00324     }
00325     //
00326     // SNMP PDU
00327     _packet[_packetPos++] = (byte)pdu->type;
00328     _packet[_packetPos++] = (byte)( sizeof(pdu->requestId) + sizeof((int32_t)pdu->error) + sizeof(pdu->errorIndex) + pdu->OID.size + pdu->VALUE.size + 14 );
00329     //
00330     // Request ID (size always 4 e.g. 4-byte int)
00331     _packet[_packetPos++] = (byte)SNMP_SYNTAX_INT;    // type
00332     _packet[_packetPos++] = (byte)sizeof(pdu->requestId);
00333     u.int32 = pdu->requestId;
00334     _packet[_packetPos++] = u.data[3];
00335     _packet[_packetPos++] = u.data[2];
00336     _packet[_packetPos++] = u.data[1];
00337     _packet[_packetPos++] = u.data[0];
00338     //
00339     // Error (size always 4 e.g. 4-byte int)
00340     _packet[_packetPos++] = (byte)SNMP_SYNTAX_INT;    // type
00341     _packet[_packetPos++] = (byte)sizeof((int32_t)pdu->error);
00342     u.int32 = pdu->error;
00343     _packet[_packetPos++] = u.data[3];
00344     _packet[_packetPos++] = u.data[2];
00345     _packet[_packetPos++] = u.data[1];
00346     _packet[_packetPos++] = u.data[0];
00347     //
00348     // Error Index (size always 4 e.g. 4-byte int)
00349     _packet[_packetPos++] = (byte)SNMP_SYNTAX_INT;    // type
00350     _packet[_packetPos++] = (byte)sizeof(pdu->errorIndex);
00351     u.int32 = pdu->errorIndex;
00352     _packet[_packetPos++] = u.data[3];
00353     _packet[_packetPos++] = u.data[2];
00354     _packet[_packetPos++] = u.data[1];
00355     _packet[_packetPos++] = u.data[0];
00356     //
00357     // Varbind List
00358     _packet[_packetPos++] = (byte)SNMP_SYNTAX_SEQUENCE;    // type
00359     _packet[_packetPos++] = (byte)( pdu->OID.size + pdu->VALUE.size + 6 ); //4
00360     //
00361     // Varbind
00362     _packet[_packetPos++] = (byte)SNMP_SYNTAX_SEQUENCE;    // type
00363     _packet[_packetPos++] = (byte)( pdu->OID.size + pdu->VALUE.size + 4 ); //2
00364     //
00365     // ObjectIdentifier
00366     _packet[_packetPos++] = (byte)SNMP_SYNTAX_OID;    // type
00367     _packet[_packetPos++] = (byte)(pdu->OID.size);
00368     for ( i = 0; i < pdu->OID.size; i++ ) {
00369         _packet[_packetPos++] = pdu->OID.data[i];
00370     }
00371     //
00372     // Value
00373     _packet[_packetPos++] = (byte)pdu->VALUE.syntax;    // type
00374     _packet[_packetPos++] = (byte)(pdu->VALUE.size);
00375     for ( i = 0; i < pdu->VALUE.size; i++ ) {
00376         _packet[_packetPos++] = pdu->VALUE.data[i];
00377     }
00378     //
00379     //
00380     //SNMP_FREE(_packet);
00381     //
00382     return _packetSize;
00383 }
00384 
00385 
00386 
00387 
00388 void SNMP::freePdu(SNMP_PDU *pdu)
00389 {
00390     //SNMP_FREE(pdu->OID.oid);
00391     //SNMP_FREE(pdu->VALUE.value);
00392     memset(pdu->OID.data, 0, SNMP_MAX_OID_LEN);
00393     memset(pdu->VALUE.data, 0, SNMP_MAX_VALUE_LEN);
00394     //free((char *) pdu);
00395 }
00396 
00397 // Create one global object
00398 //SNMP Agentbed;