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