00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00156 #include <net-snmp/net-snmp-config.h>
00157
00158 #ifdef KINETICS
00159 #include "gw.h"
00160 #endif
00161
00162 #if HAVE_STRING_H
00163 #include <string.h>
00164 #else
00165 #include <strings.h>
00166 #endif
00167
00168 #include <sys/types.h>
00169 #include <stdio.h>
00170 #ifdef HAVE_STDLIB_H
00171 #include <stdlib.h>
00172 #endif
00173 #if HAVE_WINSOCK_H
00174 #include <winsock.h>
00175 #endif
00176 #if HAVE_NETINET_IN_H
00177 #include <netinet/in.h>
00178 #endif
00179
00180 #ifdef vms
00181 #include <in.h>
00182 #endif
00183
00184 #if HAVE_DMALLOC_H
00185 #include <dmalloc.h>
00186 #endif
00187
00188 #include <net-snmp/output_api.h>
00189 #include <net-snmp/utilities.h>
00190
00191 #include <net-snmp/library/asn1.h>
00192 #include <net-snmp/library/int64.h>
00193 #include <net-snmp/library/mib.h>
00194
00195 #ifndef NULL
00196 #define NULL 0
00197 #endif
00198
00199 #include <net-snmp/library/snmp_api.h>
00200
00201 #ifndef INT32_MAX
00202 # define INT32_MAX 2147483647
00203 #endif
00204
00205 #ifndef INT32_MIN
00206 # define INT32_MIN (0 - INT32_MAX - 1)
00207 #endif
00208
00209
00210 #if SIZEOF_LONG == 4
00211 # define CHECK_OVERFLOW_S(x,y)
00212 # define CHECK_OVERFLOW_U(x,y)
00213 #else
00214 # define CHECK_OVERFLOW_S(x,y) do { int trunc = 0; \
00215 if (x > INT32_MAX) { \
00216 trunc = 1; \
00217 x &= 0xffffffff; \
00218 } else if (x < INT32_MIN) { \
00219 trunc = 1; \
00220 x = 0 - (x & 0xffffffff); \
00221 } \
00222 if (trunc) \
00223 DEBUGMSG(("asn","truncating signed value to 32 bits (%d)\n",y)); \
00224 } while(0)
00225
00226 # define CHECK_OVERFLOW_U(x,y) do { \
00227 if (x > UINT32_MAX) { \
00228 x &= 0xffffffff; \
00229 DEBUGMSG(("asn","truncating unsigned value to 32 bits (%d)\n",y)); \
00230 } \
00231 } while(0)
00232 #endif
00233
00242 static
00243 void
00244 _asn_size_err(const char *str, size_t wrongsize, size_t rightsize)
00245 {
00246 char ebuf[128];
00247
00248 snprintf(ebuf, sizeof(ebuf),
00249 "%s size %lu: s/b %lu", str,
00250 (unsigned long)wrongsize, (unsigned long)rightsize);
00251 ebuf[ sizeof(ebuf)-1 ] = 0;
00252 ERROR_MSG(ebuf);
00253 }
00254
00263 static
00264 void
00265 _asn_length_err(const char *str, size_t wrongsize, size_t rightsize)
00266 {
00267 char ebuf[128];
00268
00269 snprintf(ebuf, sizeof(ebuf),
00270 "%s length %lu too large: exceeds %lu", str,
00271 (unsigned long)wrongsize, (unsigned long)rightsize);
00272 ebuf[ sizeof(ebuf)-1 ] = 0;
00273 ERROR_MSG(ebuf);
00274 }
00275
00288 static
00289 int
00290 _asn_parse_length_check(const char *str,
00291 const u_char * bufp, const u_char * data,
00292 u_long plen, size_t dlen)
00293 {
00294 char ebuf[128];
00295 size_t header_len;
00296
00297 if (bufp == NULL) {
00298
00299
00300
00301 return 1;
00302 }
00303 header_len = bufp - data;
00304 if (plen > 0x7fffffff || header_len > 0x7fffffff ||
00305 ((size_t) plen + header_len) > dlen) {
00306 snprintf(ebuf, sizeof(ebuf),
00307 "%s: message overflow: %d len + %d delta > %d len",
00308 str, (int) plen, (int) header_len, (int) dlen);
00309 ebuf[ sizeof(ebuf)-1 ] = 0;
00310 ERROR_MSG(ebuf);
00311 return 1;
00312 }
00313 return 0;
00314 }
00315
00316
00328 static
00329 int
00330 _asn_build_header_check(const char *str, const u_char * data,
00331 size_t datalen, size_t typedlen)
00332 {
00333 char ebuf[128];
00334
00335 if (data == NULL) {
00336
00337
00338
00339 return 1;
00340 }
00341 if (datalen < typedlen) {
00342 snprintf(ebuf, sizeof(ebuf),
00343 "%s: bad header, length too short: %lu < %lu", str,
00344 (unsigned long)datalen, (unsigned long)typedlen);
00345 ebuf[ sizeof(ebuf)-1 ] = 0;
00346 ERROR_MSG(ebuf);
00347 return 1;
00348 }
00349 return 0;
00350 }
00351
00363 static
00364 int
00365 _asn_realloc_build_header_check(const char *str,
00366 u_char ** pkt,
00367 const size_t * pkt_len, size_t typedlen)
00368 {
00369 char ebuf[128];
00370
00371 if (pkt == NULL || *pkt == NULL) {
00372
00373
00374
00375 return 1;
00376 }
00377
00378 if (*pkt_len < typedlen) {
00379 snprintf(ebuf, sizeof(ebuf),
00380 "%s: bad header, length too short: %lu < %lu", str,
00381 (unsigned long)*pkt_len, (unsigned long)typedlen);
00382 ebuf[ sizeof(ebuf)-1 ] = 0;
00383 ERROR_MSG(ebuf);
00384 return 1;
00385 }
00386 return 0;
00387 }
00388
00398 int
00399 asn_check_packet(u_char * pkt, size_t len)
00400 {
00401 u_long asn_length;
00402
00403 if (len < 2)
00404 return 0;
00405
00406 if (*pkt != (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR))
00407 return -1;
00408
00409 if (*(pkt + 1) & 0x80) {
00410
00411
00412
00413 if ((int) len < (int) (*(pkt + 1) & ~0x80) + 2)
00414 return 0;
00415 asn_parse_length(pkt + 1, &asn_length);
00416 return (asn_length + 2 + (*(pkt + 1) & ~0x80));
00417 } else {
00418
00419
00420
00421 return (*(pkt + 1) + 2);
00422 }
00423 }
00424
00425 static
00426 int
00427 _asn_bitstring_check(const char *str, size_t asn_length, u_char datum)
00428 {
00429 char ebuf[128];
00430
00431 if (asn_length < 1) {
00432 snprintf(ebuf, sizeof(ebuf),
00433 "%s: length %d too small", str, (int) asn_length);
00434 ebuf[ sizeof(ebuf)-1 ] = 0;
00435 ERROR_MSG(ebuf);
00436 return 1;
00437 }
00438
00439
00440
00441
00442
00443
00444
00445 return 0;
00446 }
00447
00469 u_char *
00470 asn_parse_int(u_char * data,
00471 size_t * datalength,
00472 u_char * type, long *intp, size_t intsize)
00473 {
00474
00475
00476
00477 static const char *errpre = "parse int";
00478 register u_char *bufp = data;
00479 u_long asn_length;
00480 register long value = 0;
00481
00482 if (intsize != sizeof(long)) {
00483 _asn_size_err(errpre, intsize, sizeof(long));
00484 return NULL;
00485 }
00486 *type = *bufp++;
00487 bufp = asn_parse_length(bufp, &asn_length);
00488 if (_asn_parse_length_check
00489 (errpre, bufp, data, asn_length, *datalength))
00490 return NULL;
00491
00492 if ((size_t) asn_length > intsize) {
00493 _asn_length_err(errpre, (size_t) asn_length, intsize);
00494 return NULL;
00495 }
00496
00497 *datalength -= (int) asn_length + (bufp - data);
00498 if (*bufp & 0x80)
00499 value = -1;
00500
00501 DEBUGDUMPSETUP("recv", data, bufp - data + asn_length);
00502
00503 while (asn_length--)
00504 value = (value << 8) | *bufp++;
00505
00506 CHECK_OVERFLOW_S(value,1);
00507
00508 DEBUGMSG(("dumpv_recv", " Integer:\t%ld (0x%.2lX)\n", value, value));
00509
00510 *intp = value;
00511 return bufp;
00512 }
00513
00514
00536 u_char *
00537 asn_parse_unsigned_int(u_char * data,
00538 size_t * datalength,
00539 u_char * type, u_long * intp, size_t intsize)
00540 {
00541
00542
00543
00544 static const char *errpre = "parse uint";
00545 register u_char *bufp = data;
00546 u_long asn_length;
00547 register u_long value = 0;
00548
00549 if (intsize != sizeof(long)) {
00550 _asn_size_err(errpre, intsize, sizeof(long));
00551 return NULL;
00552 }
00553 *type = *bufp++;
00554 bufp = asn_parse_length(bufp, &asn_length);
00555 if (_asn_parse_length_check
00556 (errpre, bufp, data, asn_length, *datalength))
00557 return NULL;
00558
00559 if (((int) asn_length > (intsize + 1)) ||
00560 (((int) asn_length == intsize + 1) && *bufp != 0x00)) {
00561 _asn_length_err(errpre, (size_t) asn_length, intsize);
00562 return NULL;
00563 }
00564 *datalength -= (int) asn_length + (bufp - data);
00565 if (*bufp & 0x80)
00566 value = ~value;
00567
00568 DEBUGDUMPSETUP("recv", data, bufp - data + asn_length);
00569
00570 while (asn_length--)
00571 value = (value << 8) | *bufp++;
00572
00573 CHECK_OVERFLOW_U(value,2);
00574
00575 DEBUGMSG(("dumpv_recv", " UInteger:\t%ld (0x%.2lX)\n", value, value));
00576
00577 *intp = value;
00578 return bufp;
00579 }
00580
00581
00605 u_char *
00606 asn_build_int(u_char * data,
00607 size_t * datalength, u_char type, const long *intp, size_t intsize)
00608 {
00609
00610
00611
00612 static const char *errpre = "build int";
00613 register long integer;
00614 register u_long mask;
00615 #ifndef NETSNMP_NO_DEBUGGING
00616 u_char *initdatap = data;
00617 #endif
00618
00619 if (intsize != sizeof(long)) {
00620 _asn_size_err(errpre, intsize, sizeof(long));
00621 return NULL;
00622 }
00623 integer = *intp;
00624 CHECK_OVERFLOW_S(integer,3);
00625
00626
00627
00628
00629
00630
00631 mask = ((u_long) 0x1FF) << ((8 * (sizeof(long) - 1)) - 1);
00632
00633
00634
00635 while ((((integer & mask) == 0) || ((integer & mask) == mask))
00636 && intsize > 1) {
00637 intsize--;
00638 integer <<= 8;
00639 }
00640 data = asn_build_header(data, datalength, type, intsize);
00641 if (_asn_build_header_check(errpre, data, *datalength, intsize))
00642 return NULL;
00643
00644 *datalength -= intsize;
00645 mask = ((u_long) 0xFF) << (8 * (sizeof(long) - 1));
00646
00647
00648
00649 while (intsize--) {
00650 *data++ = (u_char) ((integer & mask) >> (8 * (sizeof(long) - 1)));
00651 integer <<= 8;
00652 }
00653 DEBUGDUMPSETUP("send", initdatap, data - initdatap);
00654 DEBUGMSG(("dumpv_send", " Integer:\t%ld (0x%.2lX)\n", *intp, *intp));
00655 return data;
00656 }
00657
00658
00659
00683 u_char *
00684 asn_build_unsigned_int(u_char * data,
00685 size_t * datalength,
00686 u_char type, const u_long * intp, size_t intsize)
00687 {
00688
00689
00690
00691 static const char *errpre = "build uint";
00692 register u_long integer;
00693 register u_long mask;
00694 int add_null_byte = 0;
00695 #ifndef NETSNMP_NO_DEBUGGING
00696 u_char *initdatap = data;
00697 #endif
00698
00699 if (intsize != sizeof(long)) {
00700 _asn_size_err(errpre, intsize, sizeof(long));
00701 return NULL;
00702 }
00703 integer = *intp;
00704 CHECK_OVERFLOW_U(integer,4);
00705
00706 mask = ((u_long) 0xFF) << (8 * (sizeof(long) - 1));
00707
00708
00709
00710 if ((u_char) ((integer & mask) >> (8 * (sizeof(long) - 1))) & 0x80) {
00711
00712
00713
00714 add_null_byte = 1;
00715 intsize++;
00716 } else {
00717
00718
00719
00720
00721
00722 mask = ((u_long) 0x1FF) << ((8 * (sizeof(long) - 1)) - 1);
00723
00724
00725
00726 while ((((integer & mask) == 0) || ((integer & mask) == mask))
00727 && intsize > 1) {
00728 intsize--;
00729 integer <<= 8;
00730 }
00731 }
00732 data = asn_build_header(data, datalength, type, intsize);
00733 if (_asn_build_header_check(errpre, data, *datalength, intsize))
00734 return NULL;
00735
00736 *datalength -= intsize;
00737 if (add_null_byte == 1) {
00738 *data++ = '\0';
00739 intsize--;
00740 }
00741 mask = ((u_long) 0xFF) << (8 * (sizeof(long) - 1));
00742
00743
00744
00745 while (intsize--) {
00746 *data++ = (u_char) ((integer & mask) >> (8 * (sizeof(long) - 1)));
00747 integer <<= 8;
00748 }
00749 DEBUGDUMPSETUP("send", initdatap, data - initdatap);
00750 DEBUGMSG(("dumpv_send", " UInteger:\t%ld (0x%.2lX)\n", *intp, *intp));
00751 return data;
00752 }
00753
00754
00783 u_char *
00784 asn_parse_string(u_char * data,
00785 size_t * datalength,
00786 u_char * type, u_char * str, size_t * strlength)
00787 {
00788 static const char *errpre = "parse string";
00789 u_char *bufp = data;
00790 u_long asn_length;
00791
00792 *type = *bufp++;
00793 bufp = asn_parse_length(bufp, &asn_length);
00794 if (_asn_parse_length_check
00795 (errpre, bufp, data, asn_length, *datalength)) {
00796 return NULL;
00797 }
00798
00799 if ((int) asn_length > *strlength) {
00800 _asn_length_err(errpre, (size_t) asn_length, *strlength);
00801 return NULL;
00802 }
00803
00804 DEBUGDUMPSETUP("recv", data, bufp - data + asn_length);
00805
00806 memmove(str, bufp, asn_length);
00807 if (*strlength > (int) asn_length)
00808 str[asn_length] = 0;
00809 *strlength = (int) asn_length;
00810 *datalength -= (int) asn_length + (bufp - data);
00811
00812 DEBUGIF("dumpv_recv") {
00813 u_char *buf = (u_char *) malloc(1 + asn_length);
00814 size_t l = (buf != NULL) ? (1 + asn_length) : 0, ol = 0;
00815
00816 if (sprint_realloc_asciistring
00817 (&buf, &l, &ol, 1, str, asn_length)) {
00818 DEBUGMSG(("dumpv_recv", " String:\t%s\n", buf));
00819 } else {
00820 if (buf == NULL) {
00821 DEBUGMSG(("dumpv_recv", " String:\t[TRUNCATED]\n"));
00822 } else {
00823 DEBUGMSG(("dumpv_recv", " String:\t%s [TRUNCATED]\n",
00824 buf));
00825 }
00826 }
00827 if (buf != NULL) {
00828 free(buf);
00829 }
00830 }
00831
00832 return bufp + asn_length;
00833 }
00834
00835
00858 u_char *
00859 asn_build_string(u_char * data,
00860 size_t * datalength,
00861 u_char type, const u_char * str, size_t strlength)
00862 {
00863
00864
00865
00866
00867
00868
00869 #ifndef NETSNMP_NO_DEBUGGING
00870 u_char *initdatap = data;
00871 #endif
00872 data = asn_build_header(data, datalength, type, strlength);
00873 if (_asn_build_header_check
00874 ("build string", data, *datalength, strlength))
00875 return NULL;
00876
00877 if (strlength) {
00878 if (str == NULL) {
00879 memset(data, 0, strlength);
00880 } else {
00881 memmove(data, str, strlength);
00882 }
00883 }
00884 *datalength -= strlength;
00885 DEBUGDUMPSETUP("send", initdatap, data - initdatap + strlength);
00886 DEBUGIF("dumpv_send") {
00887 u_char *buf = (u_char *) malloc(1 + strlength);
00888 size_t l = (buf != NULL) ? (1 + strlength) : 0, ol = 0;
00889
00890 if (sprint_realloc_asciistring
00891 (&buf, &l, &ol, 1, str, strlength)) {
00892 DEBUGMSG(("dumpv_send", " String:\t%s\n", buf));
00893 } else {
00894 if (buf == NULL) {
00895 DEBUGMSG(("dumpv_send", " String:\t[TRUNCATED]\n"));
00896 } else {
00897 DEBUGMSG(("dumpv_send", " String:\t%s [TRUNCATED]\n",
00898 buf));
00899 }
00900 }
00901 if (buf != NULL) {
00902 free(buf);
00903 }
00904 }
00905 return data + strlength;
00906 }
00907
00908
00909
00929 u_char *
00930 asn_parse_header(u_char * data, size_t * datalength, u_char * type)
00931 {
00932 register u_char *bufp;
00933 u_long asn_length;
00934
00935 if (!data || !datalength || !type) {
00936 ERROR_MSG("parse header: NULL pointer");
00937 return NULL;
00938 }
00939 bufp = data;
00940
00941
00942
00943 if (IS_EXTENSION_ID(*bufp)) {
00944 ERROR_MSG("can't process ID >= 30");
00945 return NULL;
00946 }
00947 *type = *bufp;
00948 bufp = asn_parse_length(bufp + 1, &asn_length);
00949
00950 if (_asn_parse_length_check
00951 ("parse header", bufp, data, asn_length, *datalength))
00952 return NULL;
00953
00954 #ifdef DUMP_PRINT_HEADERS
00955 DEBUGDUMPSETUP("recv", data, (bufp - data));
00956 DEBUGMSG(("dumpv_recv", " Header: 0x%.2X, len = %d (0x%X)\n", *data,
00957 asn_length, asn_length));
00958 #else
00959
00960
00961
00962
00963 #endif
00964
00965 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
00966
00967 if ((*type == ASN_OPAQUE) && (*bufp == ASN_OPAQUE_TAG1)) {
00968
00969
00970
00971
00972 switch (*(bufp + 1)) {
00973 case ASN_OPAQUE_COUNTER64:
00974 case ASN_OPAQUE_U64:
00975 case ASN_OPAQUE_FLOAT:
00976 case ASN_OPAQUE_DOUBLE:
00977 case ASN_OPAQUE_I64:
00978 *type = *(bufp + 1);
00979 break;
00980
00981 default:
00982
00983
00984
00985 *datalength = (int) asn_length;
00986 return bufp;
00987 }
00988
00989
00990
00991 bufp = asn_parse_length(bufp + 2, &asn_length);
00992 if (_asn_parse_length_check("parse opaque header", bufp, data,
00993 asn_length, *datalength))
00994 return NULL;
00995 }
00996 #endif
00997
00998 *datalength = (int) asn_length;
00999
01000 return bufp;
01001 }
01002
01017 u_char *
01018 asn_parse_sequence(u_char * data, size_t * datalength, u_char * type, u_char expected_type,
01019 const char *estr)
01020 {
01021 data = asn_parse_header(data, datalength, type);
01022 if (data && (*type != expected_type)) {
01023 char ebuf[128];
01024 snprintf(ebuf, sizeof(ebuf),
01025 "%s header type %02X: s/b %02X", estr,
01026 (u_char) * type, (u_char) expected_type);
01027 ebuf[ sizeof(ebuf)-1 ] = 0;
01028 ERROR_MSG(ebuf);
01029 return NULL;
01030 }
01031 return data;
01032 }
01033
01034
01035
01058 u_char *
01059 asn_build_header(u_char * data,
01060 size_t * datalength, u_char type, size_t length)
01061 {
01062 char ebuf[128];
01063
01064 if (*datalength < 1) {
01065 snprintf(ebuf, sizeof(ebuf),
01066 "bad header length < 1 :%lu, %lu",
01067 (unsigned long)*datalength, (unsigned long)length);
01068 ebuf[ sizeof(ebuf)-1 ] = 0;
01069 ERROR_MSG(ebuf);
01070 return NULL;
01071 }
01072 *data++ = type;
01073 (*datalength)--;
01074 return asn_build_length(data, datalength, length);
01075 }
01076
01100 u_char *
01101 asn_build_sequence(u_char * data,
01102 size_t * datalength, u_char type, size_t length)
01103 {
01104 static const char *errpre = "build seq";
01105 char ebuf[128];
01106
01107 if (*datalength < 4) {
01108 snprintf(ebuf, sizeof(ebuf),
01109 "%s: length %d < 4: PUNT", errpre,
01110 (int) *datalength);
01111 ebuf[ sizeof(ebuf)-1 ] = 0;
01112 ERROR_MSG(ebuf);
01113 return NULL;
01114 }
01115 *datalength -= 4;
01116 *data++ = type;
01117 *data++ = (u_char) (0x02 | ASN_LONG_LEN);
01118 *data++ = (u_char) ((length >> 8) & 0xFF);
01119 *data++ = (u_char) (length & 0xFF);
01120 return data;
01121 }
01122
01140 u_char *
01141 asn_parse_length(u_char * data, u_long * length)
01142 {
01143 static const char *errpre = "parse length";
01144 char ebuf[128];
01145 register u_char lengthbyte;
01146
01147 if (!data || !length) {
01148 ERROR_MSG("parse length: NULL pointer");
01149 return NULL;
01150 }
01151 lengthbyte = *data;
01152
01153 if (lengthbyte & ASN_LONG_LEN) {
01154 lengthbyte &= ~ASN_LONG_LEN;
01155 if (lengthbyte == 0) {
01156 snprintf(ebuf, sizeof(ebuf),
01157 "%s: indefinite length not supported", errpre);
01158 ebuf[ sizeof(ebuf)-1 ] = 0;
01159 ERROR_MSG(ebuf);
01160 return NULL;
01161 }
01162 if (lengthbyte > sizeof(long)) {
01163 snprintf(ebuf, sizeof(ebuf),
01164 "%s: data length %d > %lu not supported", errpre,
01165 lengthbyte, (unsigned long)sizeof(long));
01166 ebuf[ sizeof(ebuf)-1 ] = 0;
01167 ERROR_MSG(ebuf);
01168 return NULL;
01169 }
01170 data++;
01171 *length = 0;
01172 while (lengthbyte--) {
01173 *length <<= 8;
01174 *length |= *data++;
01175 }
01176 if ((long) *length < 0) {
01177 snprintf(ebuf, sizeof(ebuf),
01178 "%s: negative data length %ld\n", errpre,
01179 (long) *length);
01180 ebuf[ sizeof(ebuf)-1 ] = 0;
01181 ERROR_MSG(ebuf);
01182 return NULL;
01183 }
01184 return data;
01185 } else {
01186 *length = (long) lengthbyte;
01187 return data + 1;
01188 }
01189 }
01190
01211 u_char *
01212 asn_build_length(u_char * data, size_t * datalength, size_t length)
01213 {
01214 static const char *errpre = "build length";
01215 char ebuf[128];
01216
01217 u_char *start_data = data;
01218
01219
01220
01221
01222 if (length < 0x80) {
01223 if (*datalength < 1) {
01224 snprintf(ebuf, sizeof(ebuf),
01225 "%s: bad length < 1 :%lu, %lu", errpre,
01226 (unsigned long)*datalength, (unsigned long)length);
01227 ebuf[ sizeof(ebuf)-1 ] = 0;
01228 ERROR_MSG(ebuf);
01229 return NULL;
01230 }
01231 *data++ = (u_char) length;
01232 } else if (length <= 0xFF) {
01233 if (*datalength < 2) {
01234 snprintf(ebuf, sizeof(ebuf),
01235 "%s: bad length < 2 :%lu, %lu", errpre,
01236 (unsigned long)*datalength, (unsigned long)length);
01237 ebuf[ sizeof(ebuf)-1 ] = 0;
01238 ERROR_MSG(ebuf);
01239 return NULL;
01240 }
01241 *data++ = (u_char) (0x01 | ASN_LONG_LEN);
01242 *data++ = (u_char) length;
01243 } else {
01244 if (*datalength < 3) {
01245 snprintf(ebuf, sizeof(ebuf),
01246 "%s: bad length < 3 :%lu, %lu", errpre,
01247 (unsigned long)*datalength, (unsigned long)length);
01248 ebuf[ sizeof(ebuf)-1 ] = 0;
01249 ERROR_MSG(ebuf);
01250 return NULL;
01251 }
01252 *data++ = (u_char) (0x02 | ASN_LONG_LEN);
01253 *data++ = (u_char) ((length >> 8) & 0xFF);
01254 *data++ = (u_char) (length & 0xFF);
01255 }
01256 *datalength -= (data - start_data);
01257 return data;
01258
01259 }
01260
01286 u_char *
01287 asn_parse_objid(u_char * data,
01288 size_t * datalength,
01289 u_char * type, oid * objid, size_t * objidlength)
01290 {
01291
01292
01293
01294
01295
01296
01297 register u_char *bufp = data;
01298 register oid *oidp = objid + 1;
01299 register u_long subidentifier;
01300 register long length;
01301 u_long asn_length;
01302 size_t original_length = *objidlength;
01303
01304 *type = *bufp++;
01305 bufp = asn_parse_length(bufp, &asn_length);
01306 if (_asn_parse_length_check("parse objid", bufp, data,
01307 asn_length, *datalength))
01308 return NULL;
01309
01310 *datalength -= (int) asn_length + (bufp - data);
01311
01312 DEBUGDUMPSETUP("recv", data, bufp - data + asn_length);
01313
01314
01315
01316
01317 if (asn_length == 0)
01318 objid[0] = objid[1] = 0;
01319
01320 length = asn_length;
01321 (*objidlength)--;
01322
01323 while (length > 0 && (*objidlength)-- > 0) {
01324 subidentifier = 0;
01325 do {
01326 subidentifier =
01327 (subidentifier << 7) + (*(u_char *) bufp & ~ASN_BIT8);
01328 length--;
01329 } while ((*(u_char *) bufp++ & ASN_BIT8) && (length > 0));
01330
01331 if (length == 0) {
01332 u_char *last_byte = bufp - 1;
01333 if (*last_byte & ASN_BIT8) {
01334
01335 ERROR_MSG("subidentifier syntax error");
01336 return NULL;
01337 }
01338 }
01339 #if defined(EIGHTBIT_SUBIDS) || (SIZEOF_LONG != 4)
01340 if (subidentifier > (u_long) MAX_SUBID) {
01341 ERROR_MSG("subidentifier too large");
01342 return NULL;
01343 }
01344 #endif
01345 *oidp++ = (oid) subidentifier;
01346 }
01347
01348 if (0 != length) {
01349 ERROR_MSG("OID length exceeds buffer size");
01350 *objidlength = original_length;
01351 return NULL;
01352 }
01353
01354
01355
01356
01357
01358
01359
01360 subidentifier = (u_long) objid[1];
01361 if (subidentifier == 0x2B) {
01362 objid[0] = 1;
01363 objid[1] = 3;
01364 } else {
01365 if (subidentifier < 40) {
01366 objid[0] = 0;
01367 objid[1] = subidentifier;
01368 } else if (subidentifier < 80) {
01369 objid[0] = 1;
01370 objid[1] = subidentifier - 40;
01371 } else {
01372 objid[0] = 2;
01373 objid[1] = subidentifier - 80;
01374 }
01375 }
01376
01377 *objidlength = (int) (oidp - objid);
01378
01379 DEBUGMSG(("dumpv_recv", " ObjID: "));
01380 DEBUGMSGOID(("dumpv_recv", objid, *objidlength));
01381 DEBUGMSG(("dumpv_recv", "\n"));
01382 return bufp;
01383 }
01384
01408 u_char *
01409 asn_build_objid(u_char * data,
01410 size_t * datalength,
01411 u_char type, oid * objid, size_t objidlength)
01412 {
01413
01414
01415
01416
01417
01418
01419 size_t asnlength;
01420 register oid *op = objid;
01421 u_char objid_size[MAX_OID_LEN];
01422 register u_long objid_val;
01423 u_long first_objid_val;
01424 register int i;
01425 #ifndef NETSNMP_NO_DEBUGGING
01426 u_char *initdatap = data;
01427 #endif
01428
01429
01430
01431
01432 if (objidlength == 0) {
01433
01434
01435
01436 objid_val = 0;
01437 objidlength = 2;
01438 } else if (objid[0] > 2) {
01439 ERROR_MSG("build objid: bad first subidentifier");
01440 return NULL;
01441 } else if (objidlength == 1) {
01442
01443
01444
01445 objid_val = (op[0] * 40);
01446 objidlength = 2;
01447 op++;
01448 } else {
01449
01450
01451
01452 if ((op[1] > 40) &&
01453 (op[0] < 2)) {
01454 ERROR_MSG("build objid: bad second subidentifier");
01455 return NULL;
01456 }
01457 objid_val = (op[0] * 40) + op[1];
01458 op += 2;
01459 }
01460 first_objid_val = objid_val;
01461
01462
01463
01464
01465 if (objidlength > MAX_OID_LEN)
01466 return NULL;
01467
01468
01469
01470
01471 for (i = 1, asnlength = 0;;) {
01472
01473 CHECK_OVERFLOW_U(objid_val,5);
01474 if (objid_val < (unsigned) 0x80) {
01475 objid_size[i] = 1;
01476 asnlength += 1;
01477 } else if (objid_val < (unsigned) 0x4000) {
01478 objid_size[i] = 2;
01479 asnlength += 2;
01480 } else if (objid_val < (unsigned) 0x200000) {
01481 objid_size[i] = 3;
01482 asnlength += 3;
01483 } else if (objid_val < (unsigned) 0x10000000) {
01484 objid_size[i] = 4;
01485 asnlength += 4;
01486 } else {
01487 objid_size[i] = 5;
01488 asnlength += 5;
01489 }
01490 i++;
01491 if (i >= (int) objidlength)
01492 break;
01493 objid_val = *op++;
01494 }
01495
01496
01497
01498
01499 data = asn_build_header(data, datalength, type, asnlength);
01500 if (_asn_build_header_check
01501 ("build objid", data, *datalength, asnlength))
01502 return NULL;
01503
01504
01505
01506
01507 for (i = 1, objid_val = first_objid_val, op = objid + 2;
01508 i < (int) objidlength; i++) {
01509 if (i != 1) {
01510 objid_val = *op++;
01511 #if SIZEOF_LONG != 4
01512 if (objid_val > 0xffffffff)
01513 objid_val &= 0xffffffff;
01514 #endif
01515 }
01516 switch (objid_size[i]) {
01517 case 1:
01518 *data++ = (u_char) objid_val;
01519 break;
01520
01521 case 2:
01522 *data++ = (u_char) ((objid_val >> 7) | 0x80);
01523 *data++ = (u_char) (objid_val & 0x07f);
01524 break;
01525
01526 case 3:
01527 *data++ = (u_char) ((objid_val >> 14) | 0x80);
01528 *data++ = (u_char) ((objid_val >> 7 & 0x7f) | 0x80);
01529 *data++ = (u_char) (objid_val & 0x07f);
01530 break;
01531
01532 case 4:
01533 *data++ = (u_char) ((objid_val >> 21) | 0x80);
01534 *data++ = (u_char) ((objid_val >> 14 & 0x7f) | 0x80);
01535 *data++ = (u_char) ((objid_val >> 7 & 0x7f) | 0x80);
01536 *data++ = (u_char) (objid_val & 0x07f);
01537 break;
01538
01539 case 5:
01540 *data++ = (u_char) ((objid_val >> 28) | 0x80);
01541 *data++ = (u_char) ((objid_val >> 21 & 0x7f) | 0x80);
01542 *data++ = (u_char) ((objid_val >> 14 & 0x7f) | 0x80);
01543 *data++ = (u_char) ((objid_val >> 7 & 0x7f) | 0x80);
01544 *data++ = (u_char) (objid_val & 0x07f);
01545 break;
01546 }
01547 }
01548
01549
01550
01551
01552 *datalength -= asnlength;
01553 DEBUGDUMPSETUP("send", initdatap, data - initdatap);
01554 DEBUGMSG(("dumpv_send", " ObjID: "));
01555 DEBUGMSGOID(("dumpv_send", objid, objidlength));
01556 DEBUGMSG(("dumpv_send", "\n"));
01557 return data;
01558 }
01559
01579 u_char *
01580 asn_parse_null(u_char * data, size_t * datalength, u_char * type)
01581 {
01582
01583
01584
01585 register u_char *bufp = data;
01586 u_long asn_length;
01587
01588 *type = *bufp++;
01589 bufp = asn_parse_length(bufp, &asn_length);
01590 if (bufp == NULL) {
01591 ERROR_MSG("parse null: bad length");
01592 return NULL;
01593 }
01594 if (asn_length != 0) {
01595 ERROR_MSG("parse null: malformed ASN.1 null");
01596 return NULL;
01597 }
01598
01599 *datalength -= (bufp - data);
01600
01601 DEBUGDUMPSETUP("recv", data, bufp - data);
01602 DEBUGMSG(("dumpv_recv", " NULL\n"));
01603
01604 return bufp + asn_length;
01605 }
01606
01607
01628 u_char *
01629 asn_build_null(u_char * data, size_t * datalength, u_char type)
01630 {
01631
01632
01633
01634 #ifndef NETSNMP_NO_DEBUGGING
01635 u_char *initdatap = data;
01636 #endif
01637 data = asn_build_header(data, datalength, type, 0);
01638 DEBUGDUMPSETUP("send", initdatap, data - initdatap);
01639 DEBUGMSG(("dumpv_send", " NULL\n"));
01640 return data;
01641 }
01642
01666 u_char *
01667 asn_parse_bitstring(u_char * data,
01668 size_t * datalength,
01669 u_char * type, u_char * str, size_t * strlength)
01670 {
01671
01672
01673
01674 static const char *errpre = "parse bitstring";
01675 register u_char *bufp = data;
01676 u_long asn_length;
01677
01678 *type = *bufp++;
01679 bufp = asn_parse_length(bufp, &asn_length);
01680 if (_asn_parse_length_check(errpre, bufp, data,
01681 asn_length, *datalength))
01682 return NULL;
01683
01684 if ((size_t) asn_length > *strlength) {
01685 _asn_length_err(errpre, (size_t) asn_length, *strlength);
01686 return NULL;
01687 }
01688 if (_asn_bitstring_check(errpre, asn_length, *bufp))
01689 return NULL;
01690
01691 DEBUGDUMPSETUP("recv", data, bufp - data);
01692 DEBUGMSG(("dumpv_recv", " Bitstring: "));
01693 DEBUGMSGHEX(("dumpv_recv", data, asn_length));
01694 DEBUGMSG(("dumpv_recv", "\n"));
01695
01696 memmove(str, bufp, asn_length);
01697 *strlength = (int) asn_length;
01698 *datalength -= (int) asn_length + (bufp - data);
01699 return bufp + asn_length;
01700 }
01701
01702
01725 u_char *
01726 asn_build_bitstring(u_char * data,
01727 size_t * datalength,
01728 u_char type, const u_char * str, size_t strlength)
01729 {
01730
01731
01732
01733 static const char *errpre = "build bitstring";
01734 if (_asn_bitstring_check
01735 (errpre, strlength, (u_char)((str) ? *str : 0)))
01736 return NULL;
01737
01738 data = asn_build_header(data, datalength, type, strlength);
01739 if (_asn_build_header_check(errpre, data, *datalength, strlength))
01740 return NULL;
01741
01742 if (strlength > 0 && str)
01743 memmove(data, str, strlength);
01744 else if (strlength > 0 && !str) {
01745 ERROR_MSG("no string passed into asn_build_bitstring\n");
01746 return NULL;
01747 }
01748
01749 *datalength -= strlength;
01750 DEBUGDUMPSETUP("send", data, strlength);
01751 DEBUGMSG(("dumpv_send", " Bitstring: "));
01752 DEBUGMSGHEX(("dumpv_send", data, strlength));
01753 DEBUGMSG(("dumpv_send", "\n"));
01754 return data + strlength;
01755 }
01756
01779 u_char *
01780 asn_parse_unsigned_int64(u_char * data,
01781 size_t * datalength,
01782 u_char * type,
01783 struct counter64 * cp, size_t countersize)
01784 {
01785
01786
01787
01788 static const char *errpre = "parse uint64";
01789 const int uint64sizelimit = (4 * 2) + 1;
01790 register u_char *bufp = data;
01791 u_long asn_length;
01792 register u_long low = 0, high = 0;
01793
01794 if (countersize != sizeof(struct counter64)) {
01795 _asn_size_err(errpre, countersize, sizeof(struct counter64));
01796 return NULL;
01797 }
01798 *type = *bufp++;
01799 bufp = asn_parse_length(bufp, &asn_length);
01800 if (_asn_parse_length_check
01801 (errpre, bufp, data, asn_length, *datalength))
01802 return NULL;
01803
01804 DEBUGDUMPSETUP("recv", data, bufp - data);
01805 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
01806
01807
01808
01809 if ((*type == ASN_OPAQUE) &&
01810 (asn_length <= ASN_OPAQUE_COUNTER64_MX_BER_LEN) &&
01811 (*bufp == ASN_OPAQUE_TAG1) &&
01812 ((*(bufp + 1) == ASN_OPAQUE_COUNTER64) ||
01813 (*(bufp + 1) == ASN_OPAQUE_U64))) {
01814
01815
01816
01817 *type = *(bufp + 1);
01818
01819
01820
01821 bufp = asn_parse_length(bufp + 2, &asn_length);
01822 if (_asn_parse_length_check("parse opaque uint64", bufp, data,
01823 asn_length, *datalength))
01824 return NULL;
01825 }
01826 #endif
01827 if (((int) asn_length > uint64sizelimit) ||
01828 (((int) asn_length == uint64sizelimit) && *bufp != 0x00)) {
01829 _asn_length_err(errpre, (size_t) asn_length, uint64sizelimit);
01830 return NULL;
01831 }
01832 *datalength -= (int) asn_length + (bufp - data);
01833 if (*bufp & 0x80) {
01834 low = 0xFFFFFF;
01835 high = 0xFFFFFF;
01836 }
01837
01838 while (asn_length--) {
01839 high = ((0x00FFFFFF & high) << 8) | ((low & 0xFF000000) >> 24);
01840 low = ((low & 0x00FFFFFF) << 8) | *bufp++;
01841 }
01842
01843 CHECK_OVERFLOW_U(high,6);
01844 CHECK_OVERFLOW_U(low,6);
01845
01846 cp->low = low;
01847 cp->high = high;
01848
01849 DEBUGIF("dumpv_recv") {
01850 char i64buf[I64CHARSZ + 1];
01851 printU64(i64buf, cp);
01852 DEBUGMSG(("dumpv_recv", "Counter64: %s", i64buf));
01853 }
01854
01855 return bufp;
01856 }
01857
01858
01880 u_char *
01881 asn_build_unsigned_int64(u_char * data,
01882 size_t * datalength,
01883 u_char type,
01884 const struct counter64 * cp, size_t countersize)
01885 {
01886
01887
01888
01889
01890 register u_long low, high;
01891 register u_long mask, mask2;
01892 int add_null_byte = 0;
01893 size_t intsize;
01894 #ifndef NETSNMP_NO_DEBUGGING
01895 u_char *initdatap = data;
01896 #endif
01897
01898 if (countersize != sizeof(struct counter64)) {
01899 _asn_size_err("build uint64", countersize,
01900 sizeof(struct counter64));
01901 return NULL;
01902 }
01903 intsize = 8;
01904 low = cp->low;
01905 high = cp->high;
01906
01907 CHECK_OVERFLOW_U(high,7);
01908 CHECK_OVERFLOW_U(low,7);
01909
01910 mask = ((u_long) 0xFF) << (8 * (sizeof(long) - 1));
01911
01912
01913
01914 if ((u_char) ((high & mask) >> (8 * (sizeof(long) - 1))) & 0x80) {
01915
01916
01917
01918 add_null_byte = 1;
01919 intsize++;
01920 } else {
01921
01922
01923
01924
01925
01926
01927 mask2 = ((u_long) 0x1FF) << ((8 * (sizeof(long) - 1)) - 1);
01928
01929
01930
01931 while ((((high & mask2) == 0) || ((high & mask2) == mask2))
01932 && intsize > 1) {
01933 intsize--;
01934 high = (high << 8)
01935 | ((low & mask) >> (8 * (sizeof(long) - 1)));
01936 low <<= 8;
01937 }
01938 }
01939 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
01940
01941
01942
01943
01944
01945
01946 if (type == ASN_OPAQUE_COUNTER64) {
01947
01948
01949
01950 data = asn_build_header(data, datalength, ASN_OPAQUE, intsize + 3);
01951 if (_asn_build_header_check
01952 ("build counter u64", data, *datalength, intsize + 3))
01953 return NULL;
01954
01955
01956
01957
01958 *data++ = ASN_OPAQUE_TAG1;
01959 *data++ = ASN_OPAQUE_COUNTER64;
01960 *data++ = (u_char) intsize;
01961 *datalength = *datalength - 3;
01962 } else
01963
01964
01965
01966
01967
01968
01969 if (type == ASN_OPAQUE_U64) {
01970
01971
01972
01973 data = asn_build_header(data, datalength, ASN_OPAQUE, intsize + 3);
01974 if (_asn_build_header_check
01975 ("build opaque u64", data, *datalength, intsize + 3))
01976 return NULL;
01977
01978
01979
01980
01981 *data++ = ASN_OPAQUE_TAG1;
01982 *data++ = ASN_OPAQUE_U64;
01983 *data++ = (u_char) intsize;
01984 *datalength = *datalength - 3;
01985 } else {
01986 #endif
01987 data = asn_build_header(data, datalength, type, intsize);
01988 if (_asn_build_header_check
01989 ("build uint64", data, *datalength, intsize))
01990 return NULL;
01991
01992 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
01993 }
01994 #endif
01995 *datalength -= intsize;
01996 if (add_null_byte == 1) {
01997 *data++ = '\0';
01998 intsize--;
01999 }
02000 while (intsize--) {
02001 *data++ = (u_char) ((high & mask) >> (8 * (sizeof(long) - 1)));
02002 high = (high << 8)
02003 | ((low & mask) >> (8 * (sizeof(long) - 1)));
02004 low <<= 8;
02005
02006 }
02007 DEBUGDUMPSETUP("send", initdatap, data - initdatap);
02008 DEBUGIF("dumpv_send") {
02009 char i64buf[I64CHARSZ + 1];
02010 printU64(i64buf, cp);
02011 DEBUGMSG(("dumpv_send", "%s", i64buf));
02012 }
02013 return data;
02014 }
02015
02016 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
02017
02018
02042 u_char *
02043 asn_parse_signed_int64(u_char * data,
02044 size_t * datalength,
02045 u_char * type,
02046 struct counter64 * cp, size_t countersize)
02047 {
02048 static const char *errpre = "parse int64";
02049 const int int64sizelimit = (4 * 2) + 1;
02050 char ebuf[128];
02051 register u_char *bufp = data;
02052 u_long asn_length;
02053 register u_int low = 0, high = 0;
02054
02055 if (countersize != sizeof(struct counter64)) {
02056 _asn_size_err(errpre, countersize, sizeof(struct counter64));
02057 return NULL;
02058 }
02059 *type = *bufp++;
02060 bufp = asn_parse_length(bufp, &asn_length);
02061 if (_asn_parse_length_check
02062 (errpre, bufp, data, asn_length, *datalength))
02063 return NULL;
02064
02065 DEBUGDUMPSETUP("recv", data, bufp - data);
02066 if ((*type == ASN_OPAQUE) &&
02067 (asn_length <= ASN_OPAQUE_COUNTER64_MX_BER_LEN) &&
02068 (*bufp == ASN_OPAQUE_TAG1) && (*(bufp + 1) == ASN_OPAQUE_I64)) {
02069
02070
02071
02072 *type = *(bufp + 1);
02073
02074
02075
02076 bufp = asn_parse_length(bufp + 2, &asn_length);
02077 if (_asn_parse_length_check("parse opaque int64", bufp, data,
02078 asn_length, *datalength))
02079 return NULL;
02080 }
02081
02082
02083
02084 else {
02085 snprintf(ebuf, sizeof(ebuf),
02086 "%s: wrong type: %d, len %d, buf bytes (%02X,%02X)",
02087 errpre, *type, (int) asn_length, *bufp, *(bufp + 1));
02088 ebuf[ sizeof(ebuf)-1 ] = 0;
02089 ERROR_MSG(ebuf);
02090 return NULL;
02091 }
02092 if (((int) asn_length > int64sizelimit) ||
02093 (((int) asn_length == int64sizelimit) && *bufp != 0x00)) {
02094 _asn_length_err(errpre, (size_t) asn_length, int64sizelimit);
02095 return NULL;
02096 }
02097 *datalength -= (int) asn_length + (bufp - data);
02098 if (*bufp & 0x80) {
02099 low = 0xFFFFFF;
02100 high = 0xFFFFFF;
02101 }
02102
02103 while (asn_length--) {
02104 high = ((0x00FFFFFF & high) << 8) | ((low & 0xFF000000) >> 24);
02105 low = ((low & 0x00FFFFFF) << 8) | *bufp++;
02106 }
02107
02108 CHECK_OVERFLOW_U(high,8);
02109 CHECK_OVERFLOW_U(low,8);
02110
02111 cp->low = low;
02112 cp->high = high;
02113
02114 DEBUGIF("dumpv_recv") {
02115 char i64buf[I64CHARSZ + 1];
02116 printI64(i64buf, cp);
02117 DEBUGMSG(("dumpv_recv", "Integer64: %s", i64buf));
02118 }
02119
02120 return bufp;
02121 }
02122
02123
02124
02146 u_char *
02147 asn_build_signed_int64(u_char * data,
02148 size_t * datalength,
02149 u_char type,
02150 const struct counter64 * cp, size_t countersize)
02151 {
02152
02153
02154
02155
02156 struct counter64 c64;
02157 register u_int mask, mask2;
02158 u_long low, high;
02159 size_t intsize;
02160 #ifndef NETSNMP_NO_DEBUGGING
02161 u_char *initdatap = data;
02162 #endif
02163
02164 if (countersize != sizeof(struct counter64)) {
02165 _asn_size_err("build int64", countersize,
02166 sizeof(struct counter64));
02167 return NULL;
02168 }
02169 intsize = 8;
02170 memcpy(&c64, cp, sizeof(struct counter64));
02171 low = c64.low;
02172 high = c64.high;
02173
02174 CHECK_OVERFLOW_S(high,9);
02175 CHECK_OVERFLOW_U(low,9);
02176
02177
02178
02179
02180
02181
02182
02183 mask = ((u_int) 0xFF) << (8 * (sizeof(u_int) - 1));
02184 mask2 = ((u_int) 0x1FF) << ((8 * (sizeof(u_int) - 1)) - 1);
02185
02186
02187
02188 while ((((high & mask2) == 0) || ((high & mask2) == mask2))
02189 && intsize > 1) {
02190 intsize--;
02191 high = (high << 8)
02192 | ((low & mask) >> (8 * (sizeof(u_int) - 1)));
02193 low <<= 8;
02194 }
02195
02196
02197
02198
02199
02200
02201 data = asn_build_header(data, datalength, ASN_OPAQUE, intsize + 3);
02202 if (_asn_build_header_check
02203 ("build int64", data, *datalength, intsize + 3))
02204 return NULL;
02205
02206 *data++ = ASN_OPAQUE_TAG1;
02207 *data++ = ASN_OPAQUE_I64;
02208 *data++ = (u_char) intsize;
02209 *datalength -= (3 + intsize);
02210
02211 while (intsize--) {
02212 *data++ = (u_char) ((high & mask) >> (8 * (sizeof(u_int) - 1)));
02213 high = (high << 8)
02214 | ((low & mask) >> (8 * (sizeof(u_int) - 1)));
02215 low <<= 8;
02216 }
02217 DEBUGDUMPSETUP("send", initdatap, data - initdatap);
02218 DEBUGIF("dumpv_send") {
02219 char i64buf[I64CHARSZ + 1];
02220 printU64(i64buf, cp);
02221 DEBUGMSG(("dumpv_send", "%s", i64buf));
02222 }
02223 return data;
02224 }
02225
02226
02248 u_char *
02249 asn_parse_float(u_char * data,
02250 size_t * datalength,
02251 u_char * type, float *floatp, size_t floatsize)
02252 {
02253 register u_char *bufp = data;
02254 u_long asn_length;
02255 union {
02256 float floatVal;
02257 long longVal;
02258 u_char c[sizeof(float)];
02259 } fu;
02260
02261 if (floatsize != sizeof(float)) {
02262 _asn_size_err("parse float", floatsize, sizeof(float));
02263 return NULL;
02264 }
02265 *type = *bufp++;
02266 bufp = asn_parse_length(bufp, &asn_length);
02267 if (_asn_parse_length_check("parse float", bufp, data,
02268 asn_length, *datalength))
02269 return NULL;
02270
02271 DEBUGDUMPSETUP("recv", data, bufp - data + asn_length);
02272
02273
02274
02275 if ((*type == ASN_OPAQUE) &&
02276 (asn_length == ASN_OPAQUE_FLOAT_BER_LEN) &&
02277 (*bufp == ASN_OPAQUE_TAG1) && (*(bufp + 1) == ASN_OPAQUE_FLOAT)) {
02278
02279
02280
02281
02282 bufp = asn_parse_length(bufp + 2, &asn_length);
02283 if (_asn_parse_length_check("parse opaque float", bufp, data,
02284 asn_length, *datalength))
02285 return NULL;
02286
02287
02288
02289
02290 *type = ASN_OPAQUE_FLOAT;
02291 }
02292
02293 if (asn_length != sizeof(float)) {
02294 _asn_size_err("parse seq float", asn_length, sizeof(float));
02295 return NULL;
02296 }
02297
02298 *datalength -= (int) asn_length + (bufp - data);
02299 memcpy(&fu.c[0], bufp, asn_length);
02300
02301
02302
02303
02304 fu.longVal = ntohl(fu.longVal);
02305
02306 *floatp = fu.floatVal;
02307
02308 DEBUGMSG(("dumpv_recv", "Opaque float: %f\n", *floatp));
02309 return bufp;
02310 }
02311
02335 u_char *
02336 asn_build_float(u_char * data,
02337 size_t * datalength,
02338 u_char type, const float *floatp, size_t floatsize)
02339 {
02340 union {
02341 float floatVal;
02342 int intVal;
02343 u_char c[sizeof(float)];
02344 } fu;
02345 #ifndef NETSNMP_NO_DEBUGGING
02346 u_char *initdatap = data;
02347 #endif
02348
02349 if (floatsize != sizeof(float)) {
02350 _asn_size_err("build float", floatsize, sizeof(float));
02351 return NULL;
02352 }
02353
02354
02355
02356
02357
02358
02359
02360
02361
02362
02363 data = asn_build_header(data, datalength, ASN_OPAQUE, floatsize + 3);
02364 if (_asn_build_header_check
02365 ("build float", data, *datalength, (floatsize + 3)))
02366 return NULL;
02367
02368
02369
02370
02371 *data++ = ASN_OPAQUE_TAG1;
02372 *data++ = ASN_OPAQUE_FLOAT;
02373 *data++ = (u_char) floatsize;
02374 *datalength = *datalength - 3;
02375
02376 fu.floatVal = *floatp;
02377
02378
02379
02380 fu.intVal = htonl(fu.intVal);
02381
02382 *datalength -= floatsize;
02383 memcpy(data, &fu.c[0], floatsize);
02384
02385 DEBUGDUMPSETUP("send", initdatap, data - initdatap);
02386 DEBUGMSG(("dumpv_send", "Opaque float: %f\n", *floatp));
02387 data += floatsize;
02388 return data;
02389 }
02390
02391
02413 u_char *
02414 asn_parse_double(u_char * data,
02415 size_t * datalength,
02416 u_char * type, double *doublep, size_t doublesize)
02417 {
02418 register u_char *bufp = data;
02419 u_long asn_length;
02420 long tmp;
02421 union {
02422 double doubleVal;
02423 int intVal[2];
02424 u_char c[sizeof(double)];
02425 } fu;
02426
02427
02428 if (doublesize != sizeof(double)) {
02429 _asn_size_err("parse double", doublesize, sizeof(double));
02430 return NULL;
02431 }
02432 *type = *bufp++;
02433 bufp = asn_parse_length(bufp, &asn_length);
02434 if (_asn_parse_length_check("parse double", bufp, data,
02435 asn_length, *datalength))
02436 return NULL;
02437
02438 DEBUGDUMPSETUP("recv", data, bufp - data + asn_length);
02439
02440
02441
02442 if ((*type == ASN_OPAQUE) &&
02443 (asn_length == ASN_OPAQUE_DOUBLE_BER_LEN) &&
02444 (*bufp == ASN_OPAQUE_TAG1) && (*(bufp + 1) == ASN_OPAQUE_DOUBLE)) {
02445
02446
02447
02448
02449 bufp = asn_parse_length(bufp + 2, &asn_length);
02450 if (_asn_parse_length_check("parse opaque double", bufp, data,
02451 asn_length, *datalength))
02452 return NULL;
02453
02454
02455
02456
02457 *type = ASN_OPAQUE_DOUBLE;
02458 }
02459
02460 if (asn_length != sizeof(double)) {
02461 _asn_size_err("parse seq double", asn_length, sizeof(double));
02462 return NULL;
02463 }
02464 *datalength -= (int) asn_length + (bufp - data);
02465 memcpy(&fu.c[0], bufp, asn_length);
02466
02467
02468
02469
02470
02471 tmp = ntohl(fu.intVal[0]);
02472 fu.intVal[0] = ntohl(fu.intVal[1]);
02473 fu.intVal[1] = tmp;
02474
02475 *doublep = fu.doubleVal;
02476 DEBUGMSG(("dumpv_recv", " Opaque Double:\t%f\n", *doublep));
02477
02478 return bufp;
02479 }
02480
02481
02504 u_char *
02505 asn_build_double(u_char * data,
02506 size_t * datalength,
02507 u_char type, const double *doublep, size_t doublesize)
02508 {
02509 long tmp;
02510 union {
02511 double doubleVal;
02512 int intVal[2];
02513 u_char c[sizeof(double)];
02514 } fu;
02515 #ifndef NETSNMP_NO_DEBUGGING
02516 u_char *initdatap = data;
02517 #endif
02518
02519 if (doublesize != sizeof(double)) {
02520 _asn_size_err("build double", doublesize, sizeof(double));
02521 return NULL;
02522 }
02523
02524
02525
02526
02527
02528
02529
02530
02531
02532
02533
02534 data = asn_build_header(data, datalength, ASN_OPAQUE, doublesize + 3);
02535 if (_asn_build_header_check
02536 ("build double", data, *datalength, doublesize + 3))
02537 return NULL;
02538
02539
02540
02541
02542 *data++ = ASN_OPAQUE_TAG1;
02543 *data++ = ASN_OPAQUE_DOUBLE;
02544 *data++ = (u_char) doublesize;
02545 *datalength = *datalength - 3;
02546
02547 fu.doubleVal = *doublep;
02548
02549
02550
02551 tmp = htonl(fu.intVal[0]);
02552 fu.intVal[0] = htonl(fu.intVal[1]);
02553 fu.intVal[1] = tmp;
02554 *datalength -= doublesize;
02555 memcpy(data, &fu.c[0], doublesize);
02556
02557 data += doublesize;
02558 DEBUGDUMPSETUP("send", initdatap, data - initdatap);
02559 DEBUGMSG(("dumpv_send", " Opaque double: %f", *doublep));
02560 return data;
02561 }
02562
02563 #endif
02564
02565
02580 int
02581 asn_realloc(u_char ** pkt, size_t * pkt_len)
02582 {
02583 if (pkt != NULL && pkt_len != NULL) {
02584 size_t old_pkt_len = *pkt_len;
02585
02586 DEBUGMSGTL(("asn_realloc", " old_pkt %8p, old_pkt_len %lu\n",
02587 *pkt, (unsigned long)old_pkt_len));
02588
02589 if (snmp_realloc(pkt, pkt_len)) {
02590 DEBUGMSGTL(("asn_realloc", " new_pkt %8p, new_pkt_len %lu\n",
02591 *pkt, (unsigned long)*pkt_len));
02592 DEBUGMSGTL(("asn_realloc",
02593 " memmove(%8p + %08x, %8p, %08x)\n",
02594 *pkt, (unsigned)(*pkt_len - old_pkt_len),
02595 *pkt, (unsigned)old_pkt_len));
02596 memmove(*pkt + (*pkt_len - old_pkt_len), *pkt, old_pkt_len);
02597 memset(*pkt, (int) ' ', *pkt_len - old_pkt_len);
02598 return 1;
02599 } else {
02600 DEBUGMSG(("asn_realloc", " CANNOT REALLOC()\n"));
02601 }
02602 }
02603 return 0;
02604 }
02605
02606 #ifdef NETSNMP_USE_REVERSE_ASNENCODING
02607
02622 int
02623 asn_realloc_rbuild_length(u_char ** pkt, size_t * pkt_len,
02624 size_t * offset, int r, size_t length)
02625 {
02626 static const char *errpre = "build length";
02627 char ebuf[128];
02628 int tmp_int;
02629 size_t start_offset = *offset;
02630
02631 if (length <= 0x7f) {
02632 if (((*pkt_len - *offset) < 1)
02633 && !(r && asn_realloc(pkt, pkt_len))) {
02634 snprintf(ebuf, sizeof(ebuf),
02635 "%s: bad length < 1 :%ld, %lu", errpre,
02636 (long)(*pkt_len - *offset), (unsigned long)length);
02637 ebuf[ sizeof(ebuf)-1 ] = 0;
02638 ERROR_MSG(ebuf);
02639 return 0;
02640 }
02641 *(*pkt + *pkt_len - (++*offset)) = length;
02642 } else {
02643 while (length > 0xff) {
02644 if (((*pkt_len - *offset) < 1)
02645 && !(r && asn_realloc(pkt, pkt_len))) {
02646 snprintf(ebuf, sizeof(ebuf),
02647 "%s: bad length < 1 :%ld, %lu", errpre,
02648 (long)(*pkt_len - *offset), (unsigned long)length);
02649 ebuf[ sizeof(ebuf)-1 ] = 0;
02650 ERROR_MSG(ebuf);
02651 return 0;
02652 }
02653 *(*pkt + *pkt_len - (++*offset)) = length & 0xff;
02654 length >>= 8;
02655 }
02656
02657 while ((*pkt_len - *offset) < 2) {
02658 if (!(r && asn_realloc(pkt, pkt_len))) {
02659 snprintf(ebuf, sizeof(ebuf),
02660 "%s: bad length < 1 :%ld, %lu", errpre,
02661 (long)(*pkt_len - *offset), (unsigned long)length);
02662 ebuf[ sizeof(ebuf)-1 ] = 0;
02663 ERROR_MSG(ebuf);
02664 return 0;
02665 }
02666 }
02667
02668 *(*pkt + *pkt_len - (++*offset)) = length & 0xff;
02669 tmp_int = *offset - start_offset;
02670 *(*pkt + *pkt_len - (++*offset)) = tmp_int | 0x80;
02671 }
02672
02673 return 1;
02674 }
02675
02693 int
02694 asn_realloc_rbuild_header(u_char ** pkt, size_t * pkt_len,
02695 size_t * offset, int r,
02696 u_char type, size_t length)
02697 {
02698 char ebuf[128];
02699
02700 if (asn_realloc_rbuild_length(pkt, pkt_len, offset, r, length)) {
02701 if (((*pkt_len - *offset) < 1)
02702 && !(r && asn_realloc(pkt, pkt_len))) {
02703 snprintf(ebuf, sizeof(ebuf),
02704 "bad header length < 1 :%ld, %lu",
02705 (long)(*pkt_len - *offset), (unsigned long)length);
02706 ebuf[ sizeof(ebuf)-1 ] = 0;
02707 ERROR_MSG(ebuf);
02708 return 0;
02709 }
02710 *(*pkt + *pkt_len - (++*offset)) = type;
02711 return 1;
02712 }
02713 return 0;
02714 }
02715
02733 int
02734 asn_realloc_rbuild_int(u_char ** pkt, size_t * pkt_len,
02735 size_t * offset, int r,
02736 u_char type, const long *intp, size_t intsize)
02737 {
02738 static const char *errpre = "build int";
02739 register long integer = *intp;
02740 int testvalue;
02741 size_t start_offset = *offset;
02742
02743 if (intsize != sizeof(long)) {
02744 _asn_size_err(errpre, intsize, sizeof(long));
02745 return 0;
02746 }
02747
02748 CHECK_OVERFLOW_S(integer,10);
02749 testvalue = (integer < 0) ? -1 : 0;
02750
02751 if (((*pkt_len - *offset) < 1) && !(r && asn_realloc(pkt, pkt_len))) {
02752 return 0;
02753 }
02754 *(*pkt + *pkt_len - (++*offset)) = (u_char) integer;
02755 integer >>= 8;
02756
02757 while (integer != testvalue) {
02758 if (((*pkt_len - *offset) < 1)
02759 && !(r && asn_realloc(pkt, pkt_len))) {
02760 return 0;
02761 }
02762 *(*pkt + *pkt_len - (++*offset)) = (u_char) integer;
02763 integer >>= 8;
02764 }
02765
02766 if ((*(*pkt + *pkt_len - *offset) & 0x80) != (testvalue & 0x80)) {
02767
02768
02769
02770
02771 if (((*pkt_len - *offset) < 1)
02772 && !(r && asn_realloc(pkt, pkt_len))) {
02773 return 0;
02774 }
02775 *(*pkt + *pkt_len - (++*offset)) = testvalue & 0xff;
02776 }
02777
02778 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r, type,
02779 (*offset - start_offset))) {
02780 if (_asn_realloc_build_header_check(errpre, pkt, pkt_len,
02781 (*offset - start_offset))) {
02782 return 0;
02783 } else {
02784 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset),
02785 (*offset - start_offset));
02786 DEBUGMSG(("dumpv_send", " Integer:\t%ld (0x%.2lX)\n", *intp,
02787 *intp));
02788 return 1;
02789 }
02790 }
02791
02792 return 0;
02793 }
02794
02813 int
02814 asn_realloc_rbuild_string(u_char ** pkt, size_t * pkt_len,
02815 size_t * offset, int r,
02816 u_char type,
02817 const u_char * str, size_t strlength)
02818 {
02819 static const char *errpre = "build string";
02820 size_t start_offset = *offset;
02821
02822 while ((*pkt_len - *offset) < strlength) {
02823 if (!(r && asn_realloc(pkt, pkt_len))) {
02824 return 0;
02825 }
02826 }
02827
02828 *offset += strlength;
02829 memcpy(*pkt + *pkt_len - *offset, str, strlength);
02830
02831 if (asn_realloc_rbuild_header
02832 (pkt, pkt_len, offset, r, type, strlength)) {
02833 if (_asn_realloc_build_header_check
02834 (errpre, pkt, pkt_len, strlength)) {
02835 return 0;
02836 } else {
02837 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset),
02838 *offset - start_offset);
02839 DEBUGIF("dumpv_send") {
02840 if (strlength == 0) {
02841 DEBUGMSG(("dumpv_send", " String: [NULL]\n"));
02842 } else {
02843 u_char *buf = (u_char *) malloc(2 * strlength);
02844 size_t l =
02845 (buf != NULL) ? (2 * strlength) : 0, ol = 0;
02846
02847 if (sprint_realloc_asciistring
02848 (&buf, &l, &ol, 1, str, strlength)) {
02849 DEBUGMSG(("dumpv_send", " String:\t%s\n", buf));
02850 } else {
02851 if (buf == NULL) {
02852 DEBUGMSG(("dumpv_send",
02853 " String:\t[TRUNCATED]\n"));
02854 } else {
02855 DEBUGMSG(("dumpv_send",
02856 " String:\t%s [TRUNCATED]\n", buf));
02857 }
02858 }
02859 if (buf != NULL) {
02860 free(buf);
02861 }
02862 }
02863 }
02864 }
02865 return 1;
02866 }
02867
02868 return 0;
02869 }
02870
02888 int
02889 asn_realloc_rbuild_unsigned_int(u_char ** pkt, size_t * pkt_len,
02890 size_t * offset, int r,
02891 u_char type, const u_long * intp, size_t intsize)
02892 {
02893 static const char *errpre = "build uint";
02894 register u_long integer = *intp;
02895 size_t start_offset = *offset;
02896
02897 if (intsize != sizeof(unsigned long)) {
02898 _asn_size_err(errpre, intsize, sizeof(unsigned long));
02899 return 0;
02900 }
02901
02902 CHECK_OVERFLOW_U(integer,11);
02903
02904 if (((*pkt_len - *offset) < 1) && !(r && asn_realloc(pkt, pkt_len))) {
02905 return 0;
02906 }
02907 *(*pkt + *pkt_len - (++*offset)) = (u_char) integer;
02908 integer >>= 8;
02909
02910 while (integer != 0) {
02911 if (((*pkt_len - *offset) < 1)
02912 && !(r && asn_realloc(pkt, pkt_len))) {
02913 return 0;
02914 }
02915 *(*pkt + *pkt_len - (++*offset)) = (u_char) integer;
02916 integer >>= 8;
02917 }
02918
02919 if ((*(*pkt + *pkt_len - *offset) & 0x80) != (0 & 0x80)) {
02920
02921
02922
02923
02924 if (((*pkt_len - *offset) < 1)
02925 && !(r && asn_realloc(pkt, pkt_len))) {
02926 return 0;
02927 }
02928 *(*pkt + *pkt_len - (++*offset)) = 0;
02929 }
02930
02931 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r, type,
02932 (*offset - start_offset))) {
02933 if (_asn_realloc_build_header_check(errpre, pkt, pkt_len,
02934 (*offset - start_offset))) {
02935 return 0;
02936 } else {
02937 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset),
02938 (*offset - start_offset));
02939 DEBUGMSG(("dumpv_send", " UInteger:\t%lu (0x%.2lX)\n", *intp,
02940 *intp));
02941 return 1;
02942 }
02943 }
02944
02945 return 0;
02946 }
02947
02965 int
02966 asn_realloc_rbuild_sequence(u_char ** pkt, size_t * pkt_len,
02967 size_t * offset, int r,
02968 u_char type, size_t length)
02969 {
02970 return asn_realloc_rbuild_header(pkt, pkt_len, offset, r, type,
02971 length);
02972 }
02973
02992 int
02993 asn_realloc_rbuild_objid(u_char ** pkt, size_t * pkt_len,
02994 size_t * offset, int r,
02995 u_char type,
02996 const oid * objid, size_t objidlength)
02997 {
02998
02999
03000
03001
03002
03003
03004 register size_t i;
03005 register oid tmpint;
03006 size_t start_offset = *offset;
03007 const char *errpre = "build objid";
03008
03009
03010
03011
03012 if (objidlength == 0) {
03013
03014
03015
03016 while ((*pkt_len - *offset) < 2) {
03017 if (!(r && asn_realloc(pkt, pkt_len))) {
03018 return 0;
03019 }
03020 }
03021
03022 *(*pkt + *pkt_len - (++*offset)) = 0;
03023 *(*pkt + *pkt_len - (++*offset)) = 0;
03024 } else if (objid[0] > 2) {
03025 ERROR_MSG("build objid: bad first subidentifier");
03026 return 0;
03027 } else if (objidlength == 1) {
03028
03029
03030
03031 if (((*pkt_len - *offset) < 1)
03032 && !(r && asn_realloc(pkt, pkt_len))) {
03033 return 0;
03034 }
03035 *(*pkt + *pkt_len - (++*offset)) = (u_char) objid[0];
03036 } else {
03037 for (i = objidlength; i > 2; i--) {
03038 tmpint = objid[i - 1];
03039 CHECK_OVERFLOW_U(tmpint,12);
03040
03041 if (((*pkt_len - *offset) < 1)
03042 && !(r && asn_realloc(pkt, pkt_len))) {
03043 return 0;
03044 }
03045 *(*pkt + *pkt_len - (++*offset)) = (u_char) tmpint & 0x7f;
03046 tmpint >>= 7;
03047
03048 while (tmpint > 0) {
03049 if (((*pkt_len - *offset) < 1)
03050 && !(r && asn_realloc(pkt, pkt_len))) {
03051 return 0;
03052 }
03053 *(*pkt + *pkt_len - (++*offset)) =
03054 (u_char) ((tmpint & 0x7f) | 0x80);
03055 tmpint >>= 7;
03056 }
03057 }
03058
03059
03060
03061
03062 if ((objid[1] > 40) &&
03063 (objid[0] < 2)) {
03064 ERROR_MSG("build objid: bad second subidentifier");
03065 return 0;
03066 }
03067 tmpint = ((objid[0] * 40) + objid[1]);
03068 if (((*pkt_len - *offset) < 1)
03069 && !(r && asn_realloc(pkt, pkt_len))) {
03070 return 0;
03071 }
03072 *(*pkt + *pkt_len - (++*offset)) = (u_char) tmpint & 0x7f;
03073 tmpint >>= 7;
03074
03075 while (tmpint > 0) {
03076 if (((*pkt_len - *offset) < 1)
03077 && !(r && asn_realloc(pkt, pkt_len))) {
03078 return 0;
03079 }
03080 *(*pkt + *pkt_len - (++*offset)) =
03081 (u_char) ((tmpint & 0x7f) | 0x80);
03082 tmpint >>= 7;
03083 }
03084 }
03085
03086 tmpint = *offset - start_offset;
03087 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r, type,
03088 (*offset - start_offset))) {
03089 if (_asn_realloc_build_header_check(errpre, pkt, pkt_len,
03090 (*offset - start_offset))) {
03091 return 0;
03092 } else {
03093 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset),
03094 (*offset - start_offset));
03095 DEBUGMSG(("dumpv_send", " ObjID: "));
03096 DEBUGMSGOID(("dumpv_send", objid, objidlength));
03097 DEBUGMSG(("dumpv_send", "\n"));
03098 return 1;
03099 }
03100 }
03101
03102 return 0;
03103 }
03104
03121 int
03122 asn_realloc_rbuild_null(u_char ** pkt, size_t * pkt_len,
03123 size_t * offset, int r, u_char type)
03124 {
03125
03126
03127
03128 size_t start_offset = *offset;
03129
03130 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r, type, 0)) {
03131 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset),
03132 (*offset - start_offset));
03133 DEBUGMSG(("dumpv_send", " NULL\n"));
03134 return 1;
03135 } else {
03136 return 0;
03137 }
03138 }
03139
03158 int
03159 asn_realloc_rbuild_bitstring(u_char ** pkt, size_t * pkt_len,
03160 size_t * offset, int r,
03161 u_char type,
03162 const u_char * str, size_t strlength)
03163 {
03164
03165
03166
03167 static const char *errpre = "build bitstring";
03168 size_t start_offset = *offset;
03169
03170 while ((*pkt_len - *offset) < strlength) {
03171 if (!(r && asn_realloc(pkt, pkt_len))) {
03172 return 0;
03173 }
03174 }
03175
03176 *offset += strlength;
03177 memcpy(*pkt + *pkt_len - *offset, str, strlength);
03178
03179 if (asn_realloc_rbuild_header
03180 (pkt, pkt_len, offset, r, type, strlength)) {
03181 if (_asn_realloc_build_header_check
03182 (errpre, pkt, pkt_len, strlength)) {
03183 return 0;
03184 } else {
03185 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset),
03186 *offset - start_offset);
03187 DEBUGIF("dumpv_send") {
03188 if (strlength == 0) {
03189 DEBUGMSG(("dumpv_send", " Bitstring: [NULL]\n"));
03190 } else {
03191 u_char *buf = (u_char *) malloc(2 * strlength);
03192 size_t l =
03193 (buf != NULL) ? (2 * strlength) : 0, ol = 0;
03194
03195 if (sprint_realloc_asciistring
03196 (&buf, &l, &ol, 1, str, strlength)) {
03197 DEBUGMSG(("dumpv_send", " Bitstring:\t%s\n",
03198 buf));
03199 } else {
03200 if (buf == NULL) {
03201 DEBUGMSG(("dumpv_send",
03202 " Bitstring:\t[TRUNCATED]\n"));
03203 } else {
03204 DEBUGMSG(("dumpv_send",
03205 " Bitstring:\t%s [TRUNCATED]\n",
03206 buf));
03207 }
03208 }
03209 if (buf != NULL) {
03210 free(buf);
03211 }
03212 }
03213 }
03214 }
03215 return 1;
03216 }
03217
03218 return 0;
03219 }
03220
03238 int
03239 asn_realloc_rbuild_unsigned_int64(u_char ** pkt, size_t * pkt_len,
03240 size_t * offset, int r,
03241 u_char type,
03242 const struct counter64 *cp, size_t countersize)
03243 {
03244
03245
03246
03247 register u_long low = cp->low, high = cp->high;
03248 size_t intsize, start_offset = *offset;
03249 int count;
03250
03251 if (countersize != sizeof(struct counter64)) {
03252 _asn_size_err("build uint64", countersize,
03253 sizeof(struct counter64));
03254 return 0;
03255 }
03256
03257 CHECK_OVERFLOW_U(high,13);
03258 CHECK_OVERFLOW_U(low,13);
03259
03260
03261
03262
03263 if (((*pkt_len - *offset) < 1) && !(r && asn_realloc(pkt, pkt_len))) {
03264 return 0;
03265 }
03266 *(*pkt + *pkt_len - (++*offset)) = (u_char) low;
03267 low >>= 8;
03268 count = 1;
03269
03270 while (low != 0) {
03271 count++;
03272 if (((*pkt_len - *offset) < 1)
03273 && !(r && asn_realloc(pkt, pkt_len))) {
03274 return 0;
03275 }
03276 *(*pkt + *pkt_len - (++*offset)) = (u_char) low;
03277 low >>= 8;
03278 }
03279
03280
03281
03282
03283 if (high) {
03284
03285
03286
03287 for (; count < 4; count++) {
03288 if (((*pkt_len - *offset) < 1)
03289 && !(r && asn_realloc(pkt, pkt_len))) {
03290 return 0;
03291 }
03292 *(*pkt + *pkt_len - (++*offset)) = 0;
03293 }
03294
03295
03296
03297
03298 if (((*pkt_len - *offset) < 1)
03299 && !(r && asn_realloc(pkt, pkt_len))) {
03300 return 0;
03301 }
03302 *(*pkt + *pkt_len - (++*offset)) = (u_char) high;
03303 high >>= 8;
03304
03305 while (high != 0) {
03306 if (((*pkt_len - *offset) < 1)
03307 && !(r && asn_realloc(pkt, pkt_len))) {
03308 return 0;
03309 }
03310 *(*pkt + *pkt_len - (++*offset)) = (u_char) high;
03311 high >>= 8;
03312 }
03313 }
03314
03315 if ((*(*pkt + *pkt_len - *offset) & 0x80) != (0 & 0x80)) {
03316
03317
03318
03319
03320 if (((*pkt_len - *offset) < 1)
03321 && !(r && asn_realloc(pkt, pkt_len))) {
03322 return 0;
03323 }
03324 *(*pkt + *pkt_len - (++*offset)) = 0;
03325 }
03326
03327 intsize = *offset - start_offset;
03328
03329 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
03330
03331
03332
03333 if (type == ASN_OPAQUE_COUNTER64) {
03334 while ((*pkt_len - *offset) < 5) {
03335 if (!(r && asn_realloc(pkt, pkt_len))) {
03336 return 0;
03337 }
03338 }
03339
03340 *(*pkt + *pkt_len - (++*offset)) = (u_char) intsize;
03341 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_COUNTER64;
03342 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_TAG1;
03343
03344
03345
03346
03347 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r,
03348 ASN_OPAQUE, intsize + 3)) {
03349 if (_asn_realloc_build_header_check
03350 ("build counter u64", pkt, pkt_len, intsize + 3)) {
03351 return 0;
03352 }
03353 } else {
03354 return 0;
03355 }
03356 } else if (type == ASN_OPAQUE_U64) {
03357
03358
03359
03360 while ((*pkt_len - *offset) < 5) {
03361 if (!(r && asn_realloc(pkt, pkt_len))) {
03362 return 0;
03363 }
03364 }
03365
03366 *(*pkt + *pkt_len - (++*offset)) = (u_char) intsize;
03367 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_U64;
03368 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_TAG1;
03369
03370
03371
03372
03373 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r,
03374 ASN_OPAQUE, intsize + 3)) {
03375 if (_asn_realloc_build_header_check
03376 ("build counter u64", pkt, pkt_len, intsize + 3)) {
03377 return 0;
03378 }
03379 } else {
03380 return 0;
03381 }
03382 } else {
03383
03384 #endif
03385 if (asn_realloc_rbuild_header
03386 (pkt, pkt_len, offset, r, type, intsize)) {
03387 if (_asn_realloc_build_header_check
03388 ("build uint64", pkt, pkt_len, intsize)) {
03389 return 0;
03390 }
03391 } else {
03392 return 0;
03393 }
03394 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
03395 }
03396 #endif
03397
03398 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset), intsize);
03399 DEBUGMSG(("dumpv_send", " U64:\t%lu %lu\n", cp->high, cp->low));
03400 return 1;
03401 }
03402
03403 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
03404
03405
03423 int
03424 asn_realloc_rbuild_signed_int64(u_char ** pkt, size_t * pkt_len,
03425 size_t * offset, int r,
03426 u_char type,
03427 const struct counter64 *cp, size_t countersize)
03428 {
03429
03430
03431
03432 register long low = cp->low, high = cp->high;
03433 size_t intsize, start_offset = *offset;
03434 int count, testvalue = (high & 0x80000000) ? -1 : 0;
03435
03436 if (countersize != sizeof(struct counter64)) {
03437 _asn_size_err("build uint64", countersize,
03438 sizeof(struct counter64));
03439 return 0;
03440 }
03441
03442 CHECK_OVERFLOW_S(high,14);
03443 CHECK_OVERFLOW_U(low,14);
03444
03445
03446
03447
03448 if (((*pkt_len - *offset) < 1) && !(r && asn_realloc(pkt, pkt_len))) {
03449 return 0;
03450 }
03451 *(*pkt + *pkt_len - (++*offset)) = (u_char) low;
03452 low >>= 8;
03453 count = 1;
03454
03455 while ((int) low != testvalue && count < 4) {
03456 count++;
03457 if (((*pkt_len - *offset) < 1)
03458 && !(r && asn_realloc(pkt, pkt_len))) {
03459 return 0;
03460 }
03461 *(*pkt + *pkt_len - (++*offset)) = (u_char) low;
03462 low >>= 8;
03463 }
03464
03465
03466
03467
03468 if (high != testvalue) {
03469
03470
03471
03472 for (; count < 4; count++) {
03473 if (((*pkt_len - *offset) < 1)
03474 && !(r && asn_realloc(pkt, pkt_len))) {
03475 return 0;
03476 }
03477 *(*pkt + *pkt_len - (++*offset)) = (testvalue == 0) ? 0 : 0xff;
03478 }
03479
03480
03481
03482
03483 if (((*pkt_len - *offset) < 1)
03484 && !(r && asn_realloc(pkt, pkt_len))) {
03485 return 0;
03486 }
03487 *(*pkt + *pkt_len - (++*offset)) = (u_char) high;
03488 high >>= 8;
03489
03490 while ((int) high != testvalue) {
03491 if (((*pkt_len - *offset) < 1)
03492 && !(r && asn_realloc(pkt, pkt_len))) {
03493 return 0;
03494 }
03495 *(*pkt + *pkt_len - (++*offset)) = (u_char) high;
03496 high >>= 8;
03497 }
03498 }
03499
03500 if ((*(*pkt + *pkt_len - *offset) & 0x80) != (testvalue & 0x80)) {
03501
03502
03503
03504
03505 if (((*pkt_len - *offset) < 1)
03506 && !(r && asn_realloc(pkt, pkt_len))) {
03507 return 0;
03508 }
03509 *(*pkt + *pkt_len - (++*offset)) = (testvalue == 0) ? 0 : 0xff;
03510 }
03511
03512 intsize = *offset - start_offset;
03513
03514 while ((*pkt_len - *offset) < 5) {
03515 if (!(r && asn_realloc(pkt, pkt_len))) {
03516 return 0;
03517 }
03518 }
03519
03520 *(*pkt + *pkt_len - (++*offset)) = (u_char) intsize;
03521 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_I64;
03522 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_TAG1;
03523
03524
03525
03526
03527 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r,
03528 ASN_OPAQUE, intsize + 3)) {
03529 if (_asn_realloc_build_header_check
03530 ("build counter u64", pkt, pkt_len, intsize + 3)) {
03531 return 0;
03532 }
03533 } else {
03534 return 0;
03535 }
03536
03537 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset), intsize);
03538 DEBUGMSG(("dumpv_send", " UInt64:\t%lu %lu\n", cp->high, cp->low));
03539 return 1;
03540 }
03541
03560 int
03561 asn_realloc_rbuild_float(u_char ** pkt, size_t * pkt_len,
03562 size_t * offset, int r,
03563 u_char type, const float *floatp, size_t floatsize)
03564 {
03565 size_t start_offset = *offset;
03566 union {
03567 float floatVal;
03568 int intVal;
03569 u_char c[sizeof(float)];
03570 } fu;
03571
03572
03573
03574
03575 if (floatsize != sizeof(float) || floatsize > 122) {
03576 return 0;
03577 }
03578
03579 while ((*pkt_len - *offset) < floatsize + 3) {
03580 if (!(r && asn_realloc(pkt, pkt_len))) {
03581 return 0;
03582 }
03583 }
03584
03585
03586
03587
03588 fu.floatVal = *floatp;
03589 fu.intVal = htonl(fu.intVal);
03590 *offset += floatsize;
03591 memcpy(*pkt + *pkt_len - *offset, &(fu.c[0]), floatsize);
03592
03593
03594
03595
03596 *(*pkt + *pkt_len - (++*offset)) = (u_char) floatsize;
03597 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_FLOAT;
03598 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_TAG1;
03599
03600
03601
03602
03603 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r,
03604 ASN_OPAQUE, floatsize + 3)) {
03605 if (_asn_realloc_build_header_check("build float", pkt, pkt_len,
03606 floatsize + 3)) {
03607 return 0;
03608 } else {
03609 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset),
03610 *offset - start_offset);
03611 DEBUGMSG(("dumpv_send", "Opaque Float:\t%f\n", *floatp));
03612 return 1;
03613 }
03614 }
03615
03616 return 0;
03617 }
03618
03637 int
03638 asn_realloc_rbuild_double(u_char ** pkt, size_t * pkt_len,
03639 size_t * offset, int r,
03640 u_char type, const double *doublep, size_t doublesize)
03641 {
03642 size_t start_offset = *offset;
03643 long tmp;
03644 union {
03645 double doubleVal;
03646 int intVal[2];
03647 u_char c[sizeof(double)];
03648 } fu;
03649
03650
03651
03652
03653 if (doublesize != sizeof(double) || doublesize > 122) {
03654 return 0;
03655 }
03656
03657 while ((*pkt_len - *offset) < doublesize + 3) {
03658 if (!(r && asn_realloc(pkt, pkt_len))) {
03659 return 0;
03660 }
03661 }
03662
03663
03664
03665
03666 fu.doubleVal = *doublep;
03667 tmp = htonl(fu.intVal[0]);
03668 fu.intVal[0] = htonl(fu.intVal[1]);
03669 fu.intVal[1] = tmp;
03670 *offset += doublesize;
03671 memcpy(*pkt + *pkt_len - *offset, &(fu.c[0]), doublesize);
03672
03673
03674
03675
03676 *(*pkt + *pkt_len - (++*offset)) = (u_char) doublesize;
03677 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_DOUBLE;
03678 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_TAG1;
03679
03680
03681
03682
03683 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r,
03684 ASN_OPAQUE, doublesize + 3)) {
03685 if (_asn_realloc_build_header_check("build float", pkt, pkt_len,
03686 doublesize + 3)) {
03687 return 0;
03688 } else {
03689 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset),
03690 *offset - start_offset);
03691 DEBUGMSG(("dumpv_send", " Opaque Double:\t%f\n", *doublep));
03692 return 1;
03693 }
03694 }
03695
03696 return 0;
03697 }
03698
03699 #endif
03700 #endif
03701