Webserver+3d print
Embed:
(wiki syntax)
Show/hide line numbers
snmp_agent_pdu.c
Go to the documentation of this file.
00001 /** 00002 * @file snmp_agent_pdu.c 00003 * @brief SNMP agent (PDU processing) 00004 * 00005 * @section License 00006 * 00007 * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved. 00008 * 00009 * This file is part of CycloneTCP Open. 00010 * 00011 * This program is free software; you can redistribute it and/or 00012 * modify it under the terms of the GNU General Public License 00013 * as published by the Free Software Foundation; either version 2 00014 * of the License, or (at your option) any later version. 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU General Public License 00022 * along with this program; if not, write to the Free Software Foundation, 00023 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00024 * 00025 * @author Oryx Embedded SARL (www.oryx-embedded.com) 00026 * @version 1.7.6 00027 **/ 00028 00029 //Switch to the appropriate trace level 00030 #define TRACE_LEVEL SNMP_TRACE_LEVEL 00031 00032 //Dependencies 00033 #include "core/net.h" 00034 #include "snmp/snmp_agent.h" 00035 #include "snmp/snmp_agent_pdu.h" 00036 #include "snmp/snmp_agent_misc.h" 00037 #include "mibs/mib2_module.h" 00038 #include "crypto.h" 00039 #include "asn1.h" 00040 #include "oid.h" 00041 #include "debug.h" 00042 00043 //Check TCP/IP stack configuration 00044 #if (SNMP_AGENT_SUPPORT == ENABLED) 00045 00046 //sysUpTime.0 object (1.3.6.1.2.1.1.3.0) 00047 static const uint8_t sysUpTimeObject[] = {43, 6, 1, 2, 1, 1, 3, 0}; 00048 //snmpTrapOID.0 object (1.3.6.1.6.3.1.1.4.1.0) 00049 static const uint8_t snmpTrapOidObject[] = {43, 6, 1, 6, 3, 1, 1, 4, 1, 0}; 00050 //snmpTraps object (1.3.6.1.6.3.1.1.5) 00051 static const uint8_t snmpTrapsObject[] = {43, 6, 1, 6, 3, 1, 1, 5}; 00052 00053 00054 /** 00055 * @brief Process PDU 00056 * @param[in] context Pointer to the SNMP agent context 00057 * @return Error code 00058 **/ 00059 00060 error_t snmpProcessPdu(SnmpAgentContext *context) 00061 { 00062 error_t error; 00063 00064 //Parse PDU header 00065 error = snmpParsePduHeader(&context->request); 00066 //Any error to report? 00067 if(error) 00068 return error; 00069 00070 //Check PDU type 00071 switch(context->request.pduType) 00072 { 00073 case SNMP_PDU_GET_REQUEST: 00074 case SNMP_PDU_GET_NEXT_REQUEST: 00075 //Process GetRequest-PDU or GetNextRequest-PDU 00076 error = snmpProcessGetRequestPdu(context); 00077 break; 00078 case SNMP_PDU_GET_BULK_REQUEST: 00079 //Process GetBulkRequest-PDU 00080 error = snmpProcessGetBulkRequestPdu(context); 00081 break; 00082 case SNMP_PDU_SET_REQUEST: 00083 //Process SetRequest-PDU 00084 error = snmpProcessSetRequestPdu(context); 00085 break; 00086 default: 00087 //Invalid PDU type 00088 error = ERROR_INVALID_TYPE; 00089 break; 00090 } 00091 00092 //Check status code 00093 if(!error) 00094 { 00095 //Total number of SNMP Get-Response PDUs which have been generated 00096 //by the SNMP protocol entity 00097 MIB2_INC_COUNTER32(mib2Base.snmpGroup.snmpOutGetResponses, 1); 00098 00099 //Format PDU header 00100 error = snmpWritePduHeader(&context->response); 00101 } 00102 00103 //Return status code 00104 return error; 00105 } 00106 00107 00108 /** 00109 * @brief Process GetRequest-PDU or GetNextRequest-PDU 00110 * @param[in] context Pointer to the SNMP agent context 00111 * @return Error code 00112 **/ 00113 00114 error_t snmpProcessGetRequestPdu(SnmpAgentContext *context) 00115 { 00116 error_t error; 00117 int_t index; 00118 size_t n; 00119 size_t length; 00120 const uint8_t *p; 00121 SnmpVarBind var; 00122 00123 //Check PDU type 00124 if(context->request.pduType == SNMP_PDU_GET_REQUEST) 00125 { 00126 //Debug message 00127 TRACE_INFO("Parsing GetRequest-PDU...\r\n"); 00128 00129 //Total number of SNMP Get-Request PDUs which have been accepted and 00130 //processed by the SNMP protocol entity 00131 MIB2_INC_COUNTER32(mib2Base.snmpGroup.snmpInGetRequests, 1); 00132 } 00133 else if(context->request.pduType == SNMP_PDU_GET_NEXT_REQUEST) 00134 { 00135 //Debug message 00136 TRACE_INFO("Parsing GetNextRequest-PDU...\r\n"); 00137 00138 //Total number of SNMP Get-NextRequest PDUs which have been accepted 00139 //and processed by the SNMP protocol entity 00140 MIB2_INC_COUNTER32(mib2Base.snmpGroup.snmpInGetNexts, 1); 00141 } 00142 00143 //Enforce access policy 00144 if(context->user->mode != SNMP_ACCESS_READ_ONLY && 00145 context->user->mode != SNMP_ACCESS_READ_WRITE) 00146 { 00147 //Total number of SNMP messages delivered to the SNMP protocol entity 00148 //which represented an SNMP operation which was not allowed by the SNMP 00149 MIB2_INC_COUNTER32(mib2Base.snmpGroup.snmpInBadCommunityUses, 1); 00150 00151 //Report an error 00152 return ERROR_ACCESS_DENIED; 00153 } 00154 00155 //Initialize response message 00156 error = snmpInitResponse(context); 00157 //Any error to report? 00158 if(error) 00159 return error; 00160 00161 //Point to the first variable binding of the request 00162 p = context->request.varBindList; 00163 length = context->request.varBindListLen; 00164 00165 //Lock access to MIB bases 00166 snmpLockMib(context); 00167 00168 //Loop through the list 00169 for(index = 1; length > 0; index++) 00170 { 00171 //Parse variable binding 00172 error = snmpParseVarBinding(p, length, &var, &n); 00173 //Failed to parse variable binding? 00174 if(error) 00175 break; 00176 00177 //Make sure that the object identifier is valid 00178 error = oidCheck(var.oid, var.oidLen); 00179 //Invalid object identifier? 00180 if(error) 00181 break; 00182 00183 //GetRequest-PDU? 00184 if(context->request.pduType == SNMP_PDU_GET_REQUEST) 00185 { 00186 //Retrieve object value 00187 error = snmpGetObjectValue(context, &var); 00188 } 00189 //GetNextRequest-PDU? 00190 else 00191 { 00192 //Search the MIB for the next object 00193 error = snmpGetNextObject(context, &var); 00194 00195 //SNMPv1 version? 00196 if(context->request.version == SNMP_VERSION_1) 00197 { 00198 //Check status code 00199 if(error == NO_ERROR) 00200 { 00201 //Retrieve object value 00202 error = snmpGetObjectValue(context, &var); 00203 } 00204 else 00205 { 00206 //Stop immediately 00207 break; 00208 } 00209 } 00210 //SNMPv2c or SNMPv3 version? 00211 else 00212 { 00213 //Check status code 00214 if(error == NO_ERROR) 00215 { 00216 //Retrieve object value 00217 error = snmpGetObjectValue(context, &var); 00218 } 00219 else if(error == ERROR_OBJECT_NOT_FOUND) 00220 { 00221 //The variable binding's value field is set to endOfMibView 00222 var.objClass = ASN1_CLASS_CONTEXT_SPECIFIC; 00223 var.objType = SNMP_EXCEPTION_END_OF_MIB_VIEW; 00224 var.valueLen = 0; 00225 00226 //Catch exception 00227 error = NO_ERROR; 00228 } 00229 else 00230 { 00231 //Stop immediately 00232 break; 00233 } 00234 } 00235 } 00236 00237 //Failed to retrieve object value? 00238 if(error) 00239 { 00240 //SNMPv1 version? 00241 if(context->request.version == SNMP_VERSION_1) 00242 { 00243 //Stop immediately 00244 break; 00245 } 00246 //SNMPv2c or SNMPv3 version? 00247 else 00248 { 00249 //Catch exception 00250 if(error == ERROR_ACCESS_DENIED || 00251 error == ERROR_OBJECT_NOT_FOUND) 00252 { 00253 //The variable binding's value field is set to noSuchObject 00254 var.objClass = ASN1_CLASS_CONTEXT_SPECIFIC; 00255 var.objType = SNMP_EXCEPTION_NO_SUCH_OBJECT; 00256 var.valueLen = 0; 00257 } 00258 else if(error == ERROR_INSTANCE_NOT_FOUND) 00259 { 00260 //The variable binding's value field is set to noSuchInstance 00261 var.objClass = ASN1_CLASS_CONTEXT_SPECIFIC; 00262 var.objType = SNMP_EXCEPTION_NO_SUCH_INSTANCE; 00263 var.valueLen = 0; 00264 } 00265 else 00266 { 00267 //Stop immediately 00268 break; 00269 } 00270 } 00271 } 00272 else 00273 { 00274 //Total number of MIB objects which have been retrieved successfully 00275 //by the SNMP protocol entity as the result of receiving valid SNMP 00276 //Get-Request and Get-NextRequest PDUs 00277 MIB2_INC_COUNTER32(mib2Base.snmpGroup.snmpInTotalReqVars, 1); 00278 } 00279 00280 //Append variable binding to the list 00281 error = snmpWriteVarBinding(context, &var); 00282 //Any error to report? 00283 if(error) 00284 break; 00285 00286 //Advance data pointer 00287 p += n; 00288 length -= n; 00289 } 00290 00291 //Unlock access to MIB bases 00292 snmpUnlockMib(context); 00293 00294 //Check status code 00295 if(error) 00296 { 00297 //Set error-status and error-index fields 00298 error = snmpTranslateStatusCode(&context->response, error, index); 00299 //If the parsing of the request fails, the SNMP agent discards the message 00300 if(error) 00301 return error; 00302 00303 //Check whether an alternate Response-PDU should be sent 00304 if(context->response.version != SNMP_VERSION_1 && 00305 context->response.errorStatus == SNMP_ERROR_TOO_BIG) 00306 { 00307 //The alternate Response-PDU is formatted with the same value in its 00308 //request-id field as the received GetRequest-PDU and an empty 00309 //variable-bindings field 00310 context->response.varBindListLen = 0; 00311 } 00312 else 00313 { 00314 //The Response-PDU is re-formatted with the same values in its request-id 00315 //and variable-bindings fields as the received GetRequest-PDU 00316 error = snmpCopyVarBindingList(context); 00317 //Any error to report? 00318 if(error) 00319 return error; 00320 } 00321 } 00322 00323 //Successful processing 00324 return NO_ERROR; 00325 } 00326 00327 00328 /** 00329 * @brief Process GetBulkRequest-PDU 00330 * @param[in] context Pointer to the SNMP agent context 00331 * @return Error code 00332 **/ 00333 00334 error_t snmpProcessGetBulkRequestPdu(SnmpAgentContext *context) 00335 { 00336 #if (SNMP_V2C_SUPPORT == ENABLED || SNMP_V3_SUPPORT == ENABLED) 00337 error_t error; 00338 int_t index; 00339 size_t n; 00340 size_t m; 00341 size_t length; 00342 bool_t endOfMibView; 00343 const uint8_t *p; 00344 const uint8_t *next; 00345 SnmpVarBind var; 00346 00347 //Debug message 00348 TRACE_INFO("Parsing GetBulkRequest-PDU...\r\n"); 00349 00350 //Make sure the SNMP version identifier is valid 00351 if(context->request.version == SNMP_VERSION_1) 00352 { 00353 //The SNMP version is not acceptable 00354 return ERROR_INVALID_TYPE; 00355 } 00356 00357 //Enforce access policy 00358 if(context->user->mode != SNMP_ACCESS_READ_ONLY && 00359 context->user->mode != SNMP_ACCESS_READ_WRITE) 00360 { 00361 //Total number of SNMP messages delivered to the SNMP protocol entity 00362 //which represented an SNMP operation which was not allowed by the SNMP 00363 MIB2_INC_COUNTER32(mib2Base.snmpGroup.snmpInBadCommunityUses, 1); 00364 00365 //Report an error 00366 return ERROR_ACCESS_DENIED; 00367 } 00368 00369 //Initialize response message 00370 error = snmpInitResponse(context); 00371 //Any error to report? 00372 if(error) 00373 return error; 00374 00375 //Point to the first variable binding of the request 00376 p = context->request.varBindList; 00377 length = context->request.varBindListLen; 00378 00379 //Lock access to MIB bases 00380 snmpLockMib(context); 00381 00382 //Loop through the list 00383 for(index = 1; length > 0; index++) 00384 { 00385 //The non-repeaters field specifies the number of non-repeating objects 00386 //at the start of the variable binding list 00387 if((index - 1) == context->request.nonRepeaters) 00388 { 00389 //Pointer to the first variable binding that will be processed during 00390 //the next iteration 00391 next = context->response.varBindList + context->response.varBindListLen; 00392 00393 //Actual size of the variable binding list 00394 m = context->response.varBindListLen; 00395 00396 //This flag tells whether all variable bindings have the value field 00397 //set to endOfMibView for a given iteration 00398 endOfMibView = TRUE; 00399 00400 //If the max-repetitions field is zero, the list is trimmed to the 00401 //first non-repeating variable bindings 00402 if(context->request.maxRepetitions == 0) 00403 break; 00404 } 00405 00406 //Parse variable binding 00407 error = snmpParseVarBinding(p, length, &var, &n); 00408 //Failed to parse variable binding? 00409 if(error) 00410 break; 00411 00412 //Make sure that the object identifier is valid 00413 error = oidCheck(var.oid, var.oidLen); 00414 //Invalid object identifier? 00415 if(error) 00416 break; 00417 00418 //Search the MIB for the next object 00419 error = snmpGetNextObject(context, &var); 00420 00421 //Check status code 00422 if(error == NO_ERROR) 00423 { 00424 //Next object found 00425 endOfMibView = FALSE; 00426 //Retrieve object value 00427 error = snmpGetObjectValue(context, &var); 00428 } 00429 else if(error == ERROR_OBJECT_NOT_FOUND) 00430 { 00431 //The variable binding's value field is set to endOfMibView 00432 var.objClass = ASN1_CLASS_CONTEXT_SPECIFIC; 00433 var.objType = SNMP_EXCEPTION_END_OF_MIB_VIEW; 00434 var.valueLen = 0; 00435 00436 //Catch exception 00437 error = NO_ERROR; 00438 } 00439 else 00440 { 00441 //Stop immediately 00442 break; 00443 } 00444 00445 //Failed to retrieve object value? 00446 if(error) 00447 { 00448 //Catch exception 00449 if(error == ERROR_ACCESS_DENIED || 00450 error == ERROR_OBJECT_NOT_FOUND) 00451 { 00452 //The variable binding's value field is set to noSuchObject 00453 var.objClass = ASN1_CLASS_CONTEXT_SPECIFIC; 00454 var.objType = SNMP_EXCEPTION_NO_SUCH_OBJECT; 00455 var.valueLen = 0; 00456 } 00457 else if(error == ERROR_INSTANCE_NOT_FOUND) 00458 { 00459 //The variable binding's value field is set to noSuchInstance 00460 var.objClass = ASN1_CLASS_CONTEXT_SPECIFIC; 00461 var.objType = SNMP_EXCEPTION_NO_SUCH_INSTANCE; 00462 var.valueLen = 0; 00463 } 00464 else 00465 { 00466 //Stop immediately 00467 break; 00468 } 00469 } 00470 else 00471 { 00472 //Total number of MIB objects which have been retrieved successfully 00473 //by the SNMP protocol entity as the result of receiving valid SNMP 00474 //Get-Request and Get-NextRequest PDUs 00475 MIB2_INC_COUNTER32(mib2Base.snmpGroup.snmpInTotalReqVars, 1); 00476 } 00477 00478 //Append variable binding to the list 00479 error = snmpWriteVarBinding(context, &var); 00480 //Any error to report? 00481 if(error) 00482 break; 00483 00484 //Advance data pointer 00485 p += n; 00486 length -= n; 00487 00488 //Next iteration? 00489 if(length == 0 && index > context->request.nonRepeaters) 00490 { 00491 //Decrement repeat counter 00492 context->request.maxRepetitions--; 00493 00494 //Last iteration? 00495 if(!context->request.maxRepetitions) 00496 break; 00497 //All variable bindings have the value field set to endOfMibView? 00498 if(endOfMibView) 00499 break; 00500 00501 //Point to the first variable binding to be processed 00502 p = next; 00503 //Number of bytes to be processed 00504 length = context->response.varBindListLen - m; 00505 //Rewind index 00506 index = context->request.nonRepeaters; 00507 } 00508 } 00509 00510 //Unlock access to MIB bases 00511 snmpUnlockMib(context); 00512 00513 //Check status code 00514 if(error == ERROR_BUFFER_OVERFLOW) 00515 { 00516 //If the size of the message containing the requested number of variable 00517 //bindings would be greater than the maximum message size, then the 00518 //response is generated with a lesser number of variable bindings 00519 } 00520 else if(error) 00521 { 00522 //Set error-status and error-index fields 00523 error = snmpTranslateStatusCode(&context->response, error, index); 00524 //If the parsing of the request fails, the SNMP agent discards the message 00525 if(error) 00526 return error; 00527 00528 //The Response-PDU is re-formatted with the same values in its request-id 00529 //and variable-bindings fields as the received GetRequest-PDU 00530 error = snmpCopyVarBindingList(context); 00531 //Any error to report? 00532 if(error) 00533 return error; 00534 } 00535 00536 //Successful processing 00537 return NO_ERROR; 00538 #else 00539 //Not implemented 00540 return ERROR_NOT_IMPLEMENTED; 00541 #endif 00542 } 00543 00544 00545 /** 00546 * @brief Process SetRequest-PDU 00547 * @param[in] context Pointer to the SNMP agent context 00548 * @return Error code 00549 **/ 00550 00551 error_t snmpProcessSetRequestPdu(SnmpAgentContext *context) 00552 { 00553 error_t error; 00554 int_t index; 00555 size_t n; 00556 size_t length; 00557 const uint8_t *p; 00558 SnmpVarBind var; 00559 00560 //Debug message 00561 TRACE_INFO("Parsing SetRequest-PDU...\r\n"); 00562 00563 //Total number of SNMP Set-Request PDUs which have been accepted and 00564 //processed by the SNMP protocol entity 00565 MIB2_INC_COUNTER32(mib2Base.snmpGroup.snmpInSetRequests, 1); 00566 00567 //Enforce access policy 00568 if(context->user->mode != SNMP_ACCESS_WRITE_ONLY && 00569 context->user->mode != SNMP_ACCESS_READ_WRITE) 00570 { 00571 //Total number of SNMP messages delivered to the SNMP protocol entity 00572 //which represented an SNMP operation which was not allowed by the SNMP 00573 MIB2_INC_COUNTER32(mib2Base.snmpGroup.snmpInBadCommunityUses, 1); 00574 00575 //Report an error 00576 return ERROR_ACCESS_DENIED; 00577 } 00578 00579 //Initialize response message 00580 error = snmpInitResponse(context); 00581 //Any error to report? 00582 if(error) 00583 return error; 00584 00585 //The variable bindings are processed as a two phase operation. In the 00586 //first phase, each variable binding is validated 00587 p = context->request.varBindList; 00588 length = context->request.varBindListLen; 00589 00590 //Loop through the list 00591 for(index = 1; length > 0; index++) 00592 { 00593 //Parse variable binding 00594 error = snmpParseVarBinding(p, length, &var, &n); 00595 //Failed to parse variable binding? 00596 if(error) 00597 break; 00598 00599 //Assign object value 00600 error = snmpSetObjectValue(context, &var, FALSE); 00601 //Any error to report? 00602 if(error) 00603 break; 00604 00605 //Advance data pointer 00606 p += n; 00607 length -= n; 00608 } 00609 00610 //If all validations are successful, then each variable is altered in 00611 //the second phase 00612 if(!error) 00613 { 00614 //The changes are committed to the MIB base during the second phase 00615 p = context->request.varBindList; 00616 length = context->request.varBindListLen; 00617 00618 //Lock access to MIB bases 00619 snmpLockMib(context); 00620 00621 //Loop through the list 00622 for(index = 1; length > 0; index++) 00623 { 00624 //Parse variable binding 00625 error = snmpParseVarBinding(p, length, &var, &n); 00626 //Failed to parse variable binding? 00627 if(error) 00628 break; 00629 00630 //Assign object value 00631 error = snmpSetObjectValue(context, &var, TRUE); 00632 //Any error to report? 00633 if(error) 00634 break; 00635 00636 //Total number of MIB objects which have been altered successfully 00637 //by the SNMP protocol entity as the result of receiving valid 00638 //SNMP Set-Request PDUs 00639 MIB2_INC_COUNTER32(mib2Base.snmpGroup.snmpInTotalSetVars, 1); 00640 00641 //Advance data pointer 00642 p += n; 00643 length -= n; 00644 } 00645 00646 //Unlock access to MIB bases 00647 snmpUnlockMib(context); 00648 } 00649 00650 //Any error to report? 00651 if(error) 00652 { 00653 //Set error-status and error-index fields 00654 error = snmpTranslateStatusCode(&context->response, error, index); 00655 //If the parsing of the request fails, the SNMP agent discards the message 00656 if(error) 00657 return error; 00658 } 00659 00660 //The SNMP agent sends back a GetResponse-PDU of identical form 00661 error = snmpCopyVarBindingList(context); 00662 //Return status code 00663 return error; 00664 } 00665 00666 00667 /** 00668 * @brief Format Trap-PDU or SNMPv2-Trap-PDU 00669 * @param[in] context Pointer to the SNMP agent context 00670 * @param[in] version SNMP version identifier 00671 * @param[in] username User name or community name 00672 * @param[in] genericTrapType Generic trap type 00673 * @param[in] specificTrapCode Specific code 00674 * @param[in] objectList List of object names 00675 * @param[in] objectListSize Number of entries in the list 00676 * @return Error code 00677 **/ 00678 00679 error_t snmpFormatTrapPdu(SnmpAgentContext *context, SnmpVersion version, 00680 const char_t *username, uint_t genericTrapType, uint_t specificTrapCode, 00681 const SnmpTrapObject *objectList, uint_t objectListSize) 00682 { 00683 error_t error; 00684 uint_t i; 00685 size_t n; 00686 systime_t time; 00687 SnmpMessage *message; 00688 SnmpVarBind var; 00689 00690 //Point to the SNMP message 00691 message = &context->response; 00692 //Initialize SNMP message 00693 snmpInitMessage(message); 00694 00695 //SNMP version identifier 00696 message->version = version; 00697 00698 #if (SNMP_V1_SUPPORT == ENABLED) 00699 //SNMPv1 version? 00700 if(version == SNMP_VERSION_1) 00701 { 00702 #if (IPV4_SUPPORT == ENABLED) 00703 NetInterface *interface; 00704 00705 //Point to the underlying network interface 00706 interface = context->settings.interface; 00707 #endif 00708 00709 //Community name 00710 message->community = username; 00711 message->communityLen = strlen(username); 00712 00713 //Prepare to send a Trap-PDU 00714 message->pduType = SNMP_PDU_TRAP; 00715 //Type of object generating trap 00716 message->enterpriseOid = context->enterpriseOid; 00717 message->enterpriseOidLen = context->enterpriseOidLen; 00718 00719 #if (IPV4_SUPPORT == ENABLED) 00720 //Address of object generating trap 00721 if(interface != NULL) 00722 message->agentAddr = interface->ipv4Context.addr; 00723 #endif 00724 00725 //Generic trap type 00726 message->genericTrapType = genericTrapType; 00727 //Specific trap code 00728 message->specificTrapCode = specificTrapCode; 00729 //Timestamp 00730 message->timestamp = osGetSystemTime() / 10; 00731 } 00732 else 00733 #endif 00734 #if (SNMP_V2C_SUPPORT == ENABLED) 00735 //SNMPv2c version? 00736 if(version == SNMP_VERSION_2C) 00737 { 00738 //Community name 00739 message->community = username; 00740 message->communityLen = strlen(username); 00741 00742 //Prepare to send a SNMPv2-Trap-PDU 00743 message->pduType = SNMP_PDU_TRAP_V2; 00744 } 00745 else 00746 #endif 00747 #if (SNMP_V3_SUPPORT == ENABLED) 00748 //SNMPv3 version? 00749 if(version == SNMP_VERSION_3) 00750 { 00751 //Maximum message size supported by the sender 00752 message->msgMaxSize = SNMP_MAX_MSG_SIZE; 00753 00754 //Bit fields which control processing of the message 00755 if(context->user->authProtocol != SNMP_AUTH_PROTOCOL_NONE) 00756 message->msgFlags |= SNMP_MSG_FLAG_AUTH; 00757 if(context->user->privProtocol != SNMP_PRIV_PROTOCOL_NONE) 00758 message->msgFlags |= SNMP_MSG_FLAG_PRIV; 00759 00760 //Security model used by the sender 00761 message->msgSecurityModel = SNMP_SECURITY_MODEL_USM; 00762 00763 //Authoritative engine identifier 00764 message->msgAuthEngineId = context->contextEngine; 00765 message->msgAuthEngineIdLen = context->contextEngineLen; 00766 //Number of times the SNMP engine has rebooted 00767 message->msgAuthEngineBoots = context->engineBoots; 00768 //Number of seconds since last reboot 00769 message->msgAuthEngineTime = context->engineTime; 00770 //User name 00771 message->msgUserName = username; 00772 message->msgUserNameLen = strlen(username); 00773 //Authentication parameters 00774 message->msgAuthParameters = NULL; 00775 00776 //Length of the authentication parameters 00777 if(context->user->authProtocol == SNMP_AUTH_PROTOCOL_MD5) 00778 message->msgAuthParametersLen = 12; 00779 else if(context->user->authProtocol == SNMP_AUTH_PROTOCOL_SHA1) 00780 message->msgAuthParametersLen = 12; 00781 else if(context->user->authProtocol == SNMP_AUTH_PROTOCOL_SHA224) 00782 message->msgAuthParametersLen = 16; 00783 else if(context->user->authProtocol == SNMP_AUTH_PROTOCOL_SHA256) 00784 message->msgAuthParametersLen = 24; 00785 else if(context->user->authProtocol == SNMP_AUTH_PROTOCOL_SHA384) 00786 message->msgAuthParametersLen = 32; 00787 else if(context->user->authProtocol == SNMP_AUTH_PROTOCOL_SHA512) 00788 message->msgAuthParametersLen = 48; 00789 else 00790 message->msgAuthParametersLen = 0; 00791 00792 //Privacy parameters 00793 message->msgPrivParameters = context->privParameters; 00794 00795 //Length of the privacy parameters 00796 if(context->user->privProtocol == SNMP_PRIV_PROTOCOL_DES) 00797 message->msgPrivParametersLen = 8; 00798 else if(context->user->privProtocol == SNMP_PRIV_PROTOCOL_AES) 00799 message->msgPrivParametersLen = 8; 00800 else 00801 message->msgPrivParametersLen = 0; 00802 00803 //Context engine identifier 00804 message->contextEngineId = context->contextEngine; 00805 message->contextEngineIdLen = context->contextEngineLen; 00806 //Context name 00807 message->contextName = (uint8_t *) context->contextName; 00808 message->contextNameLen = strlen(context->contextName); 00809 00810 //Prepare to send a SNMPv2-Trap-PDU 00811 message->pduType = SNMP_PDU_TRAP_V2; 00812 } 00813 else 00814 #endif 00815 //Invalid SNMP version? 00816 { 00817 //Report an error 00818 return ERROR_INVALID_VERSION; 00819 } 00820 00821 //Make room for the message header at the beginning of the buffer 00822 error = snmpComputeMessageOverhead(&context->response); 00823 //Any error to report? 00824 if(error) 00825 return error; 00826 00827 #if (SNMP_V2C_SUPPORT == ENABLED || SNMP_V3_SUPPORT == ENABLED) 00828 //SNMPv2c or SNMPv3 version? 00829 if(version == SNMP_VERSION_2C || version == SNMP_VERSION_3) 00830 { 00831 //Get current time 00832 time = osGetSystemTime() / 10; 00833 00834 //Encode the object value using ASN.1 rules 00835 error = snmpEncodeUnsignedInt32(time, message->buffer, &n); 00836 //Any error to report? 00837 if(error) 00838 return error; 00839 00840 //The first two variable bindings in the variable binding list of an 00841 //SNMPv2-Trap-PDU are sysUpTime.0 and snmpTrapOID.0 respectively 00842 var.oid = sysUpTimeObject; 00843 var.oidLen = sizeof(sysUpTimeObject); 00844 var.objClass = ASN1_CLASS_APPLICATION; 00845 var.objType = MIB_TYPE_TIME_TICKS; 00846 var.value = message->buffer; 00847 var.valueLen = n; 00848 00849 //Append sysUpTime.0 to the variable binding list 00850 error = snmpWriteVarBinding(context, &var); 00851 //Any error to report? 00852 if(error) 00853 return error; 00854 00855 //Generic or enterprise-specific trap? 00856 if(genericTrapType < SNMP_TRAP_ENTERPRISE_SPECIFIC) 00857 { 00858 //Retrieve the length of the snmpTraps OID 00859 n = sizeof(snmpTrapsObject); 00860 //Copy the OID 00861 memcpy(message->buffer, snmpTrapsObject, n); 00862 00863 //For generic traps, the SNMPv2 snmpTrapOID parameter shall be 00864 //the corresponding trap as defined in section 2 of 3418 00865 message->buffer[n] = genericTrapType + 1; 00866 00867 //Update the length of the snmpTrapOID parameter 00868 n++; 00869 } 00870 else 00871 { 00872 //Retrieve the length of the enterprise OID 00873 n = context->enterpriseOidLen; 00874 00875 //For enterprise specific traps, the SNMPv2 snmpTrapOID parameter shall 00876 //be the concatenation of the SNMPv1 enterprise OID and two additional 00877 //sub-identifiers: '0' and the SNMPv1 specific trap parameter 00878 memcpy(message->buffer, context->enterpriseOid, n); 00879 00880 //Concatenate the '0' sub-identifier 00881 message->buffer[n++] = 0; 00882 00883 //Concatenate the specific trap parameter 00884 message->buffer[n] = specificTrapCode % 128; 00885 00886 //Loop as long as necessary 00887 for(i = 1; specificTrapCode > 128; i++) 00888 { 00889 //Split the binary representation into 7 bit chunks 00890 specificTrapCode /= 128; 00891 //Make room for the new chunk 00892 memmove(message->buffer + n + 1, message->buffer + n, i); 00893 //Set the most significant bit in the current chunk 00894 message->buffer[n] = OID_MORE_FLAG | (specificTrapCode % 128); 00895 } 00896 00897 //Update the length of the snmpTrapOID parameter 00898 n += i; 00899 } 00900 00901 //The snmpTrapOID.0 variable occurs as the second variable 00902 //binding in every SNMPv2-Trap-PDU 00903 var.oid = snmpTrapOidObject; 00904 var.oidLen = sizeof(snmpTrapOidObject); 00905 var.objClass = ASN1_CLASS_UNIVERSAL; 00906 var.objType = ASN1_TYPE_OBJECT_IDENTIFIER; 00907 var.value = message->buffer; 00908 var.valueLen = n; 00909 00910 //Append snmpTrapOID.0 to the variable binding list 00911 error = snmpWriteVarBinding(context, &var); 00912 //Any error to report? 00913 if(error) 00914 return error; 00915 } 00916 #endif 00917 00918 //Loop through the list of objects 00919 for(i = 0; i < objectListSize; i++) 00920 { 00921 //Get object identifier 00922 var.oid = objectList[i].oid; 00923 var.oidLen = objectList[i].oidLen; 00924 00925 //Retrieve object value 00926 error = snmpGetObjectValue(context, &var); 00927 //Any error to report? 00928 if(error) 00929 return error; 00930 00931 //Append variable binding to the list 00932 error = snmpWriteVarBinding(context, &var); 00933 //Any error to report? 00934 if(error) 00935 return error; 00936 } 00937 00938 //Total number of SNMP Trap PDUs which have been generated by 00939 //the SNMP protocol entity 00940 MIB2_INC_COUNTER32(mib2Base.snmpGroup.snmpOutTraps, 1); 00941 00942 //Format PDU header 00943 error = snmpWritePduHeader(&context->response); 00944 //Return status code 00945 return error; 00946 } 00947 00948 00949 /** 00950 * @brief Format Report-PDU 00951 * @param[in] context Pointer to the SNMP agent context 00952 * @param[in] errorIndication Error indication 00953 * @return Error code 00954 **/ 00955 00956 error_t snmpFormatReportPdu(SnmpAgentContext *context, error_t errorIndication) 00957 { 00958 error_t error; 00959 00960 #if (SNMP_V3_SUPPORT == ENABLED) 00961 size_t n; 00962 SnmpVarBind var; 00963 00964 //Initialize SNMP message 00965 snmpInitMessage(&context->response); 00966 00967 //SNMP version identifier 00968 context->response.version = context->request.version; 00969 00970 //Message identifier 00971 context->response.msgId = context->request.msgId; 00972 //Maximum message size supported by the sender 00973 context->response.msgMaxSize = SNMP_MAX_MSG_SIZE; 00974 //Bit fields which control processing of the message 00975 context->response.msgFlags = 0; 00976 //Security model used by the sender 00977 context->response.msgSecurityModel = SNMP_SECURITY_MODEL_USM; 00978 00979 //Authoritative engine identifier 00980 context->response.msgAuthEngineId = context->contextEngine; 00981 context->response.msgAuthEngineIdLen = context->contextEngineLen; 00982 //Number of times the SNMP engine has rebooted 00983 context->response.msgAuthEngineBoots = context->engineBoots; 00984 //Number of seconds since last reboot 00985 context->response.msgAuthEngineTime = context->engineTime; 00986 00987 //Context engine identifier 00988 context->response.contextEngineId = context->contextEngine; 00989 context->response.contextEngineIdLen = context->contextEngineLen; 00990 //Context name 00991 context->response.contextName = (uint8_t *) context->contextName; 00992 context->response.contextNameLen = strlen(context->contextName); 00993 00994 //PDU type 00995 context->response.pduType = SNMP_PDU_REPORT; 00996 //Request identifier 00997 context->response.requestId = context->request.requestId; 00998 00999 //Make room for the message header at the beginning of the buffer 01000 error = snmpComputeMessageOverhead(&context->response); 01001 //Any error to report? 01002 if(error) 01003 return error; 01004 01005 //Encode the object value using ASN.1 rules 01006 error = snmpEncodeUnsignedInt32(1, context->response.buffer, &n); 01007 //Any error to report? 01008 if(error) 01009 return error; 01010 01011 //Check error indication 01012 switch(errorIndication) 01013 { 01014 case ERROR_UNSUPPORTED_SECURITY_LEVEL: 01015 //Add the usmStatsUnsupportedSecLevels counter in the varBindList 01016 var.oid = usmStatsUnsupportedSecLevelsObject; 01017 var.oidLen = sizeof(usmStatsUnsupportedSecLevelsObject); 01018 break; 01019 case ERROR_NOT_IN_TIME_WINDOW: 01020 //Add the usmStatsNotInTimeWindows counter in the varBindList 01021 var.oid = usmStatsNotInTimeWindowsObject; 01022 var.oidLen = sizeof(usmStatsNotInTimeWindowsObject); 01023 break; 01024 case ERROR_UNKNOWN_USER_NAME: 01025 //Add the usmStatsUnknownUserNames counter in the varBindList 01026 var.oid = usmStatsUnknownUserNamesObject; 01027 var.oidLen = sizeof(usmStatsUnknownUserNamesObject); 01028 break; 01029 case ERROR_UNKNOWN_ENGINE_ID: 01030 //Add the usmStatsUnknownEngineIDs counter in the varBindList 01031 var.oid = usmStatsUnknownEngineIdsObject; 01032 var.oidLen = sizeof(usmStatsUnknownEngineIdsObject); 01033 break; 01034 case ERROR_AUTHENTICATION_FAILED: 01035 //Add the usmStatsWrongDigests counter in the varBindList 01036 var.oid = usmStatsWrongDigestsObject; 01037 var.oidLen = sizeof(usmStatsWrongDigestsObject); 01038 break; 01039 case ERROR_DECRYPTION_FAILED: 01040 //Add the usmStatsDecryptionErrors counter in the varBindList 01041 var.oid = usmStatsDecryptionErrorsObject; 01042 var.oidLen = sizeof(usmStatsDecryptionErrorsObject); 01043 break; 01044 default: 01045 //Just for sanity's sake... 01046 var.oid = NULL; 01047 var.oidLen = 0; 01048 break; 01049 } 01050 01051 //The counter is encoded in ASN.1 format 01052 var.objClass = ASN1_CLASS_APPLICATION; 01053 var.objType = MIB_TYPE_COUNTER32; 01054 var.value = context->response.buffer; 01055 var.valueLen = n; 01056 01057 //Append the variable binding list to the varBindList 01058 error = snmpWriteVarBinding(context, &var); 01059 //Any error to report? 01060 if(error) 01061 return error; 01062 01063 //Format PDU header 01064 error = snmpWritePduHeader(&context->response); 01065 #else 01066 //SNMPv3 is not supported 01067 error = ERROR_NOT_IMPLEMENTED; 01068 #endif 01069 01070 //Return status code 01071 return error; 01072 } 01073 01074 #endif 01075
Generated on Tue Jul 12 2022 17:10:16 by
