asn1.cpp
上传用户:ets1996
上传日期:2014-09-30
资源大小:353k
文件大小:61k
源码类别:

SNMP编程

开发平台:

Visual C++

  1. /*_############################################################################
  2.   _## 
  3.   _##  asn1.cpp  
  4.   _##
  5.   _##  SNMP++v3.2.22
  6.   _##  -----------------------------------------------
  7.   _##  Copyright (c) 2001-2007 Jochen Katz, Frank Fock
  8.   _##
  9.   _##  This software is based on SNMP++2.6 from Hewlett Packard:
  10.   _##  
  11.   _##    Copyright (c) 1996
  12.   _##    Hewlett-Packard Company
  13.   _##  
  14.   _##  ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS.
  15.   _##  Permission to use, copy, modify, distribute and/or sell this software 
  16.   _##  and/or its documentation is hereby granted without fee. User agrees 
  17.   _##  to display the above copyright notice and this license notice in all 
  18.   _##  copies of the software and any documentation of the software. User 
  19.   _##  agrees to assume all liability for the use of the software; 
  20.   _##  Hewlett-Packard and Jochen Katz make no representations about the 
  21.   _##  suitability of this software for any purpose. It is provided 
  22.   _##  "AS-IS" without warranty of any kind, either express or implied. User 
  23.   _##  hereby grants a royalty-free license to any and all derivatives based
  24.   _##  upon this software code base. 
  25.   _##  
  26.   _##  Stuttgart, Germany, Wed May  2 23:22:30 CEST 2007 
  27.   _##  
  28.   _##########################################################################*/
  29. /*===================================================================
  30.   Copyright (c) 1999
  31.   Hewlett-Packard Company
  32.   ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS.
  33.   Permission to use, copy, modify, distribute and/or sell this software
  34.   and/or its documentation is hereby granted without fee. User agrees
  35.   to display the above copyright notice and this license notice in all
  36.   copies of the software and any documentation of the software. User
  37.   agrees to assume all liability for the use of the software; Hewlett-Packard
  38.   makes no representations about the suitability of this software for any
  39.   purpose. It is provided "AS-IS" without warranty of any kind,either express
  40.   or implied. User hereby grants a royalty-free license to any and all
  41.   derivatives based upon this software code base.
  42.   A S N 1. C P P
  43.   ASN encoder / decoder implementation
  44.   DESIGN + AUTHOR:  Peter E. Mellquist
  45.   LANGUAGE:         ANSI C++
  46. =====================================================================*/
  47. char asn1_cpp_version[]="#(@) SNMP++ $Id: asn1.cpp 282 2007-03-22 22:03:45Z katz $";
  48. #ifdef __unix
  49. #include /**/ <sys/types.h>
  50. #include /**/ <netinet/in.h>
  51. #endif
  52. #include /**/ <stdlib.h>
  53. #ifdef WIN32
  54. #include <winsock.h>
  55. #endif
  56. #include "snmp_pp/config_snmp_pp.h"
  57. #include "snmp_pp/asn1.h"
  58. #include "snmp_pp/v3.h"
  59. #include "snmp_pp/snmperrs.h"
  60. #include "snmp_pp/log.h"
  61. #ifdef SNMP_PP_NAMESPACE
  62. namespace Snmp_pp {
  63. #endif
  64. #ifndef NULL
  65. #define NULL 0
  66. #endif
  67. #define LENMASK 0x0ff
  68. #define ASN_UNI_PRIV (ASN_UNIVERSAL | ASN_PRIMITIVE)
  69. #define ASN_SEQ_CON (ASN_SEQUENCE | ASN_CONSTRUCTOR)
  70. /*
  71.  * asn_parse_int - pulls a long out of an ASN int type.
  72.  *  On entry, datalength is input as the number of valid bytes following
  73.  *   "data".  On exit, it is returned as the number of valid bytes
  74.  *   following the end of this object.
  75.  *
  76.  *  Returns a pointer to the first byte past the end
  77.  *   of this object (i.e. the start of the next object).
  78.  *  Returns NULL on any error.
  79.  */
  80. unsigned char * asn_parse_int( unsigned char *data,
  81.        int *datalength,
  82.        unsigned char *type,
  83.        long int *intp,
  84.        int intsize)
  85. {
  86.   /*
  87.    * ASN.1 integer ::= 0x02 asnlength byte {byte}*
  88.    *       timestamp   0x43 asnlength byte {byte}*
  89.    */
  90.   unsigned char *bufp = data;
  91.   unsigned long     asn_length;
  92.   long   value = 0;
  93.   if (intsize != sizeof (long)){
  94.     ASNERROR("not long");
  95.     return NULL;
  96.   }
  97.   *type = *bufp++;
  98.   if ((*type != 0x02) && (*type != 0x43) &&
  99.       (*type != 0x41)) {
  100.     ASNERROR("Wrong Type. Not an integer");
  101.     return NULL;
  102.   }
  103.   bufp = asn_parse_length(bufp, &asn_length);
  104.   if (bufp == NULL){
  105.     ASNERROR("bad length");
  106.     return NULL;
  107.   }
  108.   if ((asn_length + (bufp - data)) > (unsigned long)(*datalength)){
  109.     ASNERROR("overflow of message");
  110.     return NULL;
  111.   }
  112.   if ((int)asn_length > intsize){
  113.     ASNERROR("I don't support such large integers");
  114.     return NULL;
  115.   }
  116.   *datalength -= (int)asn_length + SAFE_INT_CAST(bufp - data);
  117.   if (*bufp & 0x80)
  118.     value = -1; /* integer is negative */
  119.   while(asn_length--)
  120.     value = (value << 8) | *bufp++;
  121.   *intp = value;
  122.   return bufp;
  123. }
  124. /*
  125.  * asn_parse_unsigned_int - pulls an unsigned long out of an ASN int type.
  126.  *  On entry, datalength is input as the number of valid bytes following
  127.  *   "data".  On exit, it is returned as the number of valid bytes
  128.  *   following the end of this object.
  129.  *
  130.  *  Returns a pointer to the first byte past the end
  131.  *   of this object (i.e. the start of the next object).
  132.  *  Returns NULL on any error.
  133.  */
  134. unsigned char * asn_parse_unsigned_int( unsigned char *data,
  135.                                         int *datalength,
  136.                                         unsigned char *type,
  137.                                         unsigned long *intp,
  138.                                         int intsize)
  139. {
  140.   /*
  141.    * ASN.1 integer ::= 0x02 asnlength byte {byte}*
  142.    *                   0x43 asnlength byte {byte}*
  143.    */
  144.   unsigned char *bufp = data;
  145.   unsigned long     asn_length;
  146.   unsigned long value = 0;
  147.   // check the size of the object being requested
  148.   if (intsize != sizeof (long)){
  149.     ASNERROR("not long");
  150.     return NULL;
  151.   }
  152.   // get the type
  153.   *type = *bufp++;
  154.   if ((*type != 0x02) && (*type != 0x43) &&
  155.       (*type != 0x41) && (*type != 0x42) &&
  156.       (*type != 0x47)) {
  157.     ASNERROR("Wrong Type. Not an unsigned integer");
  158.     return NULL;
  159.   }
  160.   // pick up the len
  161.   bufp = asn_parse_length(bufp, &asn_length);
  162.   if (bufp == NULL){
  163.     ASNERROR("bad length");
  164.     return NULL;
  165.   }
  166.   // check the len for message overflow
  167.   if ((asn_length + (bufp - data)) > (unsigned long)(*datalength)){
  168.     ASNERROR("overflow of message");
  169.     return NULL;
  170.   }
  171.   // check for legal uint size
  172.   if (( (int)asn_length > 5) || (((int)asn_length > 4) && (*bufp != 0x00))) {
  173.     ASNERROR("I don't support such large integers");
  174.     return NULL;
  175.   }
  176.   // check for leading  0 octet
  177.   if (*bufp == 0x00) {
  178.     bufp++;
  179.     asn_length--;
  180.   }
  181.   // fix the returned data length value
  182.   *datalength -= (int)asn_length + SAFE_INT_CAST(bufp - data);
  183.   // calculate the value
  184.   for (long i=0;i<(long)asn_length;i++)
  185.     value = (value << 8) + (unsigned long) *bufp++;
  186.   // assign return value
  187.   *intp = value;
  188.   // return the bumped pointer
  189.   return bufp;
  190. }
  191. /*
  192.  * asn_build_int - builds an ASN object containing an integer.
  193.  *  On entry, datalength is input as the number of valid bytes following
  194.  *   "data".  On exit, it is returned as the number of valid bytes
  195.  *   following the end of this object.
  196.  *
  197.  *  Returns a pointer to the first byte past the end
  198.  *   of this object (i.e. the start of the next object).
  199.  *  Returns NULL on any error.
  200.  */
  201. unsigned char *asn_build_int(unsigned char *data, int *datalength,
  202.                              const unsigned char type,
  203.                              const long *intp,
  204.                              int intsize)
  205. {
  206.   /*
  207.    * ASN.1 integer ::= 0x02 asnlength byte {byte}*
  208.    */
  209.   long integer;
  210.   unsigned long mask;
  211.   if (intsize != sizeof (long))
  212.     return NULL;
  213.   integer = *intp;
  214.   /*
  215.    * Truncate "unnecessary" bytes off of the most significant end of this
  216.    * 2's complement integer.  There should be no sequence of 9
  217.    * consecutive 1's or 0's at the most significant end of the
  218.    * integer.
  219.    */
  220.   mask = 0x1FFul << ((8 * (sizeof(long) - 1)) - 1);
  221.   /* mask is 0xFF800000 on a big-endian machine */
  222.   while((((integer & mask) == 0) || ((integer & mask) == mask))
  223. && intsize > 1){
  224.     intsize--;
  225.     integer <<= 8;
  226.   }
  227.   data = asn_build_header(data, datalength, type, intsize);
  228.   if (data == NULL)
  229.     return NULL;
  230.   if (*datalength < intsize)
  231.     return NULL;
  232.   *datalength -= intsize;
  233.   mask = 0xFFul << (8 * (sizeof(long) - 1));
  234.   /* mask is 0xFF000000 on a big-endian machine */
  235.   while(intsize--){
  236.     *data++ = (unsigned char)((integer & mask) >> (8 * (sizeof(long) - 1)));
  237.     integer <<= 8;
  238.   }
  239.   return data;
  240. }
  241. /*
  242.  * asn_build_unsigned_int - builds an ASN object containing an integer.
  243.  *  On entry, datalength is input as the number of valid bytes following
  244.  *   "data".  On exit, it is returned as the number of valid bytes
  245.  *   following the end of this object.
  246.  *
  247.  *  Returns a pointer to the first byte past the end
  248.  *   of this object (i.e. the start of the next object).
  249.  *  Returns NULL on any error.
  250.  */
  251. unsigned char * asn_build_unsigned_int( unsigned char *data, // modified data
  252.                                         int *datalength,     // returned buffer length
  253.                                         unsigned char type,  // SMI type
  254.                                         unsigned long *intp, // Uint to encode
  255.                                         int intsize)         // size of uint to encode
  256. {
  257.   /*
  258.    * ASN.1 integer ::= 0x02 asnlength byte {byte}*
  259.    */
  260.   unsigned long u_integer;
  261.   long u_integer_len;
  262.   long x;
  263.   // check uint size
  264.   if (intsize != sizeof (long))
  265.     return NULL;
  266.   // local var point to var passed in
  267.   u_integer = *intp;
  268.   // figure out the len
  269.   if ((( u_integer >> 24) & LENMASK) != 0)
  270.     u_integer_len = 4;
  271.   else if ((( u_integer >> 16) & LENMASK) !=0)
  272.     u_integer_len = 3;
  273.   else if ((( u_integer >> 8) & LENMASK) !=0)
  274.     u_integer_len = 2;
  275.   else
  276.     u_integer_len =1;
  277.   // check for 5 byte len where first byte will be a null
  278.   if ((( u_integer >> (8 * (u_integer_len -1))) & 0x080) !=0) {
  279.     u_integer_len++;
  280.   }
  281.   // build up the header
  282.   data = asn_build_header( data,                 // data buffer to be modified
  283.    datalength,           // length of data buffer
  284.    type,                 // SMI type to enode
  285.    (int)u_integer_len);  // length of BER encoded item
  286.   // special case, add a null byte for len of 5
  287.   if ( u_integer_len ==5) {
  288.     *data++ = (unsigned char) 0;
  289.     for (x=1;x<u_integer_len;x++)
  290.       *data++= (unsigned char) ( u_integer >> (8 * ((u_integer_len-1)-x)& LENMASK));
  291.   }
  292.   else
  293.   {
  294.     for (x=0;x<u_integer_len;x++)
  295.       *data++= (unsigned char) ( u_integer >> (8 * ((u_integer_len-1)-x)& LENMASK));
  296.   }
  297.   *datalength -= u_integer_len;
  298.   return data;
  299. }
  300. /*
  301.  * asn_parse_string - pulls an octet string out of an ASN octet string type.
  302.  *  On entry, datalength is input as the number of valid bytes following
  303.  *   "data".  On exit, it is returned as the number of valid bytes
  304.  *   following the beginning of the next object.
  305.  *
  306.  *  "string" is filled with the octet string.
  307.  *
  308.  *  Returns a pointer to the first byte past the end
  309.  *   of this object (i.e. the start of the next object).
  310.  *  Returns NULL on any error.
  311.  */
  312. unsigned char * asn_parse_string( unsigned char *data,
  313.                                   int *datalength,
  314.                                   unsigned char *type,
  315.                                   unsigned char *str,
  316.                                   int *strlength)
  317. {
  318.   /*
  319.    * ASN.1 octet string ::= primstring | cmpdstring
  320.    * primstring ::= 0x04 asnlength byte {byte}*
  321.    * cmpdstring ::= 0x24 asnlength string {string}*
  322.    * ipaddress  ::= 0x40 4 byte byte byte byte
  323.    */
  324.   unsigned char *bufp = data;
  325.   unsigned long  asn_length;
  326.   *type = *bufp++;
  327.   if ((*type != 0x04) && (*type != 0x24) &&
  328.       (*type != 0x40) && (*type != 0x44) &&
  329.       (*type != 0x45)) {
  330.     ASNERROR("asn parse string: Wrong Type. Not a string");
  331.     return NULL;
  332.   }
  333.   bufp = asn_parse_length(bufp, &asn_length);
  334.   if (bufp == NULL)
  335.     return NULL;
  336.   if ((asn_length + (bufp - data)) > (unsigned long)(*datalength)){
  337.     ASNERROR("asn parse string: overflow of message");
  338.     return NULL;
  339.   }
  340.   if ((int)asn_length > *strlength){
  341.     ASNERROR("asn parse string: String to parse is longer than buffer, aborting parsing.");
  342.     return NULL;
  343.   }
  344.   memcpy(str, bufp, asn_length);
  345.   *strlength = (int)asn_length;
  346.   *datalength -= (int)asn_length + SAFE_INT_CAST(bufp - data);
  347.   return bufp + asn_length;
  348. }
  349. /*
  350.  * asn_build_string - Builds an ASN octet string object containing the input string.
  351.  *  On entry, datalength is input as the number of valid bytes following
  352.  *   "data".  On exit, it is returned as the number of valid bytes
  353.  *   following the beginning of the next object.
  354.  *
  355.  *  Returns a pointer to the first byte past the end
  356.  *   of this object (i.e. the start of the next object).
  357.  *  Returns NULL on any error.
  358.  */
  359. unsigned char *asn_build_string(unsigned char *data,
  360.                                 int *datalength,
  361.                                 const unsigned char type,
  362.                                 const unsigned char *string,
  363.                                 const int strlength)
  364. {
  365.   /*
  366.    * ASN.1 octet string ::= primstring | cmpdstring
  367.    * primstring ::= 0x04 asnlength byte {byte}*
  368.    * cmpdstring ::= 0x24 asnlength string {string}*
  369.    * This code will never send a compound string.
  370.    */
  371.   data = asn_build_header(data, datalength, type, strlength);
  372.   if (data == NULL)
  373.     return NULL;
  374.   if (*datalength < strlength)
  375.     return NULL;
  376.   // fixed
  377.   memcpy((unsigned char *)data, string, strlength);
  378.   *datalength -= strlength;
  379.   return data + strlength;
  380. }
  381. /*
  382.  * asn_parse_header - interprets the ID and length of the current object.
  383.  *  On entry, datalength is input as the number of valid bytes following
  384.  *   "data".  On exit, it is returned as the number of valid bytes
  385.  *   in this object following the id and length.
  386.  *
  387.  *  Returns a pointer to the first byte of the contents of this object.
  388.  *  Returns NULL on any error.
  389.  */
  390. unsigned char *asn_parse_header( unsigned char *data,
  391.  int *datalength,
  392.                                  unsigned char *type)
  393. {
  394.   unsigned char *bufp = data;
  395.   register int header_len;
  396.   unsigned long     asn_length;
  397.   /* this only works on data types < 30, i.e. no extension octets */
  398.   if (IS_EXTENSION_ID(*bufp)){
  399.     ASNERROR("can't process ID >= 30");
  400.     return NULL;
  401.   }
  402.   *type = *bufp;
  403.   bufp = asn_parse_length(bufp + 1, &asn_length);
  404.   if (bufp == NULL)
  405.     return NULL;
  406.   header_len = SAFE_INT_CAST(bufp - data);
  407.   if ((unsigned long)(header_len + asn_length) > (unsigned long)*datalength){
  408.     ASNERROR("asn length too long");
  409.     return NULL;
  410.   }
  411.   *datalength = (int)asn_length;
  412.   return bufp;
  413. }
  414. /*
  415.  * asn_build_header - builds an ASN header for an object with the ID and
  416.  * length specified.
  417.  *  On entry, datalength is input as the number of valid bytes following
  418.  *   "data".  On exit, it is returned as the number of valid bytes
  419.  *   in this object following the id and length.
  420.  *
  421.  *  This only works on data types < 30, i.e. no extension octets.
  422.  *  The maximum length is 0xFFFF;
  423.  *
  424.  *  Returns a pointer to the first byte of the contents of this object.
  425.  *  Returns NULL on any error.
  426.  */
  427. unsigned char * asn_build_header( unsigned char *data,
  428.                                   int *datalength,
  429.                                   unsigned char type,
  430.                                   int length)
  431. {
  432.   if (*datalength < 1)
  433.     return NULL;
  434.   *data++ = type;
  435.   (*datalength)--;
  436.   return asn_build_length(data, datalength, length);
  437. }
  438. /*
  439.  * asn_build_sequence - builds an ASN header for a sequence with the ID and
  440.  * length specified.
  441.  *
  442.  *  This only works on data types < 30, i.e. no extension octets.
  443.  *
  444.  *  Returns a pointer to the first byte of the contents of this object.
  445.  *  Returns NULL on any error.
  446.  */
  447. unsigned char * asn_build_sequence( unsigned char *data,
  448.                                     int *datalength,
  449.                                     unsigned char type,
  450.                                     int length)
  451. {
  452.   unsigned char * data_with_length;
  453.   if( *datalength < 2 ) /* need at least two octets for a sequence */
  454.   {
  455.     ASNERROR( "build_sequence" );
  456.     return NULL;
  457.   }
  458.   *data++ = type;
  459.   (*datalength)--;
  460.   data_with_length = asn_build_length( data, datalength, length );
  461.   if( data_with_length == NULL )
  462.   {
  463.     (*datalength)++; /* correct datalength to emulate old behavior of build_sequence */
  464.     return NULL;
  465.   }
  466.      
  467.   return data_with_length;
  468. }
  469. /*
  470.  * asn_parse_length - interprets the length of the current object.
  471.  *  On exit, length contains the value of this length field.
  472.  *
  473.  *  Returns a pointer to the first byte after this length
  474.  *  field (aka: the start of the data field).
  475.  *  Returns NULL on any error.
  476.  */
  477. unsigned char * asn_parse_length( unsigned char *data,
  478.                                   unsigned long  *length)
  479. {
  480.   unsigned char lengthbyte = *data;
  481.   *length = 0;
  482.   if (lengthbyte & ASN_LONG_LEN){
  483.     lengthbyte &= ~ASN_LONG_LEN; /* turn MSb off */
  484.     if (lengthbyte == 0){
  485.       ASNERROR("We don't support indefinite lengths");
  486.       return NULL;
  487.     }
  488.     if (lengthbyte > sizeof(int)){
  489.       ASNERROR("we can't support data lengths that long");
  490.       return NULL;
  491.     }
  492.     // fixed
  493.     memcpy((char *)length, (char *)data + 1, (int)lengthbyte);
  494.     *length = ntohl(*length);
  495.     // ntohl even on ALPHA (DEC/COMPAQ) 64bit platforms works on 32bit int,
  496.     // whereas long is 64bit - therefore:
  497. #ifdef __osf__
  498.     *length >>= (8 * ((sizeof(int)) - lengthbyte));
  499. #else
  500.     *length >>= (8 * ((sizeof(long)) - lengthbyte));
  501. #endif
  502.     // check for length greater than 2^31
  503.     if (*length > 0x80000000ul) {
  504.       ASNERROR("SNMP does not support data lengths > 2^31");
  505.       return NULL;
  506.     }
  507.     return data + lengthbyte + 1;
  508.   } else { /* short asnlength */
  509.     *length = (long)lengthbyte;
  510.     return data + 1;
  511.   }
  512. }
  513. unsigned char *asn_build_length( unsigned char *data,
  514.                                  int *datalength,
  515.                                  int length)
  516. {
  517.   unsigned char    *start_data = data;
  518.   /* no indefinite lengths sent */
  519.   if (length < 0x80){
  520.     if (*datalength < 1){
  521.       ASNERROR("build_length");
  522.       return NULL;
  523.     }
  524.     *data++ = (unsigned char)length;
  525.   }
  526.   else if (length <= 0xFF){
  527.     if (*datalength < 2){
  528.       ASNERROR("build_length");
  529.       return NULL;
  530.     }
  531.     *data++ = (unsigned char)(0x01 | ASN_LONG_LEN);
  532.     *data++ = (unsigned char)length;
  533.   }
  534.   else if (length <= 0xFFFF) { /* 0xFF < length <= 0xFFFF */
  535.     if (*datalength < 3){
  536.       ASNERROR("build_length");
  537.       return NULL;
  538.     }
  539.     *data++ = (unsigned char)(0x02 | ASN_LONG_LEN);
  540.     *data++ = (unsigned char)((length >> 8) & 0xFF);
  541.     *data++ = (unsigned char)(length & 0xFF);
  542.   }
  543.   else if (length <= 0xFFFFFF) { /* 0xFF < length <= 0xFFFF */
  544.     if (*datalength < 4){
  545.       ASNERROR("build_length");
  546.       return NULL;
  547.     }
  548.     *data++ = (unsigned char)(0x03 | ASN_LONG_LEN);
  549.     *data++ = (unsigned char)((length >> 16) & 0xFF);
  550.     *data++ = (unsigned char)((length >> 8) & 0xFF);
  551.     *data++ = (unsigned char)(length & 0xFF);
  552.   }
  553.   else {
  554.     if (*datalength < 5){
  555.       ASNERROR("build_length");
  556.       return NULL;
  557.     }
  558.     *data++ = (unsigned char)(0x04 | ASN_LONG_LEN);
  559.     *data++ = (unsigned char)((length >> 24) & 0xFF);
  560.     *data++ = (unsigned char)((length >> 16) & 0xFF);
  561.     *data++ = (unsigned char)((length >> 8) & 0xFF);
  562.     *data++ = (unsigned char)(length & 0xFF);
  563.   }
  564.   *datalength -= SAFE_INT_CAST(data - start_data);
  565.   return data;
  566. }
  567. /*
  568.  * asn_parse_objid - pulls an object indentifier out of an ASN object identifier type.
  569.  *  On entry, datalength is input as the number of valid bytes following
  570.  *   "data".  On exit, it is returned as the number of valid bytes
  571.  *   following the beginning of the next object.
  572.  *
  573.  *  "objid" is filled with the object identifier.
  574.  *
  575.  *  Returns a pointer to the first byte past the end
  576.  *   of this object (i.e. the start of the next object).
  577.  *  Returns NULL on any error.
  578.  */
  579. unsigned char *asn_parse_objid( unsigned char *data,
  580.                                 int *datalength,
  581.                                 unsigned char *type,
  582.                                 oid *objid,
  583.                                 int *objidlength)
  584. {
  585.   /*
  586.    * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}*
  587.    * subidentifier ::= {leadingbyte}* lastbyte
  588.    * leadingbyte ::= 1 7bitvalue
  589.    * lastbyte ::= 0 7bitvalue
  590.    */
  591.   unsigned char *bufp = data;
  592.   oid *oidp = objid + 1;
  593.   unsigned long subidentifier;
  594.   long   length;
  595.   unsigned long     asn_length;
  596.   *type = *bufp++;
  597.   if (*type != 0x06) {
  598.     ASNERROR("Wrong Type. Not an oid");
  599.     return NULL;
  600.   }
  601.   bufp = asn_parse_length(bufp, &asn_length);
  602.   if (bufp == NULL)
  603.     return NULL;
  604.   if ((asn_length + (bufp - data)) > (unsigned long)(*datalength)){
  605.     ASNERROR("overflow of message");
  606.     return NULL;
  607.   }
  608.   *datalength -= (int)asn_length + SAFE_INT_CAST(bufp - data);
  609.   /* Handle invalid object identifier encodings of the form 06 00 robustly */
  610.   if (asn_length == 0)
  611.     objid[0] = objid[1] = 0;
  612.   length = asn_length;
  613.   (*objidlength)--; /* account for expansion of first byte */
  614.   while (length > 0 && (*objidlength)-- > 0){
  615.     subidentifier = 0;
  616.     do { /* shift and add in low order 7 bits */
  617.       subidentifier = (subidentifier << 7) + (*(unsigned char *)bufp & ~ASN_BIT8);
  618.       length--;
  619.     } while (*(unsigned char *)bufp++ & ASN_BIT8); /* last byte has high bit clear */
  620.     if (subidentifier > (unsigned long)MAX_SUBID){
  621.       ASNERROR("subidentifier too long");
  622.       return NULL;
  623.     }
  624.     *oidp++ = (oid)subidentifier;
  625.   }
  626.   /*
  627.    * The first two subidentifiers are encoded into the first component
  628.    * with the value (X * 40) + Y, where:
  629.    * X is the value of the first subidentifier.
  630.    *  Y is the value of the second subidentifier.
  631.    */
  632.   subidentifier = (unsigned long)objid[1];
  633.   if (subidentifier == 0x2B){
  634.     objid[0] = 1;
  635.     objid[1] = 3;
  636.   } else {
  637.     objid[1] = (unsigned char)(subidentifier % 40);
  638.     objid[0] = (unsigned char)((subidentifier - objid[1]) / 40);
  639.   }
  640.   *objidlength = (int)(oidp - objid);
  641.   return bufp;
  642. }
  643. /*
  644.  * asn_build_objid - Builds an ASN object identifier object containing the
  645.  * input string.
  646.  *  On entry, datalength is input as the number of valid bytes following
  647.  *   "data".  On exit, it is returned as the number of valid bytes
  648.  *   following the beginning of the next object.
  649.  *
  650.  *  Returns a pointer to the first byte past the end
  651.  *   of this object (i.e. the start of the next object).
  652.  *  Returns NULL on any error.
  653.  */
  654. unsigned char *asn_build_objid( unsigned char *data,
  655.                                 int *datalength,
  656.                                 unsigned char type,
  657.                                 oid *objid,
  658.                                 int objidlength)
  659. {
  660.   /*
  661.    * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}*
  662.    * subidentifier ::= {leadingbyte}* lastbyte
  663.    * leadingbyte ::= 1 7bitvalue
  664.    * lastbyte ::= 0 7bitvalue
  665.    */
  666.   // F.Fock correct buffer size must be 5*8bit*MAX_OID_LEN
  667.   unsigned char buf[MAX_OID_LEN*5];
  668.   unsigned char *bp = buf;
  669.   oid *op = objid;
  670.   int    asnlength;
  671.   unsigned long subid, mask, testmask;
  672.   int bits, testbits;
  673.   if (objidlength < 2){
  674.     *bp++ = 0;
  675.     objidlength = 0;
  676.   } else {
  677.     *bp++ = (unsigned char) (op[1] + (op[0] * 40));
  678.     objidlength -= 2;
  679.     op += 2;
  680.   }
  681.   while(objidlength-- > 0){
  682.     subid = *op++;
  683.     if (subid < 127){ /* off by one? */
  684.       *bp++ = (unsigned char )subid;
  685.     } else {
  686.       mask = 0x7F; /* handle subid == 0 case */
  687.       bits = 0;
  688.       /* testmask *MUST* !!!! be of an unsigned type */
  689.       for(testmask = 0x7F, testbits = 0; testmask != 0;
  690.   testmask <<= 7, testbits += 7){
  691. if (subid & testmask){ /* if any bits set */
  692.   mask = testmask;
  693.   bits = testbits;
  694. }
  695.       }
  696.       /* mask can't be zero here */
  697.       for(;mask != 0x7F; mask >>= 7, bits -= 7){
  698. /* fix a mask that got truncated above */
  699. if (mask == 0x1E00000)
  700.   mask = 0xFE00000;
  701. *bp++ = (unsigned char)(((subid & mask) >> bits) | ASN_BIT8);
  702.       }
  703.       *bp++ = (unsigned char)(subid & mask);
  704.     }
  705.   }
  706.   asnlength = SAFE_INT_CAST(bp - buf);
  707.   data = asn_build_header(data, datalength, type, asnlength);
  708.   if (data == NULL)
  709.     return NULL;
  710.   if (*datalength < asnlength)
  711.     return NULL;
  712.   // fixed
  713.   memcpy((char *)data, (char *)buf,  asnlength);
  714.   *datalength -= asnlength;
  715.   return data + asnlength;
  716. }
  717. /*
  718.  * asn_parse_null - Interprets an ASN null type.
  719.  *  On entry, datalength is input as the number of valid bytes following
  720.  *   "data".  On exit, it is returned as the number of valid bytes
  721.  *   following the beginning of the next object.
  722.  *
  723.  *  Returns a pointer to the first byte past the end
  724.  *   of this object (i.e. the start of the next object).
  725.  *  Returns NULL on any error.
  726.  */
  727. unsigned char *asn_parse_null(unsigned char *data,
  728.                               int *datalength,
  729.                               unsigned char *type)
  730. {
  731.   /*
  732.    * ASN.1 null ::= 0x05 0x00
  733.    */
  734.   unsigned char   *bufp = data;
  735.   unsigned long     asn_length;
  736.   *type = *bufp++;
  737.   if (*type != 0x05) {
  738.     ASNERROR("Wrong Type. Not a null");
  739.     return NULL;
  740.   }
  741.   bufp = asn_parse_length(bufp, &asn_length);
  742.   if (bufp == NULL)
  743.     return NULL;
  744.   if (asn_length != 0){
  745.     ASNERROR("Malformed NULL");
  746.     return NULL;
  747.   }
  748.   *datalength -= SAFE_INT_CAST(bufp - data);
  749.   return bufp + asn_length;
  750. }
  751. /*
  752.  * asn_build_null - Builds an ASN null object.
  753.  *  On entry, datalength is input as the number of valid bytes following
  754.  *   "data".  On exit, it is returned as the number of valid bytes
  755.  *   following the beginning of the next object.
  756.  *
  757.  *  Returns a pointer to the first byte past the end
  758.  *   of this object (i.e. the start of the next object).
  759.  *  Returns NULL on any error.
  760.  */
  761. unsigned char *asn_build_null( unsigned char *data,
  762.                                int *datalength,
  763.                                unsigned char type)
  764. {
  765.   /*
  766.    * ASN.1 null ::= 0x05 0x00
  767.    */
  768.   return asn_build_header(data, datalength, type, 0);
  769. }
  770. /*
  771.  * asn_parse_bitstring - pulls a bitstring out of an ASN bitstring type.
  772.  *  On entry, datalength is input as the number of valid bytes following
  773.  *   "data".  On exit, it is returned as the number of valid bytes
  774.  *   following the beginning of the next object.
  775.  *
  776.  *  "string" is filled with the bit string.
  777.  *
  778.  *  Returns a pointer to the first byte past the end
  779.  *   of this object (i.e. the start of the next object).
  780.  *  Returns NULL on any error.
  781.  */
  782. unsigned char *asn_parse_bitstring( unsigned char *data,
  783.                                     int *datalength,
  784.                                     unsigned char *type,
  785.                                     unsigned char *string,
  786.                                     int *strlength)
  787. {
  788.   /*
  789.    * bitstring ::= 0x03 asnlength unused {byte}*
  790.    */
  791.   unsigned char *bufp = data;
  792.   unsigned long     asn_length;
  793.   *type = *bufp++;
  794.   if (*type != 0x03) {
  795.     ASNERROR("Wrong Type. Not a bitstring");
  796.     return NULL;
  797.   }
  798.   bufp = asn_parse_length(bufp, &asn_length);
  799.   if (bufp == NULL)
  800.     return NULL;
  801.   if ((asn_length + (bufp - data)) > (unsigned long)(*datalength)){
  802.     ASNERROR("overflow of message");
  803.     return NULL;
  804.   }
  805.   if ((int) asn_length > *strlength){
  806.     ASNERROR("I don't support such long bitstrings");
  807.     return NULL;
  808.   }
  809.   if (asn_length < 1){
  810.     ASNERROR("Invalid bitstring");
  811.     return NULL;
  812.   }
  813.   if (*bufp > 7){
  814.     ASNERROR("Invalid bitstring");
  815.     return NULL;
  816.   }
  817.   // fixed
  818.   memcpy((char *)string,(char *)bufp,  (int)asn_length);
  819.   *strlength = (int)asn_length;
  820.   *datalength -= (int)asn_length + SAFE_INT_CAST(bufp - data);
  821.   return bufp + asn_length;
  822. }
  823. /*
  824.  * asn_build_bitstring - Builds an ASN bit string object containing the
  825.  * input string.
  826.  *  On entry, datalength is input as the number of valid bytes following
  827.  *   "data".  On exit, it is returned as the number of valid bytes
  828.  *   following the beginning of the next object.
  829.  *
  830.  *  Returns a pointer to the first byte past the end
  831.  *   of this object (i.e. the start of the next object).
  832.  *  Returns NULL on any error.
  833.  */
  834. unsigned char *asn_build_bitstring( unsigned char *data,
  835.                                     int *datalength,
  836.                                     unsigned char type,
  837.                                     unsigned char *string,
  838.                                     int strlength)
  839. {
  840.   /*
  841.    * ASN.1 bit string ::= 0x03 asnlength unused {byte}*
  842.    */
  843.   if (strlength < 1 || *string > 7){
  844.     ASNERROR("Building invalid bitstring");
  845.     return NULL;
  846.   }
  847.   data = asn_build_header(data, datalength, type, strlength);
  848.   if (data == NULL)
  849.     return NULL;
  850.   if (*datalength < strlength)
  851.     return NULL;
  852.   // fixed
  853.   memcpy((char *)data,(char *)string, strlength);
  854.   *datalength -= strlength;
  855.   return data + strlength;
  856. }
  857. /*
  858.  * asn_parse_unsigned_int64 - pulls a 64 bit unsigned long out of an ASN int
  859.  * type.
  860.  *  On entry, datalength is input as the number of valid bytes following
  861.  *   "data".  On exit, it is returned as the number of valid bytes
  862.  *   following the end of this object.
  863.  *
  864.  *  Returns a pointer to the first byte past the end
  865.  *   of this object (i.e. the start of the next object).
  866.  *  Returns NULL on any error.
  867.  */
  868. unsigned char * asn_parse_unsigned_int64(  unsigned char *data,
  869.                                            int *datalength,
  870.                                            unsigned char *type,
  871.                                            struct counter64 *cp,
  872.                                            int countersize)
  873. {
  874.   /*
  875.    * ASN.1 integer ::= 0x02 asnlength byte {byte}*
  876.    */
  877.   unsigned char *bufp = data;
  878.   unsigned long     asn_length;
  879.   unsigned long low = 0, high = 0;
  880.   int intsize = 4;
  881.   if (countersize != sizeof(struct counter64)){
  882.     ASNERROR("not right size");
  883.     return NULL;
  884.   }
  885.   *type = *bufp++;
  886.   if ((*type != 0x02) && (*type != 0x46)) {
  887.     ASNERROR("Wrong Type. Not an integer 64");
  888.     return NULL;
  889.   }
  890.   bufp = asn_parse_length(bufp, &asn_length);
  891.   if (bufp == NULL){
  892.     ASNERROR("bad length");
  893.     return NULL;
  894.   }
  895.   if ((asn_length + (bufp - data)) > (unsigned long)(*datalength)){
  896.     ASNERROR("overflow of message");
  897.     return NULL;
  898.   }
  899.   if (((int)asn_length > (intsize * 2 + 1)) ||
  900.       (((int)asn_length == (intsize * 2) + 1) && *bufp != 0x00)){
  901.     ASNERROR("I don't support such large integers");
  902.     return NULL;
  903.   }
  904.   *datalength -= (int)asn_length + SAFE_INT_CAST(bufp - data);
  905.   if (*bufp & 0x80){
  906.     low = (unsigned long) -1; // integer is negative
  907.     high = (unsigned long) -1;
  908.   }
  909.   while(asn_length--){
  910.     high = (high << 8) | ((low & 0xFF000000) >> 24);
  911.     low = (low << 8) | *bufp++;
  912.   }
  913.   cp->low = low;
  914.   cp->high = high;
  915.   return bufp;
  916. }
  917. /*
  918.  * asn_build_unsigned_int64 - builds an ASN object containing a 64 bit integer.
  919.  *  On entry, datalength is input as the number of valid bytes following
  920.  *   "data".  On exit, it is returned as the number of valid bytes
  921.  *   following the end of this object.
  922.  *
  923.  *  Returns a pointer to the first byte past the end
  924.  *   of this object (i.e. the start of the next object).
  925.  *  Returns NULL on any error.
  926.  */
  927. unsigned char * asn_build_unsigned_int64( unsigned char *data,
  928.                                           int *datalength,
  929.                                           unsigned char type,
  930.                                           struct counter64 *cp,
  931.                                           int countersize)
  932. {
  933.   /*
  934.    * ASN.1 integer ::= 0x02 asnlength byte {byte}*
  935.    */
  936.   unsigned long low, high;
  937.   unsigned long mask, mask2;
  938.   int add_null_byte = 0;
  939.   int intsize;
  940.   if (countersize != sizeof (struct counter64))
  941.     return NULL;
  942.   intsize = 8;
  943.   low = cp->low;
  944.   high = cp->high;
  945.   mask = 0xFFul << (8 * (sizeof(long) - 1));
  946.   /* mask is 0xFF000000 on a big-endian machine */
  947.   if ((unsigned char)((high & mask) >> (8 * (sizeof(long) - 1))) & 0x80){
  948.     /* if MSB is set */
  949.     add_null_byte = 1;
  950.     intsize++;
  951.   }
  952.   else {
  953.     /*
  954.      * Truncate "unnecessary" bytes off of the most significant end of this 2's
  955.      * complement integer.
  956.      * There should be no sequence of 9 consecutive 1's or 0's at the most
  957.      * significant end of the integer.
  958.      */
  959.     mask2 = 0x1FFul << ((8 * (sizeof(long) - 1)) - 1);
  960.     /* mask2 is 0xFF800000 on a big-endian machine */
  961.     while((((high & mask2) == 0) || ((high & mask2) == mask2))
  962.   && intsize > 1){
  963.       intsize--;
  964.       high = (high << 8)
  965. | ((low & mask) >> (8 * (sizeof(long) - 1)));
  966.       low <<= 8;
  967.     }
  968.   }
  969.   data = asn_build_header(data, datalength, type, intsize);
  970.   if (data == NULL)
  971.     return NULL;
  972.   if (*datalength < intsize)
  973.     return NULL;
  974.   *datalength -= intsize;
  975.   if (add_null_byte == 1){
  976.     *data++ = '';
  977.     intsize--;
  978.   }
  979.   while(intsize--){
  980.     *data++ = (unsigned char)((high & mask) >> (8 * (sizeof(long) - 1)));
  981.     high = (high << 8)
  982.       | ((low & mask) >> (8 * (sizeof(long) - 1)));
  983.     low <<= 8;
  984.   }
  985.   return data;
  986. }
  987. // create a pdu
  988. struct snmp_pdu * snmp_pdu_create( int command)
  989. {
  990.   struct snmp_pdu *pdu;
  991.   pdu = (struct snmp_pdu *)malloc(sizeof(struct snmp_pdu));
  992.   memset((char *)pdu, 0,sizeof(struct snmp_pdu));
  993.   pdu->command = command;
  994. #ifdef _SNMPv3
  995.   pdu->msgid = 0;
  996. #endif
  997.   pdu->errstat = 0;
  998.   pdu->errindex = 0;
  999.   pdu->enterprise = NULL;
  1000.   pdu->enterprise_length = 0;
  1001.   pdu->variables = NULL;
  1002.   return pdu;
  1003. }
  1004. // free content and clear pointers
  1005. void clear_pdu(struct snmp_pdu *pdu, bool clear_all)
  1006. {
  1007.   struct variable_list *vp, *ovp;
  1008.   vp = pdu->variables;
  1009.   while (vp)
  1010.   {
  1011.     if (vp->name) free((char *)vp->name);  // free the oid part
  1012.     if (vp->val.string) free((char *)vp->val.string);  // free deep data
  1013.     ovp = vp;
  1014.     vp = vp->next_variable;     // go to the next one
  1015.     free((char *)ovp);     // free up vb itself
  1016.   }
  1017.   pdu->variables = NULL;
  1018.   // if enterprise free it up
  1019.   if (pdu->enterprise)
  1020.     free((char *)pdu->enterprise);
  1021.   pdu->enterprise = NULL;
  1022.   if (!clear_all) return;
  1023.   pdu->command = 0;
  1024.   pdu->reqid   = 0;
  1025. #ifdef _SNMPv3
  1026.   pdu->msgid   = 0;
  1027.   pdu->maxsize_scopedpdu = 0;
  1028. #endif
  1029.   pdu->errstat = 0;
  1030.   pdu->errindex = 0;
  1031.   pdu->enterprise_length = 0;
  1032.   pdu->trap_type = 0;
  1033.   pdu->specific_type = 0;
  1034.   pdu->time = 0;
  1035. }
  1036. // free a pdu
  1037. void snmp_free_pdu( struct snmp_pdu *pdu)
  1038. {
  1039.   clear_pdu(pdu); // clear and free content
  1040.   free((char *)pdu);   // free up pdu itself
  1041. }
  1042. // add a null var to a pdu
  1043. void snmp_add_var(struct snmp_pdu *pdu,
  1044.   oid *name,
  1045.   int name_length,
  1046.   SmiVALUE *smival)
  1047. {
  1048.   struct variable_list *vars;
  1049.   // if we don't have a vb list ,create one
  1050.   if (pdu->variables == NULL)
  1051.     pdu->variables = vars = (struct variable_list *)malloc(sizeof(struct variable_list));
  1052.   else
  1053.   {
  1054.     // we have one, find the end
  1055.     vars = pdu->variables;
  1056.     while (vars->next_variable) vars = vars->next_variable;
  1057.     // create a new one
  1058.     vars->next_variable = (struct variable_list *)malloc(sizeof(struct variable_list));
  1059.     // bump ptr
  1060.     vars = vars->next_variable;
  1061.   }
  1062.   // add the oid with no data
  1063.   vars->next_variable = NULL;
  1064.   // hook in the Oid portion
  1065.   vars->name = (oid *)malloc(name_length * sizeof(oid));
  1066.   // fixed
  1067.   memcpy((char *)vars->name,(char *)name, name_length * sizeof(oid));
  1068.   vars->name_length = name_length;
  1069.   // hook in the SMI value
  1070.   switch( smival->syntax)
  1071.     {
  1072.       // null , do nothing
  1073.     case sNMP_SYNTAX_NULL:
  1074.     case sNMP_SYNTAX_NOSUCHOBJECT:
  1075.     case sNMP_SYNTAX_NOSUCHINSTANCE:
  1076.     case sNMP_SYNTAX_ENDOFMIBVIEW:
  1077.       {
  1078. vars->type = (unsigned char) smival->syntax;
  1079. vars->val.string = NULL;
  1080. vars->val_len = 0;
  1081.       }
  1082.       break;
  1083.       // octects
  1084.     case sNMP_SYNTAX_OCTETS:
  1085.     case sNMP_SYNTAX_OPAQUE:
  1086.     case sNMP_SYNTAX_IPADDR:
  1087.       {
  1088. vars->type = (unsigned char) smival->syntax;
  1089. vars->val.string = (unsigned char *)malloc((unsigned)smival->value.string.len);
  1090. vars->val_len = (int) smival->value.string.len;
  1091. memcpy( (unsigned char *) vars->val.string,
  1092. (unsigned char *) smival->value.string.ptr,
  1093. (unsigned) smival->value.string.len);
  1094.       }
  1095.       break;
  1096.       // oid
  1097.     case sNMP_SYNTAX_OID:
  1098.       {
  1099. vars->type = (unsigned char) smival->syntax;
  1100.         vars->val_len = (int) smival->value.oid.len * sizeof(oid);
  1101. vars->val.objid = (oid *)malloc((unsigned)vars->val_len);
  1102. memcpy((unsigned long *)vars->val.objid,
  1103.        (unsigned long *)smival->value.oid.ptr,
  1104.        (unsigned) vars->val_len);
  1105.       }
  1106.       break;
  1107.     case sNMP_SYNTAX_TIMETICKS:
  1108.     case sNMP_SYNTAX_CNTR32:
  1109.     case sNMP_SYNTAX_GAUGE32:
  1110.       //    case sNMP_SYNTAX_UINT32:
  1111.       {
  1112. long templong;
  1113. vars->type = (unsigned char) smival->syntax;
  1114. vars->val.integer = (long *)malloc(sizeof(long));
  1115. vars->val_len = sizeof(long);
  1116. templong = (long) smival->value.uNumber;
  1117. memcpy( (long*) vars->val.integer,
  1118. (long*) &templong,
  1119. sizeof(long));
  1120.       }
  1121.       break;
  1122.     case sNMP_SYNTAX_INT32:
  1123.       {
  1124. long templong;
  1125. vars->type = (unsigned char) smival->syntax;
  1126. vars->val.integer = (long *)malloc(sizeof(long));
  1127. vars->val_len = sizeof(long);
  1128. templong = (long) smival->value.sNumber;
  1129. memcpy( (long*) vars->val.integer,
  1130. (long*) &templong,
  1131. sizeof(long));
  1132.       }
  1133.       break;
  1134.       // 64 bit counter
  1135.     case sNMP_SYNTAX_CNTR64:
  1136.       {
  1137. vars->type = ( unsigned char) smival->syntax;
  1138. vars->val.counter64 = (struct counter64 *)malloc( sizeof(struct counter64) );
  1139. vars->val_len = sizeof(struct counter64);
  1140. memcpy( (struct counter64*) vars->val.counter64,
  1141. (SmiLPCNTR64) &(smival->value.hNumber),
  1142. sizeof( SmiCNTR64));
  1143.       }
  1144.       break;
  1145.     } // end switch
  1146. }
  1147. // build the authentication, works for v1 or v2c
  1148. static unsigned char *snmp_auth_build(unsigned char *data,
  1149.       int *length,
  1150.       const long int version,
  1151.       const unsigned char *community,
  1152.       const int community_len,
  1153.       const int messagelen)
  1154. {
  1155.   // 5 is 3 octets for version and 2 for community header + len
  1156.   // This assumes that community will not be longer than 0x7f chars.
  1157.   data = asn_build_sequence(data, length,
  1158.     (unsigned char)(ASN_SEQUENCE | ASN_CONSTRUCTOR),
  1159.     messagelen + community_len + 5);
  1160.   if (data == NULL){ 
  1161.     ASNERROR("buildheader");
  1162.     return NULL;
  1163.   }
  1164.   data = asn_build_int(data, length,
  1165.        (unsigned char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
  1166.        &version, sizeof(version));
  1167.   if (data == NULL){
  1168.     ASNERROR("buildint");
  1169.     return NULL;
  1170.   }
  1171.   data = asn_build_string(data, length,
  1172.   (unsigned char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR),
  1173.   community, community_len);
  1174.   if (data == NULL){
  1175.     ASNERROR("buildstring");
  1176.     return NULL;
  1177.   }
  1178.   return data;
  1179. }
  1180. // build a variable binding
  1181. unsigned char * snmp_build_var_op(unsigned char *data,
  1182.   oid * var_name,
  1183.   int *var_name_len,
  1184.   unsigned char var_val_type,
  1185.   int var_val_len,
  1186.   unsigned char *var_val,
  1187.   int *listlength)
  1188. {
  1189.   int valueLen;
  1190.   Buffer<unsigned char> buffer(MAX_SNMP_PACKET);
  1191.   unsigned char *buffer_pos = buffer.get_ptr();
  1192.   int bufferLen = MAX_SNMP_PACKET;
  1193.   buffer_pos = asn_build_objid( buffer_pos,
  1194.   &bufferLen,
  1195.   (unsigned char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID),
  1196.   var_name,
  1197.   *var_name_len);
  1198.   if (buffer_pos == NULL){
  1199.     ASNERROR("build_var_op: build_objid failed");
  1200.     return NULL;
  1201.   }
  1202.   // based on the type...
  1203.   switch(var_val_type){
  1204.   case ASN_INTEGER:
  1205.     buffer_pos = asn_build_int(buffer_pos, &bufferLen,
  1206.                                var_val_type,
  1207.                                (long *)var_val, var_val_len);
  1208.     break;
  1209.   case SMI_GAUGE:
  1210.   case SMI_COUNTER:
  1211.   case SMI_TIMETICKS:
  1212.   case SMI_UINTEGER:
  1213.     buffer_pos = asn_build_unsigned_int(buffer_pos, &bufferLen,
  1214.                                         var_val_type,
  1215.                                         (unsigned long *)var_val, var_val_len);
  1216.     break;
  1217.   case SMI_COUNTER64:
  1218.     buffer_pos = asn_build_unsigned_int64(buffer_pos, &bufferLen,
  1219.                                           var_val_type,
  1220.                                           (struct counter64 *)var_val,
  1221.                                           var_val_len);
  1222.     break;
  1223.   case ASN_OCTET_STR:
  1224.   case SMI_IPADDRESS:
  1225.   case SMI_OPAQUE:
  1226.   case SMI_NSAP:
  1227.     buffer_pos = asn_build_string(buffer_pos, &bufferLen, var_val_type,
  1228.                                   var_val, var_val_len);
  1229.     break;
  1230.   case ASN_OBJECT_ID:
  1231.     buffer_pos = asn_build_objid(buffer_pos, &bufferLen, var_val_type,
  1232.                                  (oid *)var_val, var_val_len / sizeof(oid));
  1233.     break;
  1234.   case ASN_NULL:
  1235.     buffer_pos = asn_build_null(buffer_pos, &bufferLen, var_val_type);
  1236.     break;
  1237.   case ASN_BIT_STR:
  1238.     buffer_pos = asn_build_bitstring(buffer_pos, &bufferLen, var_val_type,
  1239.                                      var_val, var_val_len);
  1240.     break;
  1241.   case SNMP_NOSUCHOBJECT:
  1242.   case SNMP_NOSUCHINSTANCE:
  1243.   case SNMP_ENDOFMIBVIEW:
  1244.     buffer_pos = asn_build_null(buffer_pos, &bufferLen, var_val_type);
  1245.     break;
  1246.   default:
  1247.     ASNERROR("build_var_op: wrong type");
  1248.     return NULL;
  1249.   }
  1250.   if (buffer_pos == NULL){
  1251.     ASNERROR("build_var_op: value build failed");
  1252.     return NULL;
  1253.   }
  1254.   valueLen = SAFE_INT_CAST(buffer_pos - buffer.get_ptr());
  1255.   data = asn_build_sequence(data, listlength,
  1256.                             (unsigned char)(ASN_SEQUENCE | ASN_CONSTRUCTOR),
  1257.                             valueLen);
  1258.   if( data == NULL || *listlength < valueLen )
  1259.   {
  1260.     ASNERROR( "build_var_op" );
  1261.     data = NULL;
  1262.   }
  1263.   else
  1264.   {
  1265.     memcpy(data, buffer.get_ptr(), valueLen );
  1266.     data += valueLen;
  1267.     (*listlength)-=valueLen;
  1268.   }
  1269.   return data;
  1270. }
  1271. unsigned char *build_vb(struct snmp_pdu *pdu,
  1272. unsigned char *buf, int *buf_len)
  1273. {
  1274.   Buffer<unsigned char> tmp_buf(MAX_SNMP_PACKET);
  1275.   unsigned char *cp = tmp_buf.get_ptr();
  1276.   struct   variable_list *vp;
  1277.   int vb_length;
  1278.   int length = MAX_SNMP_PACKET;
  1279.   // build varbinds into packet buffer
  1280.   for(vp = pdu->variables; vp; vp = vp->next_variable)
  1281.   {
  1282.     cp = snmp_build_var_op( cp, vp->name, &vp->name_length,
  1283.     vp->type, vp->val_len,
  1284.     (unsigned char *)vp->val.string,
  1285.     &length);
  1286.     if (cp == NULL) return 0;
  1287.   }
  1288.   vb_length = SAFE_INT_CAST(cp - tmp_buf.get_ptr());
  1289.   *buf_len -= vb_length;
  1290.   if (*buf_len <= 0) return 0;
  1291.   // encode the length of encoded varbinds into buf
  1292.   cp = asn_build_header( buf, buf_len,
  1293.  (unsigned char)(ASN_SEQUENCE | ASN_CONSTRUCTOR),
  1294.  vb_length);
  1295.   if (cp == NULL) return 0;
  1296.   // copy varbinds from packet behind header in buf
  1297.   memcpy(cp, tmp_buf.get_ptr(), vb_length);
  1298.   return (cp + vb_length);
  1299. }
  1300. unsigned char *build_data_pdu(struct snmp_pdu *pdu,
  1301.       unsigned char *buf, int *buf_len,
  1302.       unsigned char *vb_buf, int vb_buf_len)
  1303. {
  1304.   Buffer<unsigned char> tmp_buf(MAX_SNMP_PACKET);
  1305.   unsigned char *cp = tmp_buf.get_ptr();
  1306.   int totallength;
  1307.   int length = MAX_SNMP_PACKET;
  1308.   // build data of pdu into tmp_buf
  1309.   if (pdu->command != TRP_REQ_MSG)
  1310.   {
  1311.     // request id
  1312.     cp = asn_build_int( cp, &length,
  1313. (unsigned char )(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
  1314. (long *)&pdu->reqid, sizeof(pdu->reqid));
  1315.     if (cp == NULL) return 0;
  1316.     // error status
  1317.     cp = asn_build_int(cp, &length,
  1318.        (unsigned char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
  1319.        (long *)&pdu->errstat, sizeof(pdu->errstat));
  1320.     if (cp == NULL) return 0;
  1321.     // error index
  1322.     cp = asn_build_int(cp, &length,
  1323.        (unsigned char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
  1324.        (long *)&pdu->errindex, sizeof(pdu->errindex));
  1325.     if (cp == NULL) return 0;
  1326.   }
  1327.   else
  1328.   { // this is a trap message
  1329.     // enterprise
  1330.     cp = asn_build_objid( cp, &length,
  1331.   (unsigned char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID),
  1332.   (oid *)pdu->enterprise, pdu->enterprise_length);
  1333.     if (cp == NULL) return 0;
  1334.     // agent-addr ; must be IPADDRESS changed by Frank Fock
  1335.     cp = asn_build_string(cp, &length,
  1336.   (unsigned char)(SMI_IPADDRESS),
  1337.   (unsigned char *)&pdu->agent_addr.sin_addr.s_addr,
  1338.   sizeof(pdu->agent_addr.sin_addr.s_addr));
  1339.     if (cp == NULL) return 0;
  1340.     long dummy = pdu->trap_type;
  1341.     // generic trap
  1342.     cp = asn_build_int(cp, &length,
  1343.        (unsigned char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
  1344.        &dummy, sizeof(dummy));
  1345.     if (cp == NULL) return 0;
  1346.     dummy = pdu->specific_type;
  1347.     // specific trap
  1348.     cp = asn_build_int( cp, &length,
  1349. (unsigned char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
  1350. &dummy, sizeof(dummy));
  1351.     if (cp == NULL) return 0;
  1352.     // timestamp
  1353.     cp = asn_build_unsigned_int(cp, &length,
  1354.                                 (unsigned char )(SMI_TIMETICKS),
  1355.                                 &pdu->time, sizeof(pdu->time));
  1356.     if (cp == NULL) return 0;
  1357.   }
  1358.   if (length < vb_buf_len) return 0;
  1359.   // save relative position of varbinds
  1360.   int vb_rel_pos = SAFE_INT_CAST(cp - tmp_buf.get_ptr());
  1361.   totallength = SAFE_INT_CAST(cp - tmp_buf.get_ptr()) + vb_buf_len;
  1362.   // build header for datapdu into buf
  1363.   cp = asn_build_header(buf, buf_len,
  1364. (unsigned char)pdu->command, totallength);
  1365.   if (cp == NULL) return 0;
  1366.   if (*buf_len < totallength) return 0;
  1367.   // copy data behind header
  1368.   memcpy(cp, tmp_buf.get_ptr(), totallength - vb_buf_len);
  1369.   memcpy((char *)cp + vb_rel_pos, (char *)vb_buf, vb_buf_len);
  1370.   *buf_len -= totallength;
  1371.   return (cp + totallength);
  1372. }
  1373. // serialize the pdu
  1374. int snmp_build(struct snmp_pdu *pdu,
  1375.                unsigned char *packet,          int *out_length,
  1376.                const long version,
  1377.                const unsigned char* community, const int community_len)
  1378. {
  1379.   Buffer<unsigned char> buf(MAX_SNMP_PACKET);
  1380.   unsigned char  *cp;
  1381.   int      length;
  1382.   int  totallength;
  1383.   // encode vbs with header into packet
  1384.   length = *out_length;
  1385.   cp = build_vb(pdu, packet, &length);
  1386.   if (cp == 0) return -1;
  1387.   totallength = SAFE_INT_CAST(cp - packet);
  1388.   if (totallength >= *out_length) return -1;
  1389.   // encode datadpu into buf
  1390.   length = MAX_SNMP_PACKET;
  1391.   cp = build_data_pdu(pdu, buf.get_ptr(), &length,
  1392.       packet, totallength);
  1393.   if (cp == 0) return -1;
  1394.   totallength = SAFE_INT_CAST(cp - buf.get_ptr());
  1395.   if (totallength >= *out_length) return -1;
  1396.   // build SNMP header
  1397.   length = *out_length;
  1398.   cp = snmp_auth_build( packet, &length, version,
  1399. community, community_len, totallength );
  1400.   if (cp == NULL) return -1;
  1401.   if ((*out_length - (cp - packet)) < totallength) return -1;
  1402.   // copy data
  1403.   memcpy(cp, buf.get_ptr(), totallength);
  1404.   totallength += SAFE_INT_CAST(cp - packet);
  1405.   *out_length = totallength;
  1406.   return 0;
  1407. }
  1408. // parse the authentication header
  1409. static unsigned char *snmp_auth_parse(unsigned char *data,
  1410.       int *length,
  1411.       unsigned char *community,
  1412.       int *community_len,
  1413.       long *version)
  1414. {
  1415.   unsigned char type;
  1416.   // get the type
  1417.   data = asn_parse_header(data, length, &type);
  1418.   if (data == NULL){
  1419.     ASNERROR("bad header");
  1420.     return NULL;
  1421.   }
  1422.   if (type != (ASN_SEQUENCE | ASN_CONSTRUCTOR)){
  1423.     ASNERROR("wrong auth header type");
  1424.     return NULL;
  1425.   }
  1426.   // get the version
  1427.   data = asn_parse_int(data, length, &type, version, sizeof(*version));
  1428.   if (data == NULL){
  1429.     ASNERROR("bad parse of version");
  1430.     return NULL;
  1431.   }
  1432.   // get the community name
  1433.   data = asn_parse_string(data, length, &type, community, community_len);
  1434.   if (data == NULL){
  1435.     ASNERROR("bad parse of community");
  1436.     return NULL;
  1437.   }
  1438.   return (unsigned char *)data;
  1439. }
  1440. unsigned char *
  1441. snmp_parse_var_op( unsigned char *data,  // IN - pointer to the start of object
  1442.    oid     *var_name,          // OUT - object id of variable
  1443.    int     *var_name_len,       // IN/OUT - length of variable name
  1444.    unsigned char  *var_val_type, // OUT - type of variable (int or octet string) (one byte)
  1445.    int     *var_val_len,        // OUT - length of variable
  1446.    unsigned char  **var_val,  // OUT - pointer to ASN1 encoded value of variable
  1447.    int     *listlength)         // IN/OUT - number of valid bytes left in var_op_list
  1448. {
  1449.   unsigned char var_op_type;
  1450.   int var_op_len = *listlength;
  1451.   unsigned char *var_op_start = data;
  1452.   data = asn_parse_header(data, &var_op_len, &var_op_type);
  1453.   if (data == NULL){
  1454.     ASNERROR("Error snmp_parse_var_op: 1");
  1455.     return NULL;
  1456.   }
  1457.   if (var_op_type != (unsigned  char)(ASN_SEQUENCE | ASN_CONSTRUCTOR))
  1458.     return NULL;
  1459.   data = asn_parse_objid(data, &var_op_len, &var_op_type, var_name, var_name_len);
  1460.   if (data == NULL){
  1461.     ASNERROR("Error snmp_parse_var_op: 2");
  1462.     return NULL;
  1463.   }
  1464.   if (var_op_type != (unsigned char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID))
  1465.     return NULL;
  1466.   *var_val = data; /* save pointer to this object */
  1467.   /* find out what type of object this is */
  1468.   data = asn_parse_header(data, &var_op_len, var_val_type);
  1469.   if (data == NULL){
  1470.     ASNERROR("Error snmp_parse_var_op: 3");
  1471.     return NULL;
  1472.   }
  1473.   if (((unsigned long)var_op_len + (data - var_op_start)) > (unsigned long)(*listlength)) {
  1474.     ASNERROR("Error snmp_parse_var_op: 4");
  1475.     return NULL;
  1476.   }
  1477.   *var_val_len = (int)var_op_len;
  1478.   data += var_op_len;
  1479.   *listlength -= (int)(data - var_op_start);
  1480.   return data;
  1481. }
  1482. int snmp_parse_vb(struct snmp_pdu *pdu, unsigned char *&data, int &data_len)
  1483. {
  1484.   unsigned char  *var_val;
  1485.   int len;
  1486.   struct variable_list *vp = 0;
  1487.   oid     objid[ASN_MAX_NAME_LEN], *op;
  1488.   unsigned char type;
  1489.   // get the vb list from received data
  1490.   data = asn_parse_header(data, &data_len, &type);
  1491.   if (data == NULL)
  1492.     return SNMP_CLASS_ASN1ERROR;
  1493.   if (type != (unsigned char)(ASN_SEQUENCE | ASN_CONSTRUCTOR))
  1494.     return SNMP_CLASS_ASN1ERROR;
  1495.   pdu->variables = NULL;
  1496.   while(data_len > 0){
  1497.     if (pdu->variables == NULL){
  1498.       pdu->variables = vp = (struct variable_list *)malloc(sizeof(struct variable_list));
  1499.     } else {
  1500.       vp->next_variable = (struct variable_list *)malloc(sizeof(struct variable_list));
  1501.       vp = vp->next_variable;
  1502.     }
  1503.     vp->next_variable = NULL;
  1504.     vp->val.string = NULL;
  1505.     vp->name = NULL;
  1506.     vp->name_length = ASN_MAX_NAME_LEN;
  1507.     data = snmp_parse_var_op( data, objid, &vp->name_length, &vp->type,
  1508.       &vp->val_len, &var_val, &data_len);
  1509.     if (data == NULL)
  1510.       return SNMP_CLASS_ASN1ERROR;
  1511.     op = (oid *)malloc((unsigned)vp->name_length * sizeof(oid));
  1512.     // fixed
  1513.     memcpy((char *)op, (char *)objid, vp->name_length * sizeof(oid));
  1514.     vp->name = op;
  1515.     len = MAX_SNMP_PACKET;
  1516.     switch((short)vp->type){
  1517.     case ASN_INTEGER:
  1518.       vp->val.integer = (long *)malloc(sizeof(long));
  1519.       vp->val_len = sizeof(long);
  1520.       asn_parse_int(var_val, &len, &vp->type, (long *)vp->val.integer, sizeof(*vp->val.integer));
  1521.       break;
  1522.     case SMI_COUNTER:
  1523.     case SMI_GAUGE:
  1524.     case SMI_TIMETICKS:
  1525.     case SMI_UINTEGER:
  1526.       vp->val.integer = (long *)malloc(sizeof(long));
  1527.       vp->val_len = sizeof(long);
  1528.       asn_parse_unsigned_int(var_val, &len, &vp->type, (unsigned long *)vp->val.integer, sizeof(*vp->val.integer));
  1529.       break;
  1530.     case SMI_COUNTER64:
  1531.       vp->val.counter64 = (struct counter64 *)malloc( sizeof(struct counter64) );
  1532.       vp->val_len = sizeof(struct counter64);
  1533.       asn_parse_unsigned_int64(var_val, &len, &vp->type,
  1534.        (struct counter64 *)vp->val.counter64,
  1535.        sizeof(*vp->val.counter64));
  1536.       break;
  1537.     case ASN_OCTET_STR:
  1538.     case SMI_IPADDRESS:
  1539.     case SMI_OPAQUE:
  1540.     case SMI_NSAP:
  1541.       vp->val.string = (unsigned char *)malloc((unsigned)vp->val_len);
  1542.       asn_parse_string(var_val, &len, &vp->type, vp->val.string, &vp->val_len);
  1543.       break;
  1544.     case ASN_OBJECT_ID:
  1545.       vp->val_len = ASN_MAX_NAME_LEN;
  1546.       asn_parse_objid(var_val, &len, &vp->type, objid, &vp->val_len);
  1547.       //vp->val_len *= sizeof(oid);
  1548.       vp->val.objid = (oid *)malloc((unsigned)vp->val_len * sizeof(oid));
  1549.       // fixed
  1550.       memcpy((char *)vp->val.objid,
  1551.      (char *)objid,
  1552.      vp->val_len * sizeof(oid));
  1553.       break;
  1554.     case SNMP_NOSUCHOBJECT:
  1555.     case SNMP_NOSUCHINSTANCE:
  1556.     case SNMP_ENDOFMIBVIEW:
  1557.     case ASN_NULL:
  1558.       break;
  1559.     default:
  1560.       ASNERROR("bad type returned ");
  1561.       return SNMP_CLASS_ASN1ERROR;
  1562.       break;
  1563.     }
  1564.   }
  1565.   return SNMP_CLASS_SUCCESS;
  1566. }
  1567. int snmp_parse_data_pdu(snmp_pdu *pdu, unsigned char *&data, int &length)
  1568. {
  1569.   oid     objid[ASN_MAX_NAME_LEN];
  1570.   int     four = 4;
  1571.   unsigned char  type;
  1572.   data = asn_parse_header(data, &length, &type);
  1573.   if (data == NULL) return SNMP_CLASS_ASN1ERROR;
  1574.   pdu->command = type;
  1575.   if (pdu->command != TRP_REQ_MSG)
  1576.   {
  1577.     // get the rid
  1578.     data = asn_parse_int(data, &length, &type,
  1579.  (long *)&pdu->reqid, sizeof(pdu->reqid));
  1580.     if (data == NULL) return SNMP_CLASS_ASN1ERROR;
  1581.     // get the error status
  1582.     data = asn_parse_int(data, &length, &type,
  1583.  (long *)&pdu->errstat, sizeof(pdu->errstat));
  1584.     if (data == NULL) return SNMP_CLASS_ASN1ERROR;
  1585.     // get the error index
  1586.     data = asn_parse_int(data, &length, &type,
  1587.  (long *)&pdu->errindex, sizeof(pdu->errindex));
  1588.     if (data == NULL) return SNMP_CLASS_ASN1ERROR;
  1589.   }
  1590.   else
  1591.   {  // is a trap
  1592.     // get the enterprise
  1593.     pdu->enterprise_length = ASN_MAX_NAME_LEN;
  1594.     data = asn_parse_objid(data, &length, &type,
  1595.    objid, &pdu->enterprise_length);
  1596.     if (data == NULL) return SNMP_CLASS_ASN1ERROR;
  1597.     pdu->enterprise = (oid *)malloc(pdu->enterprise_length * sizeof(oid));
  1598.     memcpy((char *)pdu->enterprise,(char *)objid,
  1599.    pdu->enterprise_length * sizeof(oid));
  1600.     // get source address
  1601.     data = asn_parse_string(data, &length, &type,
  1602.     (unsigned char *)&pdu->agent_addr.sin_addr.s_addr,
  1603.     &four);
  1604.     if (data == NULL) return SNMP_CLASS_ASN1ERROR;
  1605.     // get trap type
  1606.     long dummy = 0;
  1607.     data = asn_parse_int(data, &length, &type, &dummy, sizeof(dummy));
  1608.     pdu->trap_type = dummy;
  1609.     if (data == NULL) return SNMP_CLASS_ASN1ERROR;
  1610.     // trap type
  1611.     dummy = 0;
  1612.     data = asn_parse_int(data, &length, &type, &dummy, sizeof(dummy));
  1613.     pdu->specific_type = dummy;
  1614.     if (data == NULL) return SNMP_CLASS_ASN1ERROR;
  1615.     // timestamp
  1616.     data = asn_parse_unsigned_int(data, &length, &type,
  1617.                                   &pdu->time, sizeof(pdu->time));
  1618.     if (data == NULL) return SNMP_CLASS_ASN1ERROR;
  1619.   }
  1620.   return SNMP_CLASS_SUCCESS;
  1621. }
  1622. // parse a pdu
  1623. int snmp_parse( struct snmp_pdu *pdu,
  1624.                 unsigned char *data, int data_length,
  1625. unsigned char *community_name,
  1626. int &community_len,
  1627. snmp_version &spp_version)
  1628. {
  1629.   long    version = -1;
  1630.   // authenticates message and returns length if valid
  1631.   data = snmp_auth_parse(data, &data_length,
  1632.  community_name, &community_len,
  1633.  &version);
  1634.   if (data == NULL)
  1635.     return SNMP_CLASS_ASN1ERROR;
  1636.   if(version != SNMP_VERSION_1 && version != SNMP_VERSION_2C ) {
  1637.     ASNERROR("Wrong version");
  1638.     return SNMP_CLASS_BADVERSION;
  1639.   }
  1640.   spp_version = (snmp_version) version;
  1641.   int res = snmp_parse_data_pdu(pdu, data, data_length);
  1642.   if (res != SNMP_CLASS_SUCCESS)
  1643.     return res;
  1644.   return snmp_parse_vb(pdu, data, data_length);
  1645. }
  1646. #ifdef _SNMPv3
  1647. // Parse the field HeaderData of a SNMPv3 message and return the values.
  1648. unsigned char *asn1_parse_header_data(unsigned char *buf, int *buf_len,
  1649.       long *msg_id, long *msg_max_size,
  1650.       unsigned char *msg_flags,
  1651.       long *msg_security_model)
  1652. {
  1653.   unsigned char *buf_ptr = buf;
  1654.   int length = *buf_len;
  1655.   unsigned char type;
  1656.   buf = asn_parse_header( buf, &length, &type);
  1657.   if (!buf)
  1658.   {
  1659.     debugprintf(0, "Parse error in header HeaderData");
  1660.     return 0;
  1661.   }
  1662.   if (type != (ASN_SEQ_CON)){
  1663.     debugprintf(0, "wrong type in header of msgHeaderData");
  1664.     return 0;
  1665.   }
  1666.   buf = asn_parse_int(buf, &length, &type, msg_id, sizeof(*msg_id));
  1667.   if (!buf){
  1668.     debugprintf(0, "Parse error: msg_id");
  1669.     return 0;
  1670.   }
  1671.   buf = asn_parse_int(buf, &length,
  1672.       &type, msg_max_size, sizeof(*msg_max_size));
  1673.   if (!buf){
  1674.     debugprintf(0, "Parse error: msg_max_size");
  1675.     return 0;
  1676.   }
  1677.   int dummy = 1;
  1678.   buf = asn_parse_string( buf, &length, &type, msg_flags, &dummy);
  1679.   if ((dummy !=1) || (!buf)) {
  1680.     debugprintf(0, "Parse error: msg_flags");
  1681.     return 0;
  1682.   }
  1683.   buf = asn_parse_int(buf, &length, &type,
  1684.       msg_security_model, sizeof(*msg_security_model));
  1685.   if (!buf){
  1686.     debugprintf(0, "Parse error: msg_security_model");
  1687.     return 0;
  1688.   }
  1689.   if (length) {
  1690.     debugprintf(0, "Parse error: wrong length in header of HeaderData");
  1691.     return 0;
  1692.   }
  1693.   debugprintf(3, "Parsed HeaderData: globalDataLength(0x%x), msg_id(0x%lx), "
  1694.      "msg_max_size(0x%lx), msg_flags(0x%x), msg_security_model(0x%lx)",
  1695.       length, *msg_id, *msg_max_size, *msg_flags, *msg_security_model);
  1696.   *buf_len -= SAFE_INT_CAST(buf - buf_ptr);
  1697.   return buf;
  1698. }
  1699. // Encode the given values for the HeaderData into the buffer.
  1700. unsigned char *asn1_build_header_data(unsigned char *outBuf, int *maxLength,
  1701.        long msgID,
  1702.        long maxMessageSize,
  1703.        unsigned char msgFlags,
  1704.        long securityModel)
  1705. {
  1706.   unsigned char buf[MAXLENGTH_GLOBALDATA];
  1707.   unsigned char *bufPtr = (unsigned char*)&buf;
  1708.   unsigned char *outBufPtr = outBuf;
  1709.   int length = *maxLength;
  1710.   int totalLength;
  1711. #ifdef INVALID_MAXMSGSIZE
  1712.   debugprintf(-10, "nWARNING: Using constant MaxMessageSize!n");
  1713.   maxMessageSize = 65535;
  1714. #endif
  1715.   debugprintf(3, "Coding msgID(0x%lx), maxMessageSize(0x%lx), "
  1716.       "msgFlags(0x%x), securityModel(0x%lx)",
  1717.               msgID, maxMessageSize, msgFlags, securityModel);
  1718.   bufPtr = asn_build_int(bufPtr, &length,
  1719.                          (unsigned char)(ASN_UNI_PRIV | ASN_INTEGER),
  1720.                          (long *)&msgID, sizeof(msgID));
  1721.   if (bufPtr == NULL){
  1722.     debugprintf(0, "asn_build_header_data: Error coding msgID");
  1723.     return NULL;
  1724.   }
  1725.   bufPtr = asn_build_int(bufPtr, &length,
  1726.                          (unsigned char)(ASN_UNI_PRIV | ASN_INTEGER),
  1727.                          (long *)&maxMessageSize, sizeof(maxMessageSize));
  1728.   if (bufPtr == NULL){
  1729.     debugprintf(0, "asn_build_header_data: Error coding maxMessageSize");
  1730.     return NULL;
  1731.   }
  1732.   bufPtr = asn_build_string(bufPtr, &length,
  1733.                             (unsigned char)(ASN_UNI_PRIV | ASN_OCTET_STR),
  1734.                             (unsigned char*)&msgFlags, 1);
  1735.   if (bufPtr == NULL){
  1736.     debugprintf(0, "asn_build_header_data: Error coding msgFlags");
  1737.     return NULL;
  1738.   }
  1739.   bufPtr = asn_build_int(bufPtr, &length,
  1740.                          (unsigned char)(ASN_UNI_PRIV | ASN_INTEGER),
  1741.                          (long *)&securityModel, sizeof(securityModel));
  1742.   if (bufPtr == NULL){
  1743.     debugprintf(0, "asn_build_header_data: Error coding securityModel");
  1744.     return NULL;
  1745.   }
  1746.   totalLength = SAFE_INT_CAST(bufPtr - (unsigned char*)&buf);
  1747.   debugprintf(3, "Coding sequence (headerdata), length = 0x%x", totalLength);
  1748.   outBufPtr = asn_build_sequence(outBufPtr, maxLength,
  1749.                                  (unsigned char)(ASN_SEQ_CON),
  1750.                                  totalLength);
  1751.   if (outBufPtr == NULL) {
  1752.     debugprintf(0, "asn_build_header_data: Error coding seq headerdata");
  1753.     return NULL;
  1754.   }
  1755.   if (*maxLength < totalLength) {
  1756.     debugprintf(0, "asn_build_header_data: Length error");
  1757.     return NULL;
  1758.   }
  1759.   memcpy(outBufPtr, (unsigned char*)&buf, totalLength);
  1760.   outBufPtr += totalLength;
  1761.   *maxLength -= totalLength;
  1762.   debugprintf(21, "bufHeaderData:");
  1763.   debughexprintf(21, outBuf, SAFE_INT_CAST(outBufPtr - outBuf));
  1764.   return outBufPtr;
  1765. }
  1766. #endif
  1767. // Parse the ScopedPDU and return the encoded values.
  1768. unsigned char *asn1_parse_scoped_pdu(
  1769.          unsigned char *scoped_pdu, int *scoped_pdu_len,
  1770.          unsigned char *context_engine_id, int *context_engine_id_len,
  1771.          unsigned char *context_name, int *context_name_len )
  1772. {
  1773.   unsigned char type;
  1774.   scoped_pdu = asn_parse_header( scoped_pdu, scoped_pdu_len, &type);
  1775.   if (!scoped_pdu) {
  1776.     debugprintf(0, "Parse error: Wrong header in scoped_pdu.");
  1777.     return 0;
  1778.   }
  1779.   if (type != (ASN_SEQ_CON)){
  1780.     debugprintf(0, "Parse error: Wrong header type in scoped_pdu.");
  1781.     return 0;
  1782.   }
  1783.   scoped_pdu = asn_parse_string( scoped_pdu, scoped_pdu_len, &type,
  1784.                                 context_engine_id, context_engine_id_len);
  1785.   if (!scoped_pdu){
  1786.     debugprintf(0, "Parse error: context_engine_id");
  1787.     return 0;
  1788.   }
  1789.   scoped_pdu = asn_parse_string( scoped_pdu, scoped_pdu_len, &type,
  1790.                                 context_name, context_name_len);
  1791.   if (!scoped_pdu){
  1792.     debugprintf(0, "mpParseScopedPDU: bad parse of context_name");
  1793.     return 0;
  1794.   }
  1795.   debugprintf(3, "Parsed scoped_pdu: context_engine_id length(0x%x), "
  1796.       "context_name length(0x%x)",
  1797.       *context_engine_id_len, *context_name_len);
  1798.   return scoped_pdu;
  1799. }
  1800. // Encode the given values for the scopedPDU into the buffer.
  1801. unsigned char *asn1_build_scoped_pdu(
  1802.                    unsigned char *outBuf, int *max_len,
  1803.                    unsigned char *contextEngineID, long contextEngineIDLength,
  1804.                    unsigned char *contextName, long contextNameLength,
  1805.                    unsigned char *data, long dataLength)
  1806. {
  1807.   Buffer<unsigned char> buffer(MAX_SNMP_PACKET);
  1808.   unsigned char *bufPtr = buffer.get_ptr();
  1809.   unsigned char *outBufPtr = outBuf;
  1810.   long  bufLength = 0;
  1811.   LOG_BEGIN(DEBUG_LOG | 10);
  1812.   LOG("ASN1: coding (context engine id) (context name)");
  1813.   LOG(OctetStr(contextEngineID, contextEngineIDLength).get_printable());
  1814.   LOG(OctetStr(contextName, contextNameLength).get_printable());
  1815.   LOG_END;
  1816.   bufPtr = asn_build_string(bufPtr, max_len,
  1817.                             (unsigned char)(ASN_UNI_PRIV | ASN_OCTET_STR),
  1818.                             contextEngineID, contextEngineIDLength);
  1819.   if (!bufPtr)
  1820.   {
  1821.     LOG_BEGIN(ERROR_LOG | 1);
  1822.     LOG("ASN1: Error encoding contextEngineID");
  1823.     LOG_END;
  1824.     return 0;
  1825.   }
  1826.   bufPtr = asn_build_string(bufPtr, max_len,
  1827.                             (unsigned char)(ASN_UNI_PRIV | ASN_OCTET_STR),
  1828.                             contextName, contextNameLength);
  1829.   if (!bufPtr)
  1830.   {
  1831.     LOG_BEGIN(ERROR_LOG | 1);
  1832.     LOG("ASN1: Error encoding contextName");
  1833.     LOG_END;
  1834.     return 0;
  1835.   }
  1836.   bufLength = SAFE_INT_CAST(bufPtr - buffer.get_ptr());
  1837.   memcpy((char *)bufPtr, (char *)data, dataLength);
  1838.   bufLength += dataLength;
  1839.   LOG_BEGIN(DEBUG_LOG | 10);
  1840.   LOG("ASN1: Encoding scoped PDU sequence (len)");
  1841.   LOG(bufLength);
  1842.   LOG_END;
  1843.   outBufPtr = asn_build_sequence(outBufPtr, max_len,
  1844.                                  (unsigned char)(ASN_SEQ_CON),
  1845.                                  bufLength);
  1846.   if (!outBufPtr)
  1847.   {
  1848.     LOG_BEGIN(ERROR_LOG | 1);
  1849.     LOG("ASN1: Error encoding scopedPDU sequence");
  1850.     LOG_END;
  1851.     return 0;
  1852.   }
  1853.   memcpy(outBufPtr, buffer.get_ptr(), bufLength);
  1854.   outBufPtr += bufLength;
  1855. #ifdef __DEBUG
  1856.   LOG_BEGIN(DEBUG_LOG | 15);
  1857.   LOG("ASN1: Result of build_scoped_pdu (len) (data)");
  1858.   LOG(outBufPtr - outBuf);
  1859.   LOG(OctetStr(outBuf, outBufPtr - outBuf).get_printable_hex());
  1860.   LOG_END;
  1861. #endif
  1862.   return outBufPtr;
  1863. }
  1864. #ifdef SNMP_PP_NAMESPACE
  1865. }; // end of namespace Snmp_pp
  1866. #endif