2 * Abstract Syntax Notation One, ASN.1
3 * As defined in ISO/IS 8824 and ISO/IS 8825
4 * This implements a subset of the above International Standards that
5 * is sufficient to implement SNMP.
7 * Encodes abstract data types into a machine independent stream of bytes.
10 /**********************************************************************
11 Copyright 1988, 1989, 1991, 1992 by Carnegie Mellon University
15 Permission to use, copy, modify, and distribute this software and its
16 documentation for any purpose and without fee is hereby granted,
17 provided that the above copyright notice appear in all copies and that
18 both that copyright notice and this permission notice appear in
19 supporting documentation, and that the name of CMU not be
20 used in advertising or publicity pertaining to distribution of the
21 software without specific, written prior permission.
23 CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
25 CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
26 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
27 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
28 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
30 ******************************************************************/
31 #include <net-snmp/net-snmp-config.h>
43 #include <sys/types.h>
52 #include <netinet/in.h>
63 #include <net-snmp/output_api.h>
64 #include <net-snmp/utilities.h>
66 #include <net-snmp/library/asn1.h>
67 #include <net-snmp/library/int64.h>
68 #include <net-snmp/library/mib.h>
74 #include <net-snmp/library/snmp_api.h>
78 _asn_size_err(const char *str, size_t wrongsize, size_t rightsize)
82 snprintf(ebuf, sizeof(ebuf),
83 "%s size %d: s/b %d", str, wrongsize, rightsize);
84 ebuf[ sizeof(ebuf)-1 ] = 0;
90 _asn_length_err(const char *str, size_t wrongsize, size_t rightsize)
94 snprintf(ebuf, sizeof(ebuf),
95 "%s length %d too large: exceeds %d", str, wrongsize,
97 ebuf[ sizeof(ebuf)-1 ] = 0;
102 * call after asn_parse_length to verify result.
106 _asn_parse_length_check(const char *str,
107 u_char * bufp, u_char * data,
108 u_long plen, size_t dlen)
115 * error message is set
119 header_len = bufp - data;
120 if (plen > 0x7fffffff || header_len > 0x7fffffff ||
121 ((size_t) plen + header_len) > dlen) {
122 snprintf(ebuf, sizeof(ebuf),
123 "%s: message overflow: %d len + %d delta > %d len",
124 str, (int) plen, (int) header_len, (int) dlen);
125 ebuf[ sizeof(ebuf)-1 ] = 0;
133 * call after asn_build_header to verify result.
137 _asn_build_header_check(const char *str, u_char * data,
138 size_t datalen, size_t typedlen)
144 * error message is set
148 if (datalen < typedlen) {
149 snprintf(ebuf, sizeof(ebuf),
150 "%s: bad header, length too short: %d < %d", str,
152 ebuf[ sizeof(ebuf)-1 ] = 0;
161 _asn_realloc_build_header_check(const char *str,
162 u_char ** pkt, size_t * pkt_len,
167 if (pkt == NULL || *pkt == NULL) {
169 * Error message is set.
174 if (*pkt_len < typedlen) {
175 snprintf(ebuf, sizeof(ebuf),
176 "%s: bad header, length too short: %d < %d", str,
178 ebuf[ sizeof(ebuf)-1 ] = 0;
186 * checks the incoming packet for validity and returns its size or 0
189 asn_check_packet(u_char * pkt, size_t len)
194 return 0; /* always too short */
196 if (*pkt != (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR))
197 return -1; /* wrong type */
199 if (*(pkt + 1) & 0x80) {
203 if ((int) len < (int) (*(pkt + 1) & ~0x80) + 2)
204 return 0; /* still to short, incomplete length */
205 asn_parse_length(pkt + 1, &asn_length);
206 return (asn_length + 2 + (*(pkt + 1) & ~0x80));
211 return (*(pkt + 1) + 2);
217 _asn_bitstring_check(const char *str, size_t asn_length, u_char datum)
221 if (asn_length < 1) {
222 snprintf(ebuf, sizeof(ebuf),
223 "%s: length %d too small", str, (int) asn_length);
224 ebuf[ sizeof(ebuf)-1 ] = 0;
230 * sprintf(ebuf,"%s: datum %d >7: too large", str, (int)(datum));
239 * asn_parse_int - pulls a long out of an int type.
240 * On entry, datalength is input as the number of valid bytes following
241 * "data". On exit, it is returned as the number of valid bytes
242 * following the end of this object.
244 * Returns a pointer to the first byte past the end
245 * of this object (i.e. the start of the next object).
246 * Returns NULL on any error.
248 u_char * asn_parse_int(
249 u_char *data IN - pointer to start of object
250 int *datalength IN/OUT - number of valid bytes left in buffer
251 u_char *type OUT - asn type of object
252 long *intp IN/OUT - pointer to start of output buffer
253 int intsize IN - size of output buffer
257 asn_parse_int(u_char * data,
259 u_char * type, long *intp, size_t intsize)
262 * ASN.1 integer ::= 0x02 asnlength byte {byte}*
264 static const char *errpre = "parse int";
265 register u_char *bufp = data;
267 register long value = 0;
269 if (intsize != sizeof(long)) {
270 _asn_size_err(errpre, intsize, sizeof(long));
274 bufp = asn_parse_length(bufp, &asn_length);
275 if (_asn_parse_length_check
276 (errpre, bufp, data, asn_length, *datalength))
279 if ((size_t) asn_length > intsize) {
280 _asn_length_err(errpre, (size_t) asn_length, intsize);
284 *datalength -= (int) asn_length + (bufp - data);
286 value = -1; /* integer is negative */
288 DEBUGDUMPSETUP("recv", data, bufp - data + asn_length);
291 value = (value << 8) | *bufp++;
293 DEBUGMSG(("dumpv_recv", " Integer:\t%ld (0x%.2X)\n", value, value));
301 * asn_parse_unsigned_int - pulls an unsigned long out of an ASN int type.
302 * On entry, datalength is input as the number of valid bytes following
303 * "data". On exit, it is returned as the number of valid bytes
304 * following the end of this object.
306 * Returns a pointer to the first byte past the end
307 * of this object (i.e. the start of the next object).
308 * Returns NULL on any error.
310 u_char * asn_parse_unsigned_int(
311 u_char *data IN - pointer to start of object
312 int *datalength IN/OUT - number of valid bytes left in buffer
313 u_char *type OUT - asn type of object
314 u_long *intp IN/OUT - pointer to start of output buffer
315 int intsize IN - size of output buffer
318 asn_parse_unsigned_int(u_char * data,
320 u_char * type, u_long * intp, size_t intsize)
323 * ASN.1 integer ::= 0x02 asnlength byte {byte}*
325 static const char *errpre = "parse uint";
326 register u_char *bufp = data;
328 register u_long value = 0;
330 if (intsize != sizeof(long)) {
331 _asn_size_err(errpre, intsize, sizeof(long));
335 bufp = asn_parse_length(bufp, &asn_length);
336 if (_asn_parse_length_check
337 (errpre, bufp, data, asn_length, *datalength))
340 if (((int) asn_length > (intsize + 1)) ||
341 (((int) asn_length == intsize + 1) && *bufp != 0x00)) {
342 _asn_length_err(errpre, (size_t) asn_length, intsize);
345 *datalength -= (int) asn_length + (bufp - data);
347 value = ~value; /* integer is negative */
349 DEBUGDUMPSETUP("recv", data, bufp - data + asn_length);
352 value = (value << 8) | *bufp++;
354 DEBUGMSG(("dumpv_recv", " UInteger:\t%ld (0x%.2X)\n", value, value));
362 * asn_build_int - builds an ASN object containing an integer.
363 * On entry, datalength is input as the number of valid bytes following
364 * "data". On exit, it is returned as the number of valid bytes
365 * following the end of this object.
367 * Returns a pointer to the first byte past the end
368 * of this object (i.e. the start of the next object).
369 * Returns NULL on any error.
371 u_char * asn_build_int(
372 u_char *data IN - pointer to start of output buffer
373 int *datalength IN/OUT - number of valid bytes left in buffer
374 int type IN - asn type of object
375 long *intp IN - pointer to start of long integer
376 int intsize IN - size of input buffer
379 asn_build_int(u_char * data,
380 size_t * datalength, u_char type, long *intp, size_t intsize)
383 * ASN.1 integer ::= 0x02 asnlength byte {byte}*
385 static const char *errpre = "build int";
386 register long integer;
387 register u_long mask;
388 #ifndef SNMP_NO_DEBUGGING
389 u_char *initdatap = data;
392 if (intsize != sizeof(long)) {
393 _asn_size_err(errpre, intsize, sizeof(long));
398 * Truncate "unnecessary" bytes off of the most significant end of this
399 * 2's complement integer. There should be no sequence of 9
400 * consecutive 1's or 0's at the most significant end of the
403 mask = ((u_long) 0x1FF) << ((8 * (sizeof(long) - 1)) - 1);
405 * mask is 0xFF800000 on a big-endian machine
407 while ((((integer & mask) == 0) || ((integer & mask) == mask))
412 data = asn_build_header(data, datalength, type, intsize);
413 if (_asn_build_header_check(errpre, data, *datalength, intsize))
416 *datalength -= intsize;
417 mask = ((u_long) 0xFF) << (8 * (sizeof(long) - 1));
419 * mask is 0xFF000000 on a big-endian machine
422 *data++ = (u_char) ((integer & mask) >> (8 * (sizeof(long) - 1)));
425 DEBUGDUMPSETUP("send", initdatap, data - initdatap);
426 DEBUGMSG(("dumpv_send", " Integer:\t%ld (0x%.2X)\n", *intp, *intp));
432 * asn_build_unsigned_int - builds an ASN object containing an integer.
433 * On entry, datalength is input as the number of valid bytes following
434 * "data". On exit, it is returned as the number of valid bytes
435 * following the end of this object.
437 * Returns a pointer to the first byte past the end
438 * of this object (i.e. the start of the next object).
439 * Returns NULL on any error.
441 u_char * asn_build_unsigned_int(
442 u_char *data IN - pointer to start of output buffer
443 int *datalength IN/OUT - number of valid bytes left in buffer
444 u_char type IN - asn type of object
445 u_long *intp IN - pointer to start of long integer
446 int intsize IN - size of input buffer
449 asn_build_unsigned_int(u_char * data,
451 u_char type, u_long * intp, size_t intsize)
454 * ASN.1 integer ::= 0x02 asnlength byte {byte}*
456 static const char *errpre = "build uint";
457 register u_long integer;
458 register u_long mask;
459 int add_null_byte = 0;
460 #ifndef SNMP_NO_DEBUGGING
461 u_char *initdatap = data;
464 if (intsize != sizeof(long)) {
465 _asn_size_err(errpre, intsize, sizeof(long));
469 mask = ((u_long) 0xFF) << (8 * (sizeof(long) - 1));
471 * mask is 0xFF000000 on a big-endian machine
473 if ((u_char) ((integer & mask) >> (8 * (sizeof(long) - 1))) & 0x80) {
481 * Truncate "unnecessary" bytes off of the most significant end of this 2's complement integer.
482 * There should be no sequence of 9 consecutive 1's or 0's at the most significant end of the
485 mask = ((u_long) 0x1FF) << ((8 * (sizeof(long) - 1)) - 1);
487 * mask is 0xFF800000 on a big-endian machine
489 while ((((integer & mask) == 0) || ((integer & mask) == mask))
495 data = asn_build_header(data, datalength, type, intsize);
496 if (_asn_build_header_check(errpre, data, *datalength, intsize))
499 *datalength -= intsize;
500 if (add_null_byte == 1) {
504 mask = ((u_long) 0xFF) << (8 * (sizeof(long) - 1));
506 * mask is 0xFF000000 on a big-endian machine
509 *data++ = (u_char) ((integer & mask) >> (8 * (sizeof(long) - 1)));
512 DEBUGDUMPSETUP("send", initdatap, data - initdatap);
513 DEBUGMSG(("dumpv_send", " UInteger:\t%ld (0x%.2X)\n", *intp, *intp));
519 * asn_parse_string - pulls an octet string out of an ASN octet string type.
520 * On entry, datalength is input as the number of valid bytes following
521 * "data". On exit, it is returned as the number of valid bytes
522 * following the beginning of the next object.
524 * "string" is filled with the octet string.
526 * Returns a pointer to the first byte past the end
527 * of this object (i.e. the start of the next object).
528 * Returns NULL on any error.
530 * u_char * asn_parse_string(
531 * u_char *data IN - pointer to start of object
532 * int *datalength IN/OUT - number of valid bytes left in buffer
533 * u_char *type OUT - asn type of object
534 * u_char *string IN/OUT - pointer to start of output buffer
535 * int *strlength IN/OUT - size of output buffer
538 * ASN.1 octet string ::= primstring | cmpdstring
539 * primstring ::= 0x04 asnlength byte {byte}*
540 * cmpdstring ::= 0x24 asnlength string {string}*
543 asn_parse_string(u_char * data,
545 u_char * type, u_char * string, size_t * strlength)
547 static const char *errpre = "parse string";
552 bufp = asn_parse_length(bufp, &asn_length);
553 if (_asn_parse_length_check
554 (errpre, bufp, data, asn_length, *datalength)) {
558 if ((int) asn_length > *strlength) {
559 _asn_length_err(errpre, (size_t) asn_length, *strlength);
563 DEBUGDUMPSETUP("recv", data, bufp - data + asn_length);
565 memmove(string, bufp, asn_length);
566 if (*strlength > (int) asn_length)
567 string[asn_length] = 0;
568 *strlength = (int) asn_length;
569 *datalength -= (int) asn_length + (bufp - data);
571 DEBUGIF("dumpv_recv") {
572 u_char *buf = (u_char *) malloc(1 + asn_length);
573 size_t l = (buf != NULL) ? (1 + asn_length) : 0, ol = 0;
575 if (sprint_realloc_asciistring
576 (&buf, &l, &ol, 1, string, asn_length)) {
577 DEBUGMSG(("dumpv_recv", " String:\t%s\n", buf));
580 DEBUGMSG(("dumpv_recv", " String:\t[TRUNCATED]\n"));
582 DEBUGMSG(("dumpv_recv", " String:\t%s [TRUNCATED]\n",
591 return bufp + asn_length;
596 * asn_build_string - Builds an ASN octet string object containing the input string.
597 * On entry, datalength is input as the number of valid bytes following
598 * "data". On exit, it is returned as the number of valid bytes
599 * following the beginning of the next object.
601 * Returns a pointer to the first byte past the end
602 * of this object (i.e. the start of the next object).
603 * Returns NULL on any error.
605 u_char * asn_build_string(
606 u_char *data IN - pointer to start of object
607 int *datalength IN/OUT - number of valid bytes left in buffer
608 u_char type IN - asn type of object
609 u_char *string IN - pointer to start of input buffer
610 int strlength IN - size of input buffer
613 asn_build_string(u_char * data,
615 u_char type, const u_char * string, size_t strlength)
618 * ASN.1 octet string ::= primstring | cmpdstring
619 * primstring ::= 0x04 asnlength byte {byte}*
620 * cmpdstring ::= 0x24 asnlength string {string}*
621 * This code will never send a compound string.
623 #ifndef SNMP_NO_DEBUGGING
624 u_char *initdatap = data;
626 data = asn_build_header(data, datalength, type, strlength);
627 if (_asn_build_header_check
628 ("build string", data, *datalength, strlength))
632 if (string == NULL) {
633 memset(data, 0, strlength);
635 memmove(data, string, strlength);
638 *datalength -= strlength;
639 DEBUGDUMPSETUP("send", initdatap, data - initdatap + strlength);
640 DEBUGIF("dumpv_send") {
641 u_char *buf = (u_char *) malloc(1 + strlength);
642 size_t l = (buf != NULL) ? (1 + strlength) : 0, ol = 0;
644 if (sprint_realloc_asciistring
645 (&buf, &l, &ol, 1, string, strlength)) {
646 DEBUGMSG(("dumpv_send", " String:\t%s\n", buf));
649 DEBUGMSG(("dumpv_send", " String:\t[TRUNCATED]\n"));
651 DEBUGMSG(("dumpv_send", " String:\t%s [TRUNCATED]\n",
659 return data + strlength;
665 * asn_parse_header - interprets the ID and length of the current object.
666 * On entry, datalength is input as the number of valid bytes following
667 * "data". On exit, it is returned as the number of valid bytes
668 * in this object following the id and length.
670 * Returns a pointer to the first byte of the contents of this object.
671 * Returns NULL on any error.
673 u_char * asn_parse_header(
674 u_char *data IN - pointer to start of object
675 int *datalength IN/OUT - number of valid bytes left in buffer
676 u_char *type OUT - asn type of object
679 asn_parse_header(u_char * data, size_t * datalength, u_char * type)
681 register u_char *bufp;
684 if (!data || !datalength || !type) {
685 ERROR_MSG("parse header: NULL pointer");
690 * this only works on data types < 30, i.e. no extension octets
692 if (IS_EXTENSION_ID(*bufp)) {
693 ERROR_MSG("can't process ID >= 30");
697 bufp = asn_parse_length(bufp + 1, &asn_length);
699 if (_asn_parse_length_check
700 ("parse header", bufp, data, asn_length, *datalength))
703 #ifdef DUMP_PRINT_HEADERS
704 DEBUGDUMPSETUP("recv", data, (bufp - data));
705 DEBUGMSG(("dumpv_recv", " Header: 0x%.2X, len = %d (0x%X)\n", *data,
706 asn_length, asn_length));
709 * DEBUGMSGHEXTLI(("recv",data,(bufp-data)));
710 * DEBUGMSG(("dumpH_recv","\n"));
714 #ifdef OPAQUE_SPECIAL_TYPES
716 if ((*type == ASN_OPAQUE) && (*bufp == ASN_OPAQUE_TAG1)) {
719 * check if 64-but counter
721 switch (*(bufp + 1)) {
722 case ASN_OPAQUE_COUNTER64:
724 case ASN_OPAQUE_FLOAT:
725 case ASN_OPAQUE_DOUBLE:
734 *datalength = (int) asn_length;
738 * value is encoded as special format
740 bufp = asn_parse_length(bufp + 2, &asn_length);
741 if (_asn_parse_length_check("parse opaque header", bufp, data,
742 asn_length, *datalength))
745 #endif /* OPAQUE_SPECIAL_TYPES */
747 *datalength = (int) asn_length;
753 * same as asn_parse_header with test for expected type.
756 asn_parse_sequence(u_char * data, size_t * datalength, u_char * type, u_char expected_type, /* must be this type */
758 { /* error message prefix */
759 data = asn_parse_header(data, datalength, type);
760 if (data && (*type != expected_type)) {
762 snprintf(ebuf, sizeof(ebuf),
763 "%s header type %02X: s/b %02X", estr,
764 (u_char) * type, (u_char) expected_type);
765 ebuf[ sizeof(ebuf)-1 ] = 0;
775 * asn_build_header - builds an ASN header for an object with the ID and
777 * On entry, datalength is input as the number of valid bytes following
778 * "data". On exit, it is returned as the number of valid bytes
779 * in this object following the id and length.
781 * This only works on data types < 30, i.e. no extension octets.
782 * The maximum length is 0xFFFF;
784 * Returns a pointer to the first byte of the contents of this object.
785 * Returns NULL on any error.
787 u_char * asn_build_header(
788 u_char *data IN - pointer to start of object
789 size_t *datalength IN/OUT - number of valid bytes left in buffer
790 u_char type IN - asn type of object
791 size_t length IN - length of object
794 asn_build_header(u_char * data,
795 size_t * datalength, u_char type, size_t length)
799 if (*datalength < 1) {
800 snprintf(ebuf, sizeof(ebuf),
801 "bad header length < 1 :%d, %d", *datalength,
803 ebuf[ sizeof(ebuf)-1 ] = 0;
809 return asn_build_length(data, datalength, length);
813 * asn_build_sequence - builds an ASN header for a sequence with the ID and
815 * On entry, datalength is input as the number of valid bytes following
816 * "data". On exit, it is returned as the number of valid bytes
817 * in this object following the id and length.
819 * This only works on data types < 30, i.e. no extension octets.
820 * The maximum length is 0xFFFF;
822 * Returns a pointer to the first byte of the contents of this object.
823 * Returns NULL on any error.
825 u_char * asn_build_sequence(
826 u_char *data IN - pointer to start of object
827 int *datalength IN/OUT - number of valid bytes left in buffer
828 u_char type IN - asn type of object
829 int length IN - length of object
832 asn_build_sequence(u_char * data,
833 size_t * datalength, u_char type, size_t length)
835 static const char *errpre = "build seq";
838 if (*datalength < 4) {
839 snprintf(ebuf, sizeof(ebuf),
840 "%s: length %d < 4: PUNT", errpre,
842 ebuf[ sizeof(ebuf)-1 ] = 0;
848 *data++ = (u_char) (0x02 | ASN_LONG_LEN);
849 *data++ = (u_char) ((length >> 8) & 0xFF);
850 *data++ = (u_char) (length & 0xFF);
855 * asn_parse_length - interprets the length of the current object.
856 * On exit, length contains the value of this length field.
858 * Returns a pointer to the first byte after this length
859 * field (aka: the start of the data field).
860 * Returns NULL on any error.
862 u_char * asn_parse_length(
863 u_char *data IN - pointer to start of length field
864 u_long *length OUT - value of length field
867 asn_parse_length(u_char * data, u_long * length)
869 static const char *errpre = "parse length";
871 register u_char lengthbyte;
873 if (!data || !length) {
874 ERROR_MSG("parse length: NULL pointer");
879 if (lengthbyte & ASN_LONG_LEN) {
880 lengthbyte &= ~ASN_LONG_LEN; /* turn MSb off */
881 if (lengthbyte == 0) {
882 snprintf(ebuf, sizeof(ebuf),
883 "%s: indefinite length not supported", errpre);
884 ebuf[ sizeof(ebuf)-1 ] = 0;
888 if (lengthbyte > sizeof(long)) {
889 snprintf(ebuf, sizeof(ebuf),
890 "%s: data length %d > %d not supported", errpre,
891 lengthbyte, sizeof(long));
892 ebuf[ sizeof(ebuf)-1 ] = 0;
897 *length = 0; /* protect against short lengths */
898 while (lengthbyte--) {
902 if ((long) *length < 0) {
903 snprintf(ebuf, sizeof(ebuf),
904 "%s: negative data length %ld\n", errpre,
906 ebuf[ sizeof(ebuf)-1 ] = 0;
911 } else { /* short asnlength */
912 *length = (long) lengthbyte;
919 * u_char * asn_build_length(
920 * u_char *data IN - pointer to start of object
921 * int *datalength IN/OUT - number of valid bytes left in buffer
922 * int length IN - length of object
925 asn_build_length(u_char * data, size_t * datalength, size_t length)
927 static const char *errpre = "build length";
930 u_char *start_data = data;
933 * no indefinite lengths sent
936 if (*datalength < 1) {
937 snprintf(ebuf, sizeof(ebuf),
938 "%s: bad length < 1 :%d, %d", errpre,
939 *datalength, length);
940 ebuf[ sizeof(ebuf)-1 ] = 0;
944 *data++ = (u_char) length;
945 } else if (length <= 0xFF) {
946 if (*datalength < 2) {
947 snprintf(ebuf, sizeof(ebuf),
948 "%s: bad length < 2 :%d, %d", errpre,
949 *datalength, length);
950 ebuf[ sizeof(ebuf)-1 ] = 0;
954 *data++ = (u_char) (0x01 | ASN_LONG_LEN);
955 *data++ = (u_char) length;
956 } else { /* 0xFF < length <= 0xFFFF */
957 if (*datalength < 3) {
958 snprintf(ebuf, sizeof(ebuf),
959 "%s: bad length < 3 :%d, %d", errpre,
960 *datalength, length);
961 ebuf[ sizeof(ebuf)-1 ] = 0;
965 *data++ = (u_char) (0x02 | ASN_LONG_LEN);
966 *data++ = (u_char) ((length >> 8) & 0xFF);
967 *data++ = (u_char) (length & 0xFF);
969 *datalength -= (data - start_data);
975 * asn_parse_objid - pulls an object indentifier out of an ASN object identifier type.
976 * On entry, datalength is input as the number of valid bytes following
977 * "data". On exit, it is returned as the number of valid bytes
978 * following the beginning of the next object.
980 * "objid" is filled with the object identifier.
982 * Returns a pointer to the first byte past the end
983 * of this object (i.e. the start of the next object).
984 * Returns NULL on any error.
986 u_char * asn_parse_objid(
987 u_char *data IN - pointer to start of object
988 int *datalength IN/OUT - number of valid bytes left in buffer
989 u_char *type OUT - asn type of object
990 oid *objid IN/OUT - pointer to start of output buffer
991 int *objidlength IN/OUT - number of sub-id's in objid
994 asn_parse_objid(u_char * data,
996 u_char * type, oid * objid, size_t * objidlength)
999 * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}*
1000 * subidentifier ::= {leadingbyte}* lastbyte
1001 * leadingbyte ::= 1 7bitvalue
1002 * lastbyte ::= 0 7bitvalue
1004 register u_char *bufp = data;
1005 register oid *oidp = objid + 1;
1006 register u_long subidentifier;
1007 register long length;
1011 bufp = asn_parse_length(bufp, &asn_length);
1012 if (_asn_parse_length_check("parse objid", bufp, data,
1013 asn_length, *datalength))
1016 *datalength -= (int) asn_length + (bufp - data);
1018 DEBUGDUMPSETUP("recv", data, bufp - data + asn_length);
1021 * Handle invalid object identifier encodings of the form 06 00 robustly
1023 if (asn_length == 0)
1024 objid[0] = objid[1] = 0;
1026 length = asn_length;
1027 (*objidlength)--; /* account for expansion of first byte */
1029 while (length > 0 && (*objidlength)-- > 0) {
1031 do { /* shift and add in low order 7 bits */
1033 (subidentifier << 7) + (*(u_char *) bufp & ~ASN_BIT8);
1035 } while (*(u_char *) bufp++ & ASN_BIT8); /* last byte has high bit clear */
1037 * ?? note, this test will never be true, since the largest value
1038 * of subidentifier is the value of MAX_SUBID!
1040 if (subidentifier > (u_long) MAX_SUBID) {
1041 ERROR_MSG("subidentifier too large");
1044 *oidp++ = (oid) subidentifier;
1048 * The first two subidentifiers are encoded into the first component
1049 * with the value (X * 40) + Y, where:
1050 * X is the value of the first subidentifier.
1051 * Y is the value of the second subidentifier.
1053 subidentifier = (u_long) objid[1];
1054 if (subidentifier == 0x2B) {
1058 if (subidentifier < 40) {
1060 objid[1] = subidentifier;
1061 } else if (subidentifier < 80) {
1063 objid[1] = subidentifier - 40;
1066 objid[1] = subidentifier - 80;
1070 *objidlength = (int) (oidp - objid);
1072 DEBUGMSG(("dumpv_recv", " ObjID: "));
1073 DEBUGMSGOID(("dumpv_recv", objid, *objidlength));
1074 DEBUGMSG(("dumpv_recv", "\n"));
1079 * asn_build_objid - Builds an ASN object identifier object containing the
1081 * On entry, datalength is input as the number of valid bytes following
1082 * "data". On exit, it is returned as the number of valid bytes
1083 * following the beginning of the next object.
1085 * Returns a pointer to the first byte past the end
1086 * of this object (i.e. the start of the next object).
1087 * Returns NULL on any error.
1089 u_char * asn_build_objid(
1090 u_char *data IN - pointer to start of object
1091 int *datalength IN/OUT - number of valid bytes left in buffer
1092 int type IN - asn type of object
1093 oid *objid IN - pointer to start of input buffer
1094 int objidlength IN - number of sub-id's in objid
1097 asn_build_objid(u_char * data,
1098 size_t * datalength,
1099 u_char type, oid * objid, size_t objidlength)
1102 * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}*
1103 * subidentifier ::= {leadingbyte}* lastbyte
1104 * leadingbyte ::= 1 7bitvalue
1105 * lastbyte ::= 0 7bitvalue
1108 register oid *op = objid;
1109 u_char objid_size[MAX_OID_LEN];
1110 register u_long objid_val;
1111 u_long first_objid_val;
1113 #ifndef SNMP_NO_DEBUGGING
1114 u_char *initdatap = data;
1118 * check if there are at least 2 sub-identifiers
1120 if (objidlength == 0) {
1122 * there are not, so make OID have two with value of zero
1126 } else if (objid[0] > 2) {
1127 ERROR_MSG("build objid: bad first subidentifier");
1129 } else if (objidlength == 1) {
1131 * encode the first value
1133 objid_val = (op[0] * 40);
1138 * combine the first two values
1142 ERROR_MSG("build objid: bad second subidentifier");
1145 objid_val = (op[0] * 40) + op[1];
1148 first_objid_val = objid_val;
1151 * ditch illegal calls now
1153 if (objidlength > MAX_OID_LEN)
1157 * calculate the number of bytes needed to store the encoded value
1159 for (i = 1, asnlength = 0;;) {
1160 if (objid_val < (unsigned) 0x80) {
1163 } else if (objid_val < (unsigned) 0x4000) {
1166 } else if (objid_val < (unsigned) 0x200000) {
1169 } else if (objid_val < (unsigned) 0x10000000) {
1177 if (i >= (int) objidlength)
1179 objid_val = *op++; /* XXX - doesn't handle 2.X (X > 40) */
1183 * store the ASN.1 tag and length
1185 data = asn_build_header(data, datalength, type, asnlength);
1186 if (_asn_build_header_check
1187 ("build objid", data, *datalength, asnlength))
1191 * store the encoded OID value
1193 for (i = 1, objid_val = first_objid_val, op = objid + 2;
1194 i < (int) objidlength; i++) {
1197 switch (objid_size[i]) {
1199 *data++ = (u_char) objid_val;
1203 *data++ = (u_char) ((objid_val >> 7) | 0x80);
1204 *data++ = (u_char) (objid_val & 0x07f);
1208 *data++ = (u_char) ((objid_val >> 14) | 0x80);
1209 *data++ = (u_char) ((objid_val >> 7 & 0x7f) | 0x80);
1210 *data++ = (u_char) (objid_val & 0x07f);
1214 *data++ = (u_char) ((objid_val >> 21) | 0x80);
1215 *data++ = (u_char) ((objid_val >> 14 & 0x7f) | 0x80);
1216 *data++ = (u_char) ((objid_val >> 7 & 0x7f) | 0x80);
1217 *data++ = (u_char) (objid_val & 0x07f);
1221 *data++ = (u_char) ((objid_val >> 28) | 0x80);
1222 *data++ = (u_char) ((objid_val >> 21 & 0x7f) | 0x80);
1223 *data++ = (u_char) ((objid_val >> 14 & 0x7f) | 0x80);
1224 *data++ = (u_char) ((objid_val >> 7 & 0x7f) | 0x80);
1225 *data++ = (u_char) (objid_val & 0x07f);
1231 * return the length and data ptr
1233 *datalength -= asnlength;
1234 DEBUGDUMPSETUP("send", initdatap, data - initdatap);
1235 DEBUGMSG(("dumpv_send", " ObjID: "));
1236 DEBUGMSGOID(("dumpv_send", objid, objidlength));
1237 DEBUGMSG(("dumpv_send", "\n"));
1242 * asn_parse_null - Interprets an ASN null type.
1243 * On entry, datalength is input as the number of valid bytes following
1244 * "data". On exit, it is returned as the number of valid bytes
1245 * following the beginning of the next object.
1247 * Returns a pointer to the first byte past the end
1248 * of this object (i.e. the start of the next object).
1249 * Returns NULL on any error.
1251 u_char * asn_parse_null(
1252 u_char *data IN - pointer to start of object
1253 int *datalength IN/OUT - number of valid bytes left in buffer
1254 u_char *type OUT - asn type of object
1257 asn_parse_null(u_char * data, size_t * datalength, u_char * type)
1260 * ASN.1 null ::= 0x05 0x00
1262 register u_char *bufp = data;
1266 bufp = asn_parse_length(bufp, &asn_length);
1268 ERROR_MSG("parse null: bad length");
1271 if (asn_length != 0) {
1272 ERROR_MSG("parse null: malformed ASN.1 null");
1276 *datalength -= (bufp - data);
1278 DEBUGDUMPSETUP("recv", data, bufp - data);
1279 DEBUGMSG(("dumpv_recv", " NULL\n"));
1281 return bufp + asn_length;
1286 * asn_build_null - Builds an ASN null object.
1287 * On entry, datalength is input as the number of valid bytes following
1288 * "data". On exit, it is returned as the number of valid bytes
1289 * following the beginning of the next object.
1291 * Returns a pointer to the first byte past the end
1292 * of this object (i.e. the start of the next object).
1293 * Returns NULL on any error.
1295 u_char * asn_build_null(
1296 u_char *data IN - pointer to start of object
1297 int *datalength IN/OUT - number of valid bytes left in buffer
1298 u_char type IN - asn type of object
1301 asn_build_null(u_char * data, size_t * datalength, u_char type)
1304 * ASN.1 null ::= 0x05 0x00
1306 #ifndef SNMP_NO_DEBUGGING
1307 u_char *initdatap = data;
1309 data = asn_build_header(data, datalength, type, 0);
1310 DEBUGDUMPSETUP("send", initdatap, data - initdatap);
1311 DEBUGMSG(("dumpv_send", " NULL\n"));
1316 * asn_parse_bitstring - pulls a bitstring out of an ASN bitstring type.
1317 * On entry, datalength is input as the number of valid bytes following
1318 * "data". On exit, it is returned as the number of valid bytes
1319 * following the beginning of the next object.
1321 * "string" is filled with the bit string.
1323 * Returns a pointer to the first byte past the end
1324 * of this object (i.e. the start of the next object).
1325 * Returns NULL on any error.
1327 u_char * asn_parse_bitstring(
1328 u_char *data IN - pointer to start of object
1329 size_t *datalength IN/OUT - number of valid bytes left in buffer
1330 u_char *type OUT - asn type of object
1331 u_char *string IN/OUT - pointer to start of output buffer
1332 size_t *strlength IN/OUT - size of output buffer
1335 asn_parse_bitstring(u_char * data,
1336 size_t * datalength,
1337 u_char * type, u_char * string, size_t * strlength)
1340 * bitstring ::= 0x03 asnlength unused {byte}*
1342 static const char *errpre = "parse bitstring";
1343 register u_char *bufp = data;
1347 bufp = asn_parse_length(bufp, &asn_length);
1348 if (_asn_parse_length_check(errpre, bufp, data,
1349 asn_length, *datalength))
1352 if ((size_t) asn_length > *strlength) {
1353 _asn_length_err(errpre, (size_t) asn_length, *strlength);
1356 if (_asn_bitstring_check(errpre, asn_length, *bufp))
1359 DEBUGDUMPSETUP("recv", data, bufp - data);
1360 DEBUGMSG(("dumpv_recv", " Bitstring: "));
1361 DEBUGMSGHEX(("dumpv_recv", data, asn_length));
1362 DEBUGMSG(("dumpv_recv", "\n"));
1364 memmove(string, bufp, asn_length);
1365 *strlength = (int) asn_length;
1366 *datalength -= (int) asn_length + (bufp - data);
1367 return bufp + asn_length;
1372 * asn_build_bitstring - Builds an ASN bit string object containing the
1374 * On entry, datalength is input as the number of valid bytes following
1375 * "data". On exit, it is returned as the number of valid bytes
1376 * following the beginning of the next object.
1378 * Returns a pointer to the first byte past the end
1379 * of this object (i.e. the start of the next object).
1380 * Returns NULL on any error.
1382 u_char * asn_build_bitstring(
1383 u_char *data IN - pointer to start of object
1384 int *datalength IN/OUT - number of valid bytes left in buffer
1385 u_char type IN - asn type of object
1386 u_char *string IN - pointer to start of input buffer
1387 int strlength IN - size of input buffer
1390 asn_build_bitstring(u_char * data,
1391 size_t * datalength,
1392 u_char type, u_char * string, size_t strlength)
1395 * ASN.1 bit string ::= 0x03 asnlength unused {byte}*
1397 static const char *errpre = "build bitstring";
1398 if (_asn_bitstring_check
1399 (errpre, strlength, ((string) ? *string : (u_char) 0)))
1402 data = asn_build_header(data, datalength, type, strlength);
1403 if (_asn_build_header_check(errpre, data, *datalength, strlength))
1406 if (strlength > 0 && string)
1407 memmove(data, string, strlength);
1408 else if (strlength > 0 && !string) {
1409 ERROR_MSG("no string passed into asn_build_bitstring\n");
1413 *datalength -= strlength;
1414 DEBUGDUMPSETUP("send", data, strlength);
1415 DEBUGMSG(("dumpv_send", " Bitstring: "));
1416 DEBUGMSGHEX(("dumpv_send", data, strlength));
1417 DEBUGMSG(("dumpv_send", "\n"));
1418 return data + strlength;
1421 #ifdef BRCM_SNMP_SUPPORT
1423 * asn_parse_unsigned_int64 - pulls a 64 bit unsigned long out of an ASN int
1425 * On entry, datalength is input as the number of valid bytes following
1426 * "data". On exit, it is returned as the number of valid bytes
1427 * following the end of this object.
1429 * Returns a pointer to the first byte past the end
1430 * of this object (i.e. the start of the next object).
1431 * Returns NULL on any error.
1433 u_char * asn_parse_unsigned_int64(
1434 u_char *data IN - pointer to start of object
1435 int *datalength IN/OUT - number of valid bytes left in buffer
1436 u_char *type OUT - asn type of object
1437 struct counter64 *cp IN/OUT - pointer to counter struct
1438 int countersize IN - size of output buffer
1441 asn_parse_unsigned_int64(u_char * data,
1442 size_t * datalength,
1444 struct counter64 * cp, size_t countersize)
1447 * ASN.1 integer ::= 0x02 asnlength byte {byte}*
1449 static const char *errpre = "parse uint64";
1450 const int uint64sizelimit = (4 * 2) + 1;
1451 register u_char *bufp = data;
1453 register u_long low = 0, high = 0;
1455 if (countersize != sizeof(struct counter64)) {
1456 _asn_size_err(errpre, countersize, sizeof(struct counter64));
1460 bufp = asn_parse_length(bufp, &asn_length);
1461 if (_asn_parse_length_check
1462 (errpre, bufp, data, asn_length, *datalength))
1465 DEBUGDUMPSETUP("recv", data, bufp - data);
1466 #ifdef OPAQUE_SPECIAL_TYPES
1468 * 64 bit counters as opaque
1470 if ((*type == ASN_OPAQUE) &&
1471 (asn_length <= ASN_OPAQUE_COUNTER64_MX_BER_LEN) &&
1472 (*bufp == ASN_OPAQUE_TAG1) &&
1473 ((*(bufp + 1) == ASN_OPAQUE_COUNTER64) ||
1474 (*(bufp + 1) == ASN_OPAQUE_U64))) {
1476 * change type to Counter64 or U64
1478 *type = *(bufp + 1);
1480 * value is encoded as special format
1482 bufp = asn_parse_length(bufp + 2, &asn_length);
1483 if (_asn_parse_length_check("parse opaque uint64", bufp, data,
1484 asn_length, *datalength))
1487 #endif /* OPAQUE_SPECIAL_TYPES */
1488 if (((int) asn_length > uint64sizelimit) ||
1489 (((int) asn_length == uint64sizelimit) && *bufp != 0x00)) {
1490 _asn_length_err(errpre, (size_t) asn_length, uint64sizelimit);
1493 *datalength -= (int) asn_length + (bufp - data);
1495 low = ~low; /* integer is negative */
1499 while (asn_length--) {
1500 high = (high << 8) | ((low & 0xFF000000) >> 24);
1501 low = (low << 8) | *bufp++;
1507 DEBUGIF("dumpv_recv") {
1508 char i64buf[I64CHARSZ + 1];
1509 printU64(i64buf, cp);
1510 DEBUGMSG(("dumpv_recv", "Counter64: ", i64buf));
1518 * asn_build_unsigned_int64 - builds an ASN object containing a 64 bit integer.
1519 * On entry, datalength is input as the number of valid bytes following
1520 * "data". On exit, it is returned as the number of valid bytes
1521 * following the end of this object.
1523 * Returns a pointer to the first byte past the end
1524 * of this object (i.e. the start of the next object).
1525 * Returns NULL on any error.
1527 u_char * asn_build_unsigned_int64(
1528 u_char *data IN - pointer to start of output buffer
1529 size_t *datalength IN/OUT - number of valid bytes left in buffer
1530 u_char type IN - asn type of object
1531 struct counter64 *cp IN - pointer to counter struct
1532 size_t countersize IN - size of input buffer
1535 asn_build_unsigned_int64(u_char * data,
1536 size_t * datalength,
1538 struct counter64 * cp, size_t countersize)
1541 * ASN.1 integer ::= 0x02 asnlength byte {byte}*
1544 register u_long low, high;
1545 register u_long mask, mask2;
1546 int add_null_byte = 0;
1548 #ifndef SNMP_NO_DEBUGGING
1549 u_char *initdatap = data;
1552 if (countersize != sizeof(struct counter64)) {
1553 _asn_size_err("build uint64", countersize,
1554 sizeof(struct counter64));
1560 mask = ((u_long) 0xFF) << (8 * (sizeof(long) - 1));
1562 * mask is 0xFF000000 on a big-endian machine
1564 if ((u_char) ((high & mask) >> (8 * (sizeof(long) - 1))) & 0x80) {
1572 * Truncate "unnecessary" bytes off of the most significant end of this 2's
1573 * complement integer.
1574 * There should be no sequence of 9 consecutive 1's or 0's at the most
1575 * significant end of the integer.
1577 mask2 = ((u_long) 0x1FF) << ((8 * (sizeof(long) - 1)) - 1);
1579 * mask2 is 0xFF800000 on a big-endian machine
1581 while ((((high & mask2) == 0) || ((high & mask2) == mask2))
1585 | ((low & mask) >> (8 * (sizeof(long) - 1)));
1589 #ifdef OPAQUE_SPECIAL_TYPES
1591 * encode a Counter64 as an opaque (it also works in SNMPv1)
1594 * turn into Opaque holding special tagged value
1596 if (type == ASN_OPAQUE_COUNTER64) {
1598 * put the tag and length for the Opaque wrapper
1600 data = asn_build_header(data, datalength, ASN_OPAQUE, intsize + 3);
1601 if (_asn_build_header_check
1602 ("build counter u64", data, *datalength, intsize + 3))
1606 * put the special tag and length
1608 *data++ = ASN_OPAQUE_TAG1;
1609 *data++ = ASN_OPAQUE_COUNTER64;
1610 *data++ = (u_char) intsize;
1611 *datalength = *datalength - 3;
1614 * Encode the Unsigned int64 in an opaque
1617 * turn into Opaque holding special tagged value
1619 if (type == ASN_OPAQUE_U64) {
1621 * put the tag and length for the Opaque wrapper
1623 data = asn_build_header(data, datalength, ASN_OPAQUE, intsize + 3);
1624 if (_asn_build_header_check
1625 ("build opaque u64", data, *datalength, intsize + 3))
1629 * put the special tag and length
1631 *data++ = ASN_OPAQUE_TAG1;
1632 *data++ = ASN_OPAQUE_U64;
1633 *data++ = (u_char) intsize;
1634 *datalength = *datalength - 3;
1636 #endif /* OPAQUE_SPECIAL_TYPES */
1637 data = asn_build_header(data, datalength, type, intsize);
1638 if (_asn_build_header_check
1639 ("build uint64", data, *datalength, intsize))
1642 #ifdef OPAQUE_SPECIAL_TYPES
1644 #endif /* OPAQUE_SPECIAL_TYPES */
1645 *datalength -= intsize;
1646 if (add_null_byte == 1) {
1651 *data++ = (u_char) ((high & mask) >> (8 * (sizeof(long) - 1)));
1653 | ((low & mask) >> (8 * (sizeof(long) - 1)));
1657 DEBUGDUMPSETUP("send", initdatap, data - initdatap);
1658 DEBUGIF("dumpv_send") {
1659 char i64buf[I64CHARSZ + 1];
1660 printU64(i64buf, cp);
1661 DEBUGMSG(("dumpv_send", i64buf));
1666 #ifdef OPAQUE_SPECIAL_TYPES
1670 * u_char * asn_parse_signed_int64(
1671 * u_char *data IN - pointer to start of object
1672 * int *datalength IN/OUT - number of valid bytes left in buffer
1673 * u_char *type OUT - asn type of object
1674 * struct counter64 *cp IN/OUT - pointer to counter struct
1675 * int countersize IN - size of output buffer
1679 asn_parse_signed_int64(u_char * data,
1680 size_t * datalength,
1682 struct counter64 * cp, size_t countersize)
1684 static const char *errpre = "parse int64";
1685 const int int64sizelimit = (4 * 2) + 1;
1687 register u_char *bufp = data;
1689 register u_int low = 0, high = 0;
1691 if (countersize != sizeof(struct counter64)) {
1692 _asn_size_err(errpre, countersize, sizeof(struct counter64));
1696 bufp = asn_parse_length(bufp, &asn_length);
1697 if (_asn_parse_length_check
1698 (errpre, bufp, data, asn_length, *datalength))
1701 DEBUGDUMPSETUP("recv", data, bufp - data);
1702 if ((*type == ASN_OPAQUE) &&
1703 (asn_length <= ASN_OPAQUE_COUNTER64_MX_BER_LEN) &&
1704 (*bufp == ASN_OPAQUE_TAG1) && (*(bufp + 1) == ASN_OPAQUE_I64)) {
1706 * change type to Int64
1708 *type = *(bufp + 1);
1710 * value is encoded as special format
1712 bufp = asn_parse_length(bufp + 2, &asn_length);
1713 if (_asn_parse_length_check("parse opaque int64", bufp, data,
1714 asn_length, *datalength))
1718 * this should always have been true until snmp gets int64 PDU types
1721 snprintf(ebuf, sizeof(ebuf),
1722 "%s: wrong type: %d, len %d, buf bytes (%02X,%02X)",
1723 errpre, *type, (int) asn_length, *bufp, *(bufp + 1));
1724 ebuf[ sizeof(ebuf)-1 ] = 0;
1728 if (((int) asn_length > int64sizelimit) ||
1729 (((int) asn_length == int64sizelimit) && *bufp != 0x00)) {
1730 _asn_length_err(errpre, (size_t) asn_length, int64sizelimit);
1733 *datalength -= (int) asn_length + (bufp - data);
1735 low = ~low; /* integer is negative */
1739 while (asn_length--) {
1740 high = (high << 8) | ((low & 0xFF000000) >> 24);
1741 low = (low << 8) | *bufp++;
1747 DEBUGIF("dumpv_recv") {
1748 char i64buf[I64CHARSZ + 1];
1749 printI64(i64buf, cp);
1750 DEBUGMSG(("dumpv_recv", "Integer64: %s", i64buf));
1759 * u_char * asn_build_signed_int64(
1760 * u_char *data IN - pointer to start of object
1761 * int *datalength IN/OUT - number of valid bytes left in buffer
1762 * u_char type IN - asn type of object
1763 * struct counter64 *cp IN - pointer to counter struct
1764 * int countersize IN - size of input buffer
1767 asn_build_signed_int64(u_char * data,
1768 size_t * datalength,
1770 struct counter64 * cp, size_t countersize)
1773 * ASN.1 integer ::= 0x02 asnlength byte {byte}*
1776 struct counter64 c64;
1777 register u_int mask, mask2;
1780 #ifndef SNMP_NO_DEBUGGING
1781 u_char *initdatap = data;
1784 if (countersize != sizeof(struct counter64)) {
1785 _asn_size_err("build int64", countersize,
1786 sizeof(struct counter64));
1790 memcpy(&c64, cp, sizeof(struct counter64)); /* we're may modify it */
1795 * Truncate "unnecessary" bytes off of the most significant end of this
1796 * 2's complement integer. There should be no sequence of 9
1797 * consecutive 1's or 0's at the most significant end of the
1800 mask = ((u_int) 0xFF) << (8 * (sizeof(u_int) - 1));
1801 mask2 = ((u_int) 0x1FF) << ((8 * (sizeof(u_int) - 1)) - 1);
1803 * mask is 0xFF800000 on a big-endian machine
1805 while ((((high & mask2) == 0) || ((high & mask2) == mask2))
1809 | ((low & mask) >> (8 * (sizeof(u_int) - 1)));
1813 * until a real int64 gets incorperated into SNMP, we are going to
1814 * encode it as an opaque instead. First, we build the opaque
1815 * header and then the int64 tag type we use to mark it as an
1816 * int64 in the opaque string.
1818 data = asn_build_header(data, datalength, ASN_OPAQUE, intsize + 3);
1819 if (_asn_build_header_check
1820 ("build int64", data, *datalength, intsize + 3))
1823 *data++ = ASN_OPAQUE_TAG1;
1824 *data++ = ASN_OPAQUE_I64;
1825 *data++ = (u_char) intsize;
1826 *datalength -= (3 + intsize);
1829 *data++ = (u_char) ((high & mask) >> (8 * (sizeof(u_int) - 1)));
1831 | ((low & mask) >> (8 * (sizeof(u_int) - 1)));
1834 DEBUGDUMPSETUP("send", initdatap, data - initdatap);
1835 DEBUGIF("dumpv_send") {
1836 char i64buf[I64CHARSZ + 1];
1837 printU64(i64buf, cp);
1838 DEBUGMSG(("dumpv_send", i64buf));
1845 * asn_parse_float - pulls a single precision floating-point out of an opaque type.
1847 * On entry, datalength is input as the number of valid bytes following
1848 * "data". On exit, it is returned as the number of valid bytes
1849 * following the end of this object.
1851 * Returns a pointer to the first byte past the end
1852 * of this object (i.e. the start of the next object).
1853 * Returns NULL on any error.
1855 u_char * asn_parse_float(
1856 u_char *data IN - pointer to start of object
1857 int *datalength IN/OUT - number of valid bytes left in buffer
1858 u_char *type OUT - asn type of object
1859 float *floatp IN/OUT - pointer to float
1860 int floatsize IN - size of output buffer
1863 asn_parse_float(u_char * data,
1864 size_t * datalength,
1865 u_char * type, float *floatp, size_t floatsize)
1867 register u_char *bufp = data;
1872 u_char c[sizeof(float)];
1875 if (floatsize != sizeof(float)) {
1876 _asn_size_err("parse float", floatsize, sizeof(float));
1880 bufp = asn_parse_length(bufp, &asn_length);
1881 if (_asn_parse_length_check("parse float", bufp, data,
1882 asn_length, *datalength))
1885 DEBUGDUMPSETUP("recv", data, bufp - data + asn_length);
1887 * the float is encoded as an opaque
1889 if ((*type == ASN_OPAQUE) &&
1890 (asn_length == ASN_OPAQUE_FLOAT_BER_LEN) &&
1891 (*bufp == ASN_OPAQUE_TAG1) && (*(bufp + 1) == ASN_OPAQUE_FLOAT)) {
1894 * value is encoded as special format
1896 bufp = asn_parse_length(bufp + 2, &asn_length);
1897 if (_asn_parse_length_check("parse opaque float", bufp, data,
1898 asn_length, *datalength))
1902 * change type to Float
1904 *type = ASN_OPAQUE_FLOAT;
1907 if (asn_length != sizeof(float)) {
1908 _asn_size_err("parse seq float", asn_length, sizeof(float));
1912 *datalength -= (int) asn_length + (bufp - data);
1913 memcpy(&fu.c[0], bufp, asn_length);
1916 * correct for endian differences
1918 fu.longVal = ntohl(fu.longVal);
1920 *floatp = fu.floatVal;
1922 DEBUGMSG(("dumpv_recv", "Opaque float: %f\n", *floatp));
1927 * asn_build_float - builds an ASN object containing a single precision floating-point
1928 * number in an Opaque value.
1930 * On entry, datalength is input as the number of valid bytes following
1931 * "data". On exit, it is returned as the number of valid bytes
1932 * following the end of this object.
1934 * Returns a pointer to the first byte past the end
1935 * of this object (i.e. the start of the next object).
1936 * Returns NULL on any error.
1938 u_char * asn_build_float(
1939 u_char *data IN - pointer to start of object
1940 int *datalength IN/OUT - number of valid bytes left in buffer
1941 u_char type IN - asn type of object
1942 float *floatp IN - pointer to float
1943 int floatsize IN - size of input buffer
1946 asn_build_float(u_char * data,
1947 size_t * datalength,
1948 u_char type, float *floatp, size_t floatsize)
1953 u_char c[sizeof(float)];
1955 #ifndef SNMP_NO_DEBUGGING
1956 u_char *initdatap = data;
1959 if (floatsize != sizeof(float)) {
1960 _asn_size_err("build float", floatsize, sizeof(float));
1964 * encode the float as an opaque
1967 * turn into Opaque holding special tagged value
1971 * put the tag and length for the Opaque wrapper
1973 data = asn_build_header(data, datalength, ASN_OPAQUE, floatsize + 3);
1974 if (_asn_build_header_check
1975 ("build float", data, *datalength, (floatsize + 3)))
1979 * put the special tag and length
1981 *data++ = ASN_OPAQUE_TAG1;
1982 *data++ = ASN_OPAQUE_FLOAT;
1983 *data++ = (u_char) floatsize;
1984 *datalength = *datalength - 3;
1986 fu.floatVal = *floatp;
1988 * correct for endian differences
1990 fu.intVal = htonl(fu.intVal);
1992 *datalength -= floatsize;
1993 memcpy(data, &fu.c[0], floatsize);
1995 DEBUGDUMPSETUP("send", initdatap, data - initdatap);
1996 DEBUGMSG(("dumpv_send", "Opaque float: %f\n", *floatp));
2003 * u_char * asn_parse_double(
2004 * u_char *data IN - pointer to start of object
2005 * int *datalength IN/OUT - number of valid bytes left in buffer
2006 * u_char *type OUT - asn type of object
2007 * double *doublep IN/OUT - pointer to double
2008 * int doublesize IN - size of output buffer
2011 asn_parse_double(u_char * data,
2012 size_t * datalength,
2013 u_char * type, double *doublep, size_t doublesize)
2015 register u_char *bufp = data;
2021 u_char c[sizeof(double)];
2025 if (doublesize != sizeof(double)) {
2026 _asn_size_err("parse double", doublesize, sizeof(double));
2030 bufp = asn_parse_length(bufp, &asn_length);
2031 if (_asn_parse_length_check("parse double", bufp, data,
2032 asn_length, *datalength))
2035 DEBUGDUMPSETUP("recv", data, bufp - data + asn_length);
2037 * the double is encoded as an opaque
2039 if ((*type == ASN_OPAQUE) &&
2040 (asn_length == ASN_OPAQUE_DOUBLE_BER_LEN) &&
2041 (*bufp == ASN_OPAQUE_TAG1) && (*(bufp + 1) == ASN_OPAQUE_DOUBLE)) {
2044 * value is encoded as special format
2046 bufp = asn_parse_length(bufp + 2, &asn_length);
2047 if (_asn_parse_length_check("parse opaque double", bufp, data,
2048 asn_length, *datalength))
2052 * change type to Double
2054 *type = ASN_OPAQUE_DOUBLE;
2057 if (asn_length != sizeof(double)) {
2058 _asn_size_err("parse seq double", asn_length, sizeof(double));
2061 *datalength -= (int) asn_length + (bufp - data);
2062 memcpy(&fu.c[0], bufp, asn_length);
2065 * correct for endian differences
2068 tmp = ntohl(fu.intVal[0]);
2069 fu.intVal[0] = ntohl(fu.intVal[1]);
2072 *doublep = fu.doubleVal;
2073 DEBUGMSG(("dumpv_recv", " Opaque Double:\t%f\n", *doublep));
2077 #endif /* BRCM_SNMP_SUPPORT */
2081 * u_char * asn_build_double(
2082 * u_char *data IN - pointer to start of object
2083 * int *datalength IN/OUT - number of valid bytes left in buffer
2084 * u_char type IN - asn type of object
2085 * double *doublep IN - pointer to double
2086 * int doublesize IN - size of input buffer
2089 asn_build_double(u_char * data,
2090 size_t * datalength,
2091 u_char type, double *doublep, size_t doublesize)
2097 u_char c[sizeof(double)];
2099 #ifndef SNMP_NO_DEBUGGING
2100 u_char *initdatap = data;
2103 if (doublesize != sizeof(double)) {
2104 _asn_size_err("build double", doublesize, sizeof(double));
2109 * encode the double as an opaque
2112 * turn into Opaque holding special tagged value
2116 * put the tag and length for the Opaque wrapper
2118 data = asn_build_header(data, datalength, ASN_OPAQUE, doublesize + 3);
2119 if (_asn_build_header_check
2120 ("build double", data, *datalength, doublesize + 3))
2124 * put the special tag and length
2126 *data++ = ASN_OPAQUE_TAG1;
2127 *data++ = ASN_OPAQUE_DOUBLE;
2128 *data++ = (u_char) doublesize;
2129 *datalength = *datalength - 3;
2131 fu.doubleVal = *doublep;
2133 * correct for endian differences
2135 tmp = htonl(fu.intVal[0]);
2136 fu.intVal[0] = htonl(fu.intVal[1]);
2138 *datalength -= doublesize;
2139 memcpy(data, &fu.c[0], doublesize);
2142 DEBUGDUMPSETUP("send", initdatap, data - initdatap);
2143 DEBUGMSG(("dumpv_send", " Opaque double: %f", *doublep));
2147 #endif /* OPAQUE_SPECIAL_TYPES */
2151 * This function increases the size of the buffer pointed to by *pkt, which
2152 * is initially of size *pkt_len. Contents are preserved **AT THE TOP END OF
2153 * THE BUFFER** (hence making this function useful for reverse encoding).
2154 * You can change the reallocation scheme, but you **MUST** guarantee to
2155 * allocate **AT LEAST** one extra byte. If memory cannot be reallocated,
2156 * then return 0; otherwise return 1.
2160 asn_realloc(u_char ** pkt, size_t * pkt_len)
2162 if (pkt != NULL && pkt_len != NULL) {
2163 size_t old_pkt_len = *pkt_len;
2165 DEBUGMSGTL(("asn_realloc", " old_pkt %08p, old_pkt_len %08x\n",
2166 *pkt, old_pkt_len));
2168 if (snmp_realloc(pkt, pkt_len)) {
2169 DEBUGMSGTL(("asn_realloc", " new_pkt %08p, new_pkt_len %08x\n",
2171 DEBUGMSGTL(("asn_realloc",
2172 " memmove(%08p + %08x, %08p, %08x)\n", *pkt,
2173 (*pkt_len - old_pkt_len), *pkt, old_pkt_len));
2174 memmove(*pkt + (*pkt_len - old_pkt_len), *pkt, old_pkt_len);
2175 memset(*pkt, (int) ' ', *pkt_len - old_pkt_len);
2178 DEBUGMSG(("asn_realloc", " CANNOT REALLOC()\n"));
2184 #ifdef USE_REVERSE_ASNENCODING
2187 asn_realloc_rbuild_length(u_char ** pkt, size_t * pkt_len,
2188 size_t * offset, int r, size_t length)
2190 static const char *errpre = "build length";
2193 size_t start_offset = *offset;
2195 if (length <= 0x7f) {
2196 if (((*pkt_len - *offset) < 1)
2197 && !(r && asn_realloc(pkt, pkt_len))) {
2198 snprintf(ebuf, sizeof(ebuf),
2199 "%s: bad length < 1 :%d, %d", errpre,
2200 *pkt_len - *offset, length);
2201 ebuf[ sizeof(ebuf)-1 ] = 0;
2205 *(*pkt + *pkt_len - (++*offset)) = length;
2207 while (length > 0xff) {
2208 if (((*pkt_len - *offset) < 1)
2209 && !(r && asn_realloc(pkt, pkt_len))) {
2210 snprintf(ebuf, sizeof(ebuf),
2211 "%s: bad length < 1 :%d, %d", errpre,
2212 *pkt_len - *offset, length);
2213 ebuf[ sizeof(ebuf)-1 ] = 0;
2217 *(*pkt + *pkt_len - (++*offset)) = length & 0xff;
2221 while ((*pkt_len - *offset) < 2) {
2222 if (!(r && asn_realloc(pkt, pkt_len))) {
2223 snprintf(ebuf, sizeof(ebuf),
2224 "%s: bad length < 1 :%d, %d", errpre,
2225 *pkt_len - *offset, length);
2226 ebuf[ sizeof(ebuf)-1 ] = 0;
2232 *(*pkt + *pkt_len - (++*offset)) = length & 0xff;
2233 tmp_int = *offset - start_offset;
2234 *(*pkt + *pkt_len - (++*offset)) = tmp_int | 0x80;
2241 asn_realloc_rbuild_header(u_char ** pkt, size_t * pkt_len,
2242 size_t * offset, int r,
2243 u_char type, size_t length)
2247 if (asn_realloc_rbuild_length(pkt, pkt_len, offset, r, length)) {
2248 if (((*pkt_len - *offset) < 1)
2249 && !(r && asn_realloc(pkt, pkt_len))) {
2250 snprintf(ebuf, sizeof(ebuf),
2251 "bad header length < 1 :%d, %d",
2252 *pkt_len - *offset, length);
2253 ebuf[ sizeof(ebuf)-1 ] = 0;
2257 *(*pkt + *pkt_len - (++*offset)) = type;
2264 asn_realloc_rbuild_int(u_char ** pkt, size_t * pkt_len,
2265 size_t * offset, int r,
2266 u_char type, long *intp, size_t intsize)
2268 static const char *errpre = "build int";
2269 register long integer = *intp;
2270 int testvalue = (*intp < 0) ? -1 : 0;
2271 size_t start_offset = *offset;
2273 if (intsize != sizeof(long)) {
2274 _asn_size_err(errpre, intsize, sizeof(long));
2278 if (((*pkt_len - *offset) < 1) && !(r && asn_realloc(pkt, pkt_len))) {
2281 *(*pkt + *pkt_len - (++*offset)) = (u_char) integer;
2284 while (integer != testvalue) {
2285 if (((*pkt_len - *offset) < 1)
2286 && !(r && asn_realloc(pkt, pkt_len))) {
2289 *(*pkt + *pkt_len - (++*offset)) = (u_char) integer;
2293 if ((*(*pkt + *pkt_len - *offset) & 0x80) != (testvalue & 0x80)) {
2295 * Make sure left most bit is representational of the rest of the bits
2296 * that aren't encoded.
2298 if (((*pkt_len - *offset) < 1)
2299 && !(r && asn_realloc(pkt, pkt_len))) {
2302 *(*pkt + *pkt_len - (++*offset)) = testvalue & 0xff;
2305 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r, type,
2306 (*offset - start_offset))) {
2307 if (_asn_realloc_build_header_check(errpre, pkt, pkt_len,
2308 (*offset - start_offset))) {
2311 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset),
2312 (*offset - start_offset));
2313 DEBUGMSG(("dumpv_send", " Integer:\t%ld (0x%.2X)\n", *intp,
2323 asn_realloc_rbuild_string(u_char ** pkt, size_t * pkt_len,
2324 size_t * offset, int r,
2326 const u_char * string, size_t strlength)
2328 static const char *errpre = "build string";
2329 size_t start_offset = *offset;
2331 while ((*pkt_len - *offset) < strlength) {
2332 if (!(r && asn_realloc(pkt, pkt_len))) {
2337 *offset += strlength;
2338 memcpy(*pkt + *pkt_len - *offset, string, strlength);
2340 if (asn_realloc_rbuild_header
2341 (pkt, pkt_len, offset, r, type, strlength)) {
2342 if (_asn_realloc_build_header_check
2343 (errpre, pkt, pkt_len, strlength)) {
2346 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset),
2347 *offset - start_offset);
2348 DEBUGIF("dumpv_send") {
2349 if (strlength == 0) {
2350 DEBUGMSG(("dumpv_send", " String: [NULL]\n"));
2352 u_char *buf = (u_char *) malloc(2 * strlength);
2354 (buf != NULL) ? (2 * strlength) : 0, ol = 0;
2356 if (sprint_realloc_asciistring
2357 (&buf, &l, &ol, 1, string, strlength)) {
2358 DEBUGMSG(("dumpv_send", " String:\t%s\n", buf));
2361 DEBUGMSG(("dumpv_send",
2362 " String:\t[TRUNCATED]\n"));
2364 DEBUGMSG(("dumpv_send",
2365 " String:\t%s [TRUNCATED]\n", buf));
2381 asn_realloc_rbuild_unsigned_int(u_char ** pkt, size_t * pkt_len,
2382 size_t * offset, int r,
2383 u_char type, u_long * intp, size_t intsize)
2385 static const char *errpre = "build uint";
2386 register u_long integer = *intp;
2387 size_t start_offset = *offset;
2389 if (intsize != sizeof(unsigned long)) {
2390 _asn_size_err(errpre, intsize, sizeof(unsigned long));
2394 if (((*pkt_len - *offset) < 1) && !(r && asn_realloc(pkt, pkt_len))) {
2397 *(*pkt + *pkt_len - (++*offset)) = (u_char) integer;
2400 while (integer != 0) {
2401 if (((*pkt_len - *offset) < 1)
2402 && !(r && asn_realloc(pkt, pkt_len))) {
2405 *(*pkt + *pkt_len - (++*offset)) = (u_char) integer;
2409 if ((*(*pkt + *pkt_len - *offset) & 0x80) != (0 & 0x80)) {
2411 * Make sure left most bit is representational of the rest of the bits
2412 * that aren't encoded.
2414 if (((*pkt_len - *offset) < 1)
2415 && !(r && asn_realloc(pkt, pkt_len))) {
2418 *(*pkt + *pkt_len - (++*offset)) = 0;
2421 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r, type,
2422 (*offset - start_offset))) {
2423 if (_asn_realloc_build_header_check(errpre, pkt, pkt_len,
2424 (*offset - start_offset))) {
2427 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset),
2428 (*offset - start_offset));
2429 DEBUGMSG(("dumpv_send", " UInteger:\t%lu (0x%.2X)\n", *intp,
2439 asn_realloc_rbuild_sequence(u_char ** pkt, size_t * pkt_len,
2440 size_t * offset, int r,
2441 u_char type, size_t length)
2443 return asn_realloc_rbuild_header(pkt, pkt_len, offset, r, type,
2448 asn_realloc_rbuild_objid(u_char ** pkt, size_t * pkt_len,
2449 size_t * offset, int r,
2451 const oid * objid, size_t objidlength)
2454 * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}*
2455 * subidentifier ::= {leadingbyte}* lastbyte
2456 * leadingbyte ::= 1 7bitvalue
2457 * lastbyte ::= 0 7bitvalue
2460 register oid tmpint;
2461 size_t start_offset = *offset;
2462 const char *errpre = "build objid";
2465 * Check if there are at least 2 sub-identifiers.
2467 if (objidlength == 0) {
2469 * There are not, so make OID have two with value of zero.
2471 while ((*pkt_len - *offset) < 2) {
2472 if (!(r && asn_realloc(pkt, pkt_len))) {
2477 *(*pkt + *pkt_len - (++*offset)) = 0;
2478 *(*pkt + *pkt_len - (++*offset)) = 0;
2479 } else if (objid[0] > 2) {
2480 ERROR_MSG("build objid: bad first subidentifier");
2482 } else if (objidlength == 1) {
2484 * Encode the first value.
2486 if (((*pkt_len - *offset) < 1)
2487 && !(r && asn_realloc(pkt, pkt_len))) {
2490 *(*pkt + *pkt_len - (++*offset)) = (u_char) objid[0];
2492 for (i = objidlength; i > 2; i--) {
2493 tmpint = objid[i - 1];
2495 if (((*pkt_len - *offset) < 1)
2496 && !(r && asn_realloc(pkt, pkt_len))) {
2499 *(*pkt + *pkt_len - (++*offset)) = (u_char) tmpint & 0x7f;
2502 while (tmpint > 0) {
2503 if (((*pkt_len - *offset) < 1)
2504 && !(r && asn_realloc(pkt, pkt_len))) {
2507 *(*pkt + *pkt_len - (++*offset)) =
2508 (u_char) ((tmpint & 0x7f) | 0x80);
2514 * Combine the first two values.
2516 if ((objid[1] > 40) &&
2518 ERROR_MSG("build objid: bad second subidentifier");
2521 tmpint = ((objid[0] * 40) + objid[1]);
2522 if (((*pkt_len - *offset) < 1)
2523 && !(r && asn_realloc(pkt, pkt_len))) {
2526 *(*pkt + *pkt_len - (++*offset)) = (u_char) tmpint & 0x7f;
2529 while (tmpint > 0) {
2530 if (((*pkt_len - *offset) < 1)
2531 && !(r && asn_realloc(pkt, pkt_len))) {
2534 *(*pkt + *pkt_len - (++*offset)) =
2535 (u_char) ((tmpint & 0x7f) | 0x80);
2540 tmpint = *offset - start_offset;
2541 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r, type,
2542 (*offset - start_offset))) {
2543 if (_asn_realloc_build_header_check(errpre, pkt, pkt_len,
2544 (*offset - start_offset))) {
2547 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset),
2548 (*offset - start_offset));
2549 DEBUGMSG(("dumpv_send", " ObjID: "));
2550 DEBUGMSGOID(("dumpv_send", objid, objidlength));
2551 DEBUGMSG(("dumpv_send", "\n"));
2560 asn_realloc_rbuild_null(u_char ** pkt, size_t * pkt_len,
2561 size_t * offset, int r, u_char type)
2564 * ASN.1 null ::= 0x05 0x00
2566 size_t start_offset = *offset;
2568 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r, type, 0)) {
2569 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset),
2570 (*offset - start_offset));
2571 DEBUGMSG(("dumpv_send", " NULL\n"));
2579 asn_realloc_rbuild_bitstring(u_char ** pkt, size_t * pkt_len,
2580 size_t * offset, int r,
2582 u_char * string, size_t strlength)
2585 * ASN.1 bit string ::= 0x03 asnlength unused {byte}*
2587 static const char *errpre = "build bitstring";
2588 size_t start_offset = *offset;
2590 while ((*pkt_len - *offset) < strlength) {
2591 if (!(r && asn_realloc(pkt, pkt_len))) {
2596 *offset += strlength;
2597 memcpy(*pkt + *pkt_len - *offset, string, strlength);
2599 if (asn_realloc_rbuild_header
2600 (pkt, pkt_len, offset, r, type, strlength)) {
2601 if (_asn_realloc_build_header_check
2602 (errpre, pkt, pkt_len, strlength)) {
2605 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset),
2606 *offset - start_offset);
2607 DEBUGIF("dumpv_send") {
2608 if (strlength == 0) {
2609 DEBUGMSG(("dumpv_send", " Bitstring: [NULL]\n"));
2611 u_char *buf = (u_char *) malloc(2 * strlength);
2613 (buf != NULL) ? (2 * strlength) : 0, ol = 0;
2615 if (sprint_realloc_asciistring
2616 (&buf, &l, &ol, 1, string, strlength)) {
2617 DEBUGMSG(("dumpv_send", " Bitstring:\t%s\n",
2621 DEBUGMSG(("dumpv_send",
2622 " Bitstring:\t[TRUNCATED]\n"));
2624 DEBUGMSG(("dumpv_send",
2625 " Bitstring:\t%s [TRUNCATED]\n",
2641 #ifdef BRCM_SNMP_SUPPORT
2643 asn_realloc_rbuild_unsigned_int64(u_char ** pkt, size_t * pkt_len,
2644 size_t * offset, int r,
2646 struct counter64 *cp, size_t countersize)
2649 * ASN.1 integer ::= 0x02 asnlength byte {byte}*
2651 register u_long low = cp->low, high = cp->high;
2652 size_t intsize, start_offset = *offset;
2655 if (countersize != sizeof(struct counter64)) {
2656 _asn_size_err("build uint64", countersize,
2657 sizeof(struct counter64));
2662 * Encode the low 4 bytes first.
2664 if (((*pkt_len - *offset) < 1) && !(r && asn_realloc(pkt, pkt_len))) {
2667 *(*pkt + *pkt_len - (++*offset)) = (u_char) low;
2673 if (((*pkt_len - *offset) < 1)
2674 && !(r && asn_realloc(pkt, pkt_len))) {
2677 *(*pkt + *pkt_len - (++*offset)) = (u_char) low;
2682 * Then the high byte if present.
2686 * Do the rest of the low byte.
2688 for (; count < 4; count++) {
2689 if (((*pkt_len - *offset) < 1)
2690 && !(r && asn_realloc(pkt, pkt_len))) {
2693 *(*pkt + *pkt_len - (++*offset)) = 0;
2699 if (((*pkt_len - *offset) < 1)
2700 && !(r && asn_realloc(pkt, pkt_len))) {
2703 *(*pkt + *pkt_len - (++*offset)) = (u_char) high;
2707 if (((*pkt_len - *offset) < 1)
2708 && !(r && asn_realloc(pkt, pkt_len))) {
2711 *(*pkt + *pkt_len - (++*offset)) = (u_char) high;
2716 if ((*(*pkt + *pkt_len - *offset) & 0x80) != (0 & 0x80)) {
2718 * Make sure left most bit is representational of the rest of the bits
2719 * that aren't encoded.
2721 if (((*pkt_len - *offset) < 1)
2722 && !(r && asn_realloc(pkt, pkt_len))) {
2725 *(*pkt + *pkt_len - (++*offset)) = 0;
2728 intsize = *offset - start_offset;
2730 #ifdef OPAQUE_SPECIAL_TYPES
2732 * Encode a Counter64 as an opaque (it also works in SNMPv1).
2734 if (type == ASN_OPAQUE_COUNTER64) {
2735 while ((*pkt_len - *offset) < 5) {
2736 if (!(r && asn_realloc(pkt, pkt_len))) {
2741 *(*pkt + *pkt_len - (++*offset)) = (u_char) intsize;
2742 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_COUNTER64;
2743 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_TAG1;
2746 * Put the tag and length for the Opaque wrapper.
2748 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r,
2749 ASN_OPAQUE, intsize + 3)) {
2750 if (_asn_realloc_build_header_check
2751 ("build counter u64", pkt, pkt_len, intsize + 3)) {
2757 } else if (type == ASN_OPAQUE_U64) {
2759 * Encode the Unsigned int64 in an opaque.
2761 while ((*pkt_len - *offset) < 5) {
2762 if (!(r && asn_realloc(pkt, pkt_len))) {
2767 *(*pkt + *pkt_len - (++*offset)) = (u_char) intsize;
2768 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_U64;
2769 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_TAG1;
2772 * Put the tag and length for the Opaque wrapper.
2774 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r,
2775 ASN_OPAQUE, intsize + 3)) {
2776 if (_asn_realloc_build_header_check
2777 ("build counter u64", pkt, pkt_len, intsize + 3)) {
2785 #endif /* OPAQUE_SPECIAL_TYPES */
2786 if (asn_realloc_rbuild_header
2787 (pkt, pkt_len, offset, r, type, intsize)) {
2788 if (_asn_realloc_build_header_check
2789 ("build uint64", pkt, pkt_len, intsize)) {
2795 #ifdef OPAQUE_SPECIAL_TYPES
2797 #endif /* OPAQUE_SPECIAL_TYPES */
2799 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset), intsize);
2800 DEBUGMSG(("dumpv_send", " U64:\t%lu %lu\n", cp->high, cp->low));
2804 #ifdef OPAQUE_SPECIAL_TYPES
2806 asn_realloc_rbuild_signed_int64(u_char ** pkt, size_t * pkt_len,
2807 size_t * offset, int r,
2809 struct counter64 *cp, size_t countersize)
2812 * ASN.1 integer ::= 0x02 asnlength byte {byte}*
2814 register u_long low = cp->low, high = cp->high;
2815 size_t intsize, start_offset = *offset;
2816 int count, testvalue = (high & 0x80000000) ? -1 : 0;
2818 if (countersize != sizeof(struct counter64)) {
2819 _asn_size_err("build uint64", countersize,
2820 sizeof(struct counter64));
2825 * Encode the low 4 bytes first.
2827 if (((*pkt_len - *offset) < 1) && !(r && asn_realloc(pkt, pkt_len))) {
2830 *(*pkt + *pkt_len - (++*offset)) = (u_char) low;
2834 while ((int) low != testvalue) {
2836 if (((*pkt_len - *offset) < 1)
2837 && !(r && asn_realloc(pkt, pkt_len))) {
2840 *(*pkt + *pkt_len - (++*offset)) = (u_char) low;
2845 * Then the high byte if present.
2849 * Do the rest of the low byte.
2851 for (; count < 4; count++) {
2852 if (((*pkt_len - *offset) < 1)
2853 && !(r && asn_realloc(pkt, pkt_len))) {
2856 *(*pkt + *pkt_len - (++*offset)) = (testvalue == 0) ? 0 : 0xff;
2862 if (((*pkt_len - *offset) < 1)
2863 && !(r && asn_realloc(pkt, pkt_len))) {
2866 *(*pkt + *pkt_len - (++*offset)) = (u_char) high;
2869 while ((int) high != testvalue) {
2870 if (((*pkt_len - *offset) < 1)
2871 && !(r && asn_realloc(pkt, pkt_len))) {
2874 *(*pkt + *pkt_len - (++*offset)) = (u_char) high;
2879 if ((*(*pkt + *pkt_len - *offset) & 0x80) != (0 & 0x80)) {
2881 * Make sure left most bit is representational of the rest of the bits
2882 * that aren't encoded.
2884 if (((*pkt_len - *offset) < 1)
2885 && !(r && asn_realloc(pkt, pkt_len))) {
2888 *(*pkt + *pkt_len - (++*offset)) = (testvalue == 0) ? 0 : 0xff;
2891 intsize = *offset - start_offset;
2893 while ((*pkt_len - *offset) < 5) {
2894 if (!(r && asn_realloc(pkt, pkt_len))) {
2899 *(*pkt + *pkt_len - (++*offset)) = (u_char) intsize;
2900 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_I64;
2901 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_TAG1;
2904 * Put the tag and length for the Opaque wrapper.
2906 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r,
2907 ASN_OPAQUE, intsize + 3)) {
2908 if (_asn_realloc_build_header_check
2909 ("build counter u64", pkt, pkt_len, intsize + 3)) {
2916 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset), intsize);
2917 DEBUGMSG(("dumpv_send", " UInt64:\t%lu %lu\n", cp->high, cp->low));
2922 asn_realloc_rbuild_float(u_char ** pkt, size_t * pkt_len,
2923 size_t * offset, int r,
2924 u_char type, float *floatp, size_t floatsize)
2926 size_t start_offset = *offset;
2930 u_char c[sizeof(float)];
2934 * Floatsize better not be larger than realistic.
2936 if (floatsize != sizeof(float) || floatsize > 122) {
2940 while ((*pkt_len - *offset) < floatsize + 3) {
2941 if (!(r && asn_realloc(pkt, pkt_len))) {
2947 * Correct for endian differences and copy value.
2949 fu.floatVal = *floatp;
2950 fu.intVal = htonl(fu.intVal);
2951 *offset += floatsize;
2952 memcpy(*pkt + *pkt_len - *offset, &(fu.c[0]), floatsize);
2955 * Put the special tag and length (3 bytes).
2957 *(*pkt + *pkt_len - (++*offset)) = (u_char) floatsize;
2958 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_FLOAT;
2959 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_TAG1;
2962 * Put the tag and length for the Opaque wrapper.
2964 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r,
2965 ASN_OPAQUE, floatsize + 3)) {
2966 if (_asn_realloc_build_header_check("build float", pkt, pkt_len,
2970 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset),
2971 *offset - start_offset);
2972 DEBUGMSG(("dumpv_send", "Opaque Float:\t%f\n", *floatp));
2979 #endif /* BRCM_SNMP_SUPPORT */
2982 asn_realloc_rbuild_double(u_char ** pkt, size_t * pkt_len,
2983 size_t * offset, int r,
2984 u_char type, double *doublep, size_t doublesize)
2986 size_t start_offset = *offset;
2991 u_char c[sizeof(double)];
2995 * Doublesize better not be larger than realistic.
2997 if (doublesize != sizeof(double) || doublesize > 122) {
3001 while ((*pkt_len - *offset) < doublesize + 3) {
3002 if (!(r && asn_realloc(pkt, pkt_len))) {
3008 * Correct for endian differences and copy value.
3010 fu.doubleVal = *doublep;
3011 tmp = htonl(fu.intVal[0]);
3012 fu.intVal[0] = htonl(fu.intVal[1]);
3014 *offset += doublesize;
3015 memcpy(*pkt + *pkt_len - *offset, &(fu.c[0]), doublesize);
3018 * Put the special tag and length (3 bytes).
3020 *(*pkt + *pkt_len - (++*offset)) = (u_char) doublesize;
3021 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_DOUBLE;
3022 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_TAG1;
3025 * Put the tag and length for the Opaque wrapper.
3027 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r,
3028 ASN_OPAQUE, doublesize + 3)) {
3029 if (_asn_realloc_build_header_check("build float", pkt, pkt_len,
3033 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset),
3034 *offset - start_offset);
3035 DEBUGMSG(("dumpv_send", " Opaque Double:\t%f\n", *doublep));
3043 #endif /* OPAQUE_SPECIAL_TYPES */
3044 #endif /* USE_REVERSE_ASNENCODING */