SNMP Agent http://mbed.org/users/okini3939/notebook/agentbed-library/
Dependents: WeatherPlatform_20110408 WeatherPlatform WeatherStation
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 AgentbedClass::begin(EthernetNetIf *eth) 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 // init UDP socket 00042 udpsock = new UDPSocket; 00043 udpsock->setOnEvent(this, &AgentbedClass::listen); 00044 udpsock->bind(Host(eth->getIp(), SNMP_DEFAULT_PORT)); 00045 // 00046 return SNMP_API_STAT_SUCCESS; 00047 } 00048 00049 SNMP_API_STAT_CODES AgentbedClass::begin(char *getCommName, char *setCommName, uint16_t port, EthernetNetIf *eth) 00050 { 00051 // set community name set/get sizes 00052 _setSize = strlen(setCommName); 00053 _getSize = strlen(getCommName); 00054 // 00055 // validate get/set community name sizes 00056 if ( _setSize > SNMP_MAX_NAME_LEN + 1 || _getSize > SNMP_MAX_NAME_LEN + 1 ) { 00057 return SNMP_API_STAT_NAME_TOO_BIG; 00058 } 00059 // 00060 // set community names 00061 _getCommName = getCommName; 00062 _setCommName = setCommName; 00063 // 00064 // validate session port number 00065 if ( port == NULL || port == 0 ) port = SNMP_DEFAULT_PORT; 00066 // 00067 // init UDP socket 00068 udpsock = new UDPSocket; 00069 udpsock->setOnEvent(this, &AgentbedClass::listen); 00070 udpsock->bind(Host(eth->getIp(), port)); 00071 // 00072 return SNMP_API_STAT_SUCCESS; 00073 } 00074 00075 void AgentbedClass::listen (UDPSocketEvent e) 00076 { 00077 // if bytes available in receive buffer 00078 // and pointer to a function (delegate function) 00079 // isn't null, trigger the function 00080 if (e == UDPSOCKET_READABLE && _callback != NULL ) { 00081 (*_callback)(); 00082 } 00083 } 00084 00085 00086 SNMP_API_STAT_CODES AgentbedClass::requestPdu(SNMP_PDU *pdu) 00087 { 00088 char *community; 00089 // sequence length 00090 byte __attribute__((__unused__)) seqLen; 00091 // version 00092 byte verLen, verEnd; 00093 // community string 00094 byte comLen, comEnd; 00095 // pdu 00096 byte __attribute__((__unused__)) pduTyp, pduLen; 00097 byte ridLen, ridEnd; 00098 byte errLen, errEnd; 00099 byte eriLen, eriEnd; 00100 byte __attribute__((__unused__)) vblTyp, vblLen; 00101 byte __attribute__((__unused__)) vbiTyp, vbiLen; 00102 byte obiLen, obiEnd; 00103 byte __attribute__((__unused__)) valTyp, valLen, valEnd; 00104 byte i; 00105 Host dest; 00106 // 00107 // set packet packet size (skip UDP header) 00108 // _packetSize = Udp.available()-8; 00109 // 00110 memset(_packet, 0, SNMP_MAX_PACKET_LEN); 00111 // 00112 // get UDP packet 00113 _packetSize = udpsock->recvfrom((char*)_packet, SNMP_MAX_PACKET_LEN, &_dst); 00114 // 00115 // validate packet 00116 if ( _packetSize != 0 && _packetSize > SNMP_MAX_PACKET_LEN ) { 00117 // 00118 //SNMP_FREE(_packet); 00119 00120 return SNMP_API_STAT_PACKET_TOO_BIG; 00121 } 00122 // 00123 // allocate byte array based on packet size 00124 //if ( (_packet = (byte *)malloc(sizeof(byte)*_packetSize)) == NULL ) { 00125 // 00126 //SNMP_FREE(_packet); 00127 00128 // return SNMP_API_STAT_MALLOC_ERR; 00129 //} 00130 // 00131 // packet check 1 00132 if ( _packet[0] != 0x30 ) { 00133 // 00134 //SNMP_FREE(_packet); 00135 00136 return SNMP_API_STAT_PACKET_INVALID; 00137 } 00138 // 00139 // sequence length 00140 seqLen = _packet[1]; 00141 // version 00142 verLen = _packet[3]; 00143 verEnd = 3 + verLen; 00144 // community string 00145 comLen = _packet[verEnd + 2]; 00146 comEnd = verEnd + 2 + comLen; 00147 // pdu 00148 pduTyp = _packet[comEnd + 1]; 00149 pduLen = _packet[comEnd + 2]; 00150 ridLen = _packet[comEnd + 4]; 00151 ridEnd = comEnd + 4 + ridLen; 00152 errLen = _packet[ridEnd + 2]; 00153 errEnd = ridEnd + 2 + errLen; 00154 eriLen = _packet[errEnd + 2]; 00155 eriEnd = errEnd + 2 + eriLen; 00156 vblTyp = _packet[eriEnd + 1]; 00157 vblLen = _packet[eriEnd + 2]; 00158 vbiTyp = _packet[eriEnd + 3]; 00159 vbiLen = _packet[eriEnd + 4]; 00160 obiLen = _packet[eriEnd + 6]; 00161 obiEnd = eriEnd + obiLen + 6; 00162 valTyp = _packet[obiEnd + 1]; 00163 valLen = _packet[obiEnd + 2]; 00164 valEnd = obiEnd + 2 + valLen; 00165 // 00166 // extract version 00167 pdu->version = 0; 00168 for ( i = 0; i < verLen; i++ ) { 00169 pdu->version = (pdu->version << 8) | _packet[5 + i]; 00170 } 00171 // 00172 // pdu-type 00173 pdu->type = (SNMP_PDU_TYPES)pduTyp; 00174 _dstType = pdu->type; 00175 // 00176 // validate community size 00177 if ( comLen > SNMP_MAX_NAME_LEN ) { 00178 // set pdu error 00179 pdu->error = SNMP_ERR_TOO_BIG; 00180 // 00181 //SNMP_FREE(_packet); 00182 00183 return SNMP_API_STAT_NAME_TOO_BIG; 00184 } 00185 // 00186 // extract and compare community name 00187 // allocate char array based on community size 00188 if ( (community = (char *)malloc(sizeof(char)*comLen)) == NULL ) { 00189 // 00190 //SNMP_FREE(_packet); 00191 00192 return SNMP_API_STAT_MALLOC_ERR; 00193 } 00194 // 00195 for ( i = 0; i < comLen; i++ ) { 00196 community[i] = _packet[verEnd + 3 + i]; 00197 } 00198 // terminate as a string 00199 community[comLen] = '\0'; 00200 // 00201 // validate community name 00202 if ( pdu->type == SNMP_PDU_SET ) { 00203 if ( strcmp(_setCommName, community) != 0 ) 00204 // set pdu error 00205 pdu->error = SNMP_ERR_NO_SUCH_NAME; 00206 } else { 00207 if ( strcmp(_getCommName, community) != 0 ) 00208 // set pdu error 00209 pdu->error = SNMP_ERR_NO_SUCH_NAME; 00210 } 00211 // 00212 // free community buffer 00213 SNMP_FREE(community); 00214 // 00215 // extract reqiest-id 0x00 0x00 0x00 0x01 (4-byte int aka int32) 00216 pdu->requestId = 0; 00217 for ( i = 0; i < ridLen; i++ ) { 00218 pdu->requestId = (pdu->requestId << 8) | _packet[comEnd + 5 + i]; 00219 } 00220 // 00221 // extract error 00222 pdu->error = SNMP_ERR_NO_ERROR; 00223 int32_t err = 0; 00224 for ( i = 0; i < errLen; i++ ) { 00225 err = (err << 8) | _packet[ridEnd + 3 + i]; 00226 } 00227 pdu->error = (SNMP_ERR_CODES)err; 00228 // 00229 // extract error-index 00230 pdu->errorIndex = 0; 00231 for ( i = 0; i < eriLen; i++ ) { 00232 pdu->errorIndex = (pdu->errorIndex << 8) | _packet[errEnd + 3 + i]; 00233 } 00234 // 00235 // 00236 // validate object-identifier size 00237 if ( obiLen > SNMP_MAX_OID_LEN ) { 00238 // set pdu error 00239 pdu->error = SNMP_ERR_TOO_BIG; 00240 // 00241 //SNMP_FREE(_packet); 00242 00243 return SNMP_API_STAT_OID_TOO_BIG; 00244 } 00245 // 00246 // extract and contruct object-identifier 00247 /* 00248 if ( (pdu->OID.oid = (byte *)malloc(sizeof(byte)*obiLen)) == NULL ) { 00249 // free DPU receive buffer 00250 _socket.readSkip(_socket.available()); 00251 // 00252 SNMP_FREE(_packet); 00253 00254 return SNMP_API_STAT_MALLOC_ERR; 00255 } 00256 */ 00257 memset(pdu->OID.data, 0, SNMP_MAX_OID_LEN); 00258 pdu->OID.size = obiLen; 00259 for ( i = 0; i < obiLen; i++ ) { 00260 pdu->OID.data[i] = _packet[eriEnd + 7 + i]; 00261 } 00262 // 00263 // value-type 00264 pdu->VALUE.syntax = (SNMP_SYNTAXES)valTyp; 00265 // 00266 // validate value size 00267 if ( obiLen > SNMP_MAX_VALUE_LEN ) { 00268 // set pdu error 00269 pdu->error = SNMP_ERR_TOO_BIG; 00270 // 00271 //SNMP_FREE(_packet); 00272 00273 return SNMP_API_STAT_VALUE_TOO_BIG; 00274 } 00275 // 00276 // value-size 00277 pdu->VALUE.size = valLen; 00278 // 00279 // extract value 00280 // allocate char array based on oid size 00281 /* 00282 if( (pdu->VALUE.value = (byte *)malloc(sizeof(byte)*valLen)) == NULL ) { 00283 // free DPU receive buffer 00284 _socket.readSkip(_socket.available()); 00285 // 00286 SNMP_FREE(_packet); 00287 00288 return SNMP_API_STAT_MALLOC_ERR; 00289 } 00290 */ 00291 memset(pdu->VALUE.data, 0, SNMP_MAX_VALUE_LEN); 00292 for ( i = 0; i < valLen; i++ ) { 00293 pdu->VALUE.data[i] = _packet[obiEnd + 3 + i]; 00294 } 00295 // 00296 //SNMP_FREE(_packet); 00297 // 00298 return SNMP_API_STAT_SUCCESS; 00299 } 00300 00301 SNMP_API_STAT_CODES AgentbedClass::responsePdu(SNMP_PDU *pdu) 00302 { 00303 int32_u u; 00304 byte i; 00305 // 00306 // Length of entire SNMP packet 00307 _packetPos = 0; // 23 00308 _packetSize = 25 - 1 + sizeof(pdu->requestId) + sizeof(pdu->error) + sizeof(pdu->errorIndex) + pdu->OID.size + pdu->VALUE.size; 00309 // 00310 memset(_packet, 0, SNMP_MAX_PACKET_LEN); 00311 // 00312 if ( _dstType == SNMP_PDU_SET ) { 00313 _packetSize += _setSize; 00314 } else { 00315 _packetSize += _getSize; 00316 } 00317 // 00318 // allocate byte array based on packet size 00319 //if ( (_packet = (byte *)malloc(sizeof(byte)*_packetSize)) == NULL ) { 00320 // 00321 //SNMP_FREE(_packet); 00322 00323 // return SNMP_API_STAT_MALLOC_ERR; 00324 //} 00325 // 00326 _packet[_packetPos++] = (byte)SNMP_SYNTAX_SEQUENCE; // type 00327 _packet[_packetPos++] = (byte)_packetSize; // length 00328 // 00329 00330 // SNMP version 00331 _packet[_packetPos++] = (byte)SNMP_SYNTAX_INT; // type 00332 _packet[_packetPos++] = 0x01; // length 00333 _packet[_packetPos++] = 0x00; // value 00334 // 00335 // SNMP community string 00336 _packet[_packetPos++] = (byte)SNMP_SYNTAX_OCTETS; // type 00337 if ( _dstType == SNMP_PDU_SET ) { 00338 _packet[_packetPos++] = (byte)_setSize; // length 00339 for ( i = 0; i < _setSize; i++ ) { 00340 _packet[_packetPos++] = (byte)_setCommName[i]; 00341 } 00342 } else { 00343 _packet[_packetPos++] = (byte)_getSize; // length 00344 for ( i = 0; i < _getSize; i++ ) { 00345 _packet[_packetPos++] = (byte)_getCommName[i]; 00346 } 00347 } 00348 // 00349 // SNMP PDU 00350 _packet[_packetPos++] = (byte)pdu->type; 00351 _packet[_packetPos++] = (byte)( sizeof(pdu->requestId) + sizeof((int32_t)pdu->error) + sizeof(pdu->errorIndex) + pdu->OID.size + pdu->VALUE.size + 14 ); 00352 // 00353 // Request ID (size always 4 e.g. 4-byte int) 00354 _packet[_packetPos++] = (byte)SNMP_SYNTAX_INT; // type 00355 _packet[_packetPos++] = (byte)sizeof(pdu->requestId); 00356 u.int32 = pdu->requestId; 00357 _packet[_packetPos++] = u.data[3]; 00358 _packet[_packetPos++] = u.data[2]; 00359 _packet[_packetPos++] = u.data[1]; 00360 _packet[_packetPos++] = u.data[0]; 00361 // 00362 // Error (size always 4 e.g. 4-byte int) 00363 _packet[_packetPos++] = (byte)SNMP_SYNTAX_INT; // type 00364 _packet[_packetPos++] = (byte)sizeof((int32_t)pdu->error); 00365 u.int32 = pdu->error; 00366 _packet[_packetPos++] = u.data[3]; 00367 _packet[_packetPos++] = u.data[2]; 00368 _packet[_packetPos++] = u.data[1]; 00369 _packet[_packetPos++] = u.data[0]; 00370 // 00371 // Error Index (size always 4 e.g. 4-byte int) 00372 _packet[_packetPos++] = (byte)SNMP_SYNTAX_INT; // type 00373 _packet[_packetPos++] = (byte)sizeof(pdu->errorIndex); 00374 u.int32 = pdu->errorIndex; 00375 _packet[_packetPos++] = u.data[3]; 00376 _packet[_packetPos++] = u.data[2]; 00377 _packet[_packetPos++] = u.data[1]; 00378 _packet[_packetPos++] = u.data[0]; 00379 // 00380 // Varbind List 00381 _packet[_packetPos++] = (byte)SNMP_SYNTAX_SEQUENCE; // type 00382 _packet[_packetPos++] = (byte)( pdu->OID.size + pdu->VALUE.size + 6 ); //4 00383 // 00384 // Varbind 00385 _packet[_packetPos++] = (byte)SNMP_SYNTAX_SEQUENCE; // type 00386 _packet[_packetPos++] = (byte)( pdu->OID.size + pdu->VALUE.size + 4 ); //2 00387 // 00388 // ObjectIdentifier 00389 _packet[_packetPos++] = (byte)SNMP_SYNTAX_OID; // type 00390 _packet[_packetPos++] = (byte)(pdu->OID.size); 00391 for ( i = 0; i < pdu->OID.size; i++ ) { 00392 _packet[_packetPos++] = pdu->OID.data[i]; 00393 } 00394 // 00395 // Value 00396 _packet[_packetPos++] = (byte)pdu->VALUE.syntax; // type 00397 _packet[_packetPos++] = (byte)(pdu->VALUE.size); 00398 for ( i = 0; i < pdu->VALUE.size; i++ ) { 00399 _packet[_packetPos++] = pdu->VALUE.data[i]; 00400 } 00401 // 00402 udpsock->sendto((char*)_packet, _packetPos, &_dst); 00403 // 00404 //SNMP_FREE(_packet); 00405 // 00406 return SNMP_API_STAT_SUCCESS; 00407 } 00408 00409 00410 00411 void AgentbedClass::onPduReceive(onPduReceiveCallback pduReceived) 00412 { 00413 _callback = pduReceived; 00414 } 00415 00416 void AgentbedClass::freePdu(SNMP_PDU *pdu) 00417 { 00418 //SNMP_FREE(pdu->OID.oid); 00419 //SNMP_FREE(pdu->VALUE.value); 00420 memset(pdu->OID.data, 0, SNMP_MAX_OID_LEN); 00421 memset(pdu->VALUE.data, 0, SNMP_MAX_VALUE_LEN); 00422 //free((char *) pdu); 00423 } 00424 00425 // Create one global object 00426 //AgentbedClass Agentbed;
Generated on Wed Jul 13 2022 23:20:05 by 1.7.2