snmp_agent_pdu.c
Go to the documentation of this file.
1 /**
2  * @file snmp_agent_pdu.c
3  * @brief SNMP agent (PDU processing)
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.4.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL SNMP_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/net.h"
36 #include "snmp/snmp_agent.h"
37 #include "snmp/snmp_agent_pdu.h"
38 #include "snmp/snmp_agent_misc.h"
39 #include "snmp/snmp_agent_object.h"
40 #include "mibs/mib2_module.h"
41 #include "mibs/snmp_mib_module.h"
43 #include "core/crypto.h"
44 #include "encoding/asn1.h"
45 #include "encoding/oid.h"
46 #include "debug.h"
47 
48 //Check TCP/IP stack configuration
49 #if (SNMP_AGENT_SUPPORT == ENABLED)
50 
51 //snmpUnavailableContexts.0 object (1.3.6.1.6.3.12.1.4.0)
52 const uint8_t snmpUnavailableContextsObject[9] = {43, 6, 1, 6, 3, 12, 1, 4, 0};
53 //snmpUnknownContexts.0 object (1.3.6.1.6.3.12.1.5.0)
54 const uint8_t snmpUnknownContextsObject[9] = {43, 6, 1, 6, 3, 12, 1, 5, 0};
55 
56 
57 /**
58  * @brief Process PDU
59  * @param[in] context Pointer to the SNMP agent context
60  * @return Error code
61  **/
62 
64 {
65  error_t error;
66 
67  //Parse PDU header
68  error = snmpParsePduHeader(&context->request);
69  //Any error to report?
70  if(error)
71  return error;
72 
73  //Initialize response message
74  snmpInitMessage(&context->response);
75 
76  //Check PDU type
77  switch(context->request.pduType)
78  {
81  //Process GetRequest-PDU or GetNextRequest-PDU
82  error = snmpProcessGetRequestPdu(context);
83  break;
85  //Process GetBulkRequest-PDU
86  error = snmpProcessGetBulkRequestPdu(context);
87  break;
89  //Process SetRequest-PDU
90  error = snmpProcessSetRequestPdu(context);
91  break;
92 #if (SNMP_AGENT_INFORM_SUPPORT == ENABLED)
94  //Process GetResponse-PDU
95  error = snmpProcessGetResponsePdu(context);
96  break;
97  case SNMP_PDU_REPORT:
98  //Process Report-PDU
99  error = snmpProcessReportPdu(context);
100  break;
101 #endif
102  default:
103  //Invalid PDU type
104  error = ERROR_INVALID_TYPE;
105  break;
106  }
107 
108  //Check status code
109  if(!error)
110  {
111  //A GetResponse-PDU is generated by a protocol entity only upon receipt
112  //of the GetRequest-PDU, GetNextRequest-PDU, GetBulkRequest-PDU or
113  //SetRequest-PDU
114  if(context->request.pduType == SNMP_PDU_GET_REQUEST ||
115  context->request.pduType == SNMP_PDU_GET_NEXT_REQUEST ||
116  context->request.pduType == SNMP_PDU_GET_BULK_REQUEST ||
117  context->request.pduType == SNMP_PDU_SET_REQUEST)
118  {
119  //Total number of SNMP Get-Response PDUs which have been generated
120  //by the SNMP protocol entity
121  MIB2_SNMP_INC_COUNTER32(snmpOutGetResponses, 1);
122 
123  //Format PDU header
124  error = snmpWritePduHeader(&context->response);
125  }
126  }
127 
128  //Return status code
129  return error;
130 }
131 
132 
133 /**
134  * @brief Process GetRequest-PDU or GetNextRequest-PDU
135  * @param[in] context Pointer to the SNMP agent context
136  * @return Error code
137  **/
138 
140 {
141  error_t error;
142  int_t index;
143  size_t n;
144  size_t length;
145  const uint8_t *p;
146  SnmpVarBind var;
147 
148  //Check PDU type
149  if(context->request.pduType == SNMP_PDU_GET_REQUEST)
150  {
151  //Debug message
152  TRACE_INFO("Parsing GetRequest-PDU...\r\n");
153 
154  //Total number of SNMP Get-Request PDUs which have been accepted and
155  //processed by the SNMP protocol entity
156  MIB2_SNMP_INC_COUNTER32(snmpInGetRequests, 1);
157  }
158  else if(context->request.pduType == SNMP_PDU_GET_NEXT_REQUEST)
159  {
160  //Debug message
161  TRACE_INFO("Parsing GetNextRequest-PDU...\r\n");
162 
163  //Total number of SNMP Get-NextRequest PDUs which have been accepted
164  //and processed by the SNMP protocol entity
165  MIB2_SNMP_INC_COUNTER32(snmpInGetNexts, 1);
166  }
167 
168  //Enforce access policy
169  if(context->user.mode != SNMP_ACCESS_READ_ONLY &&
170  context->user.mode != SNMP_ACCESS_READ_WRITE)
171  {
172  //Total number of SNMP messages delivered to the SNMP protocol entity
173  //which represented an SNMP operation which was not allowed by the SNMP
174  MIB2_SNMP_INC_COUNTER32(snmpInBadCommunityUses, 1);
175  SNMP_MIB_INC_COUNTER32(snmpGroup.snmpInBadCommunityUses, 1);
176 
177  //Report an error
178  return ERROR_ACCESS_DENIED;
179  }
180 
181  //Initialize response message
182  error = snmpInitResponse(context);
183  //Any error to report?
184  if(error)
185  return error;
186 
187  //Point to the first variable binding of the request
188  p = context->request.varBindList;
189  length = context->request.varBindListLen;
190 
191  //Lock access to MIB bases
192  snmpLockMib(context);
193 
194  //Loop through the list
195  for(index = 1; length > 0; index++)
196  {
197  //Parse variable binding
198  error = snmpParseVarBinding(p, length, &var, &n);
199  //Failed to parse variable binding?
200  if(error)
201  break;
202 
203  //Make sure that the object identifier is valid
204  error = oidCheck(var.oid, var.oidLen);
205  //Invalid object identifier?
206  if(error)
207  break;
208 
209  //GetRequest-PDU?
210  if(context->request.pduType == SNMP_PDU_GET_REQUEST)
211  {
212  //Retrieve object value
213  error = snmpGetObjectValue(context, &context->request, &var);
214  }
215  //GetNextRequest-PDU?
216  else
217  {
218  //Search the MIB for the next object
219  error = snmpGetNextObject(context, &context->request, &var);
220 
221  //SNMPv1 version?
222  if(context->request.version == SNMP_VERSION_1)
223  {
224  //Check status code
225  if(error == NO_ERROR)
226  {
227  //Retrieve object value
228  error = snmpGetObjectValue(context, &context->request, &var);
229  }
230  else
231  {
232  //Stop immediately
233  break;
234  }
235  }
236  //SNMPv2c or SNMPv3 version?
237  else
238  {
239  //Check status code
240  if(error == NO_ERROR)
241  {
242  //Retrieve object value
243  error = snmpGetObjectValue(context, &context->request, &var);
244  }
245  else if(error == ERROR_OBJECT_NOT_FOUND)
246  {
247  //The variable binding's value field is set to endOfMibView
250  var.valueLen = 0;
251 
252  //Catch exception
253  error = NO_ERROR;
254  }
255  else
256  {
257  //Stop immediately
258  break;
259  }
260  }
261  }
262 
263  //Failed to retrieve object value?
264  if(error)
265  {
266  //SNMPv1 version?
267  if(context->request.version == SNMP_VERSION_1)
268  {
269  //Stop immediately
270  break;
271  }
272  //SNMPv2c or SNMPv3 version?
273  else
274  {
275  //Catch exception
276  if(error == ERROR_ACCESS_DENIED ||
277  error == ERROR_OBJECT_NOT_FOUND)
278  {
279  //The variable binding's value field is set to noSuchObject
282  var.valueLen = 0;
283  }
284  else if(error == ERROR_INSTANCE_NOT_FOUND)
285  {
286  //The variable binding's value field is set to noSuchInstance
289  var.valueLen = 0;
290  }
291  else
292  {
293  //Stop immediately
294  break;
295  }
296  }
297  }
298  else
299  {
300  //Total number of MIB objects which have been retrieved successfully
301  //by the SNMP protocol entity as the result of receiving valid SNMP
302  //Get-Request and Get-NextRequest PDUs
303  MIB2_SNMP_INC_COUNTER32(snmpInTotalReqVars, 1);
304  }
305 
306  //Append variable binding to the list
307  error = snmpWriteVarBinding(context, &var);
308  //Any error to report?
309  if(error)
310  break;
311 
312  //Advance data pointer
313  p += n;
314  length -= n;
315  }
316 
317  //Unlock access to MIB bases
318  snmpUnlockMib(context);
319 
320  //Check status code
321  if(error)
322  {
323  //Set error-status and error-index fields
324  error = snmpTranslateStatusCode(&context->response, error, index);
325  //If the parsing of the request fails, the SNMP agent discards the message
326  if(error)
327  return error;
328 
329  //Check whether an alternate Response-PDU should be sent
330  if(context->response.version != SNMP_VERSION_1 &&
331  context->response.errorStatus == SNMP_ERROR_TOO_BIG)
332  {
333  //The alternate Response-PDU is formatted with the same value in its
334  //request-id field as the received GetRequest-PDU and an empty
335  //variable-bindings field
336  context->response.varBindListLen = 0;
337  }
338  else
339  {
340  //The Response-PDU is re-formatted with the same values in its request-id
341  //and variable-bindings fields as the received GetRequest-PDU
342  error = snmpCopyVarBindingList(context);
343  //Any error to report?
344  if(error)
345  return error;
346  }
347  }
348 
349  //Successful processing
350  return NO_ERROR;
351 }
352 
353 
354 /**
355  * @brief Process GetBulkRequest-PDU
356  * @param[in] context Pointer to the SNMP agent context
357  * @return Error code
358  **/
359 
361 {
362 #if (SNMP_V2C_SUPPORT == ENABLED || SNMP_V3_SUPPORT == ENABLED)
363  error_t error;
364  int_t index;
365  size_t n;
366  size_t m;
367  size_t length;
368  bool_t endOfMibView;
369  const uint8_t *p;
370  const uint8_t *next;
371  SnmpVarBind var;
372 
373  //Debug message
374  TRACE_INFO("Parsing GetBulkRequest-PDU...\r\n");
375 
376  //Initialize variables
377  m = 0;
378  endOfMibView = FALSE;
379  next = NULL;
380 
381  //Make sure the SNMP version identifier is valid
382  if(context->request.version == SNMP_VERSION_1)
383  {
384  //The SNMP version is not acceptable
385  return ERROR_INVALID_TYPE;
386  }
387 
388  //Enforce access policy
389  if(context->user.mode != SNMP_ACCESS_READ_ONLY &&
390  context->user.mode != SNMP_ACCESS_READ_WRITE)
391  {
392  //Total number of SNMP messages delivered to the SNMP protocol entity
393  //which represented an SNMP operation which was not allowed by the SNMP
394  MIB2_SNMP_INC_COUNTER32(snmpInBadCommunityUses, 1);
395  SNMP_MIB_INC_COUNTER32(snmpGroup.snmpInBadCommunityUses, 1);
396 
397  //Report an error
398  return ERROR_ACCESS_DENIED;
399  }
400 
401  //Initialize response message
402  error = snmpInitResponse(context);
403  //Any error to report?
404  if(error)
405  return error;
406 
407  //Point to the first variable binding of the request
408  p = context->request.varBindList;
409  length = context->request.varBindListLen;
410 
411  //Lock access to MIB bases
412  snmpLockMib(context);
413 
414  //Loop through the list
415  for(index = 1; length > 0; index++)
416  {
417  //The non-repeaters field specifies the number of non-repeating objects
418  //at the start of the variable binding list
419  if((index - 1) == context->request.nonRepeaters)
420  {
421  //Pointer to the first variable binding that will be processed during
422  //the next iteration
423  next = context->response.varBindList + context->response.varBindListLen;
424 
425  //Actual size of the variable binding list
426  m = context->response.varBindListLen;
427 
428  //This flag tells whether all variable bindings have the value field
429  //set to endOfMibView for a given iteration
430  endOfMibView = TRUE;
431 
432  //If the max-repetitions field is zero, the list is trimmed to the
433  //first non-repeating variable bindings
434  if(context->request.maxRepetitions == 0)
435  break;
436  }
437 
438  //Parse variable binding
439  error = snmpParseVarBinding(p, length, &var, &n);
440  //Failed to parse variable binding?
441  if(error)
442  break;
443 
444  //Make sure that the object identifier is valid
445  error = oidCheck(var.oid, var.oidLen);
446  //Invalid object identifier?
447  if(error)
448  break;
449 
450  //Search the MIB for the next object
451  error = snmpGetNextObject(context, &context->request, &var);
452 
453  //Check status code
454  if(error == NO_ERROR)
455  {
456  //Next object found
457  endOfMibView = FALSE;
458  //Retrieve object value
459  error = snmpGetObjectValue(context, &context->request, &var);
460  }
461  else if(error == ERROR_OBJECT_NOT_FOUND)
462  {
463  //The variable binding's value field is set to endOfMibView
466  var.valueLen = 0;
467 
468  //Catch exception
469  error = NO_ERROR;
470  }
471  else
472  {
473  //Stop immediately
474  break;
475  }
476 
477  //Failed to retrieve object value?
478  if(error)
479  {
480  //Catch exception
481  if(error == ERROR_ACCESS_DENIED ||
482  error == ERROR_OBJECT_NOT_FOUND)
483  {
484  //The variable binding's value field is set to noSuchObject
487  var.valueLen = 0;
488  }
489  else if(error == ERROR_INSTANCE_NOT_FOUND)
490  {
491  //The variable binding's value field is set to noSuchInstance
494  var.valueLen = 0;
495  }
496  else
497  {
498  //Stop immediately
499  break;
500  }
501  }
502  else
503  {
504  //Total number of MIB objects which have been retrieved successfully
505  //by the SNMP protocol entity as the result of receiving valid SNMP
506  //Get-Request and Get-NextRequest PDUs
507  MIB2_SNMP_INC_COUNTER32(snmpInTotalReqVars, 1);
508  }
509 
510  //Append variable binding to the list
511  error = snmpWriteVarBinding(context, &var);
512  //Any error to report?
513  if(error)
514  break;
515 
516  //Advance data pointer
517  p += n;
518  length -= n;
519 
520  //Next iteration?
521  if(length == 0 && index > context->request.nonRepeaters)
522  {
523  //Decrement repeat counter
524  context->request.maxRepetitions--;
525 
526  //Last iteration?
527  if(!context->request.maxRepetitions)
528  break;
529  //All variable bindings have the value field set to endOfMibView?
530  if(endOfMibView)
531  break;
532 
533  //Point to the first variable binding to be processed
534  p = next;
535  //Number of bytes to be processed
536  length = context->response.varBindListLen - m;
537  //Rewind index
538  index = context->request.nonRepeaters;
539  }
540  }
541 
542  //Unlock access to MIB bases
543  snmpUnlockMib(context);
544 
545  //Check status code
546  if(error == ERROR_BUFFER_OVERFLOW)
547  {
548  //If the size of the message containing the requested number of variable
549  //bindings would be greater than the maximum message size, then the
550  //response is generated with a lesser number of variable bindings
551  }
552  else if(error)
553  {
554  //Set error-status and error-index fields
555  error = snmpTranslateStatusCode(&context->response, error, index);
556  //If the parsing of the request fails, the SNMP agent discards the message
557  if(error)
558  return error;
559 
560  //The Response-PDU is re-formatted with the same values in its request-id
561  //and variable-bindings fields as the received GetRequest-PDU
562  error = snmpCopyVarBindingList(context);
563  //Any error to report?
564  if(error)
565  return error;
566  }
567 
568  //Successful processing
569  return NO_ERROR;
570 #else
571  //Not implemented
572  return ERROR_NOT_IMPLEMENTED;
573 #endif
574 }
575 
576 
577 /**
578  * @brief Process SetRequest-PDU
579  * @param[in] context Pointer to the SNMP agent context
580  * @return Error code
581  **/
582 
584 {
585  error_t error;
586  int_t index;
587  size_t n;
588  size_t length;
589  const uint8_t *p;
590  SnmpVarBind var;
591 
592  //Debug message
593  TRACE_INFO("Parsing SetRequest-PDU...\r\n");
594 
595  //Total number of SNMP Set-Request PDUs which have been accepted and
596  //processed by the SNMP protocol entity
597  MIB2_SNMP_INC_COUNTER32(snmpInSetRequests, 1);
598 
599  //Enforce access policy
600  if(context->user.mode != SNMP_ACCESS_WRITE_ONLY &&
601  context->user.mode != SNMP_ACCESS_READ_WRITE)
602  {
603  //Total number of SNMP messages delivered to the SNMP protocol entity
604  //which represented an SNMP operation which was not allowed by the SNMP
605  MIB2_SNMP_INC_COUNTER32(snmpInBadCommunityUses, 1);
606  SNMP_MIB_INC_COUNTER32(snmpGroup.snmpInBadCommunityUses, 1);
607 
608  //Report an error
609  return ERROR_ACCESS_DENIED;
610  }
611 
612  //Initialize response message
613  error = snmpInitResponse(context);
614  //Any error to report?
615  if(error)
616  return error;
617 
618  //The variable bindings are processed as a two phase operation. In the
619  //first phase, each variable binding is validated
620  p = context->request.varBindList;
621  length = context->request.varBindListLen;
622 
623  //Lock access to MIB bases
624  snmpLockMib(context);
625 
626  //Loop through the list
627  for(index = 1; length > 0; index++)
628  {
629  //Parse variable binding
630  error = snmpParseVarBinding(p, length, &var, &n);
631  //Failed to parse variable binding?
632  if(error)
633  break;
634 
635  //Assign object value
636  error = snmpSetObjectValue(context, &context->request, &var, FALSE);
637  //Any error to report?
638  if(error)
639  break;
640 
641  //Advance data pointer
642  p += n;
643  length -= n;
644  }
645 
646  //If all validations are successful, then each variable is altered in
647  //the second phase
648  if(!error)
649  {
650  //The changes are committed to the MIB base during the second phase
651  p = context->request.varBindList;
652  length = context->request.varBindListLen;
653 
654  //Loop through the list
655  for(index = 1; length > 0; index++)
656  {
657  //Parse variable binding
658  error = snmpParseVarBinding(p, length, &var, &n);
659  //Failed to parse variable binding?
660  if(error)
661  break;
662 
663  //Assign object value
664  error = snmpSetObjectValue(context, &context->request, &var, TRUE);
665  //Any error to report?
666  if(error)
667  break;
668 
669  //Total number of MIB objects which have been altered successfully
670  //by the SNMP protocol entity as the result of receiving valid
671  //SNMP Set-Request PDUs
672  MIB2_SNMP_INC_COUNTER32(snmpInTotalSetVars, 1);
673 
674  //Advance data pointer
675  p += n;
676  length -= n;
677  }
678  }
679 
680  //Unlock access to MIB bases
681  snmpUnlockMib(context);
682 
683  //Any error to report?
684  if(error)
685  {
686  //Set error-status and error-index fields
687  error = snmpTranslateStatusCode(&context->response, error, index);
688  //If the parsing of the request fails, the SNMP agent discards the message
689  if(error)
690  return error;
691  }
692 
693  //The SNMP agent sends back a GetResponse-PDU of identical form
694  error = snmpCopyVarBindingList(context);
695  //Return status code
696  return error;
697 }
698 
699 
700 /**
701  * @brief Format Report-PDU
702  * @param[in] context Pointer to the SNMP agent context
703  * @param[in] errorIndication Error indication
704  * @return Error code
705  **/
706 
708 {
709  error_t error;
710 
711 #if (SNMP_V3_SUPPORT == ENABLED)
712  size_t n;
713  uint32_t counter;
714  SnmpVarBind var;
715 
716  //Initialize SNMP message
717  snmpInitMessage(&context->response);
718 
719  //SNMP version identifier
720  context->response.version = context->request.version;
721 
722  //Message identifier
723  context->response.msgId = context->request.msgId;
724  //Maximum message size supported by the sender
725  context->response.msgMaxSize = SNMP_MAX_MSG_SIZE;
726  //Bit fields which control processing of the message
727  context->response.msgFlags = 0;
728  //Security model used by the sender
729  context->response.msgSecurityModel = SNMP_SECURITY_MODEL_USM;
730 
731  //Authoritative engine identifier
732  context->response.msgAuthEngineId = context->contextEngine;
733  context->response.msgAuthEngineIdLen = context->contextEngineLen;
734 
735  //Number of times the SNMP engine has rebooted
736  context->response.msgAuthEngineBoots = context->engineBoots;
737  //Number of seconds since last reboot
738  context->response.msgAuthEngineTime = context->engineTime;
739 
740  //Context engine identifier
741  context->response.contextEngineId = context->contextEngine;
742  context->response.contextEngineIdLen = context->contextEngineLen;
743 
744  //Context name
745  context->response.contextName = context->contextName;
746  context->response.contextNameLen = osStrlen(context->contextName);
747 
748  //PDU type
749  context->response.pduType = SNMP_PDU_REPORT;
750  //Request identifier
751  context->response.requestId = context->request.requestId;
752 
753  //If the message is considered to be outside of the time window, the error
754  //must be reported with a securityLevel of authNoPriv (refer to RFC 3414,
755  //section 3.2)
756  if(errorIndication == ERROR_NOT_IN_TIME_WINDOW)
757  {
758  //Bit fields which control processing of the message
759  context->response.msgFlags = context->request.msgFlags &
761 
762  //User name
763  context->response.msgUserName = context->request.msgUserName;
764  context->response.msgUserNameLen = context->request.msgUserNameLen;
765 
766  //Authentication parameters
767  context->response.msgAuthParameters = NULL;
768  context->response.msgAuthParametersLen = context->request.msgAuthParametersLen;
769 
770  //Privacy parameters
771  context->response.msgPrivParameters = context->privParameters;
772  context->response.msgPrivParametersLen = context->request.msgPrivParametersLen;
773  }
774 
775  //Make room for the message header at the beginning of the buffer
776  error = snmpComputeMessageOverhead(&context->response);
777  //Any error to report?
778  if(error)
779  return error;
780 
781  //Initialize counter value
782  counter = 1;
783 
784  //Check error indication
785  switch(errorIndication)
786  {
788  //Total number of packets received by the SNMP engine which were dropped
789  //because they requested a securityLevel that was unknown to the SNMP
790  //engine or otherwise unavailable
791  SNMP_USM_MIB_INC_COUNTER32(usmStatsUnsupportedSecLevels, 1);
792  SNMP_USM_MIB_GET_COUNTER32(counter, usmStatsUnsupportedSecLevels);
793 
794  //Add the usmStatsUnsupportedSecLevels counter in the varBindList
797  break;
798 
800  //Total number of packets received by the SNMP engine which were dropped
801  //because they appeared outside of the authoritative SNMP engine's window
802  SNMP_USM_MIB_INC_COUNTER32(usmStatsNotInTimeWindows, 1);
803  SNMP_USM_MIB_GET_COUNTER32(counter, usmStatsNotInTimeWindows);
804 
805  //Add the usmStatsNotInTimeWindows counter in the varBindList
808  break;
809 
811  //Total number of packets received by the SNMP engine which were dropped
812  //because they referenced a user that was not known to the SNMP engine
813  SNMP_USM_MIB_INC_COUNTER32(usmStatsUnknownUserNames, 1);
814  SNMP_USM_MIB_GET_COUNTER32(counter, usmStatsUnknownUserNames);
815 
816  //Add the usmStatsUnknownUserNames counter in the varBindList
819  break;
820 
822  //Total number of packets received by the SNMP engine which were dropped
823  //because they referenced an snmpEngineID that was not known to the SNMP
824  //engine
825  SNMP_USM_MIB_INC_COUNTER32(usmStatsUnknownEngineIDs, 1);
826  SNMP_USM_MIB_GET_COUNTER32(counter, usmStatsUnknownEngineIDs);
827 
828  //Add the usmStatsUnknownEngineIDs counter in the varBindList
831  break;
832 
834  //Total number of packets received by the SNMP engine which were dropped
835  //because they didn't contain the expected digest value
836  SNMP_USM_MIB_INC_COUNTER32(usmStatsWrongDigests, 1);
837  SNMP_USM_MIB_GET_COUNTER32(counter, usmStatsWrongDigests);
838 
839  //Add the usmStatsWrongDigests counter in the varBindList
841  var.oidLen = sizeof(usmStatsWrongDigestsObject);
842  break;
843 
845  //Total number of packets received by the SNMP engine which were dropped
846  //because they could not be decrypted
847  SNMP_USM_MIB_INC_COUNTER32(usmStatsDecryptionErrors, 1);
848  SNMP_USM_MIB_GET_COUNTER32(counter, usmStatsDecryptionErrors);
849 
850  //Add the usmStatsDecryptionErrors counter in the varBindList
853  break;
854 
856  //Total number of packets received by the SNMP engine which were dropped
857  //because the context contained in the message was unavailable
858  counter = 1;
859 
860  //Add the snmpUnavailableContexts counter in the varBindList
863  break;
864 
866  //Total number of packets received by the SNMP engine which were dropped
867  //because the context contained in the message was unknown
868  counter = 1;
869 
870  //Add the snmpUnknownContexts counter in the varBindList
872  var.oidLen = sizeof(snmpUnknownContextsObject);
873  break;
874 
875  default:
876  //Just for sanity's sake...
877  var.oid = NULL;
878  var.oidLen = 0;
879  break;
880  }
881 
882  //Encode the object value using ASN.1 rules
883  error = snmpEncodeUnsignedInt32(counter, context->response.buffer, &n);
884  //Any error to report?
885  if(error)
886  return error;
887 
888  //The counter is encoded in ASN.1 format
891  var.value = context->response.buffer;
892  var.valueLen = n;
893 
894  //Append the variable binding list to the varBindList
895  error = snmpWriteVarBinding(context, &var);
896  //Any error to report?
897  if(error)
898  return error;
899 
900  //Format PDU header
901  error = snmpWritePduHeader(&context->response);
902 #else
903  //SNMPv3 is not supported
904  error = ERROR_NOT_IMPLEMENTED;
905 #endif
906 
907  //Return status code
908  return error;
909 }
910 
911 #endif
ASN.1 (Abstract Syntax Notation One)
#define ASN1_CLASS_APPLICATION
Definition: asn1.h:53
#define ASN1_CLASS_CONTEXT_SPECIFIC
Definition: asn1.h:54
signed int int_t
Definition: compiler_port.h:49
int bool_t
Definition: compiler_port.h:53
General definitions for cryptographic algorithms.
Debugging facilities.
#define TRACE_INFO(...)
Definition: debug.h:95
uint8_t n
error_t
Error codes.
Definition: error.h:43
@ ERROR_INVALID_TYPE
Definition: error.h:115
@ ERROR_UNKNOWN_ENGINE_ID
Definition: error.h:260
@ ERROR_DECRYPTION_FAILED
Definition: error.h:241
@ ERROR_UNAVAILABLE_CONTEXT
Definition: error.h:263
@ ERROR_UNKNOWN_CONTEXT
Definition: error.h:262
@ ERROR_NOT_IN_TIME_WINDOW
Definition: error.h:265
@ ERROR_UNSUPPORTED_SECURITY_LEVEL
Definition: error.h:264
@ ERROR_OBJECT_NOT_FOUND
Definition: error.h:255
@ ERROR_INSTANCE_NOT_FOUND
Definition: error.h:256
@ ERROR_AUTHENTICATION_FAILED
Definition: error.h:69
@ ERROR_ACCESS_DENIED
Definition: error.h:148
@ ERROR_NOT_IMPLEMENTED
Definition: error.h:66
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_BUFFER_OVERFLOW
Definition: error.h:142
@ ERROR_UNKNOWN_USER_NAME
Definition: error.h:261
uint16_t next
Definition: ipv4_frag.h:106
MIB-II module.
#define MIB2_SNMP_INC_COUNTER32(name, value)
Definition: mib2_module.h:192
@ MIB_TYPE_COUNTER32
Definition: mib_common.h:61
uint8_t p
Definition: ndp.h:300
uint8_t m
Definition: ndp.h:304
TCP/IP stack core.
error_t oidCheck(const uint8_t *oid, size_t oidLen)
Check whether the specified object identifier is valid.
Definition: oid.c:50
OID (Object Identifier)
#define osStrlen(s)
Definition: os_port.h:165
#define TRUE
Definition: os_port.h:50
#define FALSE
Definition: os_port.h:46
SNMP agent (Simple Network Management Protocol)
#define SnmpAgentContext
Definition: snmp_agent.h:36
error_t snmpProcessReportPdu(SnmpAgentContext *context)
Process Report-PDU.
error_t snmpProcessGetResponsePdu(SnmpAgentContext *context)
Process GetResponse-PDU.
void snmpInitMessage(SnmpMessage *message)
Initialize a SNMP message.
error_t snmpComputeMessageOverhead(SnmpMessage *message)
Compute SNMP message overhead.
error_t snmpWritePduHeader(SnmpMessage *message)
Format PDU header.
error_t snmpEncodeUnsignedInt32(uint32_t value, uint8_t *dest, size_t *length)
Encode a 32-bit unsigned integer.
error_t snmpInitResponse(SnmpAgentContext *context)
Initialize a GetResponse-PDU.
error_t snmpParsePduHeader(SnmpMessage *message)
Parse PDU header.
void snmpLockMib(SnmpAgentContext *context)
Lock MIB bases.
error_t snmpParseVarBinding(const uint8_t *p, size_t length, SnmpVarBind *var, size_t *consumed)
Parse variable binding.
error_t snmpWriteVarBinding(SnmpAgentContext *context, const SnmpVarBind *var)
Write variable binding.
error_t snmpTranslateStatusCode(SnmpMessage *message, error_t status, uint_t index)
Translate status code.
void snmpUnlockMib(SnmpAgentContext *context)
Unlock MIB bases.
error_t snmpCopyVarBindingList(SnmpAgentContext *context)
Copy the list of variable bindings.
Helper functions for SNMP agent.
error_t snmpGetNextObject(SnmpAgentContext *context, const SnmpMessage *message, SnmpVarBind *var)
Search MIBs for the next object.
error_t snmpSetObjectValue(SnmpAgentContext *context, const SnmpMessage *message, SnmpVarBind *var, bool_t commit)
Assign object value.
error_t snmpGetObjectValue(SnmpAgentContext *context, const SnmpMessage *message, SnmpVarBind *var)
Retrieve object value.
MIB object access.
error_t snmpProcessPdu(SnmpAgentContext *context)
Process PDU.
error_t snmpProcessGetRequestPdu(SnmpAgentContext *context)
Process GetRequest-PDU or GetNextRequest-PDU.
const uint8_t snmpUnavailableContextsObject[9]
error_t snmpProcessSetRequestPdu(SnmpAgentContext *context)
Process SetRequest-PDU.
const uint8_t snmpUnknownContextsObject[9]
error_t snmpProcessGetBulkRequestPdu(SnmpAgentContext *context)
Process GetBulkRequest-PDU.
error_t snmpFormatReportPdu(SnmpAgentContext *context, error_t errorIndication)
Format Report-PDU.
SNMP agent (PDU processing)
const uint8_t usmStatsUnknownUserNamesObject[10]
const uint8_t usmStatsUnsupportedSecLevelsObject[10]
const uint8_t usmStatsNotInTimeWindowsObject[10]
const uint8_t usmStatsUnknownEngineIdsObject[10]
const uint8_t usmStatsDecryptionErrorsObject[10]
const uint8_t usmStatsWrongDigestsObject[10]
@ SNMP_ACCESS_READ_ONLY
@ SNMP_ACCESS_WRITE_ONLY
@ SNMP_ACCESS_READ_WRITE
@ SNMP_SECURITY_MODEL_USM
User-based security model.
@ SNMP_MSG_FLAG_PRIV
@ SNMP_MSG_FLAG_AUTH
@ SNMP_PDU_GET_REQUEST
Definition: snmp_common.h:150
@ SNMP_PDU_GET_RESPONSE
Definition: snmp_common.h:152
@ SNMP_PDU_GET_NEXT_REQUEST
Definition: snmp_common.h:151
@ SNMP_PDU_REPORT
Definition: snmp_common.h:158
@ SNMP_PDU_GET_BULK_REQUEST
Definition: snmp_common.h:155
@ SNMP_PDU_SET_REQUEST
Definition: snmp_common.h:153
@ SNMP_EXCEPTION_NO_SUCH_OBJECT
Definition: snmp_common.h:212
@ SNMP_EXCEPTION_END_OF_MIB_VIEW
Definition: snmp_common.h:214
@ SNMP_EXCEPTION_NO_SUCH_INSTANCE
Definition: snmp_common.h:213
@ SNMP_VERSION_1
Definition: snmp_common.h:138
#define SNMP_MAX_MSG_SIZE
Definition: snmp_common.h:60
@ SNMP_ERROR_TOO_BIG
Definition: snmp_common.h:185
SNMP MIB module.
#define SNMP_MIB_INC_COUNTER32(name, value)
SNMP USM MIB module.
#define SNMP_USM_MIB_GET_COUNTER32(value, name)
#define SNMP_USM_MIB_INC_COUNTER32(name, value)
Variable binding.
const uint8_t * value
const uint8_t * oid
uint8_t length
Definition: tcp.h:368