snmp_agent_message.c
Go to the documentation of this file.
1 /**
2  * @file snmp_message.c
3  * @brief SNMP message formatting and parsing
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"
37 #include "core/crypto.h"
38 #include "encoding/asn1.h"
39 #include "debug.h"
40 
41 //Check TCP/IP stack configuration
42 #if (SNMP_AGENT_SUPPORT == ENABLED)
43 
44 
45 /**
46  * @brief Initialize a SNMP message
47  * @param[in] message Pointer to the SNMP message
48  **/
49 
51 {
52  //Current position in the message
53  message->pos = NULL;
54  //Length of the message
55  message->length = 0;
56 
57  //SNMP version identifier
58  message->version = SNMP_VERSION_1;
59 
60 #if (SNMP_V1_SUPPORT == ENABLED || SNMP_V2C_SUPPORT == ENABLED)
61  //Initialize community name
62  message->community = NULL;
63  message->communityLen = 0;
64 #endif
65 
66 #if (SNMP_V3_SUPPORT == ENABLED)
67  //Initialize msgGlobalData fields
68  message->msgId = 0;
69  message->msgMaxSize = 0;
70  message->msgFlags = 0;
71  message->msgSecurityModel = 0;
72 
73  //Initialize msgSecurityParameters fields
74  message->msgAuthEngineId = NULL;
75  message->msgAuthEngineIdLen = 0;
76  message->msgAuthEngineBoots = 0;
77  message->msgAuthEngineTime = 0;
78  message->msgUserName = NULL;
79  message->msgUserNameLen = 0;
80  message->msgAuthParameters = NULL;
81  message->msgAuthParametersLen = 0;
82  message->msgPrivParameters = NULL;
83  message->msgPrivParametersLen = 0;
84 
85  //Initialize scopedPDU fields
86  message->contextEngineId = NULL;
87  message->contextEngineIdLen = 0;
88  message->contextName = NULL;
89  message->contextNameLen = 0;
90 #endif
91 
92  //Initialize PDU fields
93  message->pduType = SNMP_PDU_GET_REQUEST;
94  message->requestId = 0;
95  message->errorStatus = SNMP_ERROR_NONE;
96  message->errorIndex = 0;
97 
98 #if (SNMP_V1_SUPPORT == ENABLED)
99  message->enterpriseOid = NULL;
100  message->enterpriseOidLen = 0;
101  message->agentAddr = IPV4_UNSPECIFIED_ADDR;
102  message->genericTrapType = 0;
103  message->specificTrapCode = 0;
104  message->timestamp = 0;
105 #endif
106 
107 #if (SNMP_V2C_SUPPORT == ENABLED || SNMP_V3_SUPPORT == ENABLED)
108  message->nonRepeaters = 0;
109  message->maxRepetitions = 0;
110 #endif
111 
112  //Initialize the list of variable bindings
113  message->varBindList = NULL;
114  message->varBindListLen = 0;
115  message->varBindListMaxLen = 0;
116  message->oidLen = 0;
117 }
118 
119 
120 /**
121  * @brief Initialize a GetResponse-PDU
122  * @param[in] context Pointer to the SNMP agent context
123  * @return Error code
124  **/
125 
127 {
128  error_t error;
129 
130  //SNMP version identifier
131  context->response.version = context->request.version;
132 
133 #if (SNMP_V1_SUPPORT == ENABLED || SNMP_V2C_SUPPORT == ENABLED)
134  //Community name
135  context->response.community = context->request.community;
136  context->response.communityLen = context->request.communityLen;
137 #endif
138 
139 #if (SNMP_V3_SUPPORT == ENABLED)
140  //Message identifier
141  context->response.msgId = context->request.msgId;
142  //Maximum message size supported by the sender
143  context->response.msgMaxSize = SNMP_MAX_MSG_SIZE;
144 
145  //Bit fields which control processing of the message
146  context->response.msgFlags = context->request.msgFlags &
148 
149  //Security model used by the sender
150  context->response.msgSecurityModel = context->request.msgSecurityModel;
151 
152  //Authoritative engine identifier
153  context->response.msgAuthEngineId = context->contextEngine;
154  context->response.msgAuthEngineIdLen = context->contextEngineLen;
155 
156  //Number of times the SNMP engine has rebooted
157  context->response.msgAuthEngineBoots = context->engineBoots;
158  //Number of seconds since last reboot
159  context->response.msgAuthEngineTime = context->engineTime;
160 
161  //User name
162  context->response.msgUserName = context->request.msgUserName;
163  context->response.msgUserNameLen = context->request.msgUserNameLen;
164 
165  //Authentication parameters
166  context->response.msgAuthParameters = NULL;
167  context->response.msgAuthParametersLen = context->request.msgAuthParametersLen;
168 
169  //Privacy parameters
170  context->response.msgPrivParameters = context->privParameters;
171  context->response.msgPrivParametersLen = context->request.msgPrivParametersLen;
172 
173  //Context engine identifier
174  context->response.contextEngineId = context->contextEngine;
175  context->response.contextEngineIdLen = context->contextEngineLen;
176 
177  //Context name
178  context->response.contextName = context->request.contextName;
179  context->response.contextNameLen = context->request.contextNameLen;
180 #endif
181 
182  //PDU type
183  context->response.pduType = SNMP_PDU_GET_RESPONSE;
184  //Request identifier
185  context->response.requestId = context->request.requestId;
186 
187  //Make room for the message header at the beginning of the buffer
188  error = snmpComputeMessageOverhead(&context->response);
189  //Return status code
190  return error;
191 }
192 
193 
194 /**
195  * @brief Compute SNMP message overhead
196  * @param[in] message Pointer to the SNMP message
197  **/
198 
200 {
201  size_t n;
202 
203 #if (SNMP_V1_SUPPORT == ENABLED)
204  //SNMPv1 version?
205  if(message->version == SNMP_VERSION_1)
206  {
207  //SNMPv1 message header overhead
209  //Take into consideration variable-length fields
210  n += message->communityLen + message->enterpriseOidLen;
211  }
212  else
213 #endif
214 #if (SNMP_V2C_SUPPORT == ENABLED)
215  //SNMPv2c version?
216  if(message->version == SNMP_VERSION_2C)
217  {
218  //SNMPv2c message header overhead
220  //Take into consideration variable-length fields
221  n += message->communityLen;
222  }
223  else
224 #endif
225 #if (SNMP_V3_SUPPORT == ENABLED)
226  //SNMPv3 version?
227  if(message->version == SNMP_VERSION_3)
228  {
229  //SNMPv3 message header overhead
231 
232  //Take into consideration variable-length fields
233  n += message->msgAuthEngineIdLen + message->msgUserNameLen +
234  message->msgAuthParametersLen + message->msgPrivParametersLen +
235  message->contextEngineIdLen + message->contextNameLen;
236  }
237  else
238 #endif
239  //Invalid SNMP version?
240  {
241  //Report an error
242  return ERROR_INVALID_VERSION;
243  }
244 
245  //Sanity check
247  return ERROR_FAILURE;
248 
249  //Make room for the message header at the beginning of the buffer
250  message->varBindList = message->buffer + n;
251  //Maximum length of the variable binding list
252  message->varBindListMaxLen = (SNMP_MAX_MSG_SIZE - SNMP_MSG_ENCRYPTION_OVERHEAD) - n;
253 
254  //Successful processing
255  return NO_ERROR;
256 }
257 
258 
259 /**
260  * @brief Parse SNMP message header
261  * @param[in,out] message Pointer to the incoming SNMP message
262  * @return Error code
263  **/
264 
266 {
267  error_t error;
268  size_t length;
269  const uint8_t *p;
270  Asn1Tag tag;
271 
272  //Point to the first byte of the SNMP message
273  p = message->buffer;
274  //Retrieve the length of the SNMP message
275  length = message->bufferLen;
276 
277  //The SNMP message is encapsulated within a sequence
278  error = asn1ReadSequence(p, length, &tag);
279  //Failed to decode ASN.1 tag?
280  if(error)
281  return error;
282 
283  //Point to the first field of the sequence
284  p = tag.value;
285  length = tag.length;
286 
287  //Read version identifier
288  error = asn1ReadInt32(p, length, &tag, &message->version);
289  //Failed to decode ASN.1 tag?
290  if(error)
291  return error;
292 
293  //Make sure the SNMP version identifier is valid
294  if(message->version != SNMP_VERSION_1 &&
295  message->version != SNMP_VERSION_2C &&
296  message->version != SNMP_VERSION_3)
297  {
298  //The SNMP version is not acceptable
299  return ERROR_INVALID_VERSION;
300  }
301 
302  //Advance data pointer
303  message->pos = (uint8_t *) p + tag.totalLength;
304  //Remaining bytes to process
305  message->length = length - tag.totalLength;
306 
307  //Successful processing
308  return NO_ERROR;
309 }
310 
311 
312 /**
313  * @brief Format SNMP message header
314  * @param[in,out] message Pointer to the outgoing SNMP message
315  * @return Error code
316  **/
317 
319 {
320  error_t error;
321  size_t n;
322  Asn1Tag tag;
323 
324  //SNMPv1 or SNMPv2c version?
325  if(message->version == SNMP_VERSION_1 ||
326  message->version == SNMP_VERSION_2C)
327  {
328  //Write the community name
329  error = snmpWriteCommunity(message);
330  //Any error to report?
331  if(error)
332  return error;
333  }
334  //SNMPv3 version?
335  else if(message->version == SNMP_VERSION_3)
336  {
337  //Write msgSecurityParameters field
339  //Any error to report?
340  if(error)
341  return error;
342 
343  //Write msgGlobalData field
344  error = snmpWriteGlobalData(message);
345  //Any error to report?
346  if(error)
347  return error;
348  }
349  //Invalid version?
350  else
351  {
352  //Report an error
353  return ERROR_INVALID_VERSION;
354  }
355 
356  //Write version identifier
357  error = asn1WriteInt32(message->version, TRUE, message->pos, &n);
358  //Any error to report?
359  if(error)
360  return error;
361 
362  //Move backward
363  message->pos -= n;
364  //Update the length of the message
365  message->length += n;
366 
367  //The SNMP message is encapsulated within a sequence
368  tag.constructed = TRUE;
371  tag.length = message->length;
372  tag.value = NULL;
373 
374  //Write the corresponding ASN.1 tag
375  error = asn1WriteTag(&tag, TRUE, message->pos, &n);
376  //Any error to report?
377  if(error)
378  return error;
379 
380  //Move backward
381  message->pos -= n;
382  //Total length of the SNMP message
383  message->length += n;
384 
385  //Successful processing
386  return NO_ERROR;
387 }
388 
389 
390 /**
391  * @brief Parse community name
392  * @param[in,out] message Pointer to the incoming SNMP message
393  * @return Error code
394  **/
395 
397 {
398 #if (SNMP_V1_SUPPORT == ENABLED || SNMP_V2C_SUPPORT == ENABLED)
399  error_t error;
400  Asn1Tag tag;
401 
402  //Read community name
403  error = asn1ReadTag(message->pos, message->length, &tag);
404  //Failed to decode ASN.1 tag?
405  if(error)
406  return error;
407 
408  //Enforce encoding, class and type
410  //The tag does not match the criteria?
411  if(error)
412  return error;
413 
414  //Save community name
415  message->community = (char_t *) tag.value;
416  message->communityLen = tag.length;
417 
418  //Advance data pointer
419  message->pos += tag.totalLength;
420  //Remaining bytes to process
421  message->length -= tag.totalLength;
422 
423  //No error to report
424  return NO_ERROR;
425 #else
426  //Not implemented
427  return ERROR_NOT_IMPLEMENTED;
428 #endif
429 }
430 
431 
432 /**
433  * @brief Format community name
434  * @param[in,out] message Pointer to the outgoing SNMP message
435  * @return Error code
436  **/
437 
439 {
440 #if (SNMP_V1_SUPPORT == ENABLED || SNMP_V2C_SUPPORT == ENABLED)
441  error_t error;
442  size_t n;
443  Asn1Tag tag;
444 
445  //The community name is an octet string
446  tag.constructed = FALSE;
449  tag.length = message->communityLen;
450  tag.value = (uint8_t *) message->community;
451 
452  //Write the corresponding ASN.1 tag
453  error = asn1WriteTag(&tag, TRUE, message->pos, &n);
454  //Any error to report?
455  if(error)
456  return error;
457 
458  //Point to the first byte of the community name
459  message->pos -= n;
460  //Total length of the message
461  message->length += n;
462 
463  //Successful processing
464  return NO_ERROR;
465 #else
466  //Not implemented
467  return ERROR_NOT_IMPLEMENTED;
468 #endif
469 }
470 
471 
472 /**
473  * @brief Parse msgGlobalData field
474  * @param[in,out] message Pointer to the incoming SNMP message
475  * @return Error code
476  **/
477 
479 {
480 #if (SNMP_V3_SUPPORT == ENABLED)
481  error_t error;
482  size_t length;
483  const uint8_t *p;
484  Asn1Tag tag;
485 
486  //Read the msgGlobalData field
487  error = asn1ReadSequence(message->pos, message->length, &tag);
488  //Failed to decode ASN.1 tag?
489  if(error)
490  return error;
491 
492  //Advance pointer over the msgGlobalData field
493  message->pos += tag.totalLength;
494  //Remaining bytes to process
495  message->length -= tag.totalLength;
496 
497  //Point to the first field of the sequence
498  p = tag.value;
499  length = tag.length;
500 
501  //The msgID is used between two SNMP entities to coordinate request
502  //messages and responses
503  error = asn1ReadInt32(p, length, &tag, &message->msgId);
504  //Failed to decode ASN.1 tag?
505  if(error)
506  return error;
507 
508  //Make sure the value is in the range 0..2147483647
509  if(message->msgId < 0)
510  return ERROR_WRONG_ENCODING;
511 
512  //Point to the next field
513  p += tag.totalLength;
514  length -= tag.totalLength;
515 
516  //The msgMaxSize field of the message conveys the maximum message size
517  //supported by the sender of the message
518  error = asn1ReadInt32(p, length, &tag, &message->msgMaxSize);
519  //Failed to decode ASN.1 tag?
520  if(error)
521  return error;
522 
523  //Make sure the value is in the range 484..2147483647
524  if(message->msgMaxSize < 484)
525  return ERROR_WRONG_ENCODING;
526 
527  //Point to the next field
528  p += tag.totalLength;
529  length -= tag.totalLength;
530 
531  //The msgFlags field of the message contains several bit fields which
532  //control processing of the message
533  error = asn1ReadTag(p, length, &tag);
534  //Failed to decode ASN.1 tag?
535  if(error)
536  return error;
537 
538  //Enforce encoding, class and type
540  //The tag does not match the criteria?
541  if(error)
542  return error;
543 
544  //The msgFlags field consists of a single byte
545  if(tag.length != sizeof(uint8_t))
546  return ERROR_WRONG_ENCODING;
547 
548  //Save the bit field
549  message->msgFlags = tag.value[0];
550 
551  //If the authFlag is not set and privFlag is set, then the snmpInvalidMsgs
552  //counter is incremented and the message is silently discarded
553  if(!(message->msgFlags & SNMP_MSG_FLAG_AUTH) &&
554  (message->msgFlags & SNMP_MSG_FLAG_PRIV))
555  {
556  //Total number of packets received by the SNMP engine which were dropped
557  //because there were invalid or inconsistent components in the message
558  SNMP_MPD_MIB_INC_COUNTER32(snmpInvalidMsgs, 1);
559 
560  //The message is discarded without further processing
561  return ERROR_FAILURE;
562  }
563 
564  //Point to the next field
565  p += tag.totalLength;
566  length -= tag.totalLength;
567 
568  //The msgSecurityModel field identifies which security model was used
569  //by the sender to generate the message
570  error = asn1ReadInt32(p, length, &tag, &message->msgSecurityModel);
571  //Failed to decode ASN.1 tag?
572  if(error)
573  return error;
574 
575  //Make sure the value is in the range 1..2147483647
576  if(message->msgSecurityModel < 1)
577  return ERROR_WRONG_ENCODING;
578 
579  //Successful processing
580  return NO_ERROR;
581 #else
582  //Not implemented
583  return ERROR_NOT_IMPLEMENTED;
584 #endif
585 }
586 
587 
588 /**
589  * @brief Format msgGlobalData field
590  * @param[in,out] message Pointer to the outgoing SNMP message
591  * @return Error code
592  **/
593 
595 {
596 #if (SNMP_V3_SUPPORT == ENABLED)
597  error_t error;
598  size_t n;
599  size_t length;
600  uint8_t *p;
601  Asn1Tag tag;
602 
603  //The msgGlobalData field is encoded in reverse order
604  p = message->pos;
605  //Length of the msgGlobalData field
606  length = 0;
607 
608  //Write msgSecurityModel field
609  error = asn1WriteInt32(message->msgSecurityModel, TRUE, p, &n);
610  //Any error to report?
611  if(error)
612  return error;
613 
614  //Move backward
615  p -= n;
616  //Update the length of the msgGlobalData field
617  length += n;
618 
619  //The msgFlags field consists of a single byte
620  tag.constructed = FALSE;
623  tag.length = sizeof(uint8_t);
624  tag.value = &message->msgFlags;
625 
626  //Write the corresponding ASN.1 tag
627  error = asn1WriteTag(&tag, TRUE, p, &n);
628  //Any error to report?
629  if(error)
630  return error;
631 
632  //Move backward
633  p -= n;
634  //Update the length of the msgGlobalData field
635  length += n;
636 
637  //Write msgMaxSize field
638  error = asn1WriteInt32(message->msgMaxSize, TRUE, p, &n);
639  //Any error to report?
640  if(error)
641  return error;
642 
643  //Move backward
644  p -= n;
645  //Update the length of the msgGlobalData field
646  length += n;
647 
648  //Write msgID field
649  error = asn1WriteInt32(message->msgId, TRUE, p, &n);
650  //Any error to report?
651  if(error)
652  return error;
653 
654  //Move backward
655  p -= n;
656  //Update the length of the msgGlobalData field
657  length += n;
658 
659  //The parameters are encapsulated within a sequence
660  tag.constructed = TRUE;
663  tag.length = length;
664  tag.value = NULL;
665 
666  //Write the corresponding ASN.1 tag
667  error = asn1WriteTag(&tag, TRUE, p, &n);
668  //Any error to report?
669  if(error)
670  return error;
671 
672  //Point to the first byte of the msgGlobalData field
673  message->pos = p - n;
674  //Total length of the message
675  message->length += length + n;
676 
677  //Successful processing
678  return NO_ERROR;
679 #else
680  //Not implemented
681  return ERROR_NOT_IMPLEMENTED;
682 #endif
683 }
684 
685 
686 /**
687  * @brief Parse msgSecurityParameters field
688  * @param[in,out] message Pointer to the incoming SNMP message
689  * @return Error code
690  **/
691 
693 {
694 #if (SNMP_V3_SUPPORT == ENABLED)
695  error_t error;
696  size_t length;
697  const uint8_t *p;
698  Asn1Tag tag;
699 
700  //Read the msgSecurityParameters field
701  error = asn1ReadTag(message->pos, message->length, &tag);
702  //Failed to decode ASN.1 tag?
703  if(error)
704  return error;
705 
706  //Enforce encoding, class and type
708  //The tag does not match the criteria?
709  if(error)
710  return error;
711 
712  //Advance pointer over the msgSecurityParameters field
713  message->pos += tag.totalLength;
714  //Remaining bytes to process
715  message->length -= tag.totalLength;
716 
717  //Point to the very first field of the sequence
718  p = tag.value;
719  length = tag.length;
720 
721  //User-based security model?
722  if(message->msgSecurityModel == SNMP_SECURITY_MODEL_USM)
723  {
724  //The USM security parameters are encapsulated within a sequence
725  error = asn1ReadSequence(p, length, &tag);
726  //Failed to decode ASN.1 tag?
727  if(error)
728  return error;
729 
730  //Point to the first field of the sequence
731  p = tag.value;
732  length = tag.length;
733 
734  //Read the msgAuthoritativeEngineID field
735  error = asn1ReadTag(p, length, &tag);
736  //Failed to decode ASN.1 tag?
737  if(error)
738  return error;
739 
740  //Enforce encoding, class and type
742  //The tag does not match the criteria?
743  if(error)
744  return error;
745 
746  //Save authoritative engine identifier
747  message->msgAuthEngineId = tag.value;
748  message->msgAuthEngineIdLen = tag.length;
749 
750  //Point to the next field
751  p += tag.totalLength;
752  length -= tag.totalLength;
753 
754  //Read the msgAuthoritativeEngineBoots field
755  error = asn1ReadInt32(p, length, &tag,
756  &message->msgAuthEngineBoots);
757  //Failed to decode ASN.1 tag?
758  if(error)
759  return error;
760 
761  //Point to the next field
762  p += tag.totalLength;
763  length -= tag.totalLength;
764 
765  //Read the msgAuthoritativeEngineTime field
766  error = asn1ReadInt32(p, length, &tag,
767  &message->msgAuthEngineTime);
768  //Failed to decode ASN.1 tag?
769  if(error)
770  return error;
771 
772  //Point to the next field
773  p += tag.totalLength;
774  length -= tag.totalLength;
775 
776  //Read the msgUserName field
777  error = asn1ReadTag(p, length, &tag);
778  //Failed to decode ASN.1 tag?
779  if(error)
780  return error;
781 
782  //Enforce encoding, class and type
784  //The tag does not match the criteria?
785  if(error)
786  return error;
787 
788  //Check the length of the user name
789  if(tag.length > 32)
790  return ERROR_WRONG_ENCODING;
791 
792  //Save user name
793  message->msgUserName = (char_t *) tag.value;
794  message->msgUserNameLen = tag.length;
795 
796  //Point to the next field
797  p += tag.totalLength;
798  length -= tag.totalLength;
799 
800  //Read the msgAuthenticationParameters field
801  error = asn1ReadTag(p, length, &tag);
802  //Failed to decode ASN.1 tag?
803  if(error)
804  return error;
805 
806  //Enforce encoding, class and type
808  //The tag does not match the criteria?
809  if(error)
810  return error;
811 
812  //Save authentication parameters
813  message->msgAuthParameters = (uint8_t *) tag.value;
814  message->msgAuthParametersLen = tag.length;
815 
816  //Point to the next field
817  p += tag.totalLength;
818  length -= tag.totalLength;
819 
820  //Read the msgPrivacyParameters field
821  error = asn1ReadTag(p, length, &tag);
822  //Failed to decode ASN.1 tag?
823  if(error)
824  return error;
825 
826  //Enforce encoding, class and type
828  //The tag does not match the criteria?
829  if(error)
830  return error;
831 
832  //Save privacy parameters
833  message->msgPrivParameters = tag.value;
834  message->msgPrivParametersLen = tag.length;
835  }
836  else
837  {
838  //Total number of packets received by the SNMP engine which were dropped
839  //because they referenced a securityModel that was not known to or
840  //supported by the SNMP engine
841  SNMP_MPD_MIB_INC_COUNTER32(snmpUnknownSecurityModels, 1);
842 
843  //The message is discarded without further processing
844  return ERROR_FAILURE;
845  }
846 
847  //Successful processing
848  return NO_ERROR;
849 #else
850  //Not implemented
851  return ERROR_NOT_IMPLEMENTED;
852 #endif
853 }
854 
855 
856 /**
857  * @brief Format msgSecurityParameters field
858  * @param[in,out] message Pointer to the outgoing SNMP message
859  * @return Error code
860  **/
861 
863 {
864 #if (SNMP_V3_SUPPORT == ENABLED)
865  error_t error;
866  size_t n;
867  size_t length;
868  uint8_t *p;
869  Asn1Tag tag;
870 
871  //The msgSecurityParameters field is encoded in reverse order
872  p = message->pos;
873  //Length of the msgSecurityParameters field
874  length = 0;
875 
876  //User-based security model?
877  if(message->msgSecurityModel == SNMP_SECURITY_MODEL_USM)
878  {
879  //Encode the msgPrivacyParameters field as an octet string
880  tag.constructed = FALSE;
883  tag.length = message->msgPrivParametersLen;
884  tag.value = message->msgPrivParameters;
885 
886  //Write the corresponding ASN.1 tag
887  error = asn1WriteTag(&tag, TRUE, p, &n);
888  //Any error to report?
889  if(error)
890  return error;
891 
892  //Move backward
893  p -= n;
894  //Update the length of the msgSecurityParameters field
895  length += n;
896 
897  //Authentication required?
898  if(message->msgAuthParametersLen > 0)
899  {
900  //Make room for the message digest
901  p -= message->msgAuthParametersLen;
902  //Update the length of the msgSecurityParameters field
903  length += message->msgAuthParametersLen;
904 
905  //Clear the message digest
906  memset(p, 0, message->msgAuthParametersLen);
907  }
908 
909  //Save the location of the msgAuthenticationParameters field
910  message->msgAuthParameters = p;
911 
912  //Encoded the msgAuthenticationParameters field as an octet string
913  tag.constructed = FALSE;
916  tag.length = message->msgAuthParametersLen;
917  tag.value = NULL;
918 
919  //Write the corresponding ASN.1 tag
920  error = asn1WriteTag(&tag, TRUE, p, &n);
921  //Any error to report?
922  if(error)
923  return error;
924 
925  //Move backward
926  p -= n;
927  //Update the length of the msgSecurityParameters field
928  length += n;
929 
930  //Encode the msgUserName field as an octet string
931  tag.constructed = FALSE;
934  tag.length = message->msgUserNameLen;
935  tag.value = (uint8_t *) message->msgUserName;
936 
937  //Write the corresponding ASN.1 tag
938  error = asn1WriteTag(&tag, TRUE, p, &n);
939  //Any error to report?
940  if(error)
941  return error;
942 
943  //Move backward
944  p -= n;
945  //Update the length of the msgSecurityParameters field
946  length += n;
947 
948  //Write the msgAuthoritativeEngineTime field
949  error = asn1WriteInt32(message->msgAuthEngineTime, TRUE, p, &n);
950  //Any error to report?
951  if(error)
952  return error;
953 
954  //Move backward
955  p -= n;
956  //Update the length of the msgSecurityParameters field
957  length += n;
958 
959  //Write the msgAuthoritativeEngineBoots field
960  error = asn1WriteInt32(message->msgAuthEngineBoots, TRUE, p, &n);
961  //Any error to report?
962  if(error)
963  return error;
964 
965  //Move backward
966  p -= n;
967  //Update the length of the msgSecurityParameters field
968  length += n;
969 
970  //The msgAuthoritativeEngineID field is an octet string
971  tag.constructed = FALSE;
974  tag.length = message->msgAuthEngineIdLen;
975  tag.value = message->msgAuthEngineId;
976 
977  //Write the corresponding ASN.1 tag
978  error = asn1WriteTag(&tag, TRUE, p, &n);
979  //Any error to report?
980  if(error)
981  return error;
982 
983  //Move backward
984  p -= n;
985  //Update the length of the msgSecurityParameters field
986  length += n;
987 
988  //The USM security parameters are encapsulated within a sequence
989  tag.constructed = TRUE;
992  tag.length = length;
993  tag.value = NULL;
994 
995  //Write the corresponding ASN.1 tag
996  error = asn1WriteTag(&tag, TRUE, p, &n);
997  //Any error to report?
998  if(error)
999  return error;
1000 
1001  //Move backward
1002  p -= n;
1003  //Update the length of the msgSecurityParameters field
1004  length += n;
1005  }
1006  else
1007  {
1008  //The security model is not supported
1009  return ERROR_FAILURE;
1010  }
1011 
1012  //The security parameters are encapsulated within an octet string
1013  tag.constructed = FALSE;
1016  tag.length = length;
1017  tag.value = NULL;
1018 
1019  //Write the corresponding ASN.1 tag
1020  error = asn1WriteTag(&tag, TRUE, p, &n);
1021  //Any error to report?
1022  if(error)
1023  return error;
1024 
1025  //Point to the first byte of the msgSecurityParameters field
1026  message->pos = p - n;
1027  //Total length of the message
1028  message->length += length + n;
1029 
1030  //Successful processing
1031  return NO_ERROR;
1032 #else
1033  //Not implemented
1034  return ERROR_NOT_IMPLEMENTED;
1035 #endif
1036 }
1037 
1038 
1039 /**
1040  * @brief Parse scopedPDU field
1041  * @param[in,out] message Pointer to the incoming SNMP message
1042  * @return Error code
1043  **/
1044 
1046 {
1047 #if (SNMP_V3_SUPPORT == ENABLED)
1048  error_t error;
1049  size_t length;
1050  const uint8_t *p;
1051  Asn1Tag tag;
1052 
1053  //Read the scopedPDU field
1054  error = asn1ReadSequence(message->pos, message->length, &tag);
1055  //Failed to decode ASN.1 tag?
1056  if(error)
1057  return error;
1058 
1059  //Point to the first field of the sequence
1060  p = tag.value;
1061  length = tag.length;
1062 
1063  //Read contextEngineID field
1064  error = asn1ReadTag(p, length, &tag);
1065  //Failed to decode ASN.1 tag?
1066  if(error)
1067  return error;
1068 
1069  //Enforce encoding, class and type
1071  //The tag does not match the criteria?
1072  if(error)
1073  return error;
1074 
1075  //Save context engine identifier
1076  message->contextEngineId = tag.value;
1077  message->contextEngineIdLen = tag.length;
1078 
1079  //Point to the next field
1080  p += tag.totalLength;
1081  length -= tag.totalLength;
1082 
1083  //Read contextName field
1084  error = asn1ReadTag(p, length, &tag);
1085  //Failed to decode ASN.1 tag?
1086  if(error)
1087  return error;
1088 
1089  //Enforce encoding, class and type
1091  //The tag does not match the criteria?
1092  if(error)
1093  return error;
1094 
1095  //Save context name
1096  message->contextName = (char_t *) tag.value;
1097  message->contextNameLen = tag.length;
1098 
1099  //Point to the first byte of the PDU
1100  message->pos = (uint8_t *) p + tag.totalLength;
1101  //Length of the PDU
1102  message->length = length - tag.totalLength;
1103 
1104  //Return status code
1105  return error;
1106 #else
1107  //Not implemented
1108  return ERROR_NOT_IMPLEMENTED;
1109 #endif
1110 }
1111 
1112 
1113 /**
1114  * @brief Format scopedPDU
1115  * @param[in,out] message Pointer to the outgoing SNMP message
1116  * @return Error code
1117  **/
1118 
1120 {
1121 #if (SNMP_V3_SUPPORT == ENABLED)
1122  error_t error;
1123  size_t n;
1124  size_t length;
1125  uint8_t *p;
1126  Asn1Tag tag;
1127 
1128  //Point to the first byte of the PDU
1129  p = message->pos;
1130  //Retrieve the length of the PDU
1131  length = message->length;
1132 
1133  //The contextName is an octet string
1134  tag.constructed = FALSE;
1137  tag.length = message->contextNameLen;
1138  tag.value = (uint8_t *) message->contextName;
1139 
1140  //Write the corresponding ASN.1 tag
1141  error = asn1WriteTag(&tag, TRUE, p, &n);
1142  //Any error to report?
1143  if(error)
1144  return error;
1145 
1146  //Move backward
1147  p -= n;
1148  //Update the length of the scopedPduData
1149  length += n;
1150 
1151  //The contextEngineID is an octet string
1152  tag.constructed = FALSE;
1155  tag.length = message->contextEngineIdLen;
1156  tag.value = message->contextEngineId;
1157 
1158  //Write the corresponding ASN.1 tag
1159  error = asn1WriteTag(&tag, TRUE, p, &n);
1160  //Any error to report?
1161  if(error)
1162  return error;
1163 
1164  //Move backward
1165  p -= n;
1166  //Update the length of the scopedPduData
1167  length += n;
1168 
1169  //The scopedPduData is encapsulated within a sequence
1170  tag.constructed = TRUE;
1173  tag.length = length;
1174  tag.value = NULL;
1175 
1176  //Write the corresponding ASN.1 tag
1177  error = asn1WriteTag(&tag, TRUE, p, &n);
1178  //Any error to report?
1179  if(error)
1180  return error;
1181 
1182  //Point to the first byte of the scopedPDU
1183  message->pos = p - n;
1184  //Length of the scopedPDU
1185  message->length = length + n;
1186 
1187  //Successful processing
1188  return NO_ERROR;
1189 #else
1190  //Not implemented
1191  return ERROR_NOT_IMPLEMENTED;
1192 #endif
1193 }
1194 
1195 
1196 /**
1197  * @brief Parse PDU header
1198  * @param[in,out] message Pointer to the incoming SNMP message
1199  * @return Error code
1200  **/
1201 
1203 {
1204  error_t error;
1205  size_t length;
1206  const uint8_t *p;
1207  Asn1Tag tag;
1208 
1209  //The PDU is encapsulated within a sequence
1210  error = asn1ReadTag(message->pos, message->length, &tag);
1211  //Failed to decode ASN.1 tag?
1212  if(error)
1213  return error;
1214 
1215  //Check encoding
1216  if(tag.constructed != TRUE)
1217  return ERROR_WRONG_ENCODING;
1218  //Enforce class
1220  return ERROR_INVALID_CLASS;
1221 
1222  //Save PDU type
1223  message->pduType = (SnmpPduType) tag.objType;
1224 
1225  //Point to the first field
1226  p = tag.value;
1227  //Remaining bytes to process
1228  length = tag.length;
1229 
1230  //Read request-id field
1231  error = asn1ReadInt32(p, length, &tag, &message->requestId);
1232  //Failed to decode ASN.1 tag?
1233  if(error)
1234  return error;
1235 
1236  //Point to the next field
1237  p += tag.totalLength;
1238  length -= tag.totalLength;
1239 
1240 #if (SNMP_V2C_SUPPORT == ENABLED || SNMP_V3_SUPPORT == ENABLED)
1241  //GetBulkRequest-PDU?
1242  if(message->pduType == SNMP_PDU_GET_BULK_REQUEST)
1243  {
1244  //Read non-repeaters field
1245  error = asn1ReadInt32(p, length, &tag, &message->nonRepeaters);
1246  //Failed to decode ASN.1 tag?
1247  if(error)
1248  return error;
1249 
1250  //If the value in the non-repeaters field is less than zero, then the
1251  //value of the field is set to zero
1252  if(message->nonRepeaters < 0)
1253  message->nonRepeaters = 0;
1254 
1255  //Point to the next field
1256  p += tag.totalLength;
1257  length -= tag.totalLength;
1258 
1259  //Read max-repetitions field
1260  error = asn1ReadInt32(p, length, &tag, &message->maxRepetitions);
1261  //Failed to decode ASN.1 tag?
1262  if(error)
1263  return error;
1264 
1265  //If the value in the max-repetitions field is less than zero, then the
1266  //value of the field is set to zero
1267  if(message->maxRepetitions < 0)
1268  message->maxRepetitions = 0;
1269  }
1270  else
1271 #endif
1272  {
1273  //Read error-status field
1274  error = asn1ReadInt32(p, length, &tag, &message->errorStatus);
1275  //Failed to decode ASN.1 tag?
1276  if(error)
1277  return error;
1278 
1279  //Point to the next field
1280  p += tag.totalLength;
1281  length -= tag.totalLength;
1282 
1283  //Read error-index field
1284  error = asn1ReadInt32(p, length, &tag, &message->errorIndex);
1285  //Failed to decode ASN.1 tag?
1286  if(error)
1287  return error;
1288  }
1289 
1290  //Point to the next field
1291  p += tag.totalLength;
1292  length -= tag.totalLength;
1293 
1294  //The variable bindings are encapsulated within a sequence
1295  error = asn1ReadSequence(p, length, &tag);
1296  //Failed to decode ASN.1 tag?
1297  if(error)
1298  return error;
1299 
1300  //Save the location of the variable binding list
1301  message->varBindList = (uint8_t *) tag.value;
1302  message->varBindListLen = tag.length;
1303 
1304  //Successful processing
1305  return NO_ERROR;
1306 }
1307 
1308 
1309 /**
1310  * @brief Format PDU header
1311  * @param[in,out] message Pointer to the outgoing SNMP message
1312  * @return Error code
1313  **/
1314 
1316 {
1317  error_t error;
1318  size_t n;
1319  size_t length;
1320  uint8_t *p;
1321  Asn1Tag tag;
1322 
1323  //The PDU header will be encoded in reverse order...
1324  p = message->varBindList;
1325  //Length of the PDU
1326  length = message->varBindListLen;
1327 
1328  //The variable bindings are encapsulated within a sequence
1329  tag.constructed = TRUE;
1332  tag.length = length;
1333  tag.value = NULL;
1334 
1335  //Write the corresponding ASN.1 tag
1336  error = asn1WriteTag(&tag, TRUE, p, &n);
1337  //Any error to report?
1338  if(error)
1339  return error;
1340 
1341  //Move backward
1342  p -= n;
1343  //Update the length of the PDU
1344  length += n;
1345 
1346  //GetRequest-PDU, GetResponse-PDU, InformRequest-PDU, SNMPv2-Trap-PDU
1347  //or Report-PDU?
1348  if(message->pduType == SNMP_PDU_GET_REQUEST ||
1349  message->pduType == SNMP_PDU_GET_RESPONSE ||
1350  message->pduType == SNMP_PDU_INFORM_REQUEST ||
1351  message->pduType == SNMP_PDU_TRAP_V2 ||
1352  message->pduType == SNMP_PDU_REPORT)
1353  {
1354  //Write error index
1355  error = asn1WriteInt32(message->errorIndex, TRUE, p, &n);
1356  //Any error to report?
1357  if(error)
1358  return error;
1359 
1360  //Move backward
1361  p -= n;
1362  //Update the length of the PDU
1363  length += n;
1364 
1365  //Write error status
1366  error = asn1WriteInt32(message->errorStatus, TRUE, p, &n);
1367  //Any error to report?
1368  if(error)
1369  return error;
1370 
1371  //Move backward
1372  p -= n;
1373  //Update the length of the PDU
1374  length += n;
1375 
1376  //Write request identifier
1377  error = asn1WriteInt32(message->requestId, TRUE, p, &n);
1378  //Any error to report?
1379  if(error)
1380  return error;
1381 
1382  //Move backward
1383  p -= n;
1384  //Update the length of the PDU
1385  length += n;
1386  }
1387 #if (SNMP_V1_SUPPORT == ENABLED)
1388  //Trap-PDU?
1389  else if(message->pduType == SNMP_PDU_TRAP)
1390  {
1391  //Encode the object value using ASN.1 rules
1392  error = snmpEncodeUnsignedInt32(message->timestamp, message->buffer, &n);
1393  //Any error to report?
1394  if(error)
1395  return error;
1396 
1397  //The time stamp is encoded in ASN.1 format
1398  tag.constructed = FALSE;
1401  tag.length = n;
1402  tag.value = message->buffer;
1403 
1404  //Write the corresponding ASN.1 tag
1405  error = asn1WriteTag(&tag, TRUE, p, &n);
1406  //Any error to report?
1407  if(error)
1408  return error;
1409 
1410  //Move backward
1411  p -= n;
1412  //Update the length of the PDU
1413  length += n;
1414 
1415  //Write specific trap code
1416  error = asn1WriteInt32(message->specificTrapCode, TRUE, p, &n);
1417  //Any error to report?
1418  if(error)
1419  return error;
1420 
1421  //Move backward
1422  p -= n;
1423  //Update the length of the PDU
1424  length += n;
1425 
1426  //Write generic trap type
1427  error = asn1WriteInt32(message->genericTrapType, TRUE, p, &n);
1428  //Any error to report?
1429  if(error)
1430  return error;
1431 
1432  //Move backward
1433  p -= n;
1434  //Update the length of the PDU
1435  length += n;
1436 
1437  //The agent address is encoded in ASN.1 format
1438  tag.constructed = FALSE;
1441  tag.length = sizeof(Ipv4Addr);
1442  tag.value = (uint8_t *) &message->agentAddr;
1443 
1444  //Write the corresponding ASN.1 tag
1445  error = asn1WriteTag(&tag, TRUE, p, &n);
1446  //Any error to report?
1447  if(error)
1448  return error;
1449 
1450  //Move backward
1451  p -= n;
1452  //Update the length of the PDU
1453  length += n;
1454 
1455  //The enterprise OID is encoded in ASN.1 format
1456  tag.constructed = FALSE;
1459  tag.length = message->enterpriseOidLen;
1460  tag.value = message->enterpriseOid;
1461 
1462  //Write the corresponding ASN.1 tag
1463  error = asn1WriteTag(&tag, TRUE, p, &n);
1464  //Any error to report?
1465  if(error)
1466  return error;
1467 
1468  //Move backward
1469  p -= n;
1470  //Update the length of the PDU
1471  length += n;
1472  }
1473 #endif
1474  //Unknown PDU type?
1475  else
1476  {
1477  //Report an error
1478  return ERROR_FAILURE;
1479  }
1480 
1481  //The PDU is encapsulated within a sequence
1482  tag.constructed = TRUE;
1484  tag.objType = message->pduType;
1485  tag.length = length;
1486  tag.value = NULL;
1487 
1488  //Write the corresponding ASN.1 tag
1489  error = asn1WriteTag(&tag, TRUE, p, &n);
1490  //Any error to report?
1491  if(error)
1492  return error;
1493 
1494  //Point to the first byte of the PDU
1495  message->pos = p - n;
1496  //Total length of the PDU
1497  message->length = length + n;
1498 
1499  //Successful processing
1500  return NO_ERROR;
1501 }
1502 
1503 
1504 /**
1505  * @brief Encode a 32-bit signed integer
1506  * @param[in] value Integer value
1507  * @param[out] dest Buffer where to encode the integer
1508  * @param[out] length Total number of bytes that have been written
1509  * @return Error code
1510  **/
1511 
1512 error_t snmpEncodeInt32(int32_t value, uint8_t *dest, size_t *length)
1513 {
1514  size_t i;
1515  size_t j;
1516  uint8_t *src;
1517 
1518  //Check parameters
1519  if(dest == NULL || length == NULL)
1520  return ERROR_INVALID_PARAMETER;
1521 
1522  //The integer is encoded MSB first
1523  value = (int32_t) htobe32(value);
1524  //Cast the integer to byte array
1525  src = (uint8_t *) &value;
1526 
1527  //An integer value is always encoded in the smallest possible number of octets
1528  for(i = 0; i < 3; i++)
1529  {
1530  //The upper 9 bits shall not have the same value (all 0 or all 1)
1531  if((src[i] != 0x00 || (src[i + 1] & 0x80) != 0x00) &&
1532  (src[i] != 0xFF || (src[i + 1] & 0x80) != 0x80))
1533  {
1534  break;
1535  }
1536  }
1537 
1538  //Point to the beginning of the output buffer
1539  j = 0;
1540 
1541  //Copy integer value
1542  while(i < 4)
1543  dest[j++] = src[i++];
1544 
1545  //Total number of bytes that have been written
1546  *length = j;
1547 
1548  //Successful processing
1549  return NO_ERROR;
1550 }
1551 
1552 
1553 /**
1554  * @brief Encode a 32-bit unsigned integer
1555  * @param[in] value Integer value
1556  * @param[out] dest Buffer where to encode the integer
1557  * @param[out] length Total number of bytes that have been written
1558  * @return Error code
1559  **/
1560 
1561 error_t snmpEncodeUnsignedInt32(uint32_t value, uint8_t *dest, size_t *length)
1562 {
1563  size_t i;
1564  size_t j;
1565  uint8_t *src;
1566 
1567  //Check parameters
1568  if(dest == NULL || length == NULL)
1569  return ERROR_INVALID_PARAMETER;
1570 
1571  //The integer is encoded MSB first
1572  value = htobe32(value);
1573  //Cast the integer to byte array
1574  src = (uint8_t *) &value;
1575 
1576  //An integer value is always encoded in the smallest possible number of octets
1577  for(i = 0; i < 3; i++)
1578  {
1579  //Check the upper 8 bits
1580  if(src[i] != 0x00)
1581  break;
1582  }
1583 
1584  //Point to the beginning of the output buffer
1585  j = 0;
1586 
1587  //Check the most significant bit
1588  if(src[i] & 0x80)
1589  dest[j++] = 0;
1590 
1591  //Copy integer value
1592  while(i < 4)
1593  dest[j++] = src[i++];
1594 
1595  //Total number of bytes that have been written
1596  *length = j;
1597 
1598  //Successful processing
1599  return NO_ERROR;
1600 }
1601 
1602 
1603 /**
1604  * @brief Encode a 64-bit unsigned integer
1605  * @param[in] value Integer value
1606  * @param[out] dest Buffer where to encode the integer
1607  * @param[out] length Total number of bytes that have been written
1608  * @return Error code
1609  **/
1610 
1611 error_t snmpEncodeUnsignedInt64(uint64_t value, uint8_t *dest, size_t *length)
1612 {
1613  size_t i;
1614  size_t j;
1615  uint8_t *src;
1616 
1617  //Check parameters
1618  if(dest == NULL || length == NULL)
1619  return ERROR_INVALID_PARAMETER;
1620 
1621  //The integer is encoded MSB first
1622  value = htobe64(value);
1623  //Cast the integer to byte array
1624  src = (uint8_t *) &value;
1625 
1626  //An integer value is always encoded in the smallest possible number of octets
1627  for(i = 0; i < 7; i++)
1628  {
1629  //Check the upper 8 bits
1630  if(src[i] != 0x00)
1631  break;
1632  }
1633 
1634  //Point to the beginning of the output buffer
1635  j = 0;
1636 
1637  //Check the most significant bit
1638  if(src[i] & 0x80)
1639  dest[j++] = 0;
1640 
1641  //Copy integer value
1642  while(i < 8)
1643  dest[j++] = src[i++];
1644 
1645  //Total number of bytes that have been written
1646  *length = j;
1647 
1648  //Successful processing
1649  return NO_ERROR;
1650 }
1651 
1652 
1653 /**
1654  * @brief Decode a 32-bit signed integer
1655  * @param[in] src Buffer that contains the encoded value
1656  * @param[in] length Number of bytes to be processed
1657  * @param[out] value Resulting integer value
1658  * @return Error code
1659  **/
1660 
1661 error_t snmpDecodeInt32(const uint8_t *src, size_t length, int32_t *value)
1662 {
1663  size_t i;
1664 
1665  //Check parameters
1666  if(src == NULL || value == NULL)
1667  return ERROR_INVALID_PARAMETER;
1668  if(length < 1)
1669  return ERROR_INVALID_PARAMETER;
1670 
1671  //The contents octets shall be a two's complement binary
1672  //number equal to the integer value
1673  *value = (src[0] & 0x80) ? -1 : 0;
1674 
1675  //Process contents octets
1676  for(i = 0; i < length; i++)
1677  {
1678  //Rotate left operation
1679  *value <<= 8;
1680  //Reconstruct integer value
1681  *value |= src[i];
1682  }
1683 
1684  //Successful processing
1685  return NO_ERROR;
1686 }
1687 
1688 
1689 /**
1690  * @brief Decode a 32-bit unsigned integer
1691  * @param[in] src Buffer that contains the encoded value
1692  * @param[in] length Number of bytes to be processed
1693  * @param[out] value Resulting integer value
1694  * @return Error code
1695  **/
1696 
1697 error_t snmpDecodeUnsignedInt32(const uint8_t *src, size_t length, uint32_t *value)
1698 {
1699  size_t i;
1700 
1701  //Check parameters
1702  if(src == NULL || value == NULL)
1703  return ERROR_INVALID_PARAMETER;
1704  if(length < 1)
1705  return ERROR_INVALID_PARAMETER;
1706 
1707  //Only accept non-negative numbers
1708  if(src[0] & 0x80)
1709  return ERROR_FAILURE;
1710 
1711  //Initialize integer value
1712  *value = 0;
1713 
1714  //Process contents octets
1715  for(i = 0; i < length; i++)
1716  {
1717  //Rotate left operation
1718  *value <<= 8;
1719  //Reconstruct integer value
1720  *value |= src[i];
1721  }
1722 
1723  //Successful processing
1724  return NO_ERROR;
1725 }
1726 
1727 
1728 /**
1729  * @brief Decode a 64-bit unsigned integer
1730  * @param[in] src Buffer that contains the encoded value
1731  * @param[in] length Number of bytes to be processed
1732  * @param[out] value Resulting integer value
1733  * @return Error code
1734  **/
1735 
1736 error_t snmpDecodeUnsignedInt64(const uint8_t *src, size_t length, uint64_t *value)
1737 {
1738  size_t i;
1739 
1740  //Check parameters
1741  if(src == NULL || value == NULL)
1742  return ERROR_INVALID_PARAMETER;
1743  if(length < 1)
1744  return ERROR_INVALID_PARAMETER;
1745 
1746  //Only accept non-negative numbers
1747  if(src[0] & 0x80)
1748  return ERROR_FAILURE;
1749 
1750  //Initialize integer value
1751  *value = 0;
1752 
1753  //Process contents octets
1754  for(i = 0; i < length; i++)
1755  {
1756  //Rotate left operation
1757  *value <<= 8;
1758  //Reconstruct integer value
1759  *value |= src[i];
1760  }
1761 
1762  //Successful processing
1763  return NO_ERROR;
1764 }
1765 
1766 #endif
uint_t objType
Definition: asn1.h:98
uint32_t Ipv4Addr
IPv4 network address.
Definition: ipv4.h:232
#define SNMP_V2C_MSG_HEADER_OVERHEAD
error_t snmpParseCommunity(SnmpMessage *message)
Parse community name.
error_t snmpDecodeUnsignedInt64(const uint8_t *src, size_t length, uint64_t *value)
Decode a 64-bit unsigned integer.
char char_t
Definition: compiler_port.h:41
error_t asn1ReadInt32(const uint8_t *data, size_t length, Asn1Tag *tag, int32_t *value)
Read an integer from the input stream.
Definition: asn1.c:186
#define SNMP_MSG_ENCRYPTION_OVERHEAD
TCP/IP stack core.
Debugging facilities.
uint8_t p
Definition: ndp.h:295
error_t snmpDecodeInt32(const uint8_t *src, size_t length, int32_t *value)
Decode a 32-bit signed integer.
Generic error code.
Definition: error.h:43
size_t totalLength
Definition: asn1.h:101
error_t snmpComputeMessageOverhead(SnmpMessage *message)
Compute SNMP message overhead.
uint8_t message[]
Definition: chap.h:150
#define htobe32(value)
Definition: cpu_endian.h:420
User-based security model.
General definitions for cryptographic algorithms.
Invalid parameter.
Definition: error.h:45
error_t snmpEncodeUnsignedInt64(uint64_t value, uint8_t *dest, size_t *length)
Encode a 64-bit unsigned integer.
error_t snmpDecodeUnsignedInt32(const uint8_t *src, size_t length, uint32_t *value)
Decode a 32-bit unsigned integer.
#define ASN1_CLASS_CONTEXT_SPECIFIC
Definition: asn1.h:47
error_t snmpWriteMessageHeader(SnmpMessage *message)
Format SNMP message header.
error_t snmpParsePduHeader(SnmpMessage *message)
Parse PDU header.
ASN.1 tag.
Definition: asn1.h:94
#define TRUE
Definition: os_port.h:48
error_t asn1WriteTag(Asn1Tag *tag, bool_t reverse, uint8_t *data, size_t *written)
Write an ASN.1 tag.
Definition: asn1.c:234
error_t asn1CheckTag(const Asn1Tag *tag, bool_t constructed, uint_t objClass, uint_t objType)
Enforce the type of a specified tag.
Definition: asn1.c:426
SNMP MPD MIB module.
#define SNMP_V3_MSG_HEADER_OVERHEAD
ASN.1 (Abstract Syntax Notation One)
error_t asn1ReadSequence(const uint8_t *data, size_t length, Asn1Tag *tag)
Read an ASN.1 sequence from the input stream.
Definition: asn1.c:158
#define ASN1_CLASS_APPLICATION
Definition: asn1.h:46
SNMP agent (Simple Network Management Protocol)
error_t snmpEncodeUnsignedInt32(uint32_t value, uint8_t *dest, size_t *length)
Encode a 32-bit unsigned integer.
error_t asn1ReadTag(const uint8_t *data, size_t length, Asn1Tag *tag)
Read an ASN.1 tag from the input stream.
Definition: asn1.c:50
size_t length
Definition: asn1.h:99
SnmpPduType
SNMP PDU types.
Definition: snmp_common.h:146
bool_t constructed
Definition: asn1.h:96
error_t snmpInitResponse(SnmpAgentContext *context)
Initialize a GetResponse-PDU.
error_t snmpWriteCommunity(SnmpMessage *message)
Format community name.
error_t asn1WriteInt32(int32_t value, bool_t reverse, uint8_t *data, size_t *written)
Write an integer to the output stream.
Definition: asn1.c:372
error_t snmpEncodeInt32(int32_t value, uint8_t *dest, size_t *length)
Encode a 32-bit signed integer.
Success.
Definition: error.h:42
error_t
Error codes.
Definition: error.h:40
SNMP message.
#define SNMP_MPD_MIB_INC_COUNTER32(name, value)
#define htobe64(value)
Definition: cpu_endian.h:421
uint8_t value[]
Definition: dtls_misc.h:141
error_t snmpParseSecurityParameters(SnmpMessage *message)
Parse msgSecurityParameters field.
uint_t objClass
Definition: asn1.h:97
#define ASN1_CLASS_UNIVERSAL
Definition: asn1.h:45
error_t snmpWriteGlobalData(SnmpMessage *message)
Format msgGlobalData field.
#define SNMP_MAX_MSG_SIZE
Definition: snmp_common.h:58
#define IPV4_UNSPECIFIED_ADDR
Definition: ipv4.h:95
#define SnmpAgentContext
Definition: snmp_agent.h:34
error_t snmpWriteSecurityParameters(SnmpMessage *message)
Format msgSecurityParameters field.
#define SNMP_V1_MSG_HEADER_OVERHEAD
error_t snmpParseGlobalData(SnmpMessage *message)
Parse msgGlobalData field.
error_t snmpParseScopedPdu(SnmpMessage *message)
Parse scopedPDU field.
error_t snmpWriteScopedPdu(SnmpMessage *message)
Format scopedPDU.
uint8_t length
Definition: dtls_misc.h:140
uint8_t n
void snmpInitMessage(SnmpMessage *message)
Initialize a SNMP message.
#define FALSE
Definition: os_port.h:44
const uint8_t * value
Definition: asn1.h:100
error_t snmpParseMessageHeader(SnmpMessage *message)
Parse SNMP message header.
error_t snmpWritePduHeader(SnmpMessage *message)
Format PDU header.