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 snmp_log(LOG_ERR,"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 snmp_log(LOG_ERR,"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%.2X)\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%.2X)\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 SNMP_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%.2X)\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 SNMP_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%.2X)\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 SNMP_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 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
01303 *type = *bufp++;
01304 bufp = asn_parse_length(bufp, &asn_length);
01305 if (_asn_parse_length_check("parse objid", bufp, data,
01306 asn_length, *datalength))
01307 return NULL;
01308
01309 *datalength -= (int) asn_length + (bufp - data);
01310
01311 DEBUGDUMPSETUP("recv", data, bufp - data + asn_length);
01312
01313
01314
01315
01316 if (asn_length == 0)
01317 objid[0] = objid[1] = 0;
01318
01319 length = asn_length;
01320 (*objidlength)--;
01321
01322 while (length > 0 && (*objidlength)-- > 0) {
01323 subidentifier = 0;
01324 do {
01325 subidentifier =
01326 (subidentifier << 7) + (*(u_char *) bufp & ~ASN_BIT8);
01327 length--;
01328 } while (*(u_char *) bufp++ & ASN_BIT8);
01329
01330 #if defined(EIGHTBIT_SUBIDS) || (SIZEOF_LONG != 4)
01331 if (subidentifier > (u_long) MAX_SUBID) {
01332 ERROR_MSG("subidentifier too large");
01333 return NULL;
01334 }
01335 #endif
01336 *oidp++ = (oid) subidentifier;
01337 }
01338
01339 if (0 != length) {
01340 ERROR_MSG("OID length exceeds buffer size");
01341 return NULL;
01342 }
01343
01344
01345
01346
01347
01348
01349
01350 subidentifier = (u_long) objid[1];
01351 if (subidentifier == 0x2B) {
01352 objid[0] = 1;
01353 objid[1] = 3;
01354 } else {
01355 if (subidentifier < 40) {
01356 objid[0] = 0;
01357 objid[1] = subidentifier;
01358 } else if (subidentifier < 80) {
01359 objid[0] = 1;
01360 objid[1] = subidentifier - 40;
01361 } else {
01362 objid[0] = 2;
01363 objid[1] = subidentifier - 80;
01364 }
01365 }
01366
01367 *objidlength = (int) (oidp - objid);
01368
01369 DEBUGMSG(("dumpv_recv", " ObjID: "));
01370 DEBUGMSGOID(("dumpv_recv", objid, *objidlength));
01371 DEBUGMSG(("dumpv_recv", "\n"));
01372 return bufp;
01373 }
01374
01398 u_char *
01399 asn_build_objid(u_char * data,
01400 size_t * datalength,
01401 u_char type, oid * objid, size_t objidlength)
01402 {
01403
01404
01405
01406
01407
01408
01409 size_t asnlength;
01410 register oid *op = objid;
01411 u_char objid_size[MAX_OID_LEN];
01412 register u_long objid_val;
01413 u_long first_objid_val;
01414 register int i;
01415 #ifndef SNMP_NO_DEBUGGING
01416 u_char *initdatap = data;
01417 #endif
01418
01419
01420
01421
01422 if (objidlength == 0) {
01423
01424
01425
01426 objid_val = 0;
01427 objidlength = 2;
01428 } else if (objid[0] > 2) {
01429 ERROR_MSG("build objid: bad first subidentifier");
01430 return NULL;
01431 } else if (objidlength == 1) {
01432
01433
01434
01435 objid_val = (op[0] * 40);
01436 objidlength = 2;
01437 op++;
01438 } else {
01439
01440
01441
01442 if ((op[1] > 40) &&
01443 (op[0] < 2)) {
01444 ERROR_MSG("build objid: bad second subidentifier");
01445 return NULL;
01446 }
01447 objid_val = (op[0] * 40) + op[1];
01448 op += 2;
01449 }
01450 first_objid_val = objid_val;
01451
01452
01453
01454
01455 if (objidlength > MAX_OID_LEN)
01456 return NULL;
01457
01458
01459
01460
01461 for (i = 1, asnlength = 0;;) {
01462
01463 CHECK_OVERFLOW_U(objid_val,5);
01464 if (objid_val < (unsigned) 0x80) {
01465 objid_size[i] = 1;
01466 asnlength += 1;
01467 } else if (objid_val < (unsigned) 0x4000) {
01468 objid_size[i] = 2;
01469 asnlength += 2;
01470 } else if (objid_val < (unsigned) 0x200000) {
01471 objid_size[i] = 3;
01472 asnlength += 3;
01473 } else if (objid_val < (unsigned) 0x10000000) {
01474 objid_size[i] = 4;
01475 asnlength += 4;
01476 } else {
01477 objid_size[i] = 5;
01478 asnlength += 5;
01479 }
01480 i++;
01481 if (i >= (int) objidlength)
01482 break;
01483 objid_val = *op++;
01484 }
01485
01486
01487
01488
01489 data = asn_build_header(data, datalength, type, asnlength);
01490 if (_asn_build_header_check
01491 ("build objid", data, *datalength, asnlength))
01492 return NULL;
01493
01494
01495
01496
01497 for (i = 1, objid_val = first_objid_val, op = objid + 2;
01498 i < (int) objidlength; i++) {
01499 if (i != 1) {
01500 objid_val = *op++;
01501 #if SIZEOF_LONG != 4
01502 if (objid_val > 0xffffffff)
01503 objid_val &= 0xffffffff;
01504 #endif
01505 }
01506 switch (objid_size[i]) {
01507 case 1:
01508 *data++ = (u_char) objid_val;
01509 break;
01510
01511 case 2:
01512 *data++ = (u_char) ((objid_val >> 7) | 0x80);
01513 *data++ = (u_char) (objid_val & 0x07f);
01514 break;
01515
01516 case 3:
01517 *data++ = (u_char) ((objid_val >> 14) | 0x80);
01518 *data++ = (u_char) ((objid_val >> 7 & 0x7f) | 0x80);
01519 *data++ = (u_char) (objid_val & 0x07f);
01520 break;
01521
01522 case 4:
01523 *data++ = (u_char) ((objid_val >> 21) | 0x80);
01524 *data++ = (u_char) ((objid_val >> 14 & 0x7f) | 0x80);
01525 *data++ = (u_char) ((objid_val >> 7 & 0x7f) | 0x80);
01526 *data++ = (u_char) (objid_val & 0x07f);
01527 break;
01528
01529 case 5:
01530 *data++ = (u_char) ((objid_val >> 28) | 0x80);
01531 *data++ = (u_char) ((objid_val >> 21 & 0x7f) | 0x80);
01532 *data++ = (u_char) ((objid_val >> 14 & 0x7f) | 0x80);
01533 *data++ = (u_char) ((objid_val >> 7 & 0x7f) | 0x80);
01534 *data++ = (u_char) (objid_val & 0x07f);
01535 break;
01536 }
01537 }
01538
01539
01540
01541
01542 *datalength -= asnlength;
01543 DEBUGDUMPSETUP("send", initdatap, data - initdatap);
01544 DEBUGMSG(("dumpv_send", " ObjID: "));
01545 DEBUGMSGOID(("dumpv_send", objid, objidlength));
01546 DEBUGMSG(("dumpv_send", "\n"));
01547 return data;
01548 }
01549
01569 u_char *
01570 asn_parse_null(u_char * data, size_t * datalength, u_char * type)
01571 {
01572
01573
01574
01575 register u_char *bufp = data;
01576 u_long asn_length;
01577
01578 *type = *bufp++;
01579 bufp = asn_parse_length(bufp, &asn_length);
01580 if (bufp == NULL) {
01581 ERROR_MSG("parse null: bad length");
01582 return NULL;
01583 }
01584 if (asn_length != 0) {
01585 ERROR_MSG("parse null: malformed ASN.1 null");
01586 return NULL;
01587 }
01588
01589 *datalength -= (bufp - data);
01590
01591 DEBUGDUMPSETUP("recv", data, bufp - data);
01592 DEBUGMSG(("dumpv_recv", " NULL\n"));
01593
01594 return bufp + asn_length;
01595 }
01596
01597
01618 u_char *
01619 asn_build_null(u_char * data, size_t * datalength, u_char type)
01620 {
01621
01622
01623
01624 #ifndef SNMP_NO_DEBUGGING
01625 u_char *initdatap = data;
01626 #endif
01627 data = asn_build_header(data, datalength, type, 0);
01628 DEBUGDUMPSETUP("send", initdatap, data - initdatap);
01629 DEBUGMSG(("dumpv_send", " NULL\n"));
01630 return data;
01631 }
01632
01656 u_char *
01657 asn_parse_bitstring(u_char * data,
01658 size_t * datalength,
01659 u_char * type, u_char * str, size_t * strlength)
01660 {
01661
01662
01663
01664 static const char *errpre = "parse bitstring";
01665 register u_char *bufp = data;
01666 u_long asn_length;
01667
01668 *type = *bufp++;
01669 bufp = asn_parse_length(bufp, &asn_length);
01670 if (_asn_parse_length_check(errpre, bufp, data,
01671 asn_length, *datalength))
01672 return NULL;
01673
01674 if ((size_t) asn_length > *strlength) {
01675 _asn_length_err(errpre, (size_t) asn_length, *strlength);
01676 return NULL;
01677 }
01678 if (_asn_bitstring_check(errpre, asn_length, *bufp))
01679 return NULL;
01680
01681 DEBUGDUMPSETUP("recv", data, bufp - data);
01682 DEBUGMSG(("dumpv_recv", " Bitstring: "));
01683 DEBUGMSGHEX(("dumpv_recv", data, asn_length));
01684 DEBUGMSG(("dumpv_recv", "\n"));
01685
01686 memmove(str, bufp, asn_length);
01687 *strlength = (int) asn_length;
01688 *datalength -= (int) asn_length + (bufp - data);
01689 return bufp + asn_length;
01690 }
01691
01692
01715 u_char *
01716 asn_build_bitstring(u_char * data,
01717 size_t * datalength,
01718 u_char type, const u_char * str, size_t strlength)
01719 {
01720
01721
01722
01723 static const char *errpre = "build bitstring";
01724 if (_asn_bitstring_check
01725 (errpre, strlength, (u_char)((str) ? *str : 0)))
01726 return NULL;
01727
01728 data = asn_build_header(data, datalength, type, strlength);
01729 if (_asn_build_header_check(errpre, data, *datalength, strlength))
01730 return NULL;
01731
01732 if (strlength > 0 && str)
01733 memmove(data, str, strlength);
01734 else if (strlength > 0 && !str) {
01735 ERROR_MSG("no string passed into asn_build_bitstring\n");
01736 return NULL;
01737 }
01738
01739 *datalength -= strlength;
01740 DEBUGDUMPSETUP("send", data, strlength);
01741 DEBUGMSG(("dumpv_send", " Bitstring: "));
01742 DEBUGMSGHEX(("dumpv_send", data, strlength));
01743 DEBUGMSG(("dumpv_send", "\n"));
01744 return data + strlength;
01745 }
01746
01769 u_char *
01770 asn_parse_unsigned_int64(u_char * data,
01771 size_t * datalength,
01772 u_char * type,
01773 struct counter64 * cp, size_t countersize)
01774 {
01775
01776
01777
01778 static const char *errpre = "parse uint64";
01779 const int uint64sizelimit = (4 * 2) + 1;
01780 register u_char *bufp = data;
01781 u_long asn_length;
01782 register u_long low = 0, high = 0;
01783
01784 if (countersize != sizeof(struct counter64)) {
01785 _asn_size_err(errpre, countersize, sizeof(struct counter64));
01786 return NULL;
01787 }
01788 *type = *bufp++;
01789 bufp = asn_parse_length(bufp, &asn_length);
01790 if (_asn_parse_length_check
01791 (errpre, bufp, data, asn_length, *datalength))
01792 return NULL;
01793
01794 DEBUGDUMPSETUP("recv", data, bufp - data);
01795 #ifdef OPAQUE_SPECIAL_TYPES
01796
01797
01798
01799 if ((*type == ASN_OPAQUE) &&
01800 (asn_length <= ASN_OPAQUE_COUNTER64_MX_BER_LEN) &&
01801 (*bufp == ASN_OPAQUE_TAG1) &&
01802 ((*(bufp + 1) == ASN_OPAQUE_COUNTER64) ||
01803 (*(bufp + 1) == ASN_OPAQUE_U64))) {
01804
01805
01806
01807 *type = *(bufp + 1);
01808
01809
01810
01811 bufp = asn_parse_length(bufp + 2, &asn_length);
01812 if (_asn_parse_length_check("parse opaque uint64", bufp, data,
01813 asn_length, *datalength))
01814 return NULL;
01815 }
01816 #endif
01817 if (((int) asn_length > uint64sizelimit) ||
01818 (((int) asn_length == uint64sizelimit) && *bufp != 0x00)) {
01819 _asn_length_err(errpre, (size_t) asn_length, uint64sizelimit);
01820 return NULL;
01821 }
01822 *datalength -= (int) asn_length + (bufp - data);
01823 if (*bufp & 0x80) {
01824 low = 0xFFFFFF;
01825 high = 0xFFFFFF;
01826 }
01827
01828 while (asn_length--) {
01829 high = ((0x00FFFFFF & high) << 8) | ((low & 0xFF000000) >> 24);
01830 low = ((low & 0x00FFFFFF) << 8) | *bufp++;
01831 }
01832
01833 CHECK_OVERFLOW_U(high,6);
01834 CHECK_OVERFLOW_U(low,6);
01835
01836 cp->low = low;
01837 cp->high = high;
01838
01839 DEBUGIF("dumpv_recv") {
01840 char i64buf[I64CHARSZ + 1];
01841 printU64(i64buf, cp);
01842 DEBUGMSG(("dumpv_recv", "Counter64: %s", i64buf));
01843 }
01844
01845 return bufp;
01846 }
01847
01848
01870 u_char *
01871 asn_build_unsigned_int64(u_char * data,
01872 size_t * datalength,
01873 u_char type,
01874 const struct counter64 * cp, size_t countersize)
01875 {
01876
01877
01878
01879
01880 register u_long low, high;
01881 register u_long mask, mask2;
01882 int add_null_byte = 0;
01883 size_t intsize;
01884 #ifndef SNMP_NO_DEBUGGING
01885 u_char *initdatap = data;
01886 #endif
01887
01888 if (countersize != sizeof(struct counter64)) {
01889 _asn_size_err("build uint64", countersize,
01890 sizeof(struct counter64));
01891 return NULL;
01892 }
01893 intsize = 8;
01894 low = cp->low;
01895 high = cp->high;
01896
01897 CHECK_OVERFLOW_U(high,7);
01898 CHECK_OVERFLOW_U(low,7);
01899
01900 mask = ((u_long) 0xFF) << (8 * (sizeof(long) - 1));
01901
01902
01903
01904 if ((u_char) ((high & mask) >> (8 * (sizeof(long) - 1))) & 0x80) {
01905
01906
01907
01908 add_null_byte = 1;
01909 intsize++;
01910 } else {
01911
01912
01913
01914
01915
01916
01917 mask2 = ((u_long) 0x1FF) << ((8 * (sizeof(long) - 1)) - 1);
01918
01919
01920
01921 while ((((high & mask2) == 0) || ((high & mask2) == mask2))
01922 && intsize > 1) {
01923 intsize--;
01924 high = (high << 8)
01925 | ((low & mask) >> (8 * (sizeof(long) - 1)));
01926 low <<= 8;
01927 }
01928 }
01929 #ifdef OPAQUE_SPECIAL_TYPES
01930
01931
01932
01933
01934
01935
01936 if (type == ASN_OPAQUE_COUNTER64) {
01937
01938
01939
01940 data = asn_build_header(data, datalength, ASN_OPAQUE, intsize + 3);
01941 if (_asn_build_header_check
01942 ("build counter u64", data, *datalength, intsize + 3))
01943 return NULL;
01944
01945
01946
01947
01948 *data++ = ASN_OPAQUE_TAG1;
01949 *data++ = ASN_OPAQUE_COUNTER64;
01950 *data++ = (u_char) intsize;
01951 *datalength = *datalength - 3;
01952 } else
01953
01954
01955
01956
01957
01958
01959 if (type == ASN_OPAQUE_U64) {
01960
01961
01962
01963 data = asn_build_header(data, datalength, ASN_OPAQUE, intsize + 3);
01964 if (_asn_build_header_check
01965 ("build opaque u64", data, *datalength, intsize + 3))
01966 return NULL;
01967
01968
01969
01970
01971 *data++ = ASN_OPAQUE_TAG1;
01972 *data++ = ASN_OPAQUE_U64;
01973 *data++ = (u_char) intsize;
01974 *datalength = *datalength - 3;
01975 } else {
01976 #endif
01977 data = asn_build_header(data, datalength, type, intsize);
01978 if (_asn_build_header_check
01979 ("build uint64", data, *datalength, intsize))
01980 return NULL;
01981
01982 #ifdef OPAQUE_SPECIAL_TYPES
01983 }
01984 #endif
01985 *datalength -= intsize;
01986 if (add_null_byte == 1) {
01987 *data++ = '\0';
01988 intsize--;
01989 }
01990 while (intsize--) {
01991 *data++ = (u_char) ((high & mask) >> (8 * (sizeof(long) - 1)));
01992 high = (high << 8)
01993 | ((low & mask) >> (8 * (sizeof(long) - 1)));
01994 low <<= 8;
01995
01996 }
01997 DEBUGDUMPSETUP("send", initdatap, data - initdatap);
01998 DEBUGIF("dumpv_send") {
01999 char i64buf[I64CHARSZ + 1];
02000 printU64(i64buf, cp);
02001 DEBUGMSG(("dumpv_send", i64buf));
02002 }
02003 return data;
02004 }
02005
02006 #ifdef OPAQUE_SPECIAL_TYPES
02007
02008
02032 u_char *
02033 asn_parse_signed_int64(u_char * data,
02034 size_t * datalength,
02035 u_char * type,
02036 struct counter64 * cp, size_t countersize)
02037 {
02038 static const char *errpre = "parse int64";
02039 const int int64sizelimit = (4 * 2) + 1;
02040 char ebuf[128];
02041 register u_char *bufp = data;
02042 u_long asn_length;
02043 register u_int low = 0, high = 0;
02044
02045 if (countersize != sizeof(struct counter64)) {
02046 _asn_size_err(errpre, countersize, sizeof(struct counter64));
02047 return NULL;
02048 }
02049 *type = *bufp++;
02050 bufp = asn_parse_length(bufp, &asn_length);
02051 if (_asn_parse_length_check
02052 (errpre, bufp, data, asn_length, *datalength))
02053 return NULL;
02054
02055 DEBUGDUMPSETUP("recv", data, bufp - data);
02056 if ((*type == ASN_OPAQUE) &&
02057 (asn_length <= ASN_OPAQUE_COUNTER64_MX_BER_LEN) &&
02058 (*bufp == ASN_OPAQUE_TAG1) && (*(bufp + 1) == ASN_OPAQUE_I64)) {
02059
02060
02061
02062 *type = *(bufp + 1);
02063
02064
02065
02066 bufp = asn_parse_length(bufp + 2, &asn_length);
02067 if (_asn_parse_length_check("parse opaque int64", bufp, data,
02068 asn_length, *datalength))
02069 return NULL;
02070 }
02071
02072
02073
02074 else {
02075 snprintf(ebuf, sizeof(ebuf),
02076 "%s: wrong type: %d, len %d, buf bytes (%02X,%02X)",
02077 errpre, *type, (int) asn_length, *bufp, *(bufp + 1));
02078 ebuf[ sizeof(ebuf)-1 ] = 0;
02079 ERROR_MSG(ebuf);
02080 return NULL;
02081 }
02082 if (((int) asn_length > int64sizelimit) ||
02083 (((int) asn_length == int64sizelimit) && *bufp != 0x00)) {
02084 _asn_length_err(errpre, (size_t) asn_length, int64sizelimit);
02085 return NULL;
02086 }
02087 *datalength -= (int) asn_length + (bufp - data);
02088 if (*bufp & 0x80) {
02089 low = 0xFFFFFF;
02090 high = 0xFFFFFF;
02091 }
02092
02093 while (asn_length--) {
02094 high = ((0x00FFFFFF & high) << 8) | ((low & 0xFF000000) >> 24);
02095 low = ((low & 0x00FFFFFF) << 8) | *bufp++;
02096 }
02097
02098 CHECK_OVERFLOW_U(high,8);
02099 CHECK_OVERFLOW_U(low,8);
02100
02101 cp->low = low;
02102 cp->high = high;
02103
02104 DEBUGIF("dumpv_recv") {
02105 char i64buf[I64CHARSZ + 1];
02106 printI64(i64buf, cp);
02107 DEBUGMSG(("dumpv_recv", "Integer64: %s", i64buf));
02108 }
02109
02110 return bufp;
02111 }
02112
02113
02114
02136 u_char *
02137 asn_build_signed_int64(u_char * data,
02138 size_t * datalength,
02139 u_char type,
02140 const struct counter64 * cp, size_t countersize)
02141 {
02142
02143
02144
02145
02146 struct counter64 c64;
02147 register u_int mask, mask2;
02148 u_long low, high;
02149 size_t intsize;
02150 #ifndef SNMP_NO_DEBUGGING
02151 u_char *initdatap = data;
02152 #endif
02153
02154 if (countersize != sizeof(struct counter64)) {
02155 _asn_size_err("build int64", countersize,
02156 sizeof(struct counter64));
02157 return NULL;
02158 }
02159 intsize = 8;
02160 memcpy(&c64, cp, sizeof(struct counter64));
02161 low = c64.low;
02162 high = c64.high;
02163
02164 CHECK_OVERFLOW_S(high,9);
02165 CHECK_OVERFLOW_U(low,9);
02166
02167
02168
02169
02170
02171
02172
02173 mask = ((u_int) 0xFF) << (8 * (sizeof(u_int) - 1));
02174 mask2 = ((u_int) 0x1FF) << ((8 * (sizeof(u_int) - 1)) - 1);
02175
02176
02177
02178 while ((((high & mask2) == 0) || ((high & mask2) == mask2))
02179 && intsize > 1) {
02180 intsize--;
02181 high = (high << 8)
02182 | ((low & mask) >> (8 * (sizeof(u_int) - 1)));
02183 low <<= 8;
02184 }
02185
02186
02187
02188
02189
02190
02191 data = asn_build_header(data, datalength, ASN_OPAQUE, intsize + 3);
02192 if (_asn_build_header_check
02193 ("build int64", data, *datalength, intsize + 3))
02194 return NULL;
02195
02196 *data++ = ASN_OPAQUE_TAG1;
02197 *data++ = ASN_OPAQUE_I64;
02198 *data++ = (u_char) intsize;
02199 *datalength -= (3 + intsize);
02200
02201 while (intsize--) {
02202 *data++ = (u_char) ((high & mask) >> (8 * (sizeof(u_int) - 1)));
02203 high = (high << 8)
02204 | ((low & mask) >> (8 * (sizeof(u_int) - 1)));
02205 low <<= 8;
02206 }
02207 DEBUGDUMPSETUP("send", initdatap, data - initdatap);
02208 DEBUGIF("dumpv_send") {
02209 char i64buf[I64CHARSZ + 1];
02210 printU64(i64buf, cp);
02211 DEBUGMSG(("dumpv_send", i64buf));
02212 }
02213 return data;
02214 }
02215
02216
02238 u_char *
02239 asn_parse_float(u_char * data,
02240 size_t * datalength,
02241 u_char * type, float *floatp, size_t floatsize)
02242 {
02243 register u_char *bufp = data;
02244 u_long asn_length;
02245 union {
02246 float floatVal;
02247 long longVal;
02248 u_char c[sizeof(float)];
02249 } fu;
02250
02251 if (floatsize != sizeof(float)) {
02252 _asn_size_err("parse float", floatsize, sizeof(float));
02253 return NULL;
02254 }
02255 *type = *bufp++;
02256 bufp = asn_parse_length(bufp, &asn_length);
02257 if (_asn_parse_length_check("parse float", bufp, data,
02258 asn_length, *datalength))
02259 return NULL;
02260
02261 DEBUGDUMPSETUP("recv", data, bufp - data + asn_length);
02262
02263
02264
02265 if ((*type == ASN_OPAQUE) &&
02266 (asn_length == ASN_OPAQUE_FLOAT_BER_LEN) &&
02267 (*bufp == ASN_OPAQUE_TAG1) && (*(bufp + 1) == ASN_OPAQUE_FLOAT)) {
02268
02269
02270
02271
02272 bufp = asn_parse_length(bufp + 2, &asn_length);
02273 if (_asn_parse_length_check("parse opaque float", bufp, data,
02274 asn_length, *datalength))
02275 return NULL;
02276
02277
02278
02279
02280 *type = ASN_OPAQUE_FLOAT;
02281 }
02282
02283 if (asn_length != sizeof(float)) {
02284 _asn_size_err("parse seq float", asn_length, sizeof(float));
02285 return NULL;
02286 }
02287
02288 *datalength -= (int) asn_length + (bufp - data);
02289 memcpy(&fu.c[0], bufp, asn_length);
02290
02291
02292
02293
02294 fu.longVal = ntohl(fu.longVal);
02295
02296 *floatp = fu.floatVal;
02297
02298 DEBUGMSG(("dumpv_recv", "Opaque float: %f\n", *floatp));
02299 return bufp;
02300 }
02301
02325 u_char *
02326 asn_build_float(u_char * data,
02327 size_t * datalength,
02328 u_char type, const float *floatp, size_t floatsize)
02329 {
02330 union {
02331 float floatVal;
02332 int intVal;
02333 u_char c[sizeof(float)];
02334 } fu;
02335 #ifndef SNMP_NO_DEBUGGING
02336 u_char *initdatap = data;
02337 #endif
02338
02339 if (floatsize != sizeof(float)) {
02340 _asn_size_err("build float", floatsize, sizeof(float));
02341 return NULL;
02342 }
02343
02344
02345
02346
02347
02348
02349
02350
02351
02352
02353 data = asn_build_header(data, datalength, ASN_OPAQUE, floatsize + 3);
02354 if (_asn_build_header_check
02355 ("build float", data, *datalength, (floatsize + 3)))
02356 return NULL;
02357
02358
02359
02360
02361 *data++ = ASN_OPAQUE_TAG1;
02362 *data++ = ASN_OPAQUE_FLOAT;
02363 *data++ = (u_char) floatsize;
02364 *datalength = *datalength - 3;
02365
02366 fu.floatVal = *floatp;
02367
02368
02369
02370 fu.intVal = htonl(fu.intVal);
02371
02372 *datalength -= floatsize;
02373 memcpy(data, &fu.c[0], floatsize);
02374
02375 DEBUGDUMPSETUP("send", initdatap, data - initdatap);
02376 DEBUGMSG(("dumpv_send", "Opaque float: %f\n", *floatp));
02377 data += floatsize;
02378 return data;
02379 }
02380
02381
02403 u_char *
02404 asn_parse_double(u_char * data,
02405 size_t * datalength,
02406 u_char * type, double *doublep, size_t doublesize)
02407 {
02408 register u_char *bufp = data;
02409 u_long asn_length;
02410 long tmp;
02411 union {
02412 double doubleVal;
02413 int intVal[2];
02414 u_char c[sizeof(double)];
02415 } fu;
02416
02417
02418 if (doublesize != sizeof(double)) {
02419 _asn_size_err("parse double", doublesize, sizeof(double));
02420 return NULL;
02421 }
02422 *type = *bufp++;
02423 bufp = asn_parse_length(bufp, &asn_length);
02424 if (_asn_parse_length_check("parse double", bufp, data,
02425 asn_length, *datalength))
02426 return NULL;
02427
02428 DEBUGDUMPSETUP("recv", data, bufp - data + asn_length);
02429
02430
02431
02432 if ((*type == ASN_OPAQUE) &&
02433 (asn_length == ASN_OPAQUE_DOUBLE_BER_LEN) &&
02434 (*bufp == ASN_OPAQUE_TAG1) && (*(bufp + 1) == ASN_OPAQUE_DOUBLE)) {
02435
02436
02437
02438
02439 bufp = asn_parse_length(bufp + 2, &asn_length);
02440 if (_asn_parse_length_check("parse opaque double", bufp, data,
02441 asn_length, *datalength))
02442 return NULL;
02443
02444
02445
02446
02447 *type = ASN_OPAQUE_DOUBLE;
02448 }
02449
02450 if (asn_length != sizeof(double)) {
02451 _asn_size_err("parse seq double", asn_length, sizeof(double));
02452 return NULL;
02453 }
02454 *datalength -= (int) asn_length + (bufp - data);
02455 memcpy(&fu.c[0], bufp, asn_length);
02456
02457
02458
02459
02460
02461 tmp = ntohl(fu.intVal[0]);
02462 fu.intVal[0] = ntohl(fu.intVal[1]);
02463 fu.intVal[1] = tmp;
02464
02465 *doublep = fu.doubleVal;
02466 DEBUGMSG(("dumpv_recv", " Opaque Double:\t%f\n", *doublep));
02467
02468 return bufp;
02469 }
02470
02471
02494 u_char *
02495 asn_build_double(u_char * data,
02496 size_t * datalength,
02497 u_char type, const double *doublep, size_t doublesize)
02498 {
02499 long tmp;
02500 union {
02501 double doubleVal;
02502 int intVal[2];
02503 u_char c[sizeof(double)];
02504 } fu;
02505 #ifndef SNMP_NO_DEBUGGING
02506 u_char *initdatap = data;
02507 #endif
02508
02509 if (doublesize != sizeof(double)) {
02510 _asn_size_err("build double", doublesize, sizeof(double));
02511 return NULL;
02512 }
02513
02514
02515
02516
02517
02518
02519
02520
02521
02522
02523
02524 data = asn_build_header(data, datalength, ASN_OPAQUE, doublesize + 3);
02525 if (_asn_build_header_check
02526 ("build double", data, *datalength, doublesize + 3))
02527 return NULL;
02528
02529
02530
02531
02532 *data++ = ASN_OPAQUE_TAG1;
02533 *data++ = ASN_OPAQUE_DOUBLE;
02534 *data++ = (u_char) doublesize;
02535 *datalength = *datalength - 3;
02536
02537 fu.doubleVal = *doublep;
02538
02539
02540
02541 tmp = htonl(fu.intVal[0]);
02542 fu.intVal[0] = htonl(fu.intVal[1]);
02543 fu.intVal[1] = tmp;
02544 *datalength -= doublesize;
02545 memcpy(data, &fu.c[0], doublesize);
02546
02547 data += doublesize;
02548 DEBUGDUMPSETUP("send", initdatap, data - initdatap);
02549 DEBUGMSG(("dumpv_send", " Opaque double: %f", *doublep));
02550 return data;
02551 }
02552
02553 #endif
02554
02555
02570 int
02571 asn_realloc(u_char ** pkt, size_t * pkt_len)
02572 {
02573 if (pkt != NULL && pkt_len != NULL) {
02574 size_t old_pkt_len = *pkt_len;
02575
02576 DEBUGMSGTL(("asn_realloc", " old_pkt %08p, old_pkt_len %08x\n",
02577 *pkt, old_pkt_len));
02578
02579 if (snmp_realloc(pkt, pkt_len)) {
02580 DEBUGMSGTL(("asn_realloc", " new_pkt %08p, new_pkt_len %08x\n",
02581 *pkt, *pkt_len));
02582 DEBUGMSGTL(("asn_realloc",
02583 " memmove(%08p + %08x, %08p, %08x)\n", *pkt,
02584 (*pkt_len - old_pkt_len), *pkt, old_pkt_len));
02585 memmove(*pkt + (*pkt_len - old_pkt_len), *pkt, old_pkt_len);
02586 memset(*pkt, (int) ' ', *pkt_len - old_pkt_len);
02587 return 1;
02588 } else {
02589 DEBUGMSG(("asn_realloc", " CANNOT REALLOC()\n"));
02590 }
02591 }
02592 return 0;
02593 }
02594
02595 #ifdef USE_REVERSE_ASNENCODING
02596
02611 int
02612 asn_realloc_rbuild_length(u_char ** pkt, size_t * pkt_len,
02613 size_t * offset, int r, size_t length)
02614 {
02615 static const char *errpre = "build length";
02616 char ebuf[128];
02617 int tmp_int;
02618 size_t start_offset = *offset;
02619
02620 if (length <= 0x7f) {
02621 if (((*pkt_len - *offset) < 1)
02622 && !(r && asn_realloc(pkt, pkt_len))) {
02623 snprintf(ebuf, sizeof(ebuf),
02624 "%s: bad length < 1 :%ld, %lu", errpre,
02625 (long)(*pkt_len - *offset), (unsigned long)length);
02626 ebuf[ sizeof(ebuf)-1 ] = 0;
02627 ERROR_MSG(ebuf);
02628 return 0;
02629 }
02630 *(*pkt + *pkt_len - (++*offset)) = length;
02631 } else {
02632 while (length > 0xff) {
02633 if (((*pkt_len - *offset) < 1)
02634 && !(r && asn_realloc(pkt, pkt_len))) {
02635 snprintf(ebuf, sizeof(ebuf),
02636 "%s: bad length < 1 :%ld, %lu", errpre,
02637 (long)(*pkt_len - *offset), (unsigned long)length);
02638 ebuf[ sizeof(ebuf)-1 ] = 0;
02639 ERROR_MSG(ebuf);
02640 return 0;
02641 }
02642 *(*pkt + *pkt_len - (++*offset)) = length & 0xff;
02643 length >>= 8;
02644 }
02645
02646 while ((*pkt_len - *offset) < 2) {
02647 if (!(r && asn_realloc(pkt, pkt_len))) {
02648 snprintf(ebuf, sizeof(ebuf),
02649 "%s: bad length < 1 :%ld, %lu", errpre,
02650 (long)(*pkt_len - *offset), (unsigned long)length);
02651 ebuf[ sizeof(ebuf)-1 ] = 0;
02652 ERROR_MSG(ebuf);
02653 return 0;
02654 }
02655 }
02656
02657 *(*pkt + *pkt_len - (++*offset)) = length & 0xff;
02658 tmp_int = *offset - start_offset;
02659 *(*pkt + *pkt_len - (++*offset)) = tmp_int | 0x80;
02660 }
02661
02662 return 1;
02663 }
02664
02682 int
02683 asn_realloc_rbuild_header(u_char ** pkt, size_t * pkt_len,
02684 size_t * offset, int r,
02685 u_char type, size_t length)
02686 {
02687 char ebuf[128];
02688
02689 if (asn_realloc_rbuild_length(pkt, pkt_len, offset, r, length)) {
02690 if (((*pkt_len - *offset) < 1)
02691 && !(r && asn_realloc(pkt, pkt_len))) {
02692 snprintf(ebuf, sizeof(ebuf),
02693 "bad header length < 1 :%ld, %lu",
02694 (long)(*pkt_len - *offset), (unsigned long)length);
02695 ebuf[ sizeof(ebuf)-1 ] = 0;
02696 ERROR_MSG(ebuf);
02697 return 0;
02698 }
02699 *(*pkt + *pkt_len - (++*offset)) = type;
02700 return 1;
02701 }
02702 return 0;
02703 }
02704
02722 int
02723 asn_realloc_rbuild_int(u_char ** pkt, size_t * pkt_len,
02724 size_t * offset, int r,
02725 u_char type, const long *intp, size_t intsize)
02726 {
02727 static const char *errpre = "build int";
02728 register long integer = *intp;
02729 int testvalue;
02730 size_t start_offset = *offset;
02731
02732 if (intsize != sizeof(long)) {
02733 _asn_size_err(errpre, intsize, sizeof(long));
02734 return 0;
02735 }
02736
02737 CHECK_OVERFLOW_S(integer,10);
02738 testvalue = (*intp < 0) ? -1 : 0;
02739
02740 if (((*pkt_len - *offset) < 1) && !(r && asn_realloc(pkt, pkt_len))) {
02741 return 0;
02742 }
02743 *(*pkt + *pkt_len - (++*offset)) = (u_char) integer;
02744 integer >>= 8;
02745
02746 while (integer != testvalue) {
02747 if (((*pkt_len - *offset) < 1)
02748 && !(r && asn_realloc(pkt, pkt_len))) {
02749 return 0;
02750 }
02751 *(*pkt + *pkt_len - (++*offset)) = (u_char) integer;
02752 integer >>= 8;
02753 }
02754
02755 if ((*(*pkt + *pkt_len - *offset) & 0x80) != (testvalue & 0x80)) {
02756
02757
02758
02759
02760 if (((*pkt_len - *offset) < 1)
02761 && !(r && asn_realloc(pkt, pkt_len))) {
02762 return 0;
02763 }
02764 *(*pkt + *pkt_len - (++*offset)) = testvalue & 0xff;
02765 }
02766
02767 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r, type,
02768 (*offset - start_offset))) {
02769 if (_asn_realloc_build_header_check(errpre, pkt, pkt_len,
02770 (*offset - start_offset))) {
02771 return 0;
02772 } else {
02773 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset),
02774 (*offset - start_offset));
02775 DEBUGMSG(("dumpv_send", " Integer:\t%ld (0x%.2X)\n", *intp,
02776 *intp));
02777 return 1;
02778 }
02779 }
02780
02781 return 0;
02782 }
02783
02802 int
02803 asn_realloc_rbuild_string(u_char ** pkt, size_t * pkt_len,
02804 size_t * offset, int r,
02805 u_char type,
02806 const u_char * str, size_t strlength)
02807 {
02808 static const char *errpre = "build string";
02809 size_t start_offset = *offset;
02810
02811 while ((*pkt_len - *offset) < strlength) {
02812 if (!(r && asn_realloc(pkt, pkt_len))) {
02813 return 0;
02814 }
02815 }
02816
02817 *offset += strlength;
02818 memcpy(*pkt + *pkt_len - *offset, str, strlength);
02819
02820 if (asn_realloc_rbuild_header
02821 (pkt, pkt_len, offset, r, type, strlength)) {
02822 if (_asn_realloc_build_header_check
02823 (errpre, pkt, pkt_len, strlength)) {
02824 return 0;
02825 } else {
02826 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset),
02827 *offset - start_offset);
02828 DEBUGIF("dumpv_send") {
02829 if (strlength == 0) {
02830 DEBUGMSG(("dumpv_send", " String: [NULL]\n"));
02831 } else {
02832 u_char *buf = (u_char *) malloc(2 * strlength);
02833 size_t l =
02834 (buf != NULL) ? (2 * strlength) : 0, ol = 0;
02835
02836 if (sprint_realloc_asciistring
02837 (&buf, &l, &ol, 1, str, strlength)) {
02838 DEBUGMSG(("dumpv_send", " String:\t%s\n", buf));
02839 } else {
02840 if (buf == NULL) {
02841 DEBUGMSG(("dumpv_send",
02842 " String:\t[TRUNCATED]\n"));
02843 } else {
02844 DEBUGMSG(("dumpv_send",
02845 " String:\t%s [TRUNCATED]\n", buf));
02846 }
02847 }
02848 if (buf != NULL) {
02849 free(buf);
02850 }
02851 }
02852 }
02853 }
02854 return 1;
02855 }
02856
02857 return 0;
02858 }
02859
02877 int
02878 asn_realloc_rbuild_unsigned_int(u_char ** pkt, size_t * pkt_len,
02879 size_t * offset, int r,
02880 u_char type, const u_long * intp, size_t intsize)
02881 {
02882 static const char *errpre = "build uint";
02883 register u_long integer = *intp;
02884 size_t start_offset = *offset;
02885
02886 if (intsize != sizeof(unsigned long)) {
02887 _asn_size_err(errpre, intsize, sizeof(unsigned long));
02888 return 0;
02889 }
02890
02891 CHECK_OVERFLOW_U(integer,11);
02892
02893 if (((*pkt_len - *offset) < 1) && !(r && asn_realloc(pkt, pkt_len))) {
02894 return 0;
02895 }
02896 *(*pkt + *pkt_len - (++*offset)) = (u_char) integer;
02897 integer >>= 8;
02898
02899 while (integer != 0) {
02900 if (((*pkt_len - *offset) < 1)
02901 && !(r && asn_realloc(pkt, pkt_len))) {
02902 return 0;
02903 }
02904 *(*pkt + *pkt_len - (++*offset)) = (u_char) integer;
02905 integer >>= 8;
02906 }
02907
02908 if ((*(*pkt + *pkt_len - *offset) & 0x80) != (0 & 0x80)) {
02909
02910
02911
02912
02913 if (((*pkt_len - *offset) < 1)
02914 && !(r && asn_realloc(pkt, pkt_len))) {
02915 return 0;
02916 }
02917 *(*pkt + *pkt_len - (++*offset)) = 0;
02918 }
02919
02920 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r, type,
02921 (*offset - start_offset))) {
02922 if (_asn_realloc_build_header_check(errpre, pkt, pkt_len,
02923 (*offset - start_offset))) {
02924 return 0;
02925 } else {
02926 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset),
02927 (*offset - start_offset));
02928 DEBUGMSG(("dumpv_send", " UInteger:\t%lu (0x%.2X)\n", *intp,
02929 *intp));
02930 return 1;
02931 }
02932 }
02933
02934 return 0;
02935 }
02936
02954 int
02955 asn_realloc_rbuild_sequence(u_char ** pkt, size_t * pkt_len,
02956 size_t * offset, int r,
02957 u_char type, size_t length)
02958 {
02959 return asn_realloc_rbuild_header(pkt, pkt_len, offset, r, type,
02960 length);
02961 }
02962
02981 int
02982 asn_realloc_rbuild_objid(u_char ** pkt, size_t * pkt_len,
02983 size_t * offset, int r,
02984 u_char type,
02985 const oid * objid, size_t objidlength)
02986 {
02987
02988
02989
02990
02991
02992
02993 register size_t i;
02994 register oid tmpint;
02995 size_t start_offset = *offset;
02996 const char *errpre = "build objid";
02997
02998
02999
03000
03001 if (objidlength == 0) {
03002
03003
03004
03005 while ((*pkt_len - *offset) < 2) {
03006 if (!(r && asn_realloc(pkt, pkt_len))) {
03007 return 0;
03008 }
03009 }
03010
03011 *(*pkt + *pkt_len - (++*offset)) = 0;
03012 *(*pkt + *pkt_len - (++*offset)) = 0;
03013 } else if (objid[0] > 2) {
03014 ERROR_MSG("build objid: bad first subidentifier");
03015 return 0;
03016 } else if (objidlength == 1) {
03017
03018
03019
03020 if (((*pkt_len - *offset) < 1)
03021 && !(r && asn_realloc(pkt, pkt_len))) {
03022 return 0;
03023 }
03024 *(*pkt + *pkt_len - (++*offset)) = (u_char) objid[0];
03025 } else {
03026 for (i = objidlength; i > 2; i--) {
03027 tmpint = objid[i - 1];
03028 CHECK_OVERFLOW_U(tmpint,12);
03029
03030 if (((*pkt_len - *offset) < 1)
03031 && !(r && asn_realloc(pkt, pkt_len))) {
03032 return 0;
03033 }
03034 *(*pkt + *pkt_len - (++*offset)) = (u_char) tmpint & 0x7f;
03035 tmpint >>= 7;
03036
03037 while (tmpint > 0) {
03038 if (((*pkt_len - *offset) < 1)
03039 && !(r && asn_realloc(pkt, pkt_len))) {
03040 return 0;
03041 }
03042 *(*pkt + *pkt_len - (++*offset)) =
03043 (u_char) ((tmpint & 0x7f) | 0x80);
03044 tmpint >>= 7;
03045 }
03046 }
03047
03048
03049
03050
03051 if ((objid[1] > 40) &&
03052 (objid[0] < 2)) {
03053 ERROR_MSG("build objid: bad second subidentifier");
03054 return 0;
03055 }
03056 tmpint = ((objid[0] * 40) + objid[1]);
03057 if (((*pkt_len - *offset) < 1)
03058 && !(r && asn_realloc(pkt, pkt_len))) {
03059 return 0;
03060 }
03061 *(*pkt + *pkt_len - (++*offset)) = (u_char) tmpint & 0x7f;
03062 tmpint >>= 7;
03063
03064 while (tmpint > 0) {
03065 if (((*pkt_len - *offset) < 1)
03066 && !(r && asn_realloc(pkt, pkt_len))) {
03067 return 0;
03068 }
03069 *(*pkt + *pkt_len - (++*offset)) =
03070 (u_char) ((tmpint & 0x7f) | 0x80);
03071 tmpint >>= 7;
03072 }
03073 }
03074
03075 tmpint = *offset - start_offset;
03076 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r, type,
03077 (*offset - start_offset))) {
03078 if (_asn_realloc_build_header_check(errpre, pkt, pkt_len,
03079 (*offset - start_offset))) {
03080 return 0;
03081 } else {
03082 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset),
03083 (*offset - start_offset));
03084 DEBUGMSG(("dumpv_send", " ObjID: "));
03085 DEBUGMSGOID(("dumpv_send", objid, objidlength));
03086 DEBUGMSG(("dumpv_send", "\n"));
03087 return 1;
03088 }
03089 }
03090
03091 return 0;
03092 }
03093
03110 int
03111 asn_realloc_rbuild_null(u_char ** pkt, size_t * pkt_len,
03112 size_t * offset, int r, u_char type)
03113 {
03114
03115
03116
03117 size_t start_offset = *offset;
03118
03119 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r, type, 0)) {
03120 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset),
03121 (*offset - start_offset));
03122 DEBUGMSG(("dumpv_send", " NULL\n"));
03123 return 1;
03124 } else {
03125 return 0;
03126 }
03127 }
03128
03147 int
03148 asn_realloc_rbuild_bitstring(u_char ** pkt, size_t * pkt_len,
03149 size_t * offset, int r,
03150 u_char type,
03151 const u_char * str, size_t strlength)
03152 {
03153
03154
03155
03156 static const char *errpre = "build bitstring";
03157 size_t start_offset = *offset;
03158
03159 while ((*pkt_len - *offset) < strlength) {
03160 if (!(r && asn_realloc(pkt, pkt_len))) {
03161 return 0;
03162 }
03163 }
03164
03165 *offset += strlength;
03166 memcpy(*pkt + *pkt_len - *offset, str, strlength);
03167
03168 if (asn_realloc_rbuild_header
03169 (pkt, pkt_len, offset, r, type, strlength)) {
03170 if (_asn_realloc_build_header_check
03171 (errpre, pkt, pkt_len, strlength)) {
03172 return 0;
03173 } else {
03174 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset),
03175 *offset - start_offset);
03176 DEBUGIF("dumpv_send") {
03177 if (strlength == 0) {
03178 DEBUGMSG(("dumpv_send", " Bitstring: [NULL]\n"));
03179 } else {
03180 u_char *buf = (u_char *) malloc(2 * strlength);
03181 size_t l =
03182 (buf != NULL) ? (2 * strlength) : 0, ol = 0;
03183
03184 if (sprint_realloc_asciistring
03185 (&buf, &l, &ol, 1, str, strlength)) {
03186 DEBUGMSG(("dumpv_send", " Bitstring:\t%s\n",
03187 buf));
03188 } else {
03189 if (buf == NULL) {
03190 DEBUGMSG(("dumpv_send",
03191 " Bitstring:\t[TRUNCATED]\n"));
03192 } else {
03193 DEBUGMSG(("dumpv_send",
03194 " Bitstring:\t%s [TRUNCATED]\n",
03195 buf));
03196 }
03197 }
03198 if (buf != NULL) {
03199 free(buf);
03200 }
03201 }
03202 }
03203 }
03204 return 1;
03205 }
03206
03207 return 0;
03208 }
03209
03227 int
03228 asn_realloc_rbuild_unsigned_int64(u_char ** pkt, size_t * pkt_len,
03229 size_t * offset, int r,
03230 u_char type,
03231 const struct counter64 *cp, size_t countersize)
03232 {
03233
03234
03235
03236 register u_long low = cp->low, high = cp->high;
03237 size_t intsize, start_offset = *offset;
03238 int count;
03239
03240 if (countersize != sizeof(struct counter64)) {
03241 _asn_size_err("build uint64", countersize,
03242 sizeof(struct counter64));
03243 return 0;
03244 }
03245
03246 CHECK_OVERFLOW_U(high,13);
03247 CHECK_OVERFLOW_U(low,13);
03248
03249
03250
03251
03252 if (((*pkt_len - *offset) < 1) && !(r && asn_realloc(pkt, pkt_len))) {
03253 return 0;
03254 }
03255 *(*pkt + *pkt_len - (++*offset)) = (u_char) low;
03256 low >>= 8;
03257 count = 1;
03258
03259 while (low != 0) {
03260 count++;
03261 if (((*pkt_len - *offset) < 1)
03262 && !(r && asn_realloc(pkt, pkt_len))) {
03263 return 0;
03264 }
03265 *(*pkt + *pkt_len - (++*offset)) = (u_char) low;
03266 low >>= 8;
03267 }
03268
03269
03270
03271
03272 if (high) {
03273
03274
03275
03276 for (; count < 4; count++) {
03277 if (((*pkt_len - *offset) < 1)
03278 && !(r && asn_realloc(pkt, pkt_len))) {
03279 return 0;
03280 }
03281 *(*pkt + *pkt_len - (++*offset)) = 0;
03282 }
03283
03284
03285
03286
03287 if (((*pkt_len - *offset) < 1)
03288 && !(r && asn_realloc(pkt, pkt_len))) {
03289 return 0;
03290 }
03291 *(*pkt + *pkt_len - (++*offset)) = (u_char) high;
03292 high >>= 8;
03293
03294 while (high != 0) {
03295 if (((*pkt_len - *offset) < 1)
03296 && !(r && asn_realloc(pkt, pkt_len))) {
03297 return 0;
03298 }
03299 *(*pkt + *pkt_len - (++*offset)) = (u_char) high;
03300 high >>= 8;
03301 }
03302 }
03303
03304 if ((*(*pkt + *pkt_len - *offset) & 0x80) != (0 & 0x80)) {
03305
03306
03307
03308
03309 if (((*pkt_len - *offset) < 1)
03310 && !(r && asn_realloc(pkt, pkt_len))) {
03311 return 0;
03312 }
03313 *(*pkt + *pkt_len - (++*offset)) = 0;
03314 }
03315
03316 intsize = *offset - start_offset;
03317
03318 #ifdef OPAQUE_SPECIAL_TYPES
03319
03320
03321
03322 if (type == ASN_OPAQUE_COUNTER64) {
03323 while ((*pkt_len - *offset) < 5) {
03324 if (!(r && asn_realloc(pkt, pkt_len))) {
03325 return 0;
03326 }
03327 }
03328
03329 *(*pkt + *pkt_len - (++*offset)) = (u_char) intsize;
03330 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_COUNTER64;
03331 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_TAG1;
03332
03333
03334
03335
03336 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r,
03337 ASN_OPAQUE, intsize + 3)) {
03338 if (_asn_realloc_build_header_check
03339 ("build counter u64", pkt, pkt_len, intsize + 3)) {
03340 return 0;
03341 }
03342 } else {
03343 return 0;
03344 }
03345 } else if (type == ASN_OPAQUE_U64) {
03346
03347
03348
03349 while ((*pkt_len - *offset) < 5) {
03350 if (!(r && asn_realloc(pkt, pkt_len))) {
03351 return 0;
03352 }
03353 }
03354
03355 *(*pkt + *pkt_len - (++*offset)) = (u_char) intsize;
03356 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_U64;
03357 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_TAG1;
03358
03359
03360
03361
03362 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r,
03363 ASN_OPAQUE, intsize + 3)) {
03364 if (_asn_realloc_build_header_check
03365 ("build counter u64", pkt, pkt_len, intsize + 3)) {
03366 return 0;
03367 }
03368 } else {
03369 return 0;
03370 }
03371 } else {
03372
03373 #endif
03374 if (asn_realloc_rbuild_header
03375 (pkt, pkt_len, offset, r, type, intsize)) {
03376 if (_asn_realloc_build_header_check
03377 ("build uint64", pkt, pkt_len, intsize)) {
03378 return 0;
03379 }
03380 } else {
03381 return 0;
03382 }
03383 #ifdef OPAQUE_SPECIAL_TYPES
03384 }
03385 #endif
03386
03387 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset), intsize);
03388 DEBUGMSG(("dumpv_send", " U64:\t%lu %lu\n", cp->high, cp->low));
03389 return 1;
03390 }
03391
03392 #ifdef OPAQUE_SPECIAL_TYPES
03393
03394
03412 int
03413 asn_realloc_rbuild_signed_int64(u_char ** pkt, size_t * pkt_len,
03414 size_t * offset, int r,
03415 u_char type,
03416 const struct counter64 *cp, size_t countersize)
03417 {
03418
03419
03420
03421 register long low = cp->low, high = cp->high;
03422 size_t intsize, start_offset = *offset;
03423 int count, testvalue = (high & 0x80000000) ? -1 : 0;
03424
03425 if (countersize != sizeof(struct counter64)) {
03426 _asn_size_err("build uint64", countersize,
03427 sizeof(struct counter64));
03428 return 0;
03429 }
03430
03431 CHECK_OVERFLOW_S(high,14);
03432 CHECK_OVERFLOW_U(low,14);
03433
03434
03435
03436
03437 if (((*pkt_len - *offset) < 1) && !(r && asn_realloc(pkt, pkt_len))) {
03438 return 0;
03439 }
03440 *(*pkt + *pkt_len - (++*offset)) = (u_char) low;
03441 low >>= 8;
03442 count = 1;
03443
03444 while ((int) low != testvalue && count < 4) {
03445 count++;
03446 if (((*pkt_len - *offset) < 1)
03447 && !(r && asn_realloc(pkt, pkt_len))) {
03448 return 0;
03449 }
03450 *(*pkt + *pkt_len - (++*offset)) = (u_char) low;
03451 low >>= 8;
03452 }
03453
03454
03455
03456
03457 if (high != testvalue) {
03458
03459
03460
03461 for (; count < 4; count++) {
03462 if (((*pkt_len - *offset) < 1)
03463 && !(r && asn_realloc(pkt, pkt_len))) {
03464 return 0;
03465 }
03466 *(*pkt + *pkt_len - (++*offset)) = (testvalue == 0) ? 0 : 0xff;
03467 }
03468
03469
03470
03471
03472 if (((*pkt_len - *offset) < 1)
03473 && !(r && asn_realloc(pkt, pkt_len))) {
03474 return 0;
03475 }
03476 *(*pkt + *pkt_len - (++*offset)) = (u_char) high;
03477 high >>= 8;
03478
03479 while ((int) high != testvalue) {
03480 if (((*pkt_len - *offset) < 1)
03481 && !(r && asn_realloc(pkt, pkt_len))) {
03482 return 0;
03483 }
03484 *(*pkt + *pkt_len - (++*offset)) = (u_char) high;
03485 high >>= 8;
03486 }
03487 }
03488
03489 if ((*(*pkt + *pkt_len - *offset) & 0x80) != (testvalue & 0x80)) {
03490
03491
03492
03493
03494 if (((*pkt_len - *offset) < 1)
03495 && !(r && asn_realloc(pkt, pkt_len))) {
03496 return 0;
03497 }
03498 *(*pkt + *pkt_len - (++*offset)) = (testvalue == 0) ? 0 : 0xff;
03499 }
03500
03501 intsize = *offset - start_offset;
03502
03503 while ((*pkt_len - *offset) < 5) {
03504 if (!(r && asn_realloc(pkt, pkt_len))) {
03505 return 0;
03506 }
03507 }
03508
03509 *(*pkt + *pkt_len - (++*offset)) = (u_char) intsize;
03510 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_I64;
03511 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_TAG1;
03512
03513
03514
03515
03516 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r,
03517 ASN_OPAQUE, intsize + 3)) {
03518 if (_asn_realloc_build_header_check
03519 ("build counter u64", pkt, pkt_len, intsize + 3)) {
03520 return 0;
03521 }
03522 } else {
03523 return 0;
03524 }
03525
03526 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset), intsize);
03527 DEBUGMSG(("dumpv_send", " UInt64:\t%lu %lu\n", cp->high, cp->low));
03528 return 1;
03529 }
03530
03549 int
03550 asn_realloc_rbuild_float(u_char ** pkt, size_t * pkt_len,
03551 size_t * offset, int r,
03552 u_char type, const float *floatp, size_t floatsize)
03553 {
03554 size_t start_offset = *offset;
03555 union {
03556 float floatVal;
03557 int intVal;
03558 u_char c[sizeof(float)];
03559 } fu;
03560
03561
03562
03563
03564 if (floatsize != sizeof(float) || floatsize > 122) {
03565 return 0;
03566 }
03567
03568 while ((*pkt_len - *offset) < floatsize + 3) {
03569 if (!(r && asn_realloc(pkt, pkt_len))) {
03570 return 0;
03571 }
03572 }
03573
03574
03575
03576
03577 fu.floatVal = *floatp;
03578 fu.intVal = htonl(fu.intVal);
03579 *offset += floatsize;
03580 memcpy(*pkt + *pkt_len - *offset, &(fu.c[0]), floatsize);
03581
03582
03583
03584
03585 *(*pkt + *pkt_len - (++*offset)) = (u_char) floatsize;
03586 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_FLOAT;
03587 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_TAG1;
03588
03589
03590
03591
03592 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r,
03593 ASN_OPAQUE, floatsize + 3)) {
03594 if (_asn_realloc_build_header_check("build float", pkt, pkt_len,
03595 floatsize + 3)) {
03596 return 0;
03597 } else {
03598 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset),
03599 *offset - start_offset);
03600 DEBUGMSG(("dumpv_send", "Opaque Float:\t%f\n", *floatp));
03601 return 1;
03602 }
03603 }
03604
03605 return 0;
03606 }
03607
03626 int
03627 asn_realloc_rbuild_double(u_char ** pkt, size_t * pkt_len,
03628 size_t * offset, int r,
03629 u_char type, const double *doublep, size_t doublesize)
03630 {
03631 size_t start_offset = *offset;
03632 long tmp;
03633 union {
03634 double doubleVal;
03635 int intVal[2];
03636 u_char c[sizeof(double)];
03637 } fu;
03638
03639
03640
03641
03642 if (doublesize != sizeof(double) || doublesize > 122) {
03643 return 0;
03644 }
03645
03646 while ((*pkt_len - *offset) < doublesize + 3) {
03647 if (!(r && asn_realloc(pkt, pkt_len))) {
03648 return 0;
03649 }
03650 }
03651
03652
03653
03654
03655 fu.doubleVal = *doublep;
03656 tmp = htonl(fu.intVal[0]);
03657 fu.intVal[0] = htonl(fu.intVal[1]);
03658 fu.intVal[1] = tmp;
03659 *offset += doublesize;
03660 memcpy(*pkt + *pkt_len - *offset, &(fu.c[0]), doublesize);
03661
03662
03663
03664
03665 *(*pkt + *pkt_len - (++*offset)) = (u_char) doublesize;
03666 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_DOUBLE;
03667 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_TAG1;
03668
03669
03670
03671
03672 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r,
03673 ASN_OPAQUE, doublesize + 3)) {
03674 if (_asn_realloc_build_header_check("build float", pkt, pkt_len,
03675 doublesize + 3)) {
03676 return 0;
03677 } else {
03678 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset),
03679 *offset - start_offset);
03680 DEBUGMSG(("dumpv_send", " Opaque Double:\t%f\n", *doublep));
03681 return 1;
03682 }
03683 }
03684
03685 return 0;
03686 }
03687
03688 #endif
03689 #endif
03690