asn1.cpp
上传用户:czjinwang
上传日期:2007-01-12
资源大小:2484k
文件大小:50k
源码类别:

SNMP编程

开发平台:

Visual C++

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