1 /*_############################################################################
6 _## -----------------------------------------------
7 _## Copyright (c) 2001-2010 Jochen Katz, Frank Fock
9 _## This software is based on SNMP++2.6 from Hewlett Packard:
11 _## Copyright (c) 1996
12 _## Hewlett-Packard Company
14 _## ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS.
15 _## Permission to use, copy, modify, distribute and/or sell this software
16 _## and/or its documentation is hereby granted without fee. User agrees
17 _## to display the above copyright notice and this license notice in all
18 _## copies of the software and any documentation of the software. User
19 _## agrees to assume all liability for the use of the software;
20 _## Hewlett-Packard and Jochen Katz make no representations about the
21 _## suitability of this software for any purpose. It is provided
22 _## "AS-IS" without warranty of any kind, either express or implied. User
23 _## hereby grants a royalty-free license to any and all derivatives based
24 _## upon this software code base.
26 _## Stuttgart, Germany, Thu Sep 2 00:07:47 CEST 2010
28 _##########################################################################*/
30 /*===================================================================
32 Hewlett-Packard Company
34 ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS.
35 Permission to use, copy, modify, distribute and/or sell this software
36 and/or its documentation is hereby granted without fee. User agrees
37 to display the above copyright notice and this license notice in all
38 copies of the software and any documentation of the software. User
39 agrees to assume all liability for the use of the software; Hewlett-Packard
40 makes no representations about the suitability of this software for any
41 purpose. It is provided "AS-IS" without warranty of any kind,either express
42 or implied. User hereby grants a royalty-free license to any and all
43 derivatives based upon this software code base.
47 ASN encoder / decoder implementation
49 DESIGN + AUTHOR: Peter E. Mellquist
50 =====================================================================*/
51 char asn1_cpp_version[]="#(@) SNMP++ $Id: asn1.cpp 1557 2009-07-03 20:16:09Z katz $";
54 #include /**/ <sys/types.h>
55 #include /**/ <netinet/in.h>
58 #include /**/ <stdlib.h>
60 #include "snmp_pp/config_snmp_pp.h"
61 #include "snmp_pp/asn1.h"
62 #include "snmp_pp/v3.h"
63 #include "snmp_pp/snmperrs.h"
64 #include "snmp_pp/log.h"
66 #ifdef SNMP_PP_NAMESPACE
75 * asn_parse_int - pulls a long out of an ASN int type.
76 * On entry, datalength is input as the number of valid bytes following
77 * "data". On exit, it is returned as the number of valid bytes
78 * following the end of this object.
80 * Returns a pointer to the first byte past the end
81 * of this object (i.e. the start of the next object).
82 * Returns NULL on any error.
84 unsigned char *asn_parse_int(unsigned char *data,
90 * ASN.1 integer ::= 0x02 asnlength byte {byte}*
91 * timestamp 0x43 asnlength byte {byte}*
93 unsigned char *bufp = data;
94 unsigned long asn_length;
98 if ((*type != 0x02) && (*type != 0x43) &&
100 ASNERROR("Wrong Type. Not an integer");
103 bufp = asn_parse_length(bufp, &asn_length);
105 ASNERROR("bad length");
108 if ((asn_length + (bufp - data)) > (unsigned long)(*datalength)) {
109 ASNERROR("overflow of message (int)");
112 if (asn_length > sizeof(*intp)) {
113 ASNERROR("I don't support such large integers");
116 *datalength -= (int)asn_length + SAFE_INT_CAST(bufp - data);
118 value = -1; /* integer is negative */
120 value = (value << 8) | *bufp++;
127 * asn_parse_unsigned_int - pulls an unsigned long out of an ASN int type.
128 * On entry, datalength is input as the number of valid bytes following
129 * "data". On exit, it is returned as the number of valid bytes
130 * following the end of this object.
132 * Returns a pointer to the first byte past the end
133 * of this object (i.e. the start of the next object).
134 * Returns NULL on any error.
136 unsigned char *asn_parse_unsigned_int(unsigned char *data,
142 * ASN.1 integer ::= 0x02 asnlength byte {byte}*
143 * 0x43 asnlength byte {byte}*
145 unsigned char *bufp = data;
146 unsigned long asn_length;
147 unsigned long value = 0;
151 if ((*type != 0x02) && (*type != 0x43) &&
152 (*type != 0x41) && (*type != 0x42) &&
154 ASNERROR("Wrong Type. Not an unsigned integer");
159 bufp = asn_parse_length(bufp, &asn_length);
161 ASNERROR("bad length");
165 // check the len for message overflow
166 if ((asn_length + (bufp - data)) > (unsigned long)(*datalength)) {
167 ASNERROR("overflow of message (uint)");
171 // check for legal uint size
172 if ((asn_length > 5) || ((asn_length > 4) && (*bufp != 0x00))) {
173 ASNERROR("I don't support such large integers");
177 // check for leading 0 octet
183 // fix the returned data length value
184 *datalength -= (int)asn_length + SAFE_INT_CAST(bufp - data);
186 // calculate the value
187 for (long i=0;i<(long)asn_length;i++)
188 value = (value << 8) + (unsigned long) *bufp++;
190 *intp = value; // assign return value
192 return bufp; // return the bumped pointer
197 * asn_build_int - builds an ASN object containing an integer.
198 * On entry, datalength is input as the number of valid bytes following
199 * "data". On exit, it is returned as the number of valid bytes
200 * following the end of this object.
202 * Returns a pointer to the first byte past the end
203 * of this object (i.e. the start of the next object).
204 * Returns NULL on any error.
206 unsigned char *asn_build_int(unsigned char *data, int *datalength,
207 const unsigned char type,
211 * ASN.1 integer ::= 0x02 asnlength byte {byte}*
213 long integer = *intp;
215 int intsize = sizeof(long);
217 /* Truncate "unnecessary" bytes off of the most significant end of this
218 * 2's complement integer. There should be no sequence of 9
219 * consecutive 1's or 0's at the most significant end of the
222 mask = 0x1FFul << ((8 * (sizeof(long) - 1)) - 1);
223 /* mask is 0xFF800000 on a big-endian machine */
224 while((((integer & mask) == 0) || ((integer & mask) == mask))
229 data = asn_build_header(data, datalength, type, intsize);
230 if (data == NULL) return NULL;
231 if (*datalength < intsize) return NULL;
232 *datalength -= intsize;
233 mask = 0xFFul << (8 * (sizeof(long) - 1));
234 /* mask is 0xFF000000 on a big-endian machine */
236 *data++ = (unsigned char)((integer & mask) >> (8 * (sizeof(long) - 1)));
244 * asn_build_unsigned_int - builds an ASN object containing an integer.
245 * On entry, datalength is input as the number of valid bytes following
246 * "data". On exit, it is returned as the number of valid bytes
247 * following the end of this object.
249 * Returns a pointer to the first byte past the end
250 * of this object (i.e. the start of the next object).
251 * Returns NULL on any error.
253 unsigned char *asn_build_unsigned_int(unsigned char *data, // modified data
254 int *datalength, // returned buffer length
255 unsigned char type, // SMI type
256 unsigned long *intp) // Uint to encode
259 * ASN.1 integer ::= 0x02 asnlength byte {byte}*
261 unsigned long u_integer = *intp;
265 // figure out the len
266 if (((u_integer >> 24) & 0xFF) != 0)
268 else if (((u_integer >> 16) & 0xFF) !=0)
270 else if (((u_integer >> 8) & 0xFF) !=0)
275 // check for 5 byte len where first byte will be a null
276 if (((u_integer >> (8 * (u_integer_len -1))) & 0x080) !=0) {
280 // build up the header
281 data = asn_build_header(data, datalength, type, u_integer_len);
282 if (data == NULL) return NULL;
283 if (*datalength < u_integer_len) return NULL;
285 // special case, add a null byte for len of 5
286 if (u_integer_len == 5) {
288 for (x=1;x<u_integer_len;x++)
289 *data++= (unsigned char) (u_integer >> (8 * ((u_integer_len-1)-x)& 0xFF));
293 for (x=0;x<u_integer_len;x++)
294 *data++= (unsigned char) (u_integer >> (8 * ((u_integer_len-1)-x)& 0xFF));
296 *datalength -= u_integer_len;
302 * asn_parse_string - pulls an octet string out of an ASN octet string type.
303 * On entry, datalength is input as the number of valid bytes following
304 * "data". On exit, it is returned as the number of valid bytes
305 * following the beginning of the next object.
307 * "string" is filled with the octet string.
309 * Returns a pointer to the first byte past the end
310 * of this object (i.e. the start of the next object).
311 * Returns NULL on any error.
313 unsigned char *asn_parse_string(unsigned char *data,
320 * ASN.1 octet string ::= primstring | cmpdstring
321 * primstring ::= 0x04 asnlength byte {byte}*
322 * cmpdstring ::= 0x24 asnlength string {string}*
323 * ipaddress ::= 0x40 4 byte byte byte byte
325 unsigned char *bufp = data;
326 unsigned long asn_length;
329 if ((*type != 0x04) && (*type != 0x24) &&
330 (*type != 0x40) && (*type != 0x44) &&
332 ASNERROR("asn parse string: Wrong Type. Not a string");
335 bufp = asn_parse_length(bufp, &asn_length);
338 if ((asn_length + (bufp - data)) > (unsigned long)(*datalength)) {
339 ASNERROR("asn parse string: overflow of message");
342 if ((int)asn_length > *strlength) {
343 ASNERROR("asn parse string: String to parse is longer than buffer, aborting parsing.");
347 memcpy(str, bufp, asn_length);
348 *strlength = (int)asn_length;
349 *datalength -= (int)asn_length + SAFE_INT_CAST(bufp - data);
350 return bufp + asn_length;
355 * asn_build_string - Builds an ASN octet string object containing the input string.
356 * On entry, datalength is input as the number of valid bytes following
357 * "data". On exit, it is returned as the number of valid bytes
358 * following the beginning of the next object.
360 * Returns a pointer to the first byte past the end
361 * of this object (i.e. the start of the next object).
362 * Returns NULL on any error.
364 unsigned char *asn_build_string(unsigned char *data,
366 const unsigned char type,
367 const unsigned char *string,
371 * ASN.1 octet string ::= primstring | cmpdstring
372 * primstring ::= 0x04 asnlength byte {byte}*
373 * cmpdstring ::= 0x24 asnlength string {string}*
374 * This code will never send a compound string.
376 data = asn_build_header(data, datalength, type, strlength);
377 if (data == NULL) return NULL;
378 if (*datalength < strlength) return NULL;
380 memcpy(data, string, strlength);
381 *datalength -= strlength;
382 return data + strlength;
387 * asn_parse_header - interprets the ID and length of the current object.
388 * On entry, datalength is input as the number of valid bytes following
389 * "data". On exit, it is returned as the number of valid bytes
390 * in this object following the id and length.
392 * Returns a pointer to the first byte of the contents of this object.
393 * Returns NULL on any error.
395 unsigned char *asn_parse_header(unsigned char *data,
399 unsigned char *bufp = data;
400 register int header_len;
401 unsigned long asn_length;
403 /* this only works on data types < 30, i.e. no extension octets */
404 if (IS_EXTENSION_ID(*bufp)) {
405 ASNERROR("can't process ID >= 30");
409 bufp = asn_parse_length(bufp + 1, &asn_length);
412 header_len = SAFE_INT_CAST(bufp - data);
413 if ((unsigned long)(header_len + asn_length) > (unsigned long)*datalength) {
414 ASNERROR("asn length too long");
417 *datalength = (int)asn_length;
422 * asn_build_header - builds an ASN header for an object with the ID and
424 * On entry, datalength is input as the number of valid bytes following
425 * "data". On exit, it is returned as the number of valid bytes
426 * in this object following the id and length.
428 * This only works on data types < 30, i.e. no extension octets.
429 * The maximum length is 0xFFFF;
431 * Returns a pointer to the first byte of the contents of this object.
432 * Returns NULL on any error.
434 unsigned char *asn_build_header(unsigned char *data,
443 return asn_build_length(data, datalength, length);
447 * asn_build_sequence - builds an ASN header for a sequence with the ID and
450 * This only works on data types < 30, i.e. no extension octets.
452 * Returns a pointer to the first byte of the contents of this object.
453 * Returns NULL on any error.
455 unsigned char *asn_build_sequence(unsigned char *data,
460 if (*datalength < 2) /* need at least two octets for a sequence */
462 ASNERROR("build_sequence");
468 unsigned char *data_with_length = asn_build_length(data, datalength, length);
469 if (data_with_length == NULL)
471 (*datalength)++; /* correct datalength to emulate old behavior of build_sequence */
475 return data_with_length;
479 * asn_parse_length - interprets the length of the current object.
480 * On exit, length contains the value of this length field.
482 * Returns a pointer to the first byte after this length
483 * field (aka: the start of the data field).
484 * Returns NULL on any error.
486 unsigned char * asn_parse_length(unsigned char *data,
487 unsigned long *length)
489 unsigned char lengthbyte = *data;
491 if (lengthbyte & ASN_LONG_LEN) {
492 lengthbyte &= ~ASN_LONG_LEN; /* turn MSb off */
493 if (lengthbyte == 0) {
494 ASNERROR("We don't support indefinite lengths");
497 if (lengthbyte > sizeof(int)) {
498 ASNERROR("we can't support data lengths that long");
501 for (int i=0 ; i < lengthbyte ; i++)
503 *length = (*length << 8) + *(data + 1 + i);
505 // check for length greater than 2^31
506 if (*length > 0x80000000ul) {
507 ASNERROR("SNMP does not support data lengths > 2^31");
510 return data + lengthbyte + 1;
511 } else { /* short asnlength */
512 *length = (long)lengthbyte;
517 unsigned char *asn_build_length(unsigned char *data,
521 unsigned char *start_data = data;
523 /* no indefinite lengths sent */
525 if (*datalength < 1) {
526 ASNERROR("build_length");
529 *data++ = (unsigned char)length;
531 else if (length <= 0xFF) {
532 if (*datalength < 2) {
533 ASNERROR("build_length");
536 *data++ = (unsigned char)(0x01 | ASN_LONG_LEN);
537 *data++ = (unsigned char)length;
539 else if (length <= 0xFFFF) { /* 0xFF < length <= 0xFFFF */
540 if (*datalength < 3) {
541 ASNERROR("build_length");
544 *data++ = (unsigned char)(0x02 | ASN_LONG_LEN);
545 *data++ = (unsigned char)((length >> 8) & 0xFF);
546 *data++ = (unsigned char)(length & 0xFF);
548 else if (length <= 0xFFFFFF) { /* 0xFF < length <= 0xFFFF */
549 if (*datalength < 4) {
550 ASNERROR("build_length");
553 *data++ = (unsigned char)(0x03 | ASN_LONG_LEN);
554 *data++ = (unsigned char)((length >> 16) & 0xFF);
555 *data++ = (unsigned char)((length >> 8) & 0xFF);
556 *data++ = (unsigned char)(length & 0xFF);
559 if (*datalength < 5) {
560 ASNERROR("build_length");
563 *data++ = (unsigned char)(0x04 | ASN_LONG_LEN);
564 *data++ = (unsigned char)((length >> 24) & 0xFF);
565 *data++ = (unsigned char)((length >> 16) & 0xFF);
566 *data++ = (unsigned char)((length >> 8) & 0xFF);
567 *data++ = (unsigned char)(length & 0xFF);
569 *datalength -= SAFE_INT_CAST(data - start_data);
574 * asn_parse_objid - pulls an object indentifier out of an ASN object identifier type.
575 * On entry, datalength is input as the number of valid bytes following
576 * "data". On exit, it is returned as the number of valid bytes
577 * following the beginning of the next object.
579 * "objid" is filled with the object identifier.
581 * Returns a pointer to the first byte past the end
582 * of this object (i.e. the start of the next object).
583 * Returns NULL on any error.
585 unsigned char *asn_parse_objid(unsigned char *data,
592 * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}*
593 * subidentifier ::= {leadingbyte}* lastbyte
594 * leadingbyte ::= 1 7bitvalue
595 * lastbyte ::= 0 7bitvalue
597 unsigned char *bufp = data;
598 oid *oidp = objid + 1;
599 unsigned long subidentifier;
601 unsigned long asn_length;
605 ASNERROR("Wrong Type. Not an oid");
608 bufp = asn_parse_length(bufp, &asn_length);
611 if ((asn_length + (bufp - data)) > (unsigned long)(*datalength)) {
612 ASNERROR("overflow of message (objid)");
615 *datalength -= (int)asn_length + SAFE_INT_CAST(bufp - data);
617 /* Handle invalid object identifier encodings of the form 06 00 robustly */
619 objid[0] = objid[1] = 0;
622 (*objidlength)--; /* account for expansion of first byte */
623 while (length > 0 && (*objidlength)-- > 0) {
625 do { /* shift and add in low order 7 bits */
626 subidentifier = (subidentifier << 7) + (*(unsigned char *)bufp & ~ASN_BIT8);
628 } while (*(unsigned char *)bufp++ & ASN_BIT8); /* last byte has high bit clear */
629 if (subidentifier > (unsigned long)MAX_SUBID) {
630 ASNERROR("subidentifier too long");
633 *oidp++ = (oid)subidentifier;
637 * The first two subidentifiers are encoded into the first component
638 * with the value (X * 40) + Y, where:
639 * X is the value of the first subidentifier.
640 * Y is the value of the second subidentifier.
642 subidentifier = (unsigned long)objid[1];
643 if (subidentifier == 0x2B) {
647 objid[1] = (unsigned char)(subidentifier % 40);
648 objid[0] = (unsigned char)((subidentifier - objid[1]) / 40);
651 *objidlength = (int)(oidp - objid);
656 * asn_build_objid - Builds an ASN object identifier object containing the
658 * On entry, datalength is input as the number of valid bytes following
659 * "data". On exit, it is returned as the number of valid bytes
660 * following the beginning of the next object.
662 * Returns a pointer to the first byte past the end
663 * of this object (i.e. the start of the next object).
664 * Returns NULL on any error.
666 unsigned char *asn_build_objid(unsigned char *data,
673 * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}*
674 * subidentifier ::= {leadingbyte}* lastbyte
675 * leadingbyte ::= 1 7bitvalue
676 * lastbyte ::= 0 7bitvalue
678 // F.Fock correct buffer size must be 5*8bit*MAX_OID_LEN
679 unsigned char buf[MAX_OID_LEN*5];
680 unsigned char *bp = buf;
683 unsigned long subid, mask, testmask;
686 if (objidlength < 2) {
690 *bp++ = (unsigned char) (op[1] + (op[0] * 40));
695 while(objidlength-- > 0) {
697 if (subid < 127) { /* off by one? */
698 *bp++ = (unsigned char)subid;
700 mask = 0x7F; /* handle subid == 0 case */
702 /* testmask *MUST* !!!! be of an unsigned type */
703 for(testmask = 0x7F, testbits = 0; testmask != 0;
704 testmask <<= 7, testbits += 7) {
705 if (subid & testmask) { /* if any bits set */
710 /* mask can't be zero here */
711 for(;mask != 0x7F; mask >>= 7, bits -= 7) {
712 /* fix a mask that got truncated above */
713 if (mask == 0x1E00000)
715 *bp++ = (unsigned char)(((subid & mask) >> bits) | ASN_BIT8);
717 *bp++ = (unsigned char)(subid & mask);
720 asnlength = SAFE_INT_CAST(bp - buf);
721 data = asn_build_header(data, datalength, type, asnlength);
722 if (data == NULL) return NULL;
723 if (*datalength < asnlength) return NULL;
725 memcpy((char *)data, (char *)buf, asnlength);
726 *datalength -= asnlength;
727 return data + asnlength;
731 * asn_parse_null - Interprets an ASN null type.
732 * On entry, datalength is input as the number of valid bytes following
733 * "data". On exit, it is returned as the number of valid bytes
734 * following the beginning of the next object.
736 * Returns a pointer to the first byte past the end
737 * of this object (i.e. the start of the next object).
738 * Returns NULL on any error.
740 unsigned char *asn_parse_null(unsigned char *data,
745 * ASN.1 null ::= 0x05 0x00
747 unsigned char *bufp = data;
748 unsigned long asn_length;
752 ASNERROR("Wrong Type. Not a null");
755 bufp = asn_parse_length(bufp, &asn_length);
758 if (asn_length != 0) {
759 ASNERROR("Malformed NULL");
762 *datalength -= SAFE_INT_CAST(bufp - data);
763 return bufp + asn_length;
768 * asn_build_null - Builds an ASN null object.
769 * On entry, datalength is input as the number of valid bytes following
770 * "data". On exit, it is returned as the number of valid bytes
771 * following the beginning of the next object.
773 * Returns a pointer to the first byte past the end
774 * of this object (i.e. the start of the next object).
775 * Returns NULL on any error.
777 unsigned char *asn_build_null(unsigned char *data,
782 * ASN.1 null ::= 0x05 0x00
784 return asn_build_header(data, datalength, type, 0);
788 * asn_parse_bitstring - pulls a bitstring out of an ASN bitstring type.
789 * On entry, datalength is input as the number of valid bytes following
790 * "data". On exit, it is returned as the number of valid bytes
791 * following the beginning of the next object.
793 * "string" is filled with the bit string.
795 * Returns a pointer to the first byte past the end
796 * of this object (i.e. the start of the next object).
797 * Returns NULL on any error.
799 unsigned char *asn_parse_bitstring(unsigned char *data,
802 unsigned char *string,
806 * bitstring ::= 0x03 asnlength unused {byte}*
808 unsigned char *bufp = data;
809 unsigned long asn_length;
813 ASNERROR("Wrong Type. Not a bitstring");
816 bufp = asn_parse_length(bufp, &asn_length);
819 if ((asn_length + (bufp - data)) > (unsigned long)(*datalength)) {
820 ASNERROR("overflow of message (bitstring)");
823 if ((int) asn_length > *strlength) {
824 ASNERROR("I don't support such long bitstrings");
827 if (asn_length < 1) {
828 ASNERROR("Invalid bitstring");
832 ASNERROR("Invalid bitstring");
836 memcpy((char *)string,(char *)bufp, (int)asn_length);
837 *strlength = (int)asn_length;
838 *datalength -= (int)asn_length + SAFE_INT_CAST(bufp - data);
839 return bufp + asn_length;
844 * asn_build_bitstring - Builds an ASN bit string object containing the
846 * On entry, datalength is input as the number of valid bytes following
847 * "data". On exit, it is returned as the number of valid bytes
848 * following the beginning of the next object.
850 * Returns a pointer to the first byte past the end
851 * of this object (i.e. the start of the next object).
852 * Returns NULL on any error.
854 unsigned char *asn_build_bitstring(unsigned char *data,
857 unsigned char *string,
861 * ASN.1 bit string ::= 0x03 asnlength unused {byte}*
863 if (strlength < 1 || *string > 7) {
864 ASNERROR("Building invalid bitstring");
867 data = asn_build_header(data, datalength, type, strlength);
868 if (data == NULL) return NULL;
869 if (*datalength < strlength) return NULL;
871 memcpy((char *)data,(char *)string, strlength);
872 *datalength -= strlength;
873 return data + strlength;
878 * asn_parse_unsigned_int64 - pulls a 64 bit unsigned long out of an ASN int
880 * On entry, datalength is input as the number of valid bytes following
881 * "data". On exit, it is returned as the number of valid bytes
882 * following the end of this object.
884 * Returns a pointer to the first byte past the end
885 * of this object (i.e. the start of the next object).
886 * Returns NULL on any error.
888 unsigned char *asn_parse_unsigned_int64(unsigned char *data,
891 struct counter64 *cp)
894 * ASN.1 integer ::= 0x02 asnlength byte {byte}*
896 unsigned char *bufp = data;
897 unsigned long asn_length;
898 unsigned long low = 0, high = 0;
901 if ((*type != 0x02) && (*type != 0x46)) {
902 ASNERROR("Wrong Type. Not an integer 64");
905 bufp = asn_parse_length(bufp, &asn_length);
907 ASNERROR("bad length");
910 if ((asn_length + (bufp - data)) > (unsigned long)(*datalength)) {
911 ASNERROR("overflow of message (uint64)");
914 if (((int)asn_length > 9) ||
915 (((int)asn_length == 9) && *bufp != 0x00)) {
916 ASNERROR("I don't support such large integers");
919 *datalength -= (int)asn_length + SAFE_INT_CAST(bufp - data);
921 low = (unsigned long) -1; // integer is negative
922 high = (unsigned long) -1;
924 while(asn_length--) {
925 high = (high << 8) | ((low & 0xFF000000) >> 24);
926 low = ((low << 8) | *bufp++) & 0xFFFFFFFF;
936 * asn_build_unsigned_int64 - builds an ASN object containing a 64 bit integer.
937 * On entry, datalength is input as the number of valid bytes following
938 * "data". On exit, it is returned as the number of valid bytes
939 * following the end of this object.
941 * Returns a pointer to the first byte past the end
942 * of this object (i.e. the start of the next object).
943 * Returns NULL on any error.
945 unsigned char *asn_build_unsigned_int64(unsigned char *data,
948 struct counter64 *cp)
951 * ASN.1 integer ::= 0x02 asnlength byte {byte}*
953 unsigned long low = cp->low;
954 unsigned long high = cp->high;
955 unsigned long mask = 0xFF000000ul;
956 int add_null_byte = 0;
959 if (((high & mask) >> 24) & 0x80) {
966 * Truncate "unnecessary" bytes off of the most significant end of this 2's
967 * complement integer.
968 * There should be no sequence of 9 consecutive 1's or 0's at the most
969 * significant end of the integer.
971 unsigned long mask2 = 0xFF800000ul;
972 while ((((high & mask2) == 0) || ((high & mask2) == mask2)) &&
975 high = (high << 8) | ((low & mask) >> 24);
979 data = asn_build_header(data, datalength, type, intsize);
980 if (data == NULL) return NULL;
981 if (*datalength < intsize) return NULL;
982 *datalength -= intsize;
983 if (add_null_byte == 1) {
988 *data++ = (unsigned char)((high & mask) >> 24);
989 high = (high << 8) | ((low & mask) >> 24);
997 struct snmp_pdu *snmp_pdu_create(int command)
999 struct snmp_pdu *pdu;
1001 pdu = (struct snmp_pdu *)malloc(sizeof(struct snmp_pdu));
1002 if (!pdu) return pdu;
1003 memset((char *)pdu, 0,sizeof(struct snmp_pdu));
1004 pdu->command = command;
1010 pdu->enterprise = NULL;
1011 pdu->enterprise_length = 0;
1012 pdu->variables = NULL;
1016 // free content and clear pointers
1017 void clear_pdu(struct snmp_pdu *pdu, bool clear_all)
1019 struct variable_list *vp, *ovp;
1021 vp = pdu->variables;
1024 if (vp->name) free((char *)vp->name); // free the oid part
1025 if (vp->val.string) free((char *)vp->val.string); // free deep data
1027 vp = vp->next_variable; // go to the next one
1028 free((char *)ovp); // free up vb itself
1030 pdu->variables = NULL;
1032 // if enterprise free it up
1033 if (pdu->enterprise)
1034 free((char *)pdu->enterprise);
1035 pdu->enterprise = NULL;
1037 if (!clear_all) return;
1043 pdu->maxsize_scopedpdu = 0;
1048 pdu->enterprise_length = 0;
1050 pdu->specific_type = 0;
1055 void snmp_free_pdu(struct snmp_pdu *pdu)
1057 clear_pdu(pdu); // clear and free content
1058 free(pdu); // free up pdu itself
1062 // add a null var to a pdu
1063 void snmp_add_var(struct snmp_pdu *pdu,
1068 struct variable_list *vars;
1070 // if we don't have a vb list ,create one
1071 if (pdu->variables == NULL)
1072 pdu->variables = vars = (struct variable_list *)malloc(sizeof(struct variable_list));
1075 // we have one, find the end
1076 vars = pdu->variables;
1077 while (vars->next_variable) vars = vars->next_variable;
1080 vars->next_variable = (struct variable_list *)malloc(sizeof(struct variable_list));
1082 vars = vars->next_variable;
1085 // add the oid with no data
1086 vars->next_variable = NULL;
1088 // hook in the Oid portion
1089 vars->name = (oid *)malloc(name_length * sizeof(oid));
1091 memcpy((char *)vars->name,(char *)name, name_length * sizeof(oid));
1092 vars->name_length = name_length;
1094 // hook in the SMI value
1095 switch(smival->syntax)
1097 // null , do nothing
1098 case sNMP_SYNTAX_NULL:
1099 case sNMP_SYNTAX_NOSUCHOBJECT:
1100 case sNMP_SYNTAX_NOSUCHINSTANCE:
1101 case sNMP_SYNTAX_ENDOFMIBVIEW:
1103 vars->type = (unsigned char) smival->syntax;
1104 vars->val.string = NULL;
1110 case sNMP_SYNTAX_OCTETS:
1111 case sNMP_SYNTAX_OPAQUE:
1112 case sNMP_SYNTAX_IPADDR:
1114 vars->type = (unsigned char) smival->syntax;
1115 vars->val.string = (unsigned char *)malloc((unsigned)smival->value.string.len);
1116 vars->val_len = (int) smival->value.string.len;
1117 memcpy((unsigned char *) vars->val.string,
1118 (unsigned char *) smival->value.string.ptr,
1119 (unsigned) smival->value.string.len);
1124 case sNMP_SYNTAX_OID:
1126 vars->type = (unsigned char) smival->syntax;
1127 vars->val_len = (int) smival->value.oid.len * sizeof(oid);
1128 vars->val.objid = (oid *)malloc((unsigned)vars->val_len);
1129 memcpy((unsigned long *)vars->val.objid,
1130 (unsigned long *)smival->value.oid.ptr,
1131 (unsigned) vars->val_len);
1137 case sNMP_SYNTAX_TIMETICKS:
1138 case sNMP_SYNTAX_CNTR32:
1139 case sNMP_SYNTAX_GAUGE32:
1140 // case sNMP_SYNTAX_UINT32:
1143 vars->type = (unsigned char) smival->syntax;
1144 vars->val.integer = (long *)malloc(sizeof(long));
1145 vars->val_len = sizeof(long);
1146 templong = (long) smival->value.uNumber;
1147 memcpy((long*) vars->val.integer,
1153 case sNMP_SYNTAX_INT32:
1156 vars->type = (unsigned char) smival->syntax;
1157 vars->val.integer = (long *)malloc(sizeof(long));
1158 vars->val_len = sizeof(long);
1159 templong = (long) smival->value.sNumber;
1160 memcpy((long*) vars->val.integer,
1167 case sNMP_SYNTAX_CNTR64:
1169 vars->type = (unsigned char) smival->syntax;
1170 vars->val.counter64 = (struct counter64 *)malloc(sizeof(struct counter64));
1171 vars->val_len = sizeof(struct counter64);
1172 memcpy((struct counter64*) vars->val.counter64,
1173 (SmiLPCNTR64) &(smival->value.hNumber),
1182 // build the authentication, works for v1 or v2c
1183 static unsigned char *snmp_auth_build(unsigned char *data,
1185 const long int version,
1186 const unsigned char *community,
1187 const int community_len,
1188 const int messagelen)
1190 // 5 is 3 octets for version and 2 for community header + len
1191 // This assumes that community will not be longer than 0x7f chars.
1192 data = asn_build_sequence(data, length, ASN_SEQ_CON,
1193 messagelen + community_len + 5);
1195 ASNERROR("buildheader");
1198 data = asn_build_int(data, length, ASN_UNI_PRIM | ASN_INTEGER, &version);
1200 ASNERROR("buildint");
1204 data = asn_build_string(data, length, ASN_UNI_PRIM | ASN_OCTET_STR,
1205 community, community_len);
1207 ASNERROR("buildstring");
1215 // build a variable binding
1216 unsigned char * snmp_build_var_op(unsigned char *data,
1219 unsigned char var_val_type,
1221 unsigned char *var_val,
1225 Buffer<unsigned char> buffer(MAX_SNMP_PACKET);
1226 unsigned char *buffer_pos = buffer.get_ptr();
1227 int bufferLen = MAX_SNMP_PACKET;
1229 buffer_pos = asn_build_objid(buffer_pos, &bufferLen,
1230 ASN_UNI_PRIM | ASN_OBJECT_ID,
1231 var_name, *var_name_len);
1232 if (buffer_pos == NULL) {
1233 ASNERROR("build_var_op: build_objid failed");
1237 // based on the type...
1238 switch(var_val_type) {
1240 if (var_val_len != sizeof(long))
1242 ASNERROR("build_var_op: Illegal size of integer");
1245 buffer_pos = asn_build_int(buffer_pos, &bufferLen,
1246 var_val_type, (long *)var_val);
1253 if (var_val_len != sizeof(unsigned long))
1255 ASNERROR("build_var_op: Illegal size of unsigned integer");
1258 buffer_pos = asn_build_unsigned_int(buffer_pos, &bufferLen,
1259 var_val_type, (unsigned long *)var_val);
1263 if (var_val_len != sizeof(counter64))
1265 ASNERROR("build_var_op: Illegal size of counter64");
1268 buffer_pos = asn_build_unsigned_int64(buffer_pos, &bufferLen,
1270 (struct counter64 *)var_val);
1277 buffer_pos = asn_build_string(buffer_pos, &bufferLen, var_val_type,
1278 var_val, var_val_len);
1282 buffer_pos = asn_build_objid(buffer_pos, &bufferLen, var_val_type,
1283 (oid *)var_val, var_val_len / sizeof(oid));
1287 buffer_pos = asn_build_null(buffer_pos, &bufferLen, var_val_type);
1291 buffer_pos = asn_build_bitstring(buffer_pos, &bufferLen, var_val_type,
1292 var_val, var_val_len);
1295 case SNMP_NOSUCHOBJECT:
1296 case SNMP_NOSUCHINSTANCE:
1297 case SNMP_ENDOFMIBVIEW:
1298 buffer_pos = asn_build_null(buffer_pos, &bufferLen, var_val_type);
1302 ASNERROR("build_var_op: wrong type");
1305 if (buffer_pos == NULL) {
1306 ASNERROR("build_var_op: value build failed");
1310 valueLen = SAFE_INT_CAST(buffer_pos - buffer.get_ptr());
1312 data = asn_build_sequence(data, listlength, ASN_SEQ_CON, valueLen);
1314 if(data == NULL || *listlength < valueLen)
1316 ASNERROR("build_var_op");
1321 memcpy(data, buffer.get_ptr(), valueLen);
1323 (*listlength)-=valueLen;
1329 unsigned char *build_vb(struct snmp_pdu *pdu,
1330 unsigned char *buf, int *buf_len)
1332 Buffer<unsigned char> tmp_buf(MAX_SNMP_PACKET);
1333 unsigned char *cp = tmp_buf.get_ptr();
1334 struct variable_list *vp;
1336 int length = MAX_SNMP_PACKET;
1338 // build varbinds into packet buffer
1339 for(vp = pdu->variables; vp; vp = vp->next_variable)
1341 cp = snmp_build_var_op(cp, vp->name, &vp->name_length,
1342 vp->type, vp->val_len,
1343 (unsigned char *)vp->val.string,
1345 if (cp == NULL) return 0;
1347 vb_length = SAFE_INT_CAST(cp - tmp_buf.get_ptr());
1348 *buf_len -= vb_length;
1349 if (*buf_len <= 0) return 0;
1351 // encode the length of encoded varbinds into buf
1352 cp = asn_build_header(buf, buf_len, ASN_SEQ_CON, vb_length);
1353 if (cp == NULL) return 0;
1355 // copy varbinds from packet behind header in buf
1356 memcpy(cp, tmp_buf.get_ptr(), vb_length);
1358 return (cp + vb_length);
1361 unsigned char *build_data_pdu(struct snmp_pdu *pdu,
1362 unsigned char *buf, int *buf_len,
1363 unsigned char *vb_buf, int vb_buf_len)
1365 Buffer<unsigned char> tmp_buf(MAX_SNMP_PACKET);
1366 unsigned char *cp = tmp_buf.get_ptr();
1368 int length = MAX_SNMP_PACKET;
1370 // build data of pdu into tmp_buf
1371 if (pdu->command != TRP_REQ_MSG)
1374 cp = asn_build_int(cp, &length, ASN_UNI_PRIM | ASN_INTEGER, &pdu->reqid);
1375 if (cp == NULL) return 0;
1378 cp = asn_build_int(cp, &length, ASN_UNI_PRIM | ASN_INTEGER, &pdu->errstat);
1379 if (cp == NULL) return 0;
1382 cp = asn_build_int(cp, &length, ASN_UNI_PRIM | ASN_INTEGER, &pdu->errindex);
1383 if (cp == NULL) return 0;
1386 { // this is a trap message
1388 cp = asn_build_objid(cp, &length, ASN_UNI_PRIM | ASN_OBJECT_ID,
1389 (oid *)pdu->enterprise, pdu->enterprise_length);
1390 if (cp == NULL) return 0;
1392 // agent-addr ; must be IPADDRESS changed by Frank Fock
1393 cp = asn_build_string(cp, &length, SMI_IPADDRESS,
1394 (unsigned char *)&pdu->agent_addr.sin_addr.s_addr,
1395 sizeof(pdu->agent_addr.sin_addr.s_addr));
1396 if (cp == NULL) return 0;
1398 long dummy = pdu->trap_type;
1400 cp = asn_build_int(cp, &length, ASN_UNI_PRIM | ASN_INTEGER, &dummy);
1401 if (cp == NULL) return 0;
1403 dummy = pdu->specific_type;
1405 cp = asn_build_int(cp, &length, ASN_UNI_PRIM | ASN_INTEGER, &dummy);
1406 if (cp == NULL) return 0;
1409 cp = asn_build_unsigned_int(cp, &length, SMI_TIMETICKS, &pdu->time);
1410 if (cp == NULL) return 0;
1413 if (length < vb_buf_len) return 0;
1415 // save relative position of varbinds
1416 int vb_rel_pos = SAFE_INT_CAST(cp - tmp_buf.get_ptr());
1417 totallength = SAFE_INT_CAST(cp - tmp_buf.get_ptr()) + vb_buf_len;
1419 // build header for datapdu into buf
1420 cp = asn_build_header(buf, buf_len,
1421 (unsigned char)pdu->command, totallength);
1422 if (cp == NULL) return 0;
1423 if (*buf_len < totallength) return 0;
1425 // copy data behind header
1426 memcpy(cp, tmp_buf.get_ptr(), totallength - vb_buf_len);
1427 memcpy((char *)cp + vb_rel_pos, (char *)vb_buf, vb_buf_len);
1428 *buf_len -= totallength;
1429 return (cp + totallength);
1432 // serialize the pdu
1433 int snmp_build(struct snmp_pdu *pdu,
1434 unsigned char *packet, int *out_length,
1436 const unsigned char* community, const int community_len)
1438 Buffer<unsigned char> buf(MAX_SNMP_PACKET);
1443 // encode vbs with header into packet
1444 length = *out_length;
1445 cp = build_vb(pdu, packet, &length);
1446 if (cp == 0) return -1;
1447 totallength = SAFE_INT_CAST(cp - packet);
1448 if (totallength >= *out_length) return -1;
1450 // encode datadpu into buf
1451 length = MAX_SNMP_PACKET;
1452 cp = build_data_pdu(pdu, buf.get_ptr(), &length,
1453 packet, totallength);
1454 if (cp == 0) return -1;
1455 totallength = SAFE_INT_CAST(cp - buf.get_ptr());
1456 if (totallength >= *out_length) return -1;
1458 // build SNMP header
1459 length = *out_length;
1460 cp = snmp_auth_build(packet, &length, version,
1461 community, community_len, totallength);
1462 if (cp == NULL) return -1;
1463 if ((*out_length - (cp - packet)) < totallength) return -1;
1466 memcpy(cp, buf.get_ptr(), totallength);
1467 totallength += SAFE_INT_CAST(cp - packet);
1468 *out_length = totallength;
1473 // parse the authentication header
1474 static unsigned char *snmp_auth_parse(unsigned char *data,
1476 unsigned char *community,
1483 data = asn_parse_header(data, length, &type);
1485 ASNERROR("bad header");
1489 if (type != ASN_SEQ_CON) {
1490 ASNERROR("wrong auth header type");
1495 data = asn_parse_int(data, length, &type, version);
1497 ASNERROR("bad parse of version");
1501 // get the community name
1502 data = asn_parse_string(data, length, &type, community, community_len);
1504 ASNERROR("bad parse of community");
1508 return (unsigned char *)data;
1512 snmp_parse_var_op(unsigned char *data, // IN - pointer to the start of object
1513 oid *var_name, // OUT - object id of variable
1514 int *var_name_len, // IN/OUT - length of variable name
1515 unsigned char *var_val_type, // OUT - type of variable (int or octet string) (one byte)
1516 int *var_val_len, // OUT - length of variable
1517 unsigned char **var_val, // OUT - pointer to ASN1 encoded value of variable
1518 int *listlength) // IN/OUT - number of valid bytes left in var_op_list
1520 unsigned char var_op_type;
1521 int var_op_len = *listlength;
1522 unsigned char *var_op_start = data;
1524 data = asn_parse_header(data, &var_op_len, &var_op_type);
1526 ASNERROR("Error snmp_parse_var_op: 1");
1529 if (var_op_type != ASN_SEQ_CON)
1531 data = asn_parse_objid(data, &var_op_len, &var_op_type, var_name, var_name_len);
1533 ASNERROR("Error snmp_parse_var_op: 2");
1536 if (var_op_type != (ASN_UNI_PRIM | ASN_OBJECT_ID))
1538 *var_val = data; /* save pointer to this object */
1539 /* find out what type of object this is */
1540 data = asn_parse_header(data, &var_op_len, var_val_type);
1542 ASNERROR("Error snmp_parse_var_op: 3");
1545 if (((unsigned long)var_op_len + (data - var_op_start)) > (unsigned long)(*listlength)) {
1546 ASNERROR("Error snmp_parse_var_op: 4");
1549 *var_val_len = (int)var_op_len;
1551 *listlength -= (int)(data - var_op_start);
1556 int snmp_parse_vb(struct snmp_pdu *pdu, unsigned char *&data, int &data_len)
1558 unsigned char *var_val;
1560 struct variable_list *vp = 0;
1561 oid objid[ASN_MAX_NAME_LEN], *op;
1564 // get the vb list from received data
1565 data = asn_parse_header(data, &data_len, &type);
1567 return SNMP_CLASS_ASN1ERROR;
1568 if (type != ASN_SEQ_CON)
1569 return SNMP_CLASS_ASN1ERROR;
1570 pdu->variables = NULL;
1571 while(data_len > 0) {
1572 if (pdu->variables == NULL) {
1573 pdu->variables = vp = (struct variable_list *)malloc(sizeof(struct variable_list));
1575 vp->next_variable = (struct variable_list *)malloc(sizeof(struct variable_list));
1576 vp = vp->next_variable;
1578 vp->next_variable = NULL;
1579 vp->val.string = NULL;
1581 vp->name_length = ASN_MAX_NAME_LEN;
1582 data = snmp_parse_var_op(data, objid, &vp->name_length, &vp->type,
1583 &vp->val_len, &var_val, &data_len);
1585 return SNMP_CLASS_ASN1ERROR;
1586 op = (oid *)malloc((unsigned)vp->name_length * sizeof(oid));
1588 memcpy((char *)op, (char *)objid, vp->name_length * sizeof(oid));
1591 len = MAX_SNMP_PACKET;
1592 switch((short)vp->type) {
1594 vp->val.integer = (long *)malloc(sizeof(long));
1595 vp->val_len = sizeof(long);
1596 asn_parse_int(var_val, &len, &vp->type, vp->val.integer);
1603 vp->val.integer = (long *)malloc(sizeof(long));
1604 vp->val_len = sizeof(long);
1605 asn_parse_unsigned_int(var_val, &len, &vp->type, vp->val.integer);
1609 vp->val.counter64 = (struct counter64 *)malloc(sizeof(struct counter64));
1610 vp->val_len = sizeof(struct counter64);
1611 asn_parse_unsigned_int64(var_val, &len, &vp->type,
1619 vp->val.string = (unsigned char *)malloc((unsigned)vp->val_len);
1620 asn_parse_string(var_val, &len, &vp->type, vp->val.string, &vp->val_len);
1624 vp->val_len = ASN_MAX_NAME_LEN;
1625 asn_parse_objid(var_val, &len, &vp->type, objid, &vp->val_len);
1626 //vp->val_len *= sizeof(oid);
1627 vp->val.objid = (oid *)malloc((unsigned)vp->val_len * sizeof(oid));
1629 memcpy((char *)vp->val.objid,
1631 vp->val_len * sizeof(oid));
1634 case SNMP_NOSUCHOBJECT:
1635 case SNMP_NOSUCHINSTANCE:
1636 case SNMP_ENDOFMIBVIEW:
1641 ASNERROR("bad type returned ");
1642 return SNMP_CLASS_ASN1ERROR;
1645 return SNMP_CLASS_SUCCESS;
1649 int snmp_parse_data_pdu(snmp_pdu *pdu, unsigned char *&data, int &length)
1651 oid objid[ASN_MAX_NAME_LEN];
1655 data = asn_parse_header(data, &length, &type);
1656 if (data == NULL) return SNMP_CLASS_ASN1ERROR;
1658 pdu->command = type;
1660 if (pdu->command != TRP_REQ_MSG)
1662 // get the rid error status and error index
1663 data = asn_parse_int(data, &length, &type, &pdu->reqid);
1664 if (data == NULL) return SNMP_CLASS_ASN1ERROR;
1666 data = asn_parse_int(data, &length, &type, &pdu->errstat);
1667 if (data == NULL) return SNMP_CLASS_ASN1ERROR;
1669 data = asn_parse_int(data, &length, &type, &pdu->errindex);
1670 if (data == NULL) return SNMP_CLASS_ASN1ERROR;
1675 // get the enterprise
1676 pdu->enterprise_length = ASN_MAX_NAME_LEN;
1677 data = asn_parse_objid(data, &length, &type,
1678 objid, &pdu->enterprise_length);
1679 if (data == NULL) return SNMP_CLASS_ASN1ERROR;
1681 pdu->enterprise = (oid *)malloc(pdu->enterprise_length * sizeof(oid));
1683 memcpy((char *)pdu->enterprise,(char *)objid,
1684 pdu->enterprise_length * sizeof(oid));
1686 // get source address
1687 data = asn_parse_string(data, &length, &type,
1688 (unsigned char *)&pdu->agent_addr.sin_addr.s_addr,
1690 if (data == NULL) return SNMP_CLASS_ASN1ERROR;
1694 data = asn_parse_int(data, &length, &type, &dummy);
1695 pdu->trap_type = dummy;
1697 if (data == NULL) return SNMP_CLASS_ASN1ERROR;
1699 // trap specific type
1701 data = asn_parse_int(data, &length, &type, &dummy);
1702 pdu->specific_type = dummy;
1703 if (data == NULL) return SNMP_CLASS_ASN1ERROR;
1706 data = asn_parse_unsigned_int(data, &length, &type, &pdu->time);
1707 if (data == NULL) return SNMP_CLASS_ASN1ERROR;
1709 return SNMP_CLASS_SUCCESS;
1714 int snmp_parse(struct snmp_pdu *pdu,
1715 unsigned char *data, int data_length,
1716 unsigned char *community_name,
1718 snmp_version &spp_version)
1722 // authenticates message and returns length if valid
1723 data = snmp_auth_parse(data, &data_length,
1724 community_name, &community_len,
1727 return SNMP_CLASS_ASN1ERROR;
1729 if(version != SNMP_VERSION_1 && version != SNMP_VERSION_2C) {
1730 ASNERROR("Wrong version");
1731 return SNMP_CLASS_BADVERSION;
1734 spp_version = (snmp_version) version;
1736 int res = snmp_parse_data_pdu(pdu, data, data_length);
1737 if (res != SNMP_CLASS_SUCCESS)
1740 return snmp_parse_vb(pdu, data, data_length);
1745 // Parse the field HeaderData of a SNMPv3 message and return the values.
1746 unsigned char *asn1_parse_header_data(unsigned char *buf, int *buf_len,
1747 long *msg_id, long *msg_max_size,
1748 unsigned char *msg_flags,
1749 long *msg_security_model)
1751 unsigned char *buf_ptr = buf;
1752 int length = *buf_len;
1755 buf = asn_parse_header(buf, &length, &type);
1758 debugprintf(0, "Parse error in header HeaderData");
1762 if (type != ASN_SEQ_CON) {
1763 debugprintf(0, "wrong type in header of msgHeaderData");
1767 buf = asn_parse_int(buf, &length, &type, msg_id);
1769 debugprintf(0, "Parse error: msg_id");
1773 buf = asn_parse_int(buf, &length, &type, msg_max_size);
1775 debugprintf(0, "Parse error: msg_max_size");
1780 buf = asn_parse_string(buf, &length, &type, msg_flags, &dummy);
1782 if ((dummy !=1) || (!buf)) {
1783 debugprintf(0, "Parse error: msg_flags");
1787 buf = asn_parse_int(buf, &length, &type, msg_security_model);
1789 debugprintf(0, "Parse error: msg_security_model");
1794 debugprintf(0, "Parse error: wrong length in header of HeaderData");
1798 debugprintf(3, "Parsed HeaderData: globalDataLength(0x%x), msg_id(%ld), "
1799 "msg_max_size(0x%lx), msg_flags(0x%x), msg_security_model(0x%lx)",
1800 length, *msg_id, *msg_max_size, *msg_flags, *msg_security_model);
1802 *buf_len -= SAFE_INT_CAST(buf - buf_ptr);
1806 // Encode the given values for the HeaderData into the buffer.
1807 unsigned char *asn1_build_header_data(unsigned char *outBuf, int *maxLength,
1809 long maxMessageSize,
1810 unsigned char msgFlags,
1814 unsigned char buf[MAXLENGTH_GLOBALDATA];
1815 unsigned char *bufPtr = (unsigned char*)&buf;
1816 unsigned char *outBufPtr = outBuf;
1817 int length = *maxLength;
1820 #ifdef INVALID_MAXMSGSIZE
1821 debugprintf(-10, "\nWARNING: Using constant MaxMessageSize!\n");
1822 maxMessageSize = 65535;
1825 debugprintf(3, "Coding msgID(%ld), maxMessageSize(0x%lx), "
1826 "msgFlags(0x%x), securityModel(0x%lx)",
1827 msgID, maxMessageSize, msgFlags, securityModel);
1829 bufPtr = asn_build_int(bufPtr, &length, ASN_UNI_PRIM | ASN_INTEGER, &msgID);
1830 if (bufPtr == NULL) {
1831 debugprintf(0, "asn_build_header_data: Error coding msgID");
1834 bufPtr = asn_build_int(bufPtr, &length, ASN_UNI_PRIM | ASN_INTEGER,
1836 if (bufPtr == NULL) {
1837 debugprintf(0, "asn_build_header_data: Error coding maxMessageSize");
1841 bufPtr = asn_build_string(bufPtr, &length, ASN_UNI_PRIM | ASN_OCTET_STR,
1843 if (bufPtr == NULL) {
1844 debugprintf(0, "asn_build_header_data: Error coding msgFlags");
1848 bufPtr = asn_build_int(bufPtr, &length, ASN_UNI_PRIM | ASN_INTEGER,
1850 if (bufPtr == NULL) {
1851 debugprintf(0, "asn_build_header_data: Error coding securityModel");
1855 totalLength = SAFE_INT_CAST(bufPtr - (unsigned char*)&buf);
1857 debugprintf(3, "Coding sequence (headerdata), length = 0x%x", totalLength);
1858 outBufPtr = asn_build_sequence(outBufPtr, maxLength, ASN_SEQ_CON,
1861 if (outBufPtr == NULL) {
1862 debugprintf(0, "asn_build_header_data: Error coding seq headerdata");
1866 if (*maxLength < totalLength) {
1867 debugprintf(0, "asn_build_header_data: Length error");
1871 memcpy(outBufPtr, (unsigned char*)&buf, totalLength);
1872 outBufPtr += totalLength;
1873 *maxLength -= totalLength;
1875 debugprintf(21, "bufHeaderData:");
1876 debughexprintf(21, outBuf, SAFE_INT_CAST(outBufPtr - outBuf));
1882 // Parse the ScopedPDU and return the encoded values.
1883 unsigned char *asn1_parse_scoped_pdu(
1884 unsigned char *scoped_pdu, int *scoped_pdu_len,
1885 unsigned char *context_engine_id, int *context_engine_id_len,
1886 unsigned char *context_name, int *context_name_len)
1890 scoped_pdu = asn_parse_header(scoped_pdu, scoped_pdu_len, &type);
1892 debugprintf(0, "Parse error: Wrong header in scoped_pdu.");
1896 if (type != ASN_SEQ_CON) {
1897 debugprintf(0, "Parse error: Wrong header type in scoped_pdu.");
1901 scoped_pdu = asn_parse_string(scoped_pdu, scoped_pdu_len, &type,
1902 context_engine_id, context_engine_id_len);
1904 debugprintf(0, "Parse error: context_engine_id");
1908 scoped_pdu = asn_parse_string(scoped_pdu, scoped_pdu_len, &type,
1909 context_name, context_name_len);
1911 debugprintf(0, "mpParseScopedPDU: bad parse of context_name");
1915 debugprintf(3, "Parsed scoped_pdu: context_engine_id length(0x%x), "
1916 "context_name length(0x%x)",
1917 *context_engine_id_len, *context_name_len);
1922 // Encode the given values for the scopedPDU into the buffer.
1923 unsigned char *asn1_build_scoped_pdu(
1924 unsigned char *outBuf, int *max_len,
1925 unsigned char *contextEngineID, long contextEngineIDLength,
1926 unsigned char *contextName, long contextNameLength,
1927 unsigned char *data, long dataLength)
1929 Buffer<unsigned char> buffer(MAX_SNMP_PACKET);
1930 unsigned char *bufPtr = buffer.get_ptr();
1931 unsigned char *outBufPtr = outBuf;
1933 LOG_BEGIN(DEBUG_LOG | 10);
1934 LOG("ASN1: coding (context engine id) (context name)");
1935 LOG(OctetStr(contextEngineID, contextEngineIDLength).get_printable());
1936 LOG(OctetStr(contextName, contextNameLength).get_printable());
1939 bufPtr = asn_build_string(bufPtr, max_len, ASN_UNI_PRIM | ASN_OCTET_STR,
1940 contextEngineID, contextEngineIDLength);
1943 LOG_BEGIN(ERROR_LOG | 1);
1944 LOG("ASN1: Error encoding contextEngineID");
1950 bufPtr = asn_build_string(bufPtr, max_len, ASN_UNI_PRIM | ASN_OCTET_STR,
1951 contextName, contextNameLength);
1954 LOG_BEGIN(ERROR_LOG | 1);
1955 LOG("ASN1: Error encoding contextName");
1961 long bufLength = SAFE_INT_CAST(bufPtr - buffer.get_ptr());
1963 memcpy((char *)bufPtr, (char *)data, dataLength);
1964 bufLength += dataLength;
1966 LOG_BEGIN(DEBUG_LOG | 10);
1967 LOG("ASN1: Encoding scoped PDU sequence (len)");
1971 outBufPtr = asn_build_sequence(outBufPtr, max_len, ASN_SEQ_CON, bufLength);
1974 LOG_BEGIN(ERROR_LOG | 1);
1975 LOG("ASN1: Error encoding scopedPDU sequence");
1981 memcpy(outBufPtr, buffer.get_ptr(), bufLength);
1982 outBufPtr += bufLength;
1985 LOG_BEGIN(DEBUG_LOG | 15);
1986 LOG("ASN1: Result of build_scoped_pdu (len) (data)");
1987 LOG(outBufPtr - outBuf);
1988 LOG(OctetStr(outBuf, outBufPtr - outBuf).get_printable_hex());
1995 #ifdef SNMP_PP_NAMESPACE
1996 }; // end of namespace Snmp_pp