net-snmp 5.7
|
00001 /* 00002 * Abstract Syntax Notation One, ASN.1 00003 * As defined in ISO/IS 8824 and ISO/IS 8825 00004 * This implements a subset of the above International Standards that 00005 * is sufficient to implement SNMP. 00006 * 00007 * Encodes abstract data types into a machine independent stream of bytes. 00008 * 00009 */ 00010 /********************************************************************** 00011 Copyright 1988, 1989, 1991, 1992 by Carnegie Mellon University 00012 00013 All Rights Reserved 00014 00015 Permission to use, copy, modify, and distribute this software and its 00016 documentation for any purpose and without fee is hereby granted, 00017 provided that the above copyright notice appear in all copies and that 00018 both that copyright notice and this permission notice appear in 00019 supporting documentation, and that the name of CMU not be 00020 used in advertising or publicity pertaining to distribution of the 00021 software without specific, written prior permission. 00022 00023 CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 00024 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 00025 CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 00026 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 00027 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 00028 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 00029 SOFTWARE. 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_NETINET_IN_H 00174 #include <netinet/in.h> 00175 #endif 00176 00177 #ifdef vms 00178 #include <in.h> 00179 #endif 00180 00181 #if HAVE_DMALLOC_H 00182 #include <dmalloc.h> 00183 #endif 00184 00185 #include <net-snmp/output_api.h> 00186 #include <net-snmp/utilities.h> 00187 00188 #include <net-snmp/library/asn1.h> 00189 #include <net-snmp/library/int64.h> 00190 #include <net-snmp/library/mib.h> 00191 00192 #ifndef NULL 00193 #define NULL 0 00194 #endif 00195 00196 #include <net-snmp/library/snmp_api.h> 00197 00198 #ifndef INT32_MAX 00199 # define INT32_MAX 2147483647 00200 #endif 00201 00202 #ifndef INT32_MIN 00203 # define INT32_MIN (0 - INT32_MAX - 1) 00204 #endif 00205 00206 00207 #if SIZEOF_LONG == 4 00208 # define CHECK_OVERFLOW_S(x,y) 00209 # define CHECK_OVERFLOW_U(x,y) 00210 #else 00211 # define CHECK_OVERFLOW_S(x,y) do { \ 00212 if (x > INT32_MAX) { \ 00213 DEBUGMSG(("asn","truncating signed value %ld to 32 bits (%d)\n",(long)(x),y)); \ 00214 x &= 0xffffffff; \ 00215 } else if (x < INT32_MIN) { \ 00216 DEBUGMSG(("asn","truncating signed value %ld to 32 bits (%d)\n",(long)(x),y)); \ 00217 x = 0 - (x & 0xffffffff); \ 00218 } \ 00219 } while(0) 00220 00221 # define CHECK_OVERFLOW_U(x,y) do { \ 00222 if (x > UINT32_MAX) { \ 00223 x &= 0xffffffff; \ 00224 DEBUGMSG(("asn","truncating unsigned value to 32 bits (%d)\n",y)); \ 00225 } \ 00226 } while(0) 00227 #endif 00228 00237 static 00238 void 00239 _asn_size_err(const char *str, size_t wrongsize, size_t rightsize) 00240 { 00241 char ebuf[128]; 00242 00243 snprintf(ebuf, sizeof(ebuf), 00244 "%s size %lu: s/b %lu", str, 00245 (unsigned long)wrongsize, (unsigned long)rightsize); 00246 ebuf[ sizeof(ebuf)-1 ] = 0; 00247 ERROR_MSG(ebuf); 00248 } 00249 00257 static 00258 void 00259 _asn_type_err(const char *str, int wrongtype) 00260 { 00261 char ebuf[128]; 00262 00263 snprintf(ebuf, sizeof(ebuf), "%s type %d", str, wrongtype); 00264 ebuf[ sizeof(ebuf)-1 ] = 0; 00265 ERROR_MSG(ebuf); 00266 } 00267 00276 static 00277 void 00278 _asn_length_err(const char *str, size_t wrongsize, size_t rightsize) 00279 { 00280 char ebuf[128]; 00281 00282 snprintf(ebuf, sizeof(ebuf), 00283 "%s length %lu too large: exceeds %lu", str, 00284 (unsigned long)wrongsize, (unsigned long)rightsize); 00285 ebuf[ sizeof(ebuf)-1 ] = 0; 00286 ERROR_MSG(ebuf); 00287 } 00288 00301 static 00302 int 00303 _asn_parse_length_check(const char *str, 00304 const u_char * bufp, const u_char * data, 00305 u_long plen, size_t dlen) 00306 { 00307 char ebuf[128]; 00308 size_t header_len; 00309 00310 if (bufp == NULL) { 00311 /* 00312 * error message is set 00313 */ 00314 return 1; 00315 } 00316 header_len = bufp - data; 00317 if (plen > 0x7fffffff || header_len > 0x7fffffff || 00318 ((size_t) plen + header_len) > dlen) { 00319 snprintf(ebuf, sizeof(ebuf), 00320 "%s: message overflow: %d len + %d delta > %d len", 00321 str, (int) plen, (int) header_len, (int) dlen); 00322 ebuf[ sizeof(ebuf)-1 ] = 0; 00323 ERROR_MSG(ebuf); 00324 return 1; 00325 } 00326 return 0; 00327 } 00328 00329 00341 static 00342 int 00343 _asn_build_header_check(const char *str, const u_char * data, 00344 size_t datalen, size_t typedlen) 00345 { 00346 char ebuf[128]; 00347 00348 if (data == NULL) { 00349 /* 00350 * error message is set 00351 */ 00352 return 1; 00353 } 00354 if (datalen < typedlen) { 00355 snprintf(ebuf, sizeof(ebuf), 00356 "%s: bad header, length too short: %lu < %lu", str, 00357 (unsigned long)datalen, (unsigned long)typedlen); 00358 ebuf[ sizeof(ebuf)-1 ] = 0; 00359 ERROR_MSG(ebuf); 00360 return 1; 00361 } 00362 return 0; 00363 } 00364 00376 static 00377 int 00378 _asn_realloc_build_header_check(const char *str, 00379 u_char ** pkt, 00380 const size_t * pkt_len, size_t typedlen) 00381 { 00382 char ebuf[128]; 00383 00384 if (pkt == NULL || *pkt == NULL) { 00385 /* 00386 * Error message is set. 00387 */ 00388 return 1; 00389 } 00390 00391 if (*pkt_len < typedlen) { 00392 snprintf(ebuf, sizeof(ebuf), 00393 "%s: bad header, length too short: %lu < %lu", str, 00394 (unsigned long)*pkt_len, (unsigned long)typedlen); 00395 ebuf[ sizeof(ebuf)-1 ] = 0; 00396 ERROR_MSG(ebuf); 00397 return 1; 00398 } 00399 return 0; 00400 } 00401 00411 int 00412 asn_check_packet(u_char * pkt, size_t len) 00413 { 00414 u_long asn_length; 00415 00416 if (len < 2) 00417 return 0; /* always too short */ 00418 00419 if (*pkt != (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR)) 00420 return -1; /* wrong type */ 00421 00422 if (*(pkt + 1) & 0x80) { 00423 /* 00424 * long length 00425 */ 00426 if ((int) len < (int) (*(pkt + 1) & ~0x80) + 2) 00427 return 0; /* still to short, incomplete length */ 00428 asn_parse_length(pkt + 1, &asn_length); 00429 return (asn_length + 2 + (*(pkt + 1) & ~0x80)); 00430 } else { 00431 /* 00432 * short length 00433 */ 00434 return (*(pkt + 1) + 2); 00435 } 00436 } 00437 00438 static 00439 int 00440 _asn_bitstring_check(const char *str, size_t asn_length, u_char datum) 00441 { 00442 char ebuf[128]; 00443 00444 if (asn_length < 1) { 00445 snprintf(ebuf, sizeof(ebuf), 00446 "%s: length %d too small", str, (int) asn_length); 00447 ebuf[ sizeof(ebuf)-1 ] = 0; 00448 ERROR_MSG(ebuf); 00449 return 1; 00450 } 00451 /* 00452 * if (datum > 7){ 00453 * sprintf(ebuf,"%s: datum %d >7: too large", str, (int)(datum)); 00454 * ERROR_MSG(ebuf); 00455 * return 1; 00456 * } 00457 */ 00458 return 0; 00459 } 00460 00482 u_char * 00483 asn_parse_int(u_char * data, 00484 size_t * datalength, 00485 u_char * type, long *intp, size_t intsize) 00486 { 00487 /* 00488 * ASN.1 integer ::= 0x02 asnlength byte {byte}* 00489 */ 00490 static const char *errpre = "parse int"; 00491 register u_char *bufp = data; 00492 u_long asn_length; 00493 register long value = 0; 00494 00495 if (intsize != sizeof(long)) { 00496 _asn_size_err(errpre, intsize, sizeof(long)); 00497 return NULL; 00498 } 00499 *type = *bufp++; 00500 if (*type != ASN_INTEGER) { 00501 _asn_type_err(errpre, *type); 00502 return NULL; 00503 } 00504 00505 bufp = asn_parse_length(bufp, &asn_length); 00506 if (_asn_parse_length_check 00507 (errpre, bufp, data, asn_length, *datalength)) 00508 return NULL; 00509 00510 if ((size_t) asn_length > intsize) { 00511 _asn_length_err(errpre, (size_t) asn_length, intsize); 00512 return NULL; 00513 } 00514 00515 *datalength -= (int) asn_length + (bufp - data); 00516 if (*bufp & 0x80) 00517 value = -1; /* integer is negative */ 00518 00519 DEBUGDUMPSETUP("recv", data, bufp - data + asn_length); 00520 00521 while (asn_length--) 00522 value = (value << 8) | *bufp++; 00523 00524 CHECK_OVERFLOW_S(value,1); 00525 00526 DEBUGMSG(("dumpv_recv", " Integer:\t%ld (0x%.2lX)\n", value, value)); 00527 00528 *intp = value; 00529 return bufp; 00530 } 00531 00532 00554 u_char * 00555 asn_parse_unsigned_int(u_char * data, 00556 size_t * datalength, 00557 u_char * type, u_long * intp, size_t intsize) 00558 { 00559 /* 00560 * ASN.1 integer ::= 0x02 asnlength byte {byte}* 00561 */ 00562 static const char *errpre = "parse uint"; 00563 register u_char *bufp = data; 00564 u_long asn_length; 00565 register u_long value = 0; 00566 00567 if (intsize != sizeof(long)) { 00568 _asn_size_err(errpre, intsize, sizeof(long)); 00569 return NULL; 00570 } 00571 *type = *bufp++; 00572 if (*type != ASN_COUNTER && *type != ASN_GAUGE && *type != ASN_TIMETICKS 00573 && *type != ASN_UINTEGER) { 00574 _asn_type_err(errpre, *type); 00575 return NULL; 00576 } 00577 bufp = asn_parse_length(bufp, &asn_length); 00578 if (_asn_parse_length_check 00579 (errpre, bufp, data, asn_length, *datalength)) 00580 return NULL; 00581 00582 if ((asn_length > (intsize + 1)) || 00583 ((asn_length == intsize + 1) && *bufp != 0x00)) { 00584 _asn_length_err(errpre, (size_t) asn_length, intsize); 00585 return NULL; 00586 } 00587 *datalength -= (int) asn_length + (bufp - data); 00588 if (*bufp & 0x80) 00589 value = ~value; /* integer is negative */ 00590 00591 DEBUGDUMPSETUP("recv", data, bufp - data + asn_length); 00592 00593 while (asn_length--) 00594 value = (value << 8) | *bufp++; 00595 00596 CHECK_OVERFLOW_U(value,2); 00597 00598 DEBUGMSG(("dumpv_recv", " UInteger:\t%ld (0x%.2lX)\n", value, value)); 00599 00600 *intp = value; 00601 return bufp; 00602 } 00603 00604 00628 u_char * 00629 asn_build_int(u_char * data, 00630 size_t * datalength, u_char type, const long *intp, size_t intsize) 00631 { 00632 /* 00633 * ASN.1 integer ::= 0x02 asnlength byte {byte}* 00634 */ 00635 static const char *errpre = "build int"; 00636 register long integer; 00637 register u_long mask; 00638 #ifndef NETSNMP_NO_DEBUGGING 00639 u_char *initdatap = data; 00640 #endif 00641 00642 if (intsize != sizeof(long)) { 00643 _asn_size_err(errpre, intsize, sizeof(long)); 00644 return NULL; 00645 } 00646 integer = *intp; 00647 CHECK_OVERFLOW_S(integer,3); 00648 /* 00649 * Truncate "unnecessary" bytes off of the most significant end of this 00650 * 2's complement integer. There should be no sequence of 9 00651 * consecutive 1's or 0's at the most significant end of the 00652 * integer. 00653 */ 00654 mask = ((u_long) 0x1FF) << ((8 * (sizeof(long) - 1)) - 1); 00655 /* 00656 * mask is 0xFF800000 on a big-endian machine 00657 */ 00658 while ((((integer & mask) == 0) || ((integer & mask) == mask)) 00659 && intsize > 1) { 00660 intsize--; 00661 integer <<= 8; 00662 } 00663 data = asn_build_header(data, datalength, type, intsize); 00664 if (_asn_build_header_check(errpre, data, *datalength, intsize)) 00665 return NULL; 00666 00667 *datalength -= intsize; 00668 mask = ((u_long) 0xFF) << (8 * (sizeof(long) - 1)); 00669 /* 00670 * mask is 0xFF000000 on a big-endian machine 00671 */ 00672 while (intsize--) { 00673 *data++ = (u_char) ((integer & mask) >> (8 * (sizeof(long) - 1))); 00674 integer <<= 8; 00675 } 00676 DEBUGDUMPSETUP("send", initdatap, data - initdatap); 00677 DEBUGMSG(("dumpv_send", " Integer:\t%ld (0x%.2lX)\n", *intp, *intp)); 00678 return data; 00679 } 00680 00681 00682 00706 u_char * 00707 asn_build_unsigned_int(u_char * data, 00708 size_t * datalength, 00709 u_char type, const u_long * intp, size_t intsize) 00710 { 00711 /* 00712 * ASN.1 integer ::= 0x02 asnlength byte {byte}* 00713 */ 00714 static const char *errpre = "build uint"; 00715 register u_long integer; 00716 register u_long mask; 00717 int add_null_byte = 0; 00718 #ifndef NETSNMP_NO_DEBUGGING 00719 u_char *initdatap = data; 00720 #endif 00721 00722 if (intsize != sizeof(long)) { 00723 _asn_size_err(errpre, intsize, sizeof(long)); 00724 return NULL; 00725 } 00726 integer = *intp; 00727 CHECK_OVERFLOW_U(integer,4); 00728 00729 mask = ((u_long) 0xFF) << (8 * (sizeof(long) - 1)); 00730 /* 00731 * mask is 0xFF000000 on a big-endian machine 00732 */ 00733 if ((u_char) ((integer & mask) >> (8 * (sizeof(long) - 1))) & 0x80) { 00734 /* 00735 * if MSB is set 00736 */ 00737 add_null_byte = 1; 00738 intsize++; 00739 } else { 00740 /* 00741 * Truncate "unnecessary" bytes off of the most significant end of this 2's complement integer. 00742 * There should be no sequence of 9 consecutive 1's or 0's at the most significant end of the 00743 * integer. 00744 */ 00745 mask = ((u_long) 0x1FF) << ((8 * (sizeof(long) - 1)) - 1); 00746 /* 00747 * mask is 0xFF800000 on a big-endian machine 00748 */ 00749 while ((((integer & mask) == 0) || ((integer & mask) == mask)) 00750 && intsize > 1) { 00751 intsize--; 00752 integer <<= 8; 00753 } 00754 } 00755 data = asn_build_header(data, datalength, type, intsize); 00756 if (_asn_build_header_check(errpre, data, *datalength, intsize)) 00757 return NULL; 00758 00759 *datalength -= intsize; 00760 if (add_null_byte == 1) { 00761 *data++ = '\0'; 00762 intsize--; 00763 } 00764 mask = ((u_long) 0xFF) << (8 * (sizeof(long) - 1)); 00765 /* 00766 * mask is 0xFF000000 on a big-endian machine 00767 */ 00768 while (intsize--) { 00769 *data++ = (u_char) ((integer & mask) >> (8 * (sizeof(long) - 1))); 00770 integer <<= 8; 00771 } 00772 DEBUGDUMPSETUP("send", initdatap, data - initdatap); 00773 DEBUGMSG(("dumpv_send", " UInteger:\t%ld (0x%.2lX)\n", *intp, *intp)); 00774 return data; 00775 } 00776 00777 00806 u_char * 00807 asn_parse_string(u_char * data, 00808 size_t * datalength, 00809 u_char * type, u_char * str, size_t * strlength) 00810 { 00811 static const char *errpre = "parse string"; 00812 u_char *bufp = data; 00813 u_long asn_length; 00814 00815 *type = *bufp++; 00816 if (*type != ASN_OCTET_STR && *type != ASN_IPADDRESS && *type != ASN_OPAQUE 00817 && *type != ASN_NSAP) { 00818 _asn_type_err(errpre, *type); 00819 return NULL; 00820 } 00821 00822 bufp = asn_parse_length(bufp, &asn_length); 00823 if (_asn_parse_length_check 00824 (errpre, bufp, data, asn_length, *datalength)) { 00825 return NULL; 00826 } 00827 00828 if (asn_length > *strlength) { 00829 _asn_length_err(errpre, (size_t) asn_length, *strlength); 00830 return NULL; 00831 } 00832 00833 DEBUGDUMPSETUP("recv", data, bufp - data + asn_length); 00834 00835 memmove(str, bufp, asn_length); 00836 if (*strlength > asn_length) 00837 str[asn_length] = 0; 00838 *strlength = asn_length; 00839 *datalength -= asn_length + (bufp - data); 00840 00841 DEBUGIF("dumpv_recv") { 00842 u_char *buf = (u_char *) malloc(1 + asn_length); 00843 size_t l = (buf != NULL) ? (1 + asn_length) : 0, ol = 0; 00844 00845 if (sprint_realloc_asciistring 00846 (&buf, &l, &ol, 1, str, asn_length)) { 00847 DEBUGMSG(("dumpv_recv", " String:\t%s\n", buf)); 00848 } else { 00849 if (buf == NULL) { 00850 DEBUGMSG(("dumpv_recv", " String:\t[TRUNCATED]\n")); 00851 } else { 00852 DEBUGMSG(("dumpv_recv", " String:\t%s [TRUNCATED]\n", 00853 buf)); 00854 } 00855 } 00856 if (buf != NULL) { 00857 free(buf); 00858 } 00859 } 00860 00861 return bufp + asn_length; 00862 } 00863 00864 00887 u_char * 00888 asn_build_string(u_char * data, 00889 size_t * datalength, 00890 u_char type, const u_char * str, size_t strlength) 00891 { 00892 /* 00893 * ASN.1 octet string ::= primstring | cmpdstring 00894 * primstring ::= 0x04 asnlength byte {byte}* 00895 * cmpdstring ::= 0x24 asnlength string {string}* 00896 * This code will never send a compound string. 00897 */ 00898 #ifndef NETSNMP_NO_DEBUGGING 00899 u_char *initdatap = data; 00900 #endif 00901 data = asn_build_header(data, datalength, type, strlength); 00902 if (_asn_build_header_check 00903 ("build string", data, *datalength, strlength)) 00904 return NULL; 00905 00906 if (strlength) { 00907 if (str == NULL) { 00908 memset(data, 0, strlength); 00909 } else { 00910 memmove(data, str, strlength); 00911 } 00912 } 00913 *datalength -= strlength; 00914 DEBUGDUMPSETUP("send", initdatap, data - initdatap + strlength); 00915 DEBUGIF("dumpv_send") { 00916 u_char *buf = (u_char *) malloc(1 + strlength); 00917 size_t l = (buf != NULL) ? (1 + strlength) : 0, ol = 0; 00918 00919 if (sprint_realloc_asciistring 00920 (&buf, &l, &ol, 1, str, strlength)) { 00921 DEBUGMSG(("dumpv_send", " String:\t%s\n", buf)); 00922 } else { 00923 if (buf == NULL) { 00924 DEBUGMSG(("dumpv_send", " String:\t[TRUNCATED]\n")); 00925 } else { 00926 DEBUGMSG(("dumpv_send", " String:\t%s [TRUNCATED]\n", 00927 buf)); 00928 } 00929 } 00930 if (buf != NULL) { 00931 free(buf); 00932 } 00933 } 00934 return data + strlength; 00935 } 00936 00937 00938 00958 u_char * 00959 asn_parse_header(u_char * data, size_t * datalength, u_char * type) 00960 { 00961 register u_char *bufp; 00962 u_long asn_length; 00963 00964 if (!data || !datalength || !type) { 00965 ERROR_MSG("parse header: NULL pointer"); 00966 return NULL; 00967 } 00968 bufp = data; 00969 /* 00970 * this only works on data types < 30, i.e. no extension octets 00971 */ 00972 if (IS_EXTENSION_ID(*bufp)) { 00973 ERROR_MSG("can't process ID >= 30"); 00974 return NULL; 00975 } 00976 *type = *bufp; 00977 bufp = asn_parse_length(bufp + 1, &asn_length); 00978 00979 if (_asn_parse_length_check 00980 ("parse header", bufp, data, asn_length, *datalength)) 00981 return NULL; 00982 00983 #ifdef DUMP_PRINT_HEADERS 00984 DEBUGDUMPSETUP("recv", data, (bufp - data)); 00985 DEBUGMSG(("dumpv_recv", " Header: 0x%.2X, len = %d (0x%X)\n", *data, 00986 asn_length, asn_length)); 00987 #else 00988 /* 00989 * DEBUGMSGHEXTLI(("recv",data,(bufp-data))); 00990 * DEBUGMSG(("dumpH_recv","\n")); 00991 */ 00992 #endif 00993 00994 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES 00995 00996 if ((*type == ASN_OPAQUE) && (*bufp == ASN_OPAQUE_TAG1)) { 00997 00998 /* 00999 * check if 64-but counter 01000 */ 01001 switch (*(bufp + 1)) { 01002 case ASN_OPAQUE_COUNTER64: 01003 case ASN_OPAQUE_U64: 01004 case ASN_OPAQUE_FLOAT: 01005 case ASN_OPAQUE_DOUBLE: 01006 case ASN_OPAQUE_I64: 01007 *type = *(bufp + 1); 01008 break; 01009 01010 default: 01011 /* 01012 * just an Opaque 01013 */ 01014 *datalength = (int) asn_length; 01015 return bufp; 01016 } 01017 /* 01018 * value is encoded as special format 01019 */ 01020 bufp = asn_parse_length(bufp + 2, &asn_length); 01021 if (_asn_parse_length_check("parse opaque header", bufp, data, 01022 asn_length, *datalength)) 01023 return NULL; 01024 } 01025 #endif /* NETSNMP_WITH_OPAQUE_SPECIAL_TYPES */ 01026 01027 *datalength = (int) asn_length; 01028 01029 return bufp; 01030 } 01031 01046 u_char * 01047 asn_parse_sequence(u_char * data, size_t * datalength, u_char * type, u_char expected_type, /* must be this type */ 01048 const char *estr) 01049 { /* error message prefix */ 01050 data = asn_parse_header(data, datalength, type); 01051 if (data && (*type != expected_type)) { 01052 char ebuf[128]; 01053 snprintf(ebuf, sizeof(ebuf), 01054 "%s header type %02X: s/b %02X", estr, 01055 (u_char) * type, (u_char) expected_type); 01056 ebuf[ sizeof(ebuf)-1 ] = 0; 01057 ERROR_MSG(ebuf); 01058 return NULL; 01059 } 01060 return data; 01061 } 01062 01063 01064 01087 u_char * 01088 asn_build_header(u_char * data, 01089 size_t * datalength, u_char type, size_t length) 01090 { 01091 char ebuf[128]; 01092 01093 if (*datalength < 1) { 01094 snprintf(ebuf, sizeof(ebuf), 01095 "bad header length < 1 :%lu, %lu", 01096 (unsigned long)*datalength, (unsigned long)length); 01097 ebuf[ sizeof(ebuf)-1 ] = 0; 01098 ERROR_MSG(ebuf); 01099 return NULL; 01100 } 01101 *data++ = type; 01102 (*datalength)--; 01103 return asn_build_length(data, datalength, length); 01104 } 01105 01129 u_char * 01130 asn_build_sequence(u_char * data, 01131 size_t * datalength, u_char type, size_t length) 01132 { 01133 static const char *errpre = "build seq"; 01134 char ebuf[128]; 01135 01136 if (*datalength < 4) { 01137 snprintf(ebuf, sizeof(ebuf), 01138 "%s: length %d < 4: PUNT", errpre, 01139 (int) *datalength); 01140 ebuf[ sizeof(ebuf)-1 ] = 0; 01141 ERROR_MSG(ebuf); 01142 return NULL; 01143 } 01144 *datalength -= 4; 01145 *data++ = type; 01146 *data++ = (u_char) (0x02 | ASN_LONG_LEN); 01147 *data++ = (u_char) ((length >> 8) & 0xFF); 01148 *data++ = (u_char) (length & 0xFF); 01149 return data; 01150 } 01151 01169 u_char * 01170 asn_parse_length(u_char * data, u_long * length) 01171 { 01172 static const char *errpre = "parse length"; 01173 char ebuf[128]; 01174 register u_char lengthbyte; 01175 01176 if (!data || !length) { 01177 ERROR_MSG("parse length: NULL pointer"); 01178 return NULL; 01179 } 01180 lengthbyte = *data; 01181 01182 if (lengthbyte & ASN_LONG_LEN) { 01183 lengthbyte &= ~ASN_LONG_LEN; /* turn MSb off */ 01184 if (lengthbyte == 0) { 01185 snprintf(ebuf, sizeof(ebuf), 01186 "%s: indefinite length not supported", errpre); 01187 ebuf[ sizeof(ebuf)-1 ] = 0; 01188 ERROR_MSG(ebuf); 01189 return NULL; 01190 } 01191 if (lengthbyte > sizeof(long)) { 01192 snprintf(ebuf, sizeof(ebuf), 01193 "%s: data length %d > %lu not supported", errpre, 01194 lengthbyte, (unsigned long)sizeof(long)); 01195 ebuf[ sizeof(ebuf)-1 ] = 0; 01196 ERROR_MSG(ebuf); 01197 return NULL; 01198 } 01199 data++; 01200 *length = 0; /* protect against short lengths */ 01201 while (lengthbyte--) { 01202 *length <<= 8; 01203 *length |= *data++; 01204 } 01205 if ((long) *length < 0) { 01206 snprintf(ebuf, sizeof(ebuf), 01207 "%s: negative data length %ld\n", errpre, 01208 (long) *length); 01209 ebuf[ sizeof(ebuf)-1 ] = 0; 01210 ERROR_MSG(ebuf); 01211 return NULL; 01212 } 01213 return data; 01214 } else { /* short asnlength */ 01215 *length = (long) lengthbyte; 01216 return data + 1; 01217 } 01218 } 01219 01240 u_char * 01241 asn_build_length(u_char * data, size_t * datalength, size_t length) 01242 { 01243 static const char *errpre = "build length"; 01244 char ebuf[128]; 01245 01246 u_char *start_data = data; 01247 01248 /* 01249 * no indefinite lengths sent 01250 */ 01251 if (length < 0x80) { 01252 if (*datalength < 1) { 01253 snprintf(ebuf, sizeof(ebuf), 01254 "%s: bad length < 1 :%lu, %lu", errpre, 01255 (unsigned long)*datalength, (unsigned long)length); 01256 ebuf[ sizeof(ebuf)-1 ] = 0; 01257 ERROR_MSG(ebuf); 01258 return NULL; 01259 } 01260 *data++ = (u_char) length; 01261 } else if (length <= 0xFF) { 01262 if (*datalength < 2) { 01263 snprintf(ebuf, sizeof(ebuf), 01264 "%s: bad length < 2 :%lu, %lu", errpre, 01265 (unsigned long)*datalength, (unsigned long)length); 01266 ebuf[ sizeof(ebuf)-1 ] = 0; 01267 ERROR_MSG(ebuf); 01268 return NULL; 01269 } 01270 *data++ = (u_char) (0x01 | ASN_LONG_LEN); 01271 *data++ = (u_char) length; 01272 } else { /* 0xFF < length <= 0xFFFF */ 01273 if (*datalength < 3) { 01274 snprintf(ebuf, sizeof(ebuf), 01275 "%s: bad length < 3 :%lu, %lu", errpre, 01276 (unsigned long)*datalength, (unsigned long)length); 01277 ebuf[ sizeof(ebuf)-1 ] = 0; 01278 ERROR_MSG(ebuf); 01279 return NULL; 01280 } 01281 *data++ = (u_char) (0x02 | ASN_LONG_LEN); 01282 *data++ = (u_char) ((length >> 8) & 0xFF); 01283 *data++ = (u_char) (length & 0xFF); 01284 } 01285 *datalength -= (data - start_data); 01286 return data; 01287 01288 } 01289 01315 u_char * 01316 asn_parse_objid(u_char * data, 01317 size_t * datalength, 01318 u_char * type, oid * objid, size_t * objidlength) 01319 { 01320 static const char *errpre = "parse objid"; 01321 /* 01322 * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}* 01323 * subidentifier ::= {leadingbyte}* lastbyte 01324 * leadingbyte ::= 1 7bitvalue 01325 * lastbyte ::= 0 7bitvalue 01326 */ 01327 register u_char *bufp = data; 01328 register oid *oidp = objid + 1; 01329 register u_long subidentifier; 01330 register long length; 01331 u_long asn_length; 01332 size_t original_length = *objidlength; 01333 01334 *type = *bufp++; 01335 if (*type != ASN_OBJECT_ID) { 01336 _asn_type_err(errpre, *type); 01337 return NULL; 01338 } 01339 bufp = asn_parse_length(bufp, &asn_length); 01340 if (_asn_parse_length_check("parse objid", bufp, data, 01341 asn_length, *datalength)) 01342 return NULL; 01343 01344 *datalength -= (int) asn_length + (bufp - data); 01345 01346 DEBUGDUMPSETUP("recv", data, bufp - data + asn_length); 01347 01348 /* 01349 * Handle invalid object identifier encodings of the form 06 00 robustly 01350 */ 01351 if (asn_length == 0) 01352 objid[0] = objid[1] = 0; 01353 01354 length = asn_length; 01355 (*objidlength)--; /* account for expansion of first byte */ 01356 01357 while (length > 0 && (*objidlength)-- > 0) { 01358 subidentifier = 0; 01359 do { /* shift and add in low order 7 bits */ 01360 subidentifier = 01361 (subidentifier << 7) + (*(u_char *) bufp & ~ASN_BIT8); 01362 length--; 01363 } while ((*(u_char *) bufp++ & ASN_BIT8) && (length > 0)); /* last byte has high bit clear */ 01364 01365 if (length == 0) { 01366 u_char *last_byte = bufp - 1; 01367 if (*last_byte & ASN_BIT8) { 01368 /* last byte has high bit set -> wrong BER encoded OID */ 01369 ERROR_MSG("subidentifier syntax error"); 01370 return NULL; 01371 } 01372 } 01373 #if defined(EIGHTBIT_SUBIDS) || (SIZEOF_LONG != 4) 01374 if (subidentifier > (u_long) MAX_SUBID) { 01375 ERROR_MSG("subidentifier too large"); 01376 return NULL; 01377 } 01378 #endif 01379 *oidp++ = (oid) subidentifier; 01380 } 01381 01382 if (0 != length) { 01383 ERROR_MSG("OID length exceeds buffer size"); 01384 *objidlength = original_length; 01385 return NULL; 01386 } 01387 01388 /* 01389 * The first two subidentifiers are encoded into the first component 01390 * with the value (X * 40) + Y, where: 01391 * X is the value of the first subidentifier. 01392 * Y is the value of the second subidentifier. 01393 */ 01394 subidentifier = (u_long) objid[1]; 01395 if (subidentifier == 0x2B) { 01396 objid[0] = 1; 01397 objid[1] = 3; 01398 } else { 01399 if (subidentifier < 40) { 01400 objid[0] = 0; 01401 objid[1] = subidentifier; 01402 } else if (subidentifier < 80) { 01403 objid[0] = 1; 01404 objid[1] = subidentifier - 40; 01405 } else { 01406 objid[0] = 2; 01407 objid[1] = subidentifier - 80; 01408 } 01409 } 01410 01411 *objidlength = (int) (oidp - objid); 01412 01413 DEBUGMSG(("dumpv_recv", " ObjID: ")); 01414 DEBUGMSGOID(("dumpv_recv", objid, *objidlength)); 01415 DEBUGMSG(("dumpv_recv", "\n")); 01416 return bufp; 01417 } 01418 01442 u_char * 01443 asn_build_objid(u_char * data, 01444 size_t * datalength, 01445 u_char type, oid * objid, size_t objidlength) 01446 { 01447 /* 01448 * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}* 01449 * subidentifier ::= {leadingbyte}* lastbyte 01450 * leadingbyte ::= 1 7bitvalue 01451 * lastbyte ::= 0 7bitvalue 01452 */ 01453 size_t asnlength; 01454 register oid *op = objid; 01455 u_char objid_size[MAX_OID_LEN]; 01456 register u_long objid_val; 01457 u_long first_objid_val; 01458 register int i; 01459 #ifndef NETSNMP_NO_DEBUGGING 01460 u_char *initdatap = data; 01461 #endif 01462 01463 /* 01464 * check if there are at least 2 sub-identifiers 01465 */ 01466 if (objidlength == 0) { 01467 /* 01468 * there are not, so make OID have two with value of zero 01469 */ 01470 objid_val = 0; 01471 objidlength = 2; 01472 } else if (objid[0] > 2) { 01473 ERROR_MSG("build objid: bad first subidentifier"); 01474 return NULL; 01475 } else if (objidlength == 1) { 01476 /* 01477 * encode the first value 01478 */ 01479 objid_val = (op[0] * 40); 01480 objidlength = 2; 01481 op++; 01482 } else { 01483 /* 01484 * combine the first two values 01485 */ 01486 if ((op[1] > 40) && 01487 (op[0] < 2)) { 01488 ERROR_MSG("build objid: bad second subidentifier"); 01489 return NULL; 01490 } 01491 objid_val = (op[0] * 40) + op[1]; 01492 op += 2; 01493 } 01494 first_objid_val = objid_val; 01495 01496 /* 01497 * ditch illegal calls now 01498 */ 01499 if (objidlength > MAX_OID_LEN) 01500 return NULL; 01501 01502 /* 01503 * calculate the number of bytes needed to store the encoded value 01504 */ 01505 for (i = 1, asnlength = 0;;) { 01506 01507 CHECK_OVERFLOW_U(objid_val,5); 01508 if (objid_val < (unsigned) 0x80) { 01509 objid_size[i] = 1; 01510 asnlength += 1; 01511 } else if (objid_val < (unsigned) 0x4000) { 01512 objid_size[i] = 2; 01513 asnlength += 2; 01514 } else if (objid_val < (unsigned) 0x200000) { 01515 objid_size[i] = 3; 01516 asnlength += 3; 01517 } else if (objid_val < (unsigned) 0x10000000) { 01518 objid_size[i] = 4; 01519 asnlength += 4; 01520 } else { 01521 objid_size[i] = 5; 01522 asnlength += 5; 01523 } 01524 i++; 01525 if (i >= (int) objidlength) 01526 break; 01527 objid_val = *op++; /* XXX - doesn't handle 2.X (X > 40) */ 01528 } 01529 01530 /* 01531 * store the ASN.1 tag and length 01532 */ 01533 data = asn_build_header(data, datalength, type, asnlength); 01534 if (_asn_build_header_check 01535 ("build objid", data, *datalength, asnlength)) 01536 return NULL; 01537 01538 /* 01539 * store the encoded OID value 01540 */ 01541 for (i = 1, objid_val = first_objid_val, op = objid + 2; 01542 i < (int) objidlength; i++) { 01543 if (i != 1) { 01544 objid_val = *op++; 01545 #if SIZEOF_LONG != 4 01546 if (objid_val > 0xffffffff) /* already logged warning above */ 01547 objid_val &= 0xffffffff; 01548 #endif 01549 } 01550 switch (objid_size[i]) { 01551 case 1: 01552 *data++ = (u_char) objid_val; 01553 break; 01554 01555 case 2: 01556 *data++ = (u_char) ((objid_val >> 7) | 0x80); 01557 *data++ = (u_char) (objid_val & 0x07f); 01558 break; 01559 01560 case 3: 01561 *data++ = (u_char) ((objid_val >> 14) | 0x80); 01562 *data++ = (u_char) ((objid_val >> 7 & 0x7f) | 0x80); 01563 *data++ = (u_char) (objid_val & 0x07f); 01564 break; 01565 01566 case 4: 01567 *data++ = (u_char) ((objid_val >> 21) | 0x80); 01568 *data++ = (u_char) ((objid_val >> 14 & 0x7f) | 0x80); 01569 *data++ = (u_char) ((objid_val >> 7 & 0x7f) | 0x80); 01570 *data++ = (u_char) (objid_val & 0x07f); 01571 break; 01572 01573 case 5: 01574 *data++ = (u_char) ((objid_val >> 28) | 0x80); 01575 *data++ = (u_char) ((objid_val >> 21 & 0x7f) | 0x80); 01576 *data++ = (u_char) ((objid_val >> 14 & 0x7f) | 0x80); 01577 *data++ = (u_char) ((objid_val >> 7 & 0x7f) | 0x80); 01578 *data++ = (u_char) (objid_val & 0x07f); 01579 break; 01580 } 01581 } 01582 01583 /* 01584 * return the length and data ptr 01585 */ 01586 *datalength -= asnlength; 01587 DEBUGDUMPSETUP("send", initdatap, data - initdatap); 01588 DEBUGMSG(("dumpv_send", " ObjID: ")); 01589 DEBUGMSGOID(("dumpv_send", objid, objidlength)); 01590 DEBUGMSG(("dumpv_send", "\n")); 01591 return data; 01592 } 01593 01613 u_char * 01614 asn_parse_null(u_char * data, size_t * datalength, u_char * type) 01615 { 01616 /* 01617 * ASN.1 null ::= 0x05 0x00 01618 */ 01619 register u_char *bufp = data; 01620 u_long asn_length; 01621 01622 *type = *bufp++; 01623 bufp = asn_parse_length(bufp, &asn_length); 01624 if (bufp == NULL) { 01625 ERROR_MSG("parse null: bad length"); 01626 return NULL; 01627 } 01628 if (asn_length != 0) { 01629 ERROR_MSG("parse null: malformed ASN.1 null"); 01630 return NULL; 01631 } 01632 01633 *datalength -= (bufp - data); 01634 01635 DEBUGDUMPSETUP("recv", data, bufp - data); 01636 DEBUGMSG(("dumpv_recv", " NULL\n")); 01637 01638 return bufp + asn_length; 01639 } 01640 01641 01662 u_char * 01663 asn_build_null(u_char * data, size_t * datalength, u_char type) 01664 { 01665 /* 01666 * ASN.1 null ::= 0x05 0x00 01667 */ 01668 #ifndef NETSNMP_NO_DEBUGGING 01669 u_char *initdatap = data; 01670 #endif 01671 data = asn_build_header(data, datalength, type, 0); 01672 DEBUGDUMPSETUP("send", initdatap, data - initdatap); 01673 DEBUGMSG(("dumpv_send", " NULL\n")); 01674 return data; 01675 } 01676 01700 u_char * 01701 asn_parse_bitstring(u_char * data, 01702 size_t * datalength, 01703 u_char * type, u_char * str, size_t * strlength) 01704 { 01705 /* 01706 * bitstring ::= 0x03 asnlength unused {byte}* 01707 */ 01708 static const char *errpre = "parse bitstring"; 01709 register u_char *bufp = data; 01710 u_long asn_length; 01711 01712 *type = *bufp++; 01713 if (*type != ASN_BIT_STR) { 01714 _asn_type_err(errpre, *type); 01715 return NULL; 01716 } 01717 bufp = asn_parse_length(bufp, &asn_length); 01718 if (_asn_parse_length_check(errpre, bufp, data, 01719 asn_length, *datalength)) 01720 return NULL; 01721 01722 if ((size_t) asn_length > *strlength) { 01723 _asn_length_err(errpre, (size_t) asn_length, *strlength); 01724 return NULL; 01725 } 01726 if (_asn_bitstring_check(errpre, asn_length, *bufp)) 01727 return NULL; 01728 01729 DEBUGDUMPSETUP("recv", data, bufp - data); 01730 DEBUGMSG(("dumpv_recv", " Bitstring: ")); 01731 DEBUGMSGHEX(("dumpv_recv", data, asn_length)); 01732 DEBUGMSG(("dumpv_recv", "\n")); 01733 01734 memmove(str, bufp, asn_length); 01735 *strlength = (int) asn_length; 01736 *datalength -= (int) asn_length + (bufp - data); 01737 return bufp + asn_length; 01738 } 01739 01740 01763 u_char * 01764 asn_build_bitstring(u_char * data, 01765 size_t * datalength, 01766 u_char type, const u_char * str, size_t strlength) 01767 { 01768 /* 01769 * ASN.1 bit string ::= 0x03 asnlength unused {byte}* 01770 */ 01771 static const char *errpre = "build bitstring"; 01772 if (_asn_bitstring_check 01773 (errpre, strlength, (u_char)((str) ? *str : 0))) 01774 return NULL; 01775 01776 data = asn_build_header(data, datalength, type, strlength); 01777 if (_asn_build_header_check(errpre, data, *datalength, strlength)) 01778 return NULL; 01779 01780 if (strlength > 0 && str) 01781 memmove(data, str, strlength); 01782 else if (strlength > 0 && !str) { 01783 ERROR_MSG("no string passed into asn_build_bitstring\n"); 01784 return NULL; 01785 } 01786 01787 *datalength -= strlength; 01788 DEBUGDUMPSETUP("send", data, strlength); 01789 DEBUGMSG(("dumpv_send", " Bitstring: ")); 01790 DEBUGMSGHEX(("dumpv_send", data, strlength)); 01791 DEBUGMSG(("dumpv_send", "\n")); 01792 return data + strlength; 01793 } 01794 01817 u_char * 01818 asn_parse_unsigned_int64(u_char * data, 01819 size_t * datalength, 01820 u_char * type, 01821 struct counter64 * cp, size_t countersize) 01822 { 01823 /* 01824 * ASN.1 integer ::= 0x02 asnlength byte {byte}* 01825 */ 01826 static const char *errpre = "parse uint64"; 01827 const int uint64sizelimit = (4 * 2) + 1; 01828 register u_char *bufp = data; 01829 u_long asn_length; 01830 register u_long low = 0, high = 0; 01831 01832 if (countersize != sizeof(struct counter64)) { 01833 _asn_size_err(errpre, countersize, sizeof(struct counter64)); 01834 return NULL; 01835 } 01836 *type = *bufp++; 01837 if (*type != ASN_COUNTER64 01838 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES 01839 && *type != ASN_OPAQUE_COUNTER64 && *type != ASN_OPAQUE_U64 01840 #endif 01841 ) { 01842 _asn_type_err(errpre, *type); 01843 return NULL; 01844 } 01845 bufp = asn_parse_length(bufp, &asn_length); 01846 if (_asn_parse_length_check 01847 (errpre, bufp, data, asn_length, *datalength)) 01848 return NULL; 01849 01850 DEBUGDUMPSETUP("recv", data, bufp - data); 01851 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES 01852 /* 01853 * 64 bit counters as opaque 01854 */ 01855 if ((*type == ASN_OPAQUE) && 01856 (asn_length <= ASN_OPAQUE_COUNTER64_MX_BER_LEN) && 01857 (*bufp == ASN_OPAQUE_TAG1) && 01858 ((*(bufp + 1) == ASN_OPAQUE_COUNTER64) || 01859 (*(bufp + 1) == ASN_OPAQUE_U64))) { 01860 /* 01861 * change type to Counter64 or U64 01862 */ 01863 *type = *(bufp + 1); 01864 /* 01865 * value is encoded as special format 01866 */ 01867 bufp = asn_parse_length(bufp + 2, &asn_length); 01868 if (_asn_parse_length_check("parse opaque uint64", bufp, data, 01869 asn_length, *datalength)) 01870 return NULL; 01871 } 01872 #endif /* NETSNMP_WITH_OPAQUE_SPECIAL_TYPES */ 01873 if (((int) asn_length > uint64sizelimit) || 01874 (((int) asn_length == uint64sizelimit) && *bufp != 0x00)) { 01875 _asn_length_err(errpre, (size_t) asn_length, uint64sizelimit); 01876 return NULL; 01877 } 01878 *datalength -= (int) asn_length + (bufp - data); 01879 while (asn_length--) { 01880 high = ((0x00FFFFFF & high) << 8) | ((low & 0xFF000000U) >> 24); 01881 low = ((low & 0x00FFFFFF) << 8) | *bufp++; 01882 } 01883 01884 CHECK_OVERFLOW_U(high,6); 01885 CHECK_OVERFLOW_U(low,6); 01886 01887 cp->low = low; 01888 cp->high = high; 01889 01890 DEBUGIF("dumpv_recv") { 01891 char i64buf[I64CHARSZ + 1]; 01892 printU64(i64buf, cp); 01893 DEBUGMSG(("dumpv_recv", "Counter64: %s\n", i64buf)); 01894 } 01895 01896 return bufp; 01897 } 01898 01899 01921 u_char * 01922 asn_build_unsigned_int64(u_char * data, 01923 size_t * datalength, 01924 u_char type, 01925 const struct counter64 * cp, size_t countersize) 01926 { 01927 /* 01928 * ASN.1 integer ::= 0x02 asnlength byte {byte}* 01929 */ 01930 01931 register u_long low, high; 01932 register u_long mask, mask2; 01933 int add_null_byte = 0; 01934 size_t intsize; 01935 #ifndef NETSNMP_NO_DEBUGGING 01936 u_char *initdatap = data; 01937 #endif 01938 01939 if (countersize != sizeof(struct counter64)) { 01940 _asn_size_err("build uint64", countersize, 01941 sizeof(struct counter64)); 01942 return NULL; 01943 } 01944 intsize = 8; 01945 low = cp->low; 01946 high = cp->high; 01947 01948 CHECK_OVERFLOW_U(high,7); 01949 CHECK_OVERFLOW_U(low,7); 01950 01951 mask = 0xff000000U; 01952 if (high & 0x80000000U) { 01953 /* 01954 * if MSB is set 01955 */ 01956 add_null_byte = 1; 01957 intsize++; 01958 } else { 01959 /* 01960 * Truncate "unnecessary" bytes off of the most significant end of this 2's 01961 * complement integer. 01962 * There should be no sequence of 9 consecutive 1's or 0's at the most 01963 * significant end of the integer. 01964 */ 01965 mask2 = 0xff800000U; 01966 while ((((high & mask2) == 0) || ((high & mask2) == mask2)) 01967 && intsize > 1) { 01968 intsize--; 01969 high = ((high & 0x00ffffffu) << 8) | ((low & mask) >> 24); 01970 low = (low & 0x00ffffffu) << 8; 01971 } 01972 } 01973 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES 01974 /* 01975 * encode a Counter64 as an opaque (it also works in SNMPv1) 01976 */ 01977 /* 01978 * turn into Opaque holding special tagged value 01979 */ 01980 if (type == ASN_OPAQUE_COUNTER64) { 01981 /* 01982 * put the tag and length for the Opaque wrapper 01983 */ 01984 data = asn_build_header(data, datalength, ASN_OPAQUE, intsize + 3); 01985 if (_asn_build_header_check 01986 ("build counter u64", data, *datalength, intsize + 3)) 01987 return NULL; 01988 01989 /* 01990 * put the special tag and length 01991 */ 01992 *data++ = ASN_OPAQUE_TAG1; 01993 *data++ = ASN_OPAQUE_COUNTER64; 01994 *data++ = (u_char) intsize; 01995 *datalength = *datalength - 3; 01996 } else 01997 /* 01998 * Encode the Unsigned int64 in an opaque 01999 */ 02000 /* 02001 * turn into Opaque holding special tagged value 02002 */ 02003 if (type == ASN_OPAQUE_U64) { 02004 /* 02005 * put the tag and length for the Opaque wrapper 02006 */ 02007 data = asn_build_header(data, datalength, ASN_OPAQUE, intsize + 3); 02008 if (_asn_build_header_check 02009 ("build opaque u64", data, *datalength, intsize + 3)) 02010 return NULL; 02011 02012 /* 02013 * put the special tag and length 02014 */ 02015 *data++ = ASN_OPAQUE_TAG1; 02016 *data++ = ASN_OPAQUE_U64; 02017 *data++ = (u_char) intsize; 02018 *datalength = *datalength - 3; 02019 } else { 02020 #endif /* NETSNMP_WITH_OPAQUE_SPECIAL_TYPES */ 02021 data = asn_build_header(data, datalength, type, intsize); 02022 if (_asn_build_header_check 02023 ("build uint64", data, *datalength, intsize)) 02024 return NULL; 02025 02026 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES 02027 } 02028 #endif /* NETSNMP_WITH_OPAQUE_SPECIAL_TYPES */ 02029 *datalength -= intsize; 02030 if (add_null_byte == 1) { 02031 *data++ = '\0'; 02032 intsize--; 02033 } 02034 while (intsize--) { 02035 *data++ = (u_char) (high >> 24); 02036 high = ((high & 0x00ffffff) << 8) | ((low & mask) >> 24); 02037 low = (low & 0x00ffffff) << 8; 02038 02039 } 02040 DEBUGDUMPSETUP("send", initdatap, data - initdatap); 02041 DEBUGIF("dumpv_send") { 02042 char i64buf[I64CHARSZ + 1]; 02043 printU64(i64buf, cp); 02044 DEBUGMSG(("dumpv_send", "%s", i64buf)); 02045 } 02046 return data; 02047 } 02048 02049 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES 02050 02051 02075 u_char * 02076 asn_parse_signed_int64(u_char * data, 02077 size_t * datalength, 02078 u_char * type, 02079 struct counter64 * cp, size_t countersize) 02080 { 02081 static const char *errpre = "parse int64"; 02082 const int int64sizelimit = (4 * 2) + 1; 02083 char ebuf[128]; 02084 register u_char *bufp = data; 02085 u_long asn_length; 02086 register u_int low = 0, high = 0; 02087 02088 if (countersize != sizeof(struct counter64)) { 02089 _asn_size_err(errpre, countersize, sizeof(struct counter64)); 02090 return NULL; 02091 } 02092 *type = *bufp++; 02093 bufp = asn_parse_length(bufp, &asn_length); 02094 if (_asn_parse_length_check 02095 (errpre, bufp, data, asn_length, *datalength)) 02096 return NULL; 02097 02098 DEBUGDUMPSETUP("recv", data, bufp - data); 02099 if ((*type == ASN_OPAQUE) && 02100 (asn_length <= ASN_OPAQUE_COUNTER64_MX_BER_LEN) && 02101 (*bufp == ASN_OPAQUE_TAG1) && (*(bufp + 1) == ASN_OPAQUE_I64)) { 02102 /* 02103 * change type to Int64 02104 */ 02105 *type = *(bufp + 1); 02106 /* 02107 * value is encoded as special format 02108 */ 02109 bufp = asn_parse_length(bufp + 2, &asn_length); 02110 if (_asn_parse_length_check("parse opaque int64", bufp, data, 02111 asn_length, *datalength)) 02112 return NULL; 02113 } 02114 /* 02115 * this should always have been true until snmp gets int64 PDU types 02116 */ 02117 else { 02118 snprintf(ebuf, sizeof(ebuf), 02119 "%s: wrong type: %d, len %d, buf bytes (%02X,%02X)", 02120 errpre, *type, (int) asn_length, *bufp, *(bufp + 1)); 02121 ebuf[ sizeof(ebuf)-1 ] = 0; 02122 ERROR_MSG(ebuf); 02123 return NULL; 02124 } 02125 if (((int) asn_length > int64sizelimit) || 02126 (((int) asn_length == int64sizelimit) && *bufp != 0x00)) { 02127 _asn_length_err(errpre, (size_t) asn_length, int64sizelimit); 02128 return NULL; 02129 } 02130 *datalength -= (int) asn_length + (bufp - data); 02131 if (*bufp & 0x80) { 02132 low = 0xFFFFFFFFU; /* first byte bit 1 means start the data with 1s */ 02133 high = 0xFFFFFF; 02134 } 02135 02136 while (asn_length--) { 02137 high = ((0x00FFFFFF & high) << 8) | ((low & 0xFF000000U) >> 24); 02138 low = ((low & 0x00FFFFFF) << 8) | *bufp++; 02139 } 02140 02141 CHECK_OVERFLOW_U(high,8); 02142 CHECK_OVERFLOW_U(low,8); 02143 02144 cp->low = low; 02145 cp->high = high; 02146 02147 DEBUGIF("dumpv_recv") { 02148 char i64buf[I64CHARSZ + 1]; 02149 printI64(i64buf, cp); 02150 DEBUGMSG(("dumpv_recv", "Integer64: %s\n", i64buf)); 02151 } 02152 02153 return bufp; 02154 } 02155 02156 02157 02179 u_char * 02180 asn_build_signed_int64(u_char * data, 02181 size_t * datalength, 02182 u_char type, 02183 const struct counter64 * cp, size_t countersize) 02184 { 02185 /* 02186 * ASN.1 integer ::= 0x02 asnlength byte {byte}* 02187 */ 02188 02189 register u_int mask, mask2; 02190 u_long low; 02191 long high; /* MUST be signed because of CHECK_OVERFLOW_S(). */ 02192 size_t intsize; 02193 #ifndef NETSNMP_NO_DEBUGGING 02194 u_char *initdatap = data; 02195 #endif 02196 02197 if (countersize != sizeof(struct counter64)) { 02198 _asn_size_err("build int64", countersize, 02199 sizeof(struct counter64)); 02200 return NULL; 02201 } 02202 intsize = 8; 02203 low = cp->low; 02204 high = cp->high; /* unsigned to signed conversion */ 02205 02206 CHECK_OVERFLOW_S(high,9); 02207 CHECK_OVERFLOW_U(low,9); 02208 02209 /* 02210 * Truncate "unnecessary" bytes off of the most significant end of this 02211 * 2's complement integer. There should be no sequence of 9 02212 * consecutive 1's or 0's at the most significant end of the 02213 * integer. 02214 */ 02215 mask = 0xFF000000U; 02216 mask2 = 0xFF800000U; 02217 while ((((high & mask2) == 0) || ((high & mask2) == mask2)) 02218 && intsize > 1) { 02219 intsize--; 02220 high = ((high & 0x00ffffff) << 8) | ((low & mask) >> 24); 02221 low = (low & 0x00ffffff) << 8; 02222 } 02223 /* 02224 * until a real int64 gets incorperated into SNMP, we are going to 02225 * encode it as an opaque instead. First, we build the opaque 02226 * header and then the int64 tag type we use to mark it as an 02227 * int64 in the opaque string. 02228 */ 02229 data = asn_build_header(data, datalength, ASN_OPAQUE, intsize + 3); 02230 if (_asn_build_header_check 02231 ("build int64", data, *datalength, intsize + 3)) 02232 return NULL; 02233 02234 *data++ = ASN_OPAQUE_TAG1; 02235 *data++ = ASN_OPAQUE_I64; 02236 *data++ = (u_char) intsize; 02237 *datalength -= (3 + intsize); 02238 02239 while (intsize--) { 02240 *data++ = (u_char) (high >> 24); 02241 high = ((high & 0x00ffffff) << 8) | ((low & mask) >> 24); 02242 low = (low & 0x00ffffff) << 8; 02243 } 02244 DEBUGDUMPSETUP("send", initdatap, data - initdatap); 02245 DEBUGIF("dumpv_send") { 02246 char i64buf[I64CHARSZ + 1]; 02247 printU64(i64buf, cp); 02248 DEBUGMSG(("dumpv_send", "%s\n", i64buf)); 02249 } 02250 return data; 02251 } 02252 02253 02275 u_char * 02276 asn_parse_float(u_char * data, 02277 size_t * datalength, 02278 u_char * type, float *floatp, size_t floatsize) 02279 { 02280 static const char *errpre = "parse float"; 02281 register u_char *bufp = data; 02282 u_long asn_length; 02283 union { 02284 float floatVal; 02285 long longVal; 02286 u_char c[sizeof(float)]; 02287 } fu; 02288 02289 if (floatsize != sizeof(float)) { 02290 _asn_size_err("parse float", floatsize, sizeof(float)); 02291 return NULL; 02292 } 02293 *type = *bufp++; 02294 bufp = asn_parse_length(bufp, &asn_length); 02295 if (_asn_parse_length_check("parse float", bufp, data, 02296 asn_length, *datalength)) 02297 return NULL; 02298 02299 DEBUGDUMPSETUP("recv", data, bufp - data + asn_length); 02300 /* 02301 * the float is encoded as an opaque 02302 */ 02303 if ((*type == ASN_OPAQUE) && 02304 (asn_length == ASN_OPAQUE_FLOAT_BER_LEN) && 02305 (*bufp == ASN_OPAQUE_TAG1) && (*(bufp + 1) == ASN_OPAQUE_FLOAT)) { 02306 02307 /* 02308 * value is encoded as special format 02309 */ 02310 bufp = asn_parse_length(bufp + 2, &asn_length); 02311 if (_asn_parse_length_check("parse opaque float", bufp, data, 02312 asn_length, *datalength)) 02313 return NULL; 02314 02315 /* 02316 * change type to Float 02317 */ 02318 *type = ASN_OPAQUE_FLOAT; 02319 } 02320 02321 if (*type != ASN_OPAQUE_FLOAT) { 02322 _asn_type_err(errpre, *type); 02323 return NULL; 02324 } 02325 02326 if (asn_length != sizeof(float)) { 02327 _asn_size_err("parse seq float", asn_length, sizeof(float)); 02328 return NULL; 02329 } 02330 02331 *datalength -= (int) asn_length + (bufp - data); 02332 memcpy(&fu.c[0], bufp, asn_length); 02333 02334 /* 02335 * correct for endian differences 02336 */ 02337 fu.longVal = ntohl(fu.longVal); 02338 02339 *floatp = fu.floatVal; 02340 02341 DEBUGMSG(("dumpv_recv", "Opaque float: %f\n", *floatp)); 02342 return bufp; 02343 } 02344 02368 u_char * 02369 asn_build_float(u_char * data, 02370 size_t * datalength, 02371 u_char type, const float *floatp, size_t floatsize) 02372 { 02373 union { 02374 float floatVal; 02375 int intVal; 02376 u_char c[sizeof(float)]; 02377 } fu; 02378 #ifndef NETSNMP_NO_DEBUGGING 02379 u_char *initdatap = data; 02380 #endif 02381 02382 if (floatsize != sizeof(float)) { 02383 _asn_size_err("build float", floatsize, sizeof(float)); 02384 return NULL; 02385 } 02386 /* 02387 * encode the float as an opaque 02388 */ 02389 /* 02390 * turn into Opaque holding special tagged value 02391 */ 02392 02393 /* 02394 * put the tag and length for the Opaque wrapper 02395 */ 02396 data = asn_build_header(data, datalength, ASN_OPAQUE, floatsize + 3); 02397 if (_asn_build_header_check 02398 ("build float", data, *datalength, (floatsize + 3))) 02399 return NULL; 02400 02401 /* 02402 * put the special tag and length 02403 */ 02404 *data++ = ASN_OPAQUE_TAG1; 02405 *data++ = ASN_OPAQUE_FLOAT; 02406 *data++ = (u_char) floatsize; 02407 *datalength = *datalength - 3; 02408 02409 fu.floatVal = *floatp; 02410 /* 02411 * correct for endian differences 02412 */ 02413 fu.intVal = htonl(fu.intVal); 02414 02415 *datalength -= floatsize; 02416 memcpy(data, &fu.c[0], floatsize); 02417 02418 DEBUGDUMPSETUP("send", initdatap, data - initdatap); 02419 DEBUGMSG(("dumpv_send", "Opaque float: %f\n", *floatp)); 02420 data += floatsize; 02421 return data; 02422 } 02423 02424 02446 u_char * 02447 asn_parse_double(u_char * data, 02448 size_t * datalength, 02449 u_char * type, double *doublep, size_t doublesize) 02450 { 02451 static const char *errpre = "parse double"; 02452 register u_char *bufp = data; 02453 u_long asn_length; 02454 long tmp; 02455 union { 02456 double doubleVal; 02457 int intVal[2]; 02458 u_char c[sizeof(double)]; 02459 } fu; 02460 02461 02462 if (doublesize != sizeof(double)) { 02463 _asn_size_err("parse double", doublesize, sizeof(double)); 02464 return NULL; 02465 } 02466 *type = *bufp++; 02467 bufp = asn_parse_length(bufp, &asn_length); 02468 if (_asn_parse_length_check("parse double", bufp, data, 02469 asn_length, *datalength)) 02470 return NULL; 02471 02472 DEBUGDUMPSETUP("recv", data, bufp - data + asn_length); 02473 /* 02474 * the double is encoded as an opaque 02475 */ 02476 if ((*type == ASN_OPAQUE) && 02477 (asn_length == ASN_OPAQUE_DOUBLE_BER_LEN) && 02478 (*bufp == ASN_OPAQUE_TAG1) && (*(bufp + 1) == ASN_OPAQUE_DOUBLE)) { 02479 02480 /* 02481 * value is encoded as special format 02482 */ 02483 bufp = asn_parse_length(bufp + 2, &asn_length); 02484 if (_asn_parse_length_check("parse opaque double", bufp, data, 02485 asn_length, *datalength)) 02486 return NULL; 02487 02488 /* 02489 * change type to Double 02490 */ 02491 *type = ASN_OPAQUE_DOUBLE; 02492 } 02493 02494 if (*type != ASN_OPAQUE_DOUBLE) { 02495 _asn_type_err(errpre, *type); 02496 return NULL; 02497 } 02498 02499 if (asn_length != sizeof(double)) { 02500 _asn_size_err("parse seq double", asn_length, sizeof(double)); 02501 return NULL; 02502 } 02503 *datalength -= (int) asn_length + (bufp - data); 02504 memcpy(&fu.c[0], bufp, asn_length); 02505 02506 /* 02507 * correct for endian differences 02508 */ 02509 02510 tmp = ntohl(fu.intVal[0]); 02511 fu.intVal[0] = ntohl(fu.intVal[1]); 02512 fu.intVal[1] = tmp; 02513 02514 *doublep = fu.doubleVal; 02515 DEBUGMSG(("dumpv_recv", " Opaque Double:\t%f\n", *doublep)); 02516 02517 return bufp; 02518 } 02519 02520 02543 u_char * 02544 asn_build_double(u_char * data, 02545 size_t * datalength, 02546 u_char type, const double *doublep, size_t doublesize) 02547 { 02548 long tmp; 02549 union { 02550 double doubleVal; 02551 int intVal[2]; 02552 u_char c[sizeof(double)]; 02553 } fu; 02554 #ifndef NETSNMP_NO_DEBUGGING 02555 u_char *initdatap = data; 02556 #endif 02557 02558 if (doublesize != sizeof(double)) { 02559 _asn_size_err("build double", doublesize, sizeof(double)); 02560 return NULL; 02561 } 02562 02563 /* 02564 * encode the double as an opaque 02565 */ 02566 /* 02567 * turn into Opaque holding special tagged value 02568 */ 02569 02570 /* 02571 * put the tag and length for the Opaque wrapper 02572 */ 02573 data = asn_build_header(data, datalength, ASN_OPAQUE, doublesize + 3); 02574 if (_asn_build_header_check 02575 ("build double", data, *datalength, doublesize + 3)) 02576 return NULL; 02577 02578 /* 02579 * put the special tag and length 02580 */ 02581 *data++ = ASN_OPAQUE_TAG1; 02582 *data++ = ASN_OPAQUE_DOUBLE; 02583 *data++ = (u_char) doublesize; 02584 *datalength = *datalength - 3; 02585 02586 fu.doubleVal = *doublep; 02587 /* 02588 * correct for endian differences 02589 */ 02590 tmp = htonl(fu.intVal[0]); 02591 fu.intVal[0] = htonl(fu.intVal[1]); 02592 fu.intVal[1] = tmp; 02593 *datalength -= doublesize; 02594 memcpy(data, &fu.c[0], doublesize); 02595 02596 data += doublesize; 02597 DEBUGDUMPSETUP("send", initdatap, data - initdatap); 02598 DEBUGMSG(("dumpv_send", " Opaque double: %f\n", *doublep)); 02599 return data; 02600 } 02601 02602 #endif /* NETSNMP_WITH_OPAQUE_SPECIAL_TYPES */ 02603 02604 02619 int 02620 asn_realloc(u_char ** pkt, size_t * pkt_len) 02621 { 02622 if (pkt != NULL && pkt_len != NULL) { 02623 size_t old_pkt_len = *pkt_len; 02624 02625 DEBUGMSGTL(("asn_realloc", " old_pkt %8p, old_pkt_len %lu\n", 02626 *pkt, (unsigned long)old_pkt_len)); 02627 02628 if (snmp_realloc(pkt, pkt_len)) { 02629 DEBUGMSGTL(("asn_realloc", " new_pkt %8p, new_pkt_len %lu\n", 02630 *pkt, (unsigned long)*pkt_len)); 02631 DEBUGMSGTL(("asn_realloc", 02632 " memmove(%8p + %08x, %8p, %08x)\n", 02633 *pkt, (unsigned)(*pkt_len - old_pkt_len), 02634 *pkt, (unsigned)old_pkt_len)); 02635 memmove(*pkt + (*pkt_len - old_pkt_len), *pkt, old_pkt_len); 02636 memset(*pkt, (int) ' ', *pkt_len - old_pkt_len); 02637 return 1; 02638 } else { 02639 DEBUGMSG(("asn_realloc", " CANNOT REALLOC()\n")); 02640 } 02641 } 02642 return 0; 02643 } 02644 02645 #ifdef NETSNMP_USE_REVERSE_ASNENCODING 02646 02661 int 02662 asn_realloc_rbuild_length(u_char ** pkt, size_t * pkt_len, 02663 size_t * offset, int r, size_t length) 02664 { 02665 static const char *errpre = "build length"; 02666 char ebuf[128]; 02667 int tmp_int; 02668 size_t start_offset = *offset; 02669 02670 if (length <= 0x7f) { 02671 if (((*pkt_len - *offset) < 1) 02672 && !(r && asn_realloc(pkt, pkt_len))) { 02673 snprintf(ebuf, sizeof(ebuf), 02674 "%s: bad length < 1 :%ld, %lu", errpre, 02675 (long)(*pkt_len - *offset), (unsigned long)length); 02676 ebuf[ sizeof(ebuf)-1 ] = 0; 02677 ERROR_MSG(ebuf); 02678 return 0; 02679 } 02680 *(*pkt + *pkt_len - (++*offset)) = length; 02681 } else { 02682 while (length > 0xff) { 02683 if (((*pkt_len - *offset) < 1) 02684 && !(r && asn_realloc(pkt, pkt_len))) { 02685 snprintf(ebuf, sizeof(ebuf), 02686 "%s: bad length < 1 :%ld, %lu", errpre, 02687 (long)(*pkt_len - *offset), (unsigned long)length); 02688 ebuf[ sizeof(ebuf)-1 ] = 0; 02689 ERROR_MSG(ebuf); 02690 return 0; 02691 } 02692 *(*pkt + *pkt_len - (++*offset)) = length & 0xff; 02693 length >>= 8; 02694 } 02695 02696 while ((*pkt_len - *offset) < 2) { 02697 if (!(r && asn_realloc(pkt, pkt_len))) { 02698 snprintf(ebuf, sizeof(ebuf), 02699 "%s: bad length < 1 :%ld, %lu", errpre, 02700 (long)(*pkt_len - *offset), (unsigned long)length); 02701 ebuf[ sizeof(ebuf)-1 ] = 0; 02702 ERROR_MSG(ebuf); 02703 return 0; 02704 } 02705 } 02706 02707 *(*pkt + *pkt_len - (++*offset)) = length & 0xff; 02708 tmp_int = *offset - start_offset; 02709 *(*pkt + *pkt_len - (++*offset)) = tmp_int | 0x80; 02710 } 02711 02712 return 1; 02713 } 02714 02732 int 02733 asn_realloc_rbuild_header(u_char ** pkt, size_t * pkt_len, 02734 size_t * offset, int r, 02735 u_char type, size_t length) 02736 { 02737 char ebuf[128]; 02738 02739 if (asn_realloc_rbuild_length(pkt, pkt_len, offset, r, length)) { 02740 if (((*pkt_len - *offset) < 1) 02741 && !(r && asn_realloc(pkt, pkt_len))) { 02742 snprintf(ebuf, sizeof(ebuf), 02743 "bad header length < 1 :%ld, %lu", 02744 (long)(*pkt_len - *offset), (unsigned long)length); 02745 ebuf[ sizeof(ebuf)-1 ] = 0; 02746 ERROR_MSG(ebuf); 02747 return 0; 02748 } 02749 *(*pkt + *pkt_len - (++*offset)) = type; 02750 return 1; 02751 } 02752 return 0; 02753 } 02754 02772 int 02773 asn_realloc_rbuild_int(u_char ** pkt, size_t * pkt_len, 02774 size_t * offset, int r, 02775 u_char type, const long *intp, size_t intsize) 02776 { 02777 static const char *errpre = "build int"; 02778 register long integer = *intp; 02779 int testvalue; 02780 size_t start_offset = *offset; 02781 02782 if (intsize != sizeof(long)) { 02783 _asn_size_err(errpre, intsize, sizeof(long)); 02784 return 0; 02785 } 02786 02787 CHECK_OVERFLOW_S(integer,10); 02788 testvalue = (integer < 0) ? -1 : 0; 02789 02790 if (((*pkt_len - *offset) < 1) && !(r && asn_realloc(pkt, pkt_len))) { 02791 return 0; 02792 } 02793 *(*pkt + *pkt_len - (++*offset)) = (u_char) integer; 02794 integer >>= 8; 02795 02796 while (integer != testvalue) { 02797 if (((*pkt_len - *offset) < 1) 02798 && !(r && asn_realloc(pkt, pkt_len))) { 02799 return 0; 02800 } 02801 *(*pkt + *pkt_len - (++*offset)) = (u_char) integer; 02802 integer >>= 8; 02803 } 02804 02805 if ((*(*pkt + *pkt_len - *offset) & 0x80) != (testvalue & 0x80)) { 02806 /* 02807 * Make sure left most bit is representational of the rest of the bits 02808 * that aren't encoded. 02809 */ 02810 if (((*pkt_len - *offset) < 1) 02811 && !(r && asn_realloc(pkt, pkt_len))) { 02812 return 0; 02813 } 02814 *(*pkt + *pkt_len - (++*offset)) = testvalue & 0xff; 02815 } 02816 02817 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r, type, 02818 (*offset - start_offset))) { 02819 if (_asn_realloc_build_header_check(errpre, pkt, pkt_len, 02820 (*offset - start_offset))) { 02821 return 0; 02822 } else { 02823 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset), 02824 (*offset - start_offset)); 02825 DEBUGMSG(("dumpv_send", " Integer:\t%ld (0x%.2lX)\n", *intp, 02826 *intp)); 02827 return 1; 02828 } 02829 } 02830 02831 return 0; 02832 } 02833 02852 int 02853 asn_realloc_rbuild_string(u_char ** pkt, size_t * pkt_len, 02854 size_t * offset, int r, 02855 u_char type, 02856 const u_char * str, size_t strlength) 02857 { 02858 static const char *errpre = "build string"; 02859 size_t start_offset = *offset; 02860 02861 while ((*pkt_len - *offset) < strlength) { 02862 if (!(r && asn_realloc(pkt, pkt_len))) { 02863 return 0; 02864 } 02865 } 02866 02867 *offset += strlength; 02868 memcpy(*pkt + *pkt_len - *offset, str, strlength); 02869 02870 if (asn_realloc_rbuild_header 02871 (pkt, pkt_len, offset, r, type, strlength)) { 02872 if (_asn_realloc_build_header_check 02873 (errpre, pkt, pkt_len, strlength)) { 02874 return 0; 02875 } else { 02876 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset), 02877 *offset - start_offset); 02878 DEBUGIF("dumpv_send") { 02879 if (strlength == 0) { 02880 DEBUGMSG(("dumpv_send", " String: [NULL]\n")); 02881 } else { 02882 u_char *buf = (u_char *) malloc(2 * strlength); 02883 size_t l = 02884 (buf != NULL) ? (2 * strlength) : 0, ol = 0; 02885 02886 if (sprint_realloc_asciistring 02887 (&buf, &l, &ol, 1, str, strlength)) { 02888 DEBUGMSG(("dumpv_send", " String:\t%s\n", buf)); 02889 } else { 02890 if (buf == NULL) { 02891 DEBUGMSG(("dumpv_send", 02892 " String:\t[TRUNCATED]\n")); 02893 } else { 02894 DEBUGMSG(("dumpv_send", 02895 " String:\t%s [TRUNCATED]\n", buf)); 02896 } 02897 } 02898 if (buf != NULL) { 02899 free(buf); 02900 } 02901 } 02902 } 02903 } 02904 return 1; 02905 } 02906 02907 return 0; 02908 } 02909 02927 int 02928 asn_realloc_rbuild_unsigned_int(u_char ** pkt, size_t * pkt_len, 02929 size_t * offset, int r, 02930 u_char type, const u_long * intp, size_t intsize) 02931 { 02932 static const char *errpre = "build uint"; 02933 register u_long integer = *intp; 02934 size_t start_offset = *offset; 02935 02936 if (intsize != sizeof(unsigned long)) { 02937 _asn_size_err(errpre, intsize, sizeof(unsigned long)); 02938 return 0; 02939 } 02940 02941 CHECK_OVERFLOW_U(integer,11); 02942 02943 if (((*pkt_len - *offset) < 1) && !(r && asn_realloc(pkt, pkt_len))) { 02944 return 0; 02945 } 02946 *(*pkt + *pkt_len - (++*offset)) = (u_char) integer; 02947 integer >>= 8; 02948 02949 while (integer != 0) { 02950 if (((*pkt_len - *offset) < 1) 02951 && !(r && asn_realloc(pkt, pkt_len))) { 02952 return 0; 02953 } 02954 *(*pkt + *pkt_len - (++*offset)) = (u_char) integer; 02955 integer >>= 8; 02956 } 02957 02958 if ((*(*pkt + *pkt_len - *offset) & 0x80) != (0 & 0x80)) { 02959 /* 02960 * Make sure left most bit is representational of the rest of the bits 02961 * that aren't encoded. 02962 */ 02963 if (((*pkt_len - *offset) < 1) 02964 && !(r && asn_realloc(pkt, pkt_len))) { 02965 return 0; 02966 } 02967 *(*pkt + *pkt_len - (++*offset)) = 0; 02968 } 02969 02970 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r, type, 02971 (*offset - start_offset))) { 02972 if (_asn_realloc_build_header_check(errpre, pkt, pkt_len, 02973 (*offset - start_offset))) { 02974 return 0; 02975 } else { 02976 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset), 02977 (*offset - start_offset)); 02978 DEBUGMSG(("dumpv_send", " UInteger:\t%lu (0x%.2lX)\n", *intp, 02979 *intp)); 02980 return 1; 02981 } 02982 } 02983 02984 return 0; 02985 } 02986 03004 int 03005 asn_realloc_rbuild_sequence(u_char ** pkt, size_t * pkt_len, 03006 size_t * offset, int r, 03007 u_char type, size_t length) 03008 { 03009 return asn_realloc_rbuild_header(pkt, pkt_len, offset, r, type, 03010 length); 03011 } 03012 03031 int 03032 asn_realloc_rbuild_objid(u_char ** pkt, size_t * pkt_len, 03033 size_t * offset, int r, 03034 u_char type, 03035 const oid * objid, size_t objidlength) 03036 { 03037 /* 03038 * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}* 03039 * subidentifier ::= {leadingbyte}* lastbyte 03040 * leadingbyte ::= 1 7bitvalue 03041 * lastbyte ::= 0 7bitvalue 03042 */ 03043 register size_t i; 03044 register oid tmpint; 03045 size_t start_offset = *offset; 03046 const char *errpre = "build objid"; 03047 03048 /* 03049 * Check if there are at least 2 sub-identifiers. 03050 */ 03051 if (objidlength == 0) { 03052 /* 03053 * There are not, so make OID have two with value of zero. 03054 */ 03055 while ((*pkt_len - *offset) < 2) { 03056 if (!(r && asn_realloc(pkt, pkt_len))) { 03057 return 0; 03058 } 03059 } 03060 03061 *(*pkt + *pkt_len - (++*offset)) = 0; 03062 *(*pkt + *pkt_len - (++*offset)) = 0; 03063 } else if (objid[0] > 2) { 03064 ERROR_MSG("build objid: bad first subidentifier"); 03065 return 0; 03066 } else if (objidlength == 1) { 03067 /* 03068 * Encode the first value. 03069 */ 03070 if (((*pkt_len - *offset) < 1) 03071 && !(r && asn_realloc(pkt, pkt_len))) { 03072 return 0; 03073 } 03074 *(*pkt + *pkt_len - (++*offset)) = (u_char) objid[0]; 03075 } else { 03076 for (i = objidlength; i > 2; i--) { 03077 tmpint = objid[i - 1]; 03078 CHECK_OVERFLOW_U(tmpint,12); 03079 03080 if (((*pkt_len - *offset) < 1) 03081 && !(r && asn_realloc(pkt, pkt_len))) { 03082 return 0; 03083 } 03084 *(*pkt + *pkt_len - (++*offset)) = (u_char) tmpint & 0x7f; 03085 tmpint >>= 7; 03086 03087 while (tmpint > 0) { 03088 if (((*pkt_len - *offset) < 1) 03089 && !(r && asn_realloc(pkt, pkt_len))) { 03090 return 0; 03091 } 03092 *(*pkt + *pkt_len - (++*offset)) = 03093 (u_char) ((tmpint & 0x7f) | 0x80); 03094 tmpint >>= 7; 03095 } 03096 } 03097 03098 /* 03099 * Combine the first two values. 03100 */ 03101 if ((objid[1] > 40) && 03102 (objid[0] < 2)) { 03103 ERROR_MSG("build objid: bad second subidentifier"); 03104 return 0; 03105 } 03106 tmpint = ((objid[0] * 40) + objid[1]); 03107 if (((*pkt_len - *offset) < 1) 03108 && !(r && asn_realloc(pkt, pkt_len))) { 03109 return 0; 03110 } 03111 *(*pkt + *pkt_len - (++*offset)) = (u_char) tmpint & 0x7f; 03112 tmpint >>= 7; 03113 03114 while (tmpint > 0) { 03115 if (((*pkt_len - *offset) < 1) 03116 && !(r && asn_realloc(pkt, pkt_len))) { 03117 return 0; 03118 } 03119 *(*pkt + *pkt_len - (++*offset)) = 03120 (u_char) ((tmpint & 0x7f) | 0x80); 03121 tmpint >>= 7; 03122 } 03123 } 03124 03125 tmpint = *offset - start_offset; 03126 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r, type, 03127 (*offset - start_offset))) { 03128 if (_asn_realloc_build_header_check(errpre, pkt, pkt_len, 03129 (*offset - start_offset))) { 03130 return 0; 03131 } else { 03132 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset), 03133 (*offset - start_offset)); 03134 DEBUGMSG(("dumpv_send", " ObjID: ")); 03135 DEBUGMSGOID(("dumpv_send", objid, objidlength)); 03136 DEBUGMSG(("dumpv_send", "\n")); 03137 return 1; 03138 } 03139 } 03140 03141 return 0; 03142 } 03143 03160 int 03161 asn_realloc_rbuild_null(u_char ** pkt, size_t * pkt_len, 03162 size_t * offset, int r, u_char type) 03163 { 03164 /* 03165 * ASN.1 null ::= 0x05 0x00 03166 */ 03167 size_t start_offset = *offset; 03168 03169 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r, type, 0)) { 03170 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset), 03171 (*offset - start_offset)); 03172 DEBUGMSG(("dumpv_send", " NULL\n")); 03173 return 1; 03174 } else { 03175 return 0; 03176 } 03177 } 03178 03197 int 03198 asn_realloc_rbuild_bitstring(u_char ** pkt, size_t * pkt_len, 03199 size_t * offset, int r, 03200 u_char type, 03201 const u_char * str, size_t strlength) 03202 { 03203 /* 03204 * ASN.1 bit string ::= 0x03 asnlength unused {byte}* 03205 */ 03206 static const char *errpre = "build bitstring"; 03207 size_t start_offset = *offset; 03208 03209 while ((*pkt_len - *offset) < strlength) { 03210 if (!(r && asn_realloc(pkt, pkt_len))) { 03211 return 0; 03212 } 03213 } 03214 03215 *offset += strlength; 03216 memcpy(*pkt + *pkt_len - *offset, str, strlength); 03217 03218 if (asn_realloc_rbuild_header 03219 (pkt, pkt_len, offset, r, type, strlength)) { 03220 if (_asn_realloc_build_header_check 03221 (errpre, pkt, pkt_len, strlength)) { 03222 return 0; 03223 } else { 03224 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset), 03225 *offset - start_offset); 03226 DEBUGIF("dumpv_send") { 03227 if (strlength == 0) { 03228 DEBUGMSG(("dumpv_send", " Bitstring: [NULL]\n")); 03229 } else { 03230 u_char *buf = (u_char *) malloc(2 * strlength); 03231 size_t l = 03232 (buf != NULL) ? (2 * strlength) : 0, ol = 0; 03233 03234 if (sprint_realloc_asciistring 03235 (&buf, &l, &ol, 1, str, strlength)) { 03236 DEBUGMSG(("dumpv_send", " Bitstring:\t%s\n", 03237 buf)); 03238 } else { 03239 if (buf == NULL) { 03240 DEBUGMSG(("dumpv_send", 03241 " Bitstring:\t[TRUNCATED]\n")); 03242 } else { 03243 DEBUGMSG(("dumpv_send", 03244 " Bitstring:\t%s [TRUNCATED]\n", 03245 buf)); 03246 } 03247 } 03248 if (buf != NULL) { 03249 free(buf); 03250 } 03251 } 03252 } 03253 } 03254 return 1; 03255 } 03256 03257 return 0; 03258 } 03259 03277 int 03278 asn_realloc_rbuild_unsigned_int64(u_char ** pkt, size_t * pkt_len, 03279 size_t * offset, int r, 03280 u_char type, 03281 const struct counter64 *cp, size_t countersize) 03282 { 03283 /* 03284 * ASN.1 integer ::= 0x02 asnlength byte {byte}* 03285 */ 03286 register u_long low = cp->low, high = cp->high; 03287 size_t intsize, start_offset = *offset; 03288 int count; 03289 03290 if (countersize != sizeof(struct counter64)) { 03291 _asn_size_err("build uint64", countersize, 03292 sizeof(struct counter64)); 03293 return 0; 03294 } 03295 03296 CHECK_OVERFLOW_U(high,13); 03297 CHECK_OVERFLOW_U(low,13); 03298 03299 /* 03300 * Encode the low 4 bytes first. 03301 */ 03302 if (((*pkt_len - *offset) < 1) && !(r && asn_realloc(pkt, pkt_len))) { 03303 return 0; 03304 } 03305 *(*pkt + *pkt_len - (++*offset)) = (u_char) low; 03306 low >>= 8; 03307 count = 1; 03308 03309 while (low != 0) { 03310 count++; 03311 if (((*pkt_len - *offset) < 1) 03312 && !(r && asn_realloc(pkt, pkt_len))) { 03313 return 0; 03314 } 03315 *(*pkt + *pkt_len - (++*offset)) = (u_char) low; 03316 low >>= 8; 03317 } 03318 03319 /* 03320 * Then the high byte if present. 03321 */ 03322 if (high) { 03323 /* 03324 * Do the rest of the low byte. 03325 */ 03326 for (; count < 4; count++) { 03327 if (((*pkt_len - *offset) < 1) 03328 && !(r && asn_realloc(pkt, pkt_len))) { 03329 return 0; 03330 } 03331 *(*pkt + *pkt_len - (++*offset)) = 0; 03332 } 03333 03334 /* 03335 * Do high byte. 03336 */ 03337 if (((*pkt_len - *offset) < 1) 03338 && !(r && asn_realloc(pkt, pkt_len))) { 03339 return 0; 03340 } 03341 *(*pkt + *pkt_len - (++*offset)) = (u_char) high; 03342 high >>= 8; 03343 03344 while (high != 0) { 03345 if (((*pkt_len - *offset) < 1) 03346 && !(r && asn_realloc(pkt, pkt_len))) { 03347 return 0; 03348 } 03349 *(*pkt + *pkt_len - (++*offset)) = (u_char) high; 03350 high >>= 8; 03351 } 03352 } 03353 03354 if ((*(*pkt + *pkt_len - *offset) & 0x80) != (0 & 0x80)) { 03355 /* 03356 * Make sure left most bit is representational of the rest of the bits 03357 * that aren't encoded. 03358 */ 03359 if (((*pkt_len - *offset) < 1) 03360 && !(r && asn_realloc(pkt, pkt_len))) { 03361 return 0; 03362 } 03363 *(*pkt + *pkt_len - (++*offset)) = 0; 03364 } 03365 03366 intsize = *offset - start_offset; 03367 03368 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES 03369 /* 03370 * Encode a Counter64 as an opaque (it also works in SNMPv1). 03371 */ 03372 if (type == ASN_OPAQUE_COUNTER64) { 03373 while ((*pkt_len - *offset) < 5) { 03374 if (!(r && asn_realloc(pkt, pkt_len))) { 03375 return 0; 03376 } 03377 } 03378 03379 *(*pkt + *pkt_len - (++*offset)) = (u_char) intsize; 03380 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_COUNTER64; 03381 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_TAG1; 03382 03383 /* 03384 * Put the tag and length for the Opaque wrapper. 03385 */ 03386 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r, 03387 ASN_OPAQUE, intsize + 3)) { 03388 if (_asn_realloc_build_header_check 03389 ("build counter u64", pkt, pkt_len, intsize + 3)) { 03390 return 0; 03391 } 03392 } else { 03393 return 0; 03394 } 03395 } else if (type == ASN_OPAQUE_U64) { 03396 /* 03397 * Encode the Unsigned int64 in an opaque. 03398 */ 03399 while ((*pkt_len - *offset) < 5) { 03400 if (!(r && asn_realloc(pkt, pkt_len))) { 03401 return 0; 03402 } 03403 } 03404 03405 *(*pkt + *pkt_len - (++*offset)) = (u_char) intsize; 03406 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_U64; 03407 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_TAG1; 03408 03409 /* 03410 * Put the tag and length for the Opaque wrapper. 03411 */ 03412 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r, 03413 ASN_OPAQUE, intsize + 3)) { 03414 if (_asn_realloc_build_header_check 03415 ("build counter u64", pkt, pkt_len, intsize + 3)) { 03416 return 0; 03417 } 03418 } else { 03419 return 0; 03420 } 03421 } else { 03422 03423 #endif /* NETSNMP_WITH_OPAQUE_SPECIAL_TYPES */ 03424 if (asn_realloc_rbuild_header 03425 (pkt, pkt_len, offset, r, type, intsize)) { 03426 if (_asn_realloc_build_header_check 03427 ("build uint64", pkt, pkt_len, intsize)) { 03428 return 0; 03429 } 03430 } else { 03431 return 0; 03432 } 03433 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES 03434 } 03435 #endif /* NETSNMP_WITH_OPAQUE_SPECIAL_TYPES */ 03436 03437 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset), intsize); 03438 DEBUGMSG(("dumpv_send", " U64:\t%lu %lu\n", cp->high, cp->low)); 03439 return 1; 03440 } 03441 03442 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES 03443 03444 03462 int 03463 asn_realloc_rbuild_signed_int64(u_char ** pkt, size_t * pkt_len, 03464 size_t * offset, int r, 03465 u_char type, 03466 const struct counter64 *cp, size_t countersize) 03467 { 03468 /* 03469 * ASN.1 integer ::= 0x02 asnlength byte {byte}* 03470 */ 03471 register long low = cp->low, high = cp->high; 03472 size_t intsize, start_offset = *offset; 03473 int count, testvalue = (high & 0x80000000) ? -1 : 0; 03474 03475 if (countersize != sizeof(struct counter64)) { 03476 _asn_size_err("build uint64", countersize, 03477 sizeof(struct counter64)); 03478 return 0; 03479 } 03480 03481 CHECK_OVERFLOW_S(high,14); 03482 CHECK_OVERFLOW_U(low,14); 03483 03484 /* 03485 * Encode the low 4 bytes first. 03486 */ 03487 if (((*pkt_len - *offset) < 1) && !(r && asn_realloc(pkt, pkt_len))) { 03488 return 0; 03489 } 03490 *(*pkt + *pkt_len - (++*offset)) = (u_char) low; 03491 low >>= 8; 03492 count = 1; 03493 03494 while ((int) low != testvalue && count < 4) { 03495 count++; 03496 if (((*pkt_len - *offset) < 1) 03497 && !(r && asn_realloc(pkt, pkt_len))) { 03498 return 0; 03499 } 03500 *(*pkt + *pkt_len - (++*offset)) = (u_char) low; 03501 low >>= 8; 03502 } 03503 03504 /* 03505 * Then the high byte if present. 03506 */ 03507 if (high != testvalue) { 03508 /* 03509 * Do the rest of the low byte. 03510 */ 03511 for (; count < 4; count++) { 03512 if (((*pkt_len - *offset) < 1) 03513 && !(r && asn_realloc(pkt, pkt_len))) { 03514 return 0; 03515 } 03516 *(*pkt + *pkt_len - (++*offset)) = (testvalue == 0) ? 0 : 0xff; 03517 } 03518 03519 /* 03520 * Do high byte. 03521 */ 03522 if (((*pkt_len - *offset) < 1) 03523 && !(r && asn_realloc(pkt, pkt_len))) { 03524 return 0; 03525 } 03526 *(*pkt + *pkt_len - (++*offset)) = (u_char) high; 03527 high >>= 8; 03528 03529 while ((int) high != testvalue) { 03530 if (((*pkt_len - *offset) < 1) 03531 && !(r && asn_realloc(pkt, pkt_len))) { 03532 return 0; 03533 } 03534 *(*pkt + *pkt_len - (++*offset)) = (u_char) high; 03535 high >>= 8; 03536 } 03537 } 03538 03539 if ((*(*pkt + *pkt_len - *offset) & 0x80) != (testvalue & 0x80)) { 03540 /* 03541 * Make sure left most bit is representational of the rest of the bits 03542 * that aren't encoded. 03543 */ 03544 if (((*pkt_len - *offset) < 1) 03545 && !(r && asn_realloc(pkt, pkt_len))) { 03546 return 0; 03547 } 03548 *(*pkt + *pkt_len - (++*offset)) = (testvalue == 0) ? 0 : 0xff; 03549 } 03550 03551 intsize = *offset - start_offset; 03552 03553 while ((*pkt_len - *offset) < 5) { 03554 if (!(r && asn_realloc(pkt, pkt_len))) { 03555 return 0; 03556 } 03557 } 03558 03559 *(*pkt + *pkt_len - (++*offset)) = (u_char) intsize; 03560 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_I64; 03561 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_TAG1; 03562 03563 /* 03564 * Put the tag and length for the Opaque wrapper. 03565 */ 03566 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r, 03567 ASN_OPAQUE, intsize + 3)) { 03568 if (_asn_realloc_build_header_check 03569 ("build counter u64", pkt, pkt_len, intsize + 3)) { 03570 return 0; 03571 } 03572 } else { 03573 return 0; 03574 } 03575 03576 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset), intsize); 03577 DEBUGMSG(("dumpv_send", " UInt64:\t%lu %lu\n", cp->high, cp->low)); 03578 return 1; 03579 } 03580 03599 int 03600 asn_realloc_rbuild_float(u_char ** pkt, size_t * pkt_len, 03601 size_t * offset, int r, 03602 u_char type, const float *floatp, size_t floatsize) 03603 { 03604 size_t start_offset = *offset; 03605 union { 03606 float floatVal; 03607 int intVal; 03608 u_char c[sizeof(float)]; 03609 } fu; 03610 03611 /* 03612 * Floatsize better not be larger than realistic. 03613 */ 03614 if (floatsize != sizeof(float) || floatsize > 122) { 03615 return 0; 03616 } 03617 03618 while ((*pkt_len - *offset) < floatsize + 3) { 03619 if (!(r && asn_realloc(pkt, pkt_len))) { 03620 return 0; 03621 } 03622 } 03623 03624 /* 03625 * Correct for endian differences and copy value. 03626 */ 03627 fu.floatVal = *floatp; 03628 fu.intVal = htonl(fu.intVal); 03629 *offset += floatsize; 03630 memcpy(*pkt + *pkt_len - *offset, &(fu.c[0]), floatsize); 03631 03632 /* 03633 * Put the special tag and length (3 bytes). 03634 */ 03635 *(*pkt + *pkt_len - (++*offset)) = (u_char) floatsize; 03636 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_FLOAT; 03637 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_TAG1; 03638 03639 /* 03640 * Put the tag and length for the Opaque wrapper. 03641 */ 03642 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r, 03643 ASN_OPAQUE, floatsize + 3)) { 03644 if (_asn_realloc_build_header_check("build float", pkt, pkt_len, 03645 floatsize + 3)) { 03646 return 0; 03647 } else { 03648 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset), 03649 *offset - start_offset); 03650 DEBUGMSG(("dumpv_send", "Opaque Float:\t%f\n", *floatp)); 03651 return 1; 03652 } 03653 } 03654 03655 return 0; 03656 } 03657 03676 int 03677 asn_realloc_rbuild_double(u_char ** pkt, size_t * pkt_len, 03678 size_t * offset, int r, 03679 u_char type, const double *doublep, size_t doublesize) 03680 { 03681 size_t start_offset = *offset; 03682 long tmp; 03683 union { 03684 double doubleVal; 03685 int intVal[2]; 03686 u_char c[sizeof(double)]; 03687 } fu; 03688 03689 /* 03690 * Doublesize better not be larger than realistic. 03691 */ 03692 if (doublesize != sizeof(double) || doublesize > 122) { 03693 return 0; 03694 } 03695 03696 while ((*pkt_len - *offset) < doublesize + 3) { 03697 if (!(r && asn_realloc(pkt, pkt_len))) { 03698 return 0; 03699 } 03700 } 03701 03702 /* 03703 * Correct for endian differences and copy value. 03704 */ 03705 fu.doubleVal = *doublep; 03706 tmp = htonl(fu.intVal[0]); 03707 fu.intVal[0] = htonl(fu.intVal[1]); 03708 fu.intVal[1] = tmp; 03709 *offset += doublesize; 03710 memcpy(*pkt + *pkt_len - *offset, &(fu.c[0]), doublesize); 03711 03712 /* 03713 * Put the special tag and length (3 bytes). 03714 */ 03715 *(*pkt + *pkt_len - (++*offset)) = (u_char) doublesize; 03716 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_DOUBLE; 03717 *(*pkt + *pkt_len - (++*offset)) = ASN_OPAQUE_TAG1; 03718 03719 /* 03720 * Put the tag and length for the Opaque wrapper. 03721 */ 03722 if (asn_realloc_rbuild_header(pkt, pkt_len, offset, r, 03723 ASN_OPAQUE, doublesize + 3)) { 03724 if (_asn_realloc_build_header_check("build float", pkt, pkt_len, 03725 doublesize + 3)) { 03726 return 0; 03727 } else { 03728 DEBUGDUMPSETUP("send", (*pkt + *pkt_len - *offset), 03729 *offset - start_offset); 03730 DEBUGMSG(("dumpv_send", " Opaque Double:\t%f\n", *doublep)); 03731 return 1; 03732 } 03733 } 03734 03735 return 0; 03736 } 03737 03738 #endif /* NETSNMP_WITH_OPAQUE_SPECIAL_TYPES */ 03739 #endif /* NETSNMP_USE_REVERSE_ASNENCODING */ 03740