Embed:
(wiki syntax)
Show/hide line numbers
snmp_agent_dispatch.c
Go to the documentation of this file.
00001 /** 00002 * @file snmp_agent_dispatch.c 00003 * @brief SNMP message dispatching 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_dispatch.h" 00036 #include "snmp/snmp_agent_pdu.h" 00037 #include "snmp/snmp_agent_misc.h" 00038 #include "mibs/mib2_module.h" 00039 #include "crypto.h" 00040 #include "asn1.h" 00041 #include "oid.h" 00042 #include "debug.h" 00043 00044 //Check TCP/IP stack configuration 00045 #if (SNMP_AGENT_SUPPORT == ENABLED) 00046 00047 00048 /** 00049 * @brief Process incoming SNMP message 00050 * @param[in] context Pointer to the SNMP agent context 00051 * @return Error code 00052 **/ 00053 00054 error_t snmpProcessMessage(SnmpAgentContext *context) 00055 { 00056 error_t error; 00057 00058 //Total number of messages delivered to the SNMP entity from the 00059 //transport service 00060 MIB2_INC_COUNTER32(mib2Base.snmpGroup.snmpInPkts, 1); 00061 00062 //Refresh SNMP engine time 00063 snmpRefreshEngineTime(context); 00064 00065 //Message parsing initialization 00066 snmpInitMessage(&context->request); 00067 00068 //Parse SNMP message header 00069 error = snmpParseMessageHeader(&context->request); 00070 //Any error to report? 00071 if(error) 00072 return error; 00073 00074 //The SNMP agent verifies the version number. If there is a mismatch, 00075 //it discards the datagram and performs no further actions 00076 if(context->request.version < context->settings.versionMin || 00077 context->request.version > context->settings.versionMax) 00078 { 00079 //Debug message 00080 TRACE_WARNING(" Invalid SNMP version!\r\n"); 00081 //Discard incoming SNMP message 00082 return ERROR_INVALID_VERSION; 00083 } 00084 00085 #if (SNMP_V1_SUPPORT == ENABLED) 00086 //SNMPv1 version? 00087 if(context->request.version == SNMP_VERSION_1) 00088 { 00089 //Process incoming SNMPv1 message 00090 error = snmpv1ProcessMessage(context); 00091 } 00092 else 00093 #endif 00094 #if (SNMP_V2C_SUPPORT == ENABLED) 00095 //SNMPv2c version? 00096 if(context->request.version == SNMP_VERSION_2C) 00097 { 00098 //Process incoming SNMPv2c message 00099 error = snmpv2cProcessMessage(context); 00100 } 00101 else 00102 #endif 00103 #if (SNMP_V3_SUPPORT == ENABLED) 00104 //SNMPv3 version? 00105 if(context->request.version == SNMP_VERSION_3) 00106 { 00107 //Process incoming SNMPv3 message 00108 error = snmpv3ProcessMessage(context); 00109 } 00110 else 00111 #endif 00112 //Invalid SNMP version? 00113 { 00114 //Debug message 00115 TRACE_WARNING(" Invalid SNMP version!\r\n"); 00116 00117 //Total number of SNMP messages which were delivered to the SNMP 00118 //protocol entity and were for an unsupported SNMP version 00119 MIB2_INC_COUNTER32(mib2Base.snmpGroup.snmpInBadVersions, 1); 00120 00121 //Discard incoming SNMP message 00122 error = ERROR_INVALID_VERSION; 00123 } 00124 00125 //Check status code 00126 if(error == NO_ERROR) 00127 { 00128 //Total number of messages which were passed from the SNMP protocol 00129 //entity to the transport service 00130 MIB2_INC_COUNTER32(mib2Base.snmpGroup.snmpOutPkts, 1); 00131 } 00132 else if(error == ERROR_INVALID_TAG) 00133 { 00134 //Total number of ASN.1 or BER errors encountered by the SNMP protocol 00135 //entity when decoding received SNMP messages 00136 MIB2_INC_COUNTER32(mib2Base.snmpGroup.snmpInASNParseErrs, 1); 00137 } 00138 00139 //Return status code 00140 return error; 00141 } 00142 00143 00144 /** 00145 * @brief Process incoming SNMPv1 message 00146 * @param[in] context Pointer to the SNMP agent context 00147 * @return Error code 00148 **/ 00149 00150 error_t snmpv1ProcessMessage(SnmpAgentContext *context) 00151 { 00152 error_t error; 00153 00154 #if (SNMP_V1_SUPPORT == ENABLED) 00155 //Parse community name 00156 error = snmpParseCommunity(&context->request); 00157 //Any error to report? 00158 if(error) 00159 return error; 00160 00161 //Information about the community name is extracted from the local 00162 //configuration datastore 00163 context->user = snmpFindUser(context, context->request.community, 00164 context->request.communityLen); 00165 00166 //Invalid community name? 00167 if(context->user == NULL) 00168 { 00169 //Debug message 00170 TRACE_WARNING(" Invalid community name!\r\n"); 00171 00172 //Total number of SNMP messages delivered to the SNMP protocol entity 00173 //which used a SNMP community name not known to said entity 00174 MIB2_INC_COUNTER32(mib2Base.snmpGroup.snmpInBadCommunityNames, 1); 00175 00176 //Report an error 00177 return ERROR_UNKNOWN_USER_NAME; 00178 } 00179 00180 //Process PDU 00181 error = snmpProcessPdu(context); 00182 //Any error to report? 00183 if(error) 00184 return error; 00185 00186 //Format SNMP message header 00187 error = snmpWriteMessageHeader(&context->response); 00188 #else 00189 //Report an error 00190 error = ERROR_INVALID_VERSION; 00191 #endif 00192 00193 //Return status code 00194 return error; 00195 } 00196 00197 00198 /** 00199 * @brief Process incoming SNMPv2c message 00200 * @param[in] context Pointer to the SNMP agent context 00201 * @return Error code 00202 **/ 00203 00204 error_t snmpv2cProcessMessage(SnmpAgentContext *context) 00205 { 00206 error_t error; 00207 00208 #if (SNMP_V2C_SUPPORT == ENABLED) 00209 //Parse community name 00210 error = snmpParseCommunity(&context->request); 00211 //Any error to report? 00212 if(error) 00213 return error; 00214 00215 //Information about the community name is extracted from the local 00216 //configuration datastore 00217 context->user = snmpFindUser(context, context->request.community, 00218 context->request.communityLen); 00219 00220 //Invalid community name? 00221 if(context->user == NULL) 00222 { 00223 //Debug message 00224 TRACE_WARNING(" Invalid community name!\r\n"); 00225 00226 //Total number of SNMP messages delivered to the SNMP protocol entity 00227 //which used a SNMP community name not known to said entity 00228 MIB2_INC_COUNTER32(mib2Base.snmpGroup.snmpInBadCommunityNames, 1); 00229 00230 //Report an error 00231 return ERROR_UNKNOWN_USER_NAME; 00232 } 00233 00234 //Process PDU 00235 error = snmpProcessPdu(context); 00236 //Any error to report? 00237 if(error) 00238 return error; 00239 00240 //Format SNMP message header 00241 error = snmpWriteMessageHeader(&context->response); 00242 #else 00243 //Report an error 00244 error = ERROR_INVALID_VERSION; 00245 #endif 00246 00247 //Return status code 00248 return error; 00249 } 00250 00251 00252 /** 00253 * @brief Process incoming SNMPv3 message 00254 * @param[in] context Pointer to the SNMP agent context 00255 * @return Error code 00256 **/ 00257 00258 error_t snmpv3ProcessMessage(SnmpAgentContext *context) 00259 { 00260 error_t error; 00261 00262 #if (SNMP_V3_SUPPORT == ENABLED) 00263 //Parse msgGlobalData field 00264 error = snmpParseGlobalData(&context->request); 00265 //Any error to report? 00266 if(error) 00267 return error; 00268 00269 //Parse msgSecurityParameters field 00270 error = snmpParseSecurityParameters(&context->request); 00271 //Any error to report? 00272 if(error) 00273 return error; 00274 00275 //Start of exception handling block 00276 do 00277 { 00278 //Information about the value of the msgUserName field is extracted 00279 //from the local configuration datastore 00280 context->user = snmpFindUser(context, context->request.msgUserName, 00281 context->request.msgUserNameLen); 00282 00283 //Check security parameters 00284 error = snmpCheckSecurityParameters(context->user, &context->request, 00285 context->contextEngine, context->contextEngineLen); 00286 //Invalid security parameters? 00287 if(error) 00288 break; 00289 00290 //Check whether the authFlag is set 00291 if(context->request.msgFlags & SNMP_MSG_FLAG_AUTH) 00292 { 00293 //Authenticate incoming SNMP message 00294 error = snmpAuthIncomingMessage(context->user, &context->request); 00295 //Data authentication failed? 00296 if(error) 00297 break; 00298 00299 //Replay protection 00300 error = snmpCheckEngineTime(context, &context->request); 00301 //Message outside of the time window? 00302 if(error) 00303 break; 00304 } 00305 00306 //Check whether the privFlag is set 00307 if(context->request.msgFlags & SNMP_MSG_FLAG_PRIV) 00308 { 00309 //Decrypt data 00310 error = snmpDecryptData(context->user, &context->request); 00311 //Data decryption failed? 00312 if(error) 00313 break; 00314 } 00315 00316 //End of exception handling block 00317 } while(0); 00318 00319 //Check error indication 00320 if(error == ERROR_UNSUPPORTED_SECURITY_LEVEL || 00321 error == ERROR_NOT_IN_TIME_WINDOW || 00322 error == ERROR_UNKNOWN_USER_NAME || 00323 error == ERROR_UNKNOWN_ENGINE_ID || 00324 error == ERROR_AUTHENTICATION_FAILED || 00325 error == ERROR_DECRYPTION_FAILED) 00326 { 00327 //Report the error indication to the remote SNMP engine using a Report-PDU 00328 error = snmpFormatReportPdu(context, error); 00329 //Any error to report? 00330 if(error) 00331 return error; 00332 } 00333 else if(error == NO_ERROR) 00334 { 00335 //Parse scopedPDU 00336 error = snmpParseScopedPdu(&context->request); 00337 //Any error to report? 00338 if(error) 00339 return error; 00340 00341 //Process PDU 00342 error = snmpProcessPdu(context); 00343 //Any error to report? 00344 if(error) 00345 return error; 00346 } 00347 else 00348 { 00349 //Stop processing 00350 return error; 00351 } 00352 00353 //Format scopedPDU 00354 error = snmpWriteScopedPdu(&context->response); 00355 //Any error to report? 00356 if(error) 00357 return error; 00358 00359 //Check whether the privFlag is set 00360 if(context->response.msgFlags & SNMP_MSG_FLAG_PRIV) 00361 { 00362 //Encrypt data 00363 error = snmpEncryptData(context->user, &context->response, &context->salt); 00364 //Any error to report? 00365 if(error) 00366 return error; 00367 } 00368 00369 //Format SNMP message header 00370 error = snmpWriteMessageHeader(&context->response); 00371 //Any error to report? 00372 if(error) 00373 return error; 00374 00375 //Check whether the authFlag is set 00376 if(context->response.msgFlags & SNMP_MSG_FLAG_AUTH) 00377 { 00378 //Authenticate outgoing SNMP message 00379 error = snmpAuthOutgoingMessage(context->user, &context->response); 00380 //Any error to report? 00381 if(error) 00382 return error; 00383 } 00384 #else 00385 //Report an error 00386 error = ERROR_INVALID_VERSION; 00387 #endif 00388 00389 //Return status code 00390 return error; 00391 } 00392 00393 #endif 00394
Generated on Tue Jul 12 2022 17:10:16 by
