asn1.c

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_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          * error message is set 
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          * error message is set 
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          * Error message is set.  
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;               /* always too short */
00405 
00406     if (*pkt != (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR))
00407         return -1;              /* wrong type */
00408 
00409     if (*(pkt + 1) & 0x80) {
00410         /*
00411          * long length 
00412          */
00413         if ((int) len < (int) (*(pkt + 1) & ~0x80) + 2)
00414             return 0;           /* still to short, incomplete length */
00415         asn_parse_length(pkt + 1, &asn_length);
00416         return (asn_length + 2 + (*(pkt + 1) & ~0x80));
00417     } else {
00418         /*
00419          * short length 
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      * if (datum > 7){
00440      * sprintf(ebuf,"%s: datum %d >7: too large", str, (int)(datum));
00441      * ERROR_MSG(ebuf);
00442      * return 1;
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      * ASN.1 integer ::= 0x02 asnlength byte {byte}*
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;             /* integer is negative */
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      * ASN.1 integer ::= 0x02 asnlength byte {byte}*
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;         /* integer is negative */
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      * ASN.1 integer ::= 0x02 asnlength byte {byte}*
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      * Truncate "unnecessary" bytes off of the most significant end of this
00627      * 2's complement integer.  There should be no sequence of 9
00628      * consecutive 1's or 0's at the most significant end of the
00629      * integer.
00630      */
00631     mask = ((u_long) 0x1FF) << ((8 * (sizeof(long) - 1)) - 1);
00632     /*
00633      * mask is 0xFF800000 on a big-endian machine 
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      * mask is 0xFF000000 on a big-endian machine 
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      * ASN.1 integer ::= 0x02 asnlength byte {byte}*
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      * mask is 0xFF000000 on a big-endian machine 
00709      */
00710     if ((u_char) ((integer & mask) >> (8 * (sizeof(long) - 1))) & 0x80) {
00711         /*
00712          * if MSB is set 
00713          */
00714         add_null_byte = 1;
00715         intsize++;
00716     } else {
00717         /*
00718          * Truncate "unnecessary" bytes off of the most significant end of this 2's complement integer.
00719          * There should be no sequence of 9 consecutive 1's or 0's at the most significant end of the
00720          * integer.
00721          */
00722         mask = ((u_long) 0x1FF) << ((8 * (sizeof(long) - 1)) - 1);
00723         /*
00724          * mask is 0xFF800000 on a big-endian machine 
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      * mask is 0xFF000000 on a big-endian machine 
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      * ASN.1 octet string ::= primstring | cmpdstring
00865      * primstring ::= 0x04 asnlength byte {byte}*
00866      * cmpdstring ::= 0x24 asnlength string {string}*
00867      * This code will never send a compound string.
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      * this only works on data types < 30, i.e. no extension octets 
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      * DEBUGMSGHEXTLI(("recv",data,(bufp-data)));
00961      * DEBUGMSG(("dumpH_recv","\n"));
00962      */
00963 #endif
00964 
00965 #ifdef OPAQUE_SPECIAL_TYPES
00966 
00967     if ((*type == ASN_OPAQUE) && (*bufp == ASN_OPAQUE_TAG1)) {
00968 
00969         /*
00970          * check if 64-but counter 
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              * just an Opaque 
00984              */
00985             *datalength = (int) asn_length;
00986             return bufp;
00987         }
00988         /*
00989          * value is encoded as special format 
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                          /* OPAQUE_SPECIAL_TYPES */
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,     /* must be this type */
01019                    const char *estr)
01020 {                               /* error message prefix */
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;    /* turn MSb off */
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;            /* protect against short lengths */
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 {                    /* short asnlength */
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      * no indefinite lengths sent 
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 {                    /* 0xFF < length <= 0xFFFF */
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      * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}*
01293      * subidentifier ::= {leadingbyte}* lastbyte
01294      * leadingbyte ::= 1 7bitvalue
01295      * lastbyte ::= 0 7bitvalue
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      * Handle invalid object identifier encodings of the form 06 00 robustly 
01315      */
01316     if (asn_length == 0)
01317         objid[0] = objid[1] = 0;
01318 
01319     length = asn_length;
01320     (*objidlength)--;           /* account for expansion of first byte */
01321 
01322     while (length > 0 && (*objidlength)-- > 0) {
01323         subidentifier = 0;
01324         do {                    /* shift and add in low order 7 bits */
01325             subidentifier =
01326                 (subidentifier << 7) + (*(u_char *) bufp & ~ASN_BIT8);
01327             length--;
01328         } while (*(u_char *) bufp++ & ASN_BIT8);        /* last byte has high bit clear */
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      * The first two subidentifiers are encoded into the first component
01346      * with the value (X * 40) + Y, where:
01347      *  X is the value of the first subidentifier.
01348      *  Y is the value of the second subidentifier.
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      * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}*
01405      * subidentifier ::= {leadingbyte}* lastbyte
01406      * leadingbyte ::= 1 7bitvalue
01407      * lastbyte ::= 0 7bitvalue
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      * check if there are at least 2 sub-identifiers 
01421      */
01422     if (objidlength == 0) {
01423         /*
01424          * there are not, so make OID have two with value of zero 
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          * encode the first value 
01434          */
01435         objid_val = (op[0] * 40);
01436         objidlength = 2;
01437         op++;
01438     } else {
01439         /*
01440          * combine the first two values 
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      * ditch illegal calls now 
01454      */
01455     if (objidlength > MAX_OID_LEN)
01456         return NULL;
01457 
01458     /*
01459      * calculate the number of bytes needed to store the encoded value 
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++;      /* XXX - doesn't handle 2.X (X > 40) */
01484     }
01485 
01486     /*
01487      * store the ASN.1 tag and length 
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      * store the encoded OID value 
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) /* already logged warning above */
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      * return the length and data ptr 
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      * ASN.1 null ::= 0x05 0x00
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      * ASN.1 null ::= 0x05 0x00
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      * bitstring ::= 0x03 asnlength unused {byte}*
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      * ASN.1 bit string ::= 0x03 asnlength unused {byte}*
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      * ASN.1 integer ::= 0x02 asnlength byte {byte}*
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      * 64 bit counters as opaque 
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          * change type to Counter64 or U64 
01806          */
01807         *type = *(bufp + 1);
01808         /*
01809          * value is encoded as special format 
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                          /* OPAQUE_SPECIAL_TYPES */
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;     /* first byte bit 1 means start the data with 1s */
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      * ASN.1 integer ::= 0x02 asnlength byte {byte}*
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      * mask is 0xFF000000 on a big-endian machine 
01903      */
01904     if ((u_char) ((high & mask) >> (8 * (sizeof(long) - 1))) & 0x80) {
01905         /*
01906          * if MSB is set 
01907          */
01908         add_null_byte = 1;
01909         intsize++;
01910     } else {
01911         /*
01912          * Truncate "unnecessary" bytes off of the most significant end of this 2's
01913          * complement integer.
01914          * There should be no sequence of 9 consecutive 1's or 0's at the most
01915          * significant end of the integer.
01916          */
01917         mask2 = ((u_long) 0x1FF) << ((8 * (sizeof(long) - 1)) - 1);
01918         /*
01919          * mask2 is 0xFF800000 on a big-endian machine 
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      * encode a Counter64 as an opaque (it also works in SNMPv1) 
01932      */
01933     /*
01934      * turn into Opaque holding special tagged value 
01935      */
01936     if (type == ASN_OPAQUE_COUNTER64) {
01937         /*
01938          * put the tag and length for the Opaque wrapper 
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          * put the special tag and length 
01947          */
01948         *data++ = ASN_OPAQUE_TAG1;
01949         *data++ = ASN_OPAQUE_COUNTER64;
01950         *data++ = (u_char) intsize;
01951         *datalength = *datalength - 3;
01952     } else
01953         /*
01954          * Encode the Unsigned int64 in an opaque 
01955          */
01956         /*
01957          * turn into Opaque holding special tagged value 
01958          */
01959     if (type == ASN_OPAQUE_U64) {
01960         /*
01961          * put the tag and length for the Opaque wrapper 
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          * put the special tag and length 
01970          */
01971         *data++ = ASN_OPAQUE_TAG1;
01972         *data++ = ASN_OPAQUE_U64;
01973         *data++ = (u_char) intsize;
01974         *datalength = *datalength - 3;
01975     } else {
01976 #endif                          /* OPAQUE_SPECIAL_TYPES */
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                          /* OPAQUE_SPECIAL_TYPES */
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          * change type to Int64 
02061          */
02062         *type = *(bufp + 1);
02063         /*
02064          * value is encoded as special format 
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      * this should always have been true until snmp gets int64 PDU types 
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;     /* first byte bit 1 means start the data with 1s */
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      * ASN.1 integer ::= 0x02 asnlength byte {byte}*
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)); /* we're may modify it */
02161     low = c64.low;
02162     high = c64.high;
02163 
02164     CHECK_OVERFLOW_S(high,9);
02165     CHECK_OVERFLOW_U(low,9);
02166 
02167     /*
02168      * Truncate "unnecessary" bytes off of the most significant end of this
02169      * 2's complement integer.  There should be no sequence of 9
02170      * consecutive 1's or 0's at the most significant end of the
02171      * integer.
02172      */
02173     mask = ((u_int) 0xFF) << (8 * (sizeof(u_int) - 1));
02174     mask2 = ((u_int) 0x1FF) << ((8 * (sizeof(u_int) - 1)) - 1);
02175     /*
02176      * mask is 0xFF800000 on a big-endian machine 
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      * until a real int64 gets incorperated into SNMP, we are going to
02187      * encode it as an opaque instead.  First, we build the opaque
02188      * header and then the int64 tag type we use to mark it as an
02189      * int64 in the opaque string. 
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      * the float is encoded as an opaque 
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          * value is encoded as special format 
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          * change type to Float 
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      * correct for endian differences 
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      * encode the float as an opaque 
02345      */
02346     /*
02347      * turn into Opaque holding special tagged value 
02348      */
02349 
02350     /*
02351      * put the tag and length for the Opaque wrapper 
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      * put the special tag and length 
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      * correct for endian differences 
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      * the double is encoded as an opaque 
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          * value is encoded as special format 
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          * change type to Double 
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      * correct for endian differences 
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      * encode the double as an opaque 
02516      */
02517     /*
02518      * turn into Opaque holding special tagged value 
02519      */
02520 
02521     /*
02522      * put the tag and length for the Opaque wrapper 
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      * put the special tag and length 
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      * correct for endian differences 
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                          /* OPAQUE_SPECIAL_TYPES */
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          * Make sure left most bit is representational of the rest of the bits
02758          * that aren't encoded.  
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          * Make sure left most bit is representational of the rest of the bits
02911          * that aren't encoded.  
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      * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}*
02989      * subidentifier ::= {leadingbyte}* lastbyte
02990      * leadingbyte ::= 1 7bitvalue
02991      * lastbyte ::= 0 7bitvalue
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      * Check if there are at least 2 sub-identifiers.  
03000      */
03001     if (objidlength == 0) {
03002         /*
03003          * There are not, so make OID have two with value of zero.  
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          * Encode the first value.  
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          * Combine the first two values.  
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      * ASN.1 null ::= 0x05 0x00
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      * ASN.1 bit string ::= 0x03 asnlength unused {byte}*
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      * ASN.1 integer ::= 0x02 asnlength byte {byte}*
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      * Encode the low 4 bytes first.  
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      * Then the high byte if present.  
03271      */
03272     if (high) {
03273         /*
03274          * Do the rest of the low byte.  
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          * Do high byte.  
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          * Make sure left most bit is representational of the rest of the bits
03307          * that aren't encoded.  
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      * Encode a Counter64 as an opaque (it also works in SNMPv1).  
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          * Put the tag and length for the Opaque wrapper.  
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          * Encode the Unsigned int64 in an opaque.  
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          * Put the tag and length for the Opaque wrapper.  
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                          /* OPAQUE_SPECIAL_TYPES */
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                          /* OPAQUE_SPECIAL_TYPES */
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      * ASN.1 integer ::= 0x02 asnlength byte {byte}*
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      * Encode the low 4 bytes first.  
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      * Then the high byte if present.  
03456      */
03457     if (high != testvalue) {
03458         /*
03459          * Do the rest of the low byte.  
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          * Do high byte.  
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          * Make sure left most bit is representational of the rest of the bits
03492          * that aren't encoded.  
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      * Put the tag and length for the Opaque wrapper.  
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      * Floatsize better not be larger than realistic.  
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      * Correct for endian differences and copy value.  
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      * Put the special tag and length (3 bytes).  
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      * Put the tag and length for the Opaque wrapper.  
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      * Doublesize better not be larger than realistic.  
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      * Correct for endian differences and copy value.  
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      * Put the special tag and length (3 bytes).  
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      * Put the tag and length for the Opaque wrapper.  
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                          /* OPAQUE_SPECIAL_TYPES */
03689 #endif                          /*  USE_REVERSE_ASNENCODING  */
03690 

net-snmpに対してSat Sep 5 13:14:20 2009に生成されました。  doxygen 1.4.7