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

SNMP编程

开发平台:

Visual C++

  1. /*===================================================================
  2.   Copyright (c) 1999
  3.   Hewlett-Packard Company
  4.   ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS.
  5.   Permission to use, copy, modify, distribute and/or sell this software 
  6.   and/or its documentation is hereby granted without fee. User agrees 
  7.   to display the above copyright notice and this license notice in all 
  8.   copies of the software and any documentation of the software. User 
  9.   agrees to assume all liability for the use of the software; Hewlett-Packard 
  10.   makes no representations about the suitability of this software for any 
  11.   purpose. It is provided "AS-IS without warranty of any kind,either express 
  12.   or implied. User hereby grants a royalty-free license to any and all 
  13.   derivatives based upon this software code base. 
  14.   S N M P . C P P
  15.   SNMP CLASS IMPLEMENATION FOR WINDOWS WIN32
  16.   DESCRIPTION:
  17.   This module contains the implementation of the SNMP and
  18.   transport init/deinit functions.
  19.   LANGUAGE:
  20.   ANSI C++
  21.   OPERATING SYSTEM:
  22.   Win32
  23.   DESIGN:
  24.   Peter E Mellquist
  25.   AUTHOR:
  26.   Peter E Mellquist
  27.  
  28. =====================================================================*/
  29. char snmp_cpp_version[]="#(@)SNMP++ 2.8 $Header: snmp.cpp,v 1.25 96/09/11 14:02:06 hmgr Exp $";
  30. //-----[ External C includes ]-----------------------------------------
  31. extern "C"
  32. {
  33. #include "winsnmp.h"  // winsnmp include file
  34. #include <stdio.h>    // standard io
  35. }
  36. #define _INCLUDE_SNMP_ERR_STRINGS
  37. //-----[ SNMP++ Includes ]--------------------------------------------
  38. #include "oid.h"        // class def for oids
  39. #include "vb.h"         // class def for vbs
  40. #include "snmp_pp.h"    // class def for this module
  41. #include "pdu_cont.h"   // pdu container class def
  42. //-----[ macros ]------------------------------------------------------
  43. #define MAX_DOTTED_OID_SIZE 255   // maximum size for a dotted string
  44. #define SNMP_MSG WM_USER+176      // winsnmp callback msg
  45. #define SNMP_GWW_HINSTANCE -6     // gww instance
  46. //-----[ snmp engine variables ]--------------------------------------- 
  47. static char SzSnmpClass[] =  "sppcls32";     // pdu handler registered name
  48. DLLOPT Pdu_Container *pdu_container;         // pointer to pdu container class
  49. int pdu_ref_count=0;                         // reference count of transport
  50. int snmp_ref_count=0;                        // reference count for xport
  51. // mutual exclusion variables for thread safety
  52. CRITICAL_SECTION my_critical_section;                           
  53. #define SNMP_WAIT EnterCriticalSection( &my_critical_section)
  54. #define SNMP_SIGNAL LeaveCriticalSection( &my_critical_section)
  55. //-----[ Trap Builder API ]----------------------------------------
  56. typedef SNMPAPI_STATUS (PASCAL *functionTrap)( HSNMP_PDU, smiLPOID, smiLPIPADDR, smiLPINT, smiLPINT, smiLPTIMETICKS);
  57. //-----[ port setting API ]-----------------------------------------
  58. typedef SNMPAPI_STATUS (PASCAL *functionPortSet) (HSNMP_ENTITY hEntity,WORD port);
  59. //--------------[ well known trap ids ]-----------------------------------
  60. // SMI trap oid def
  61. class snmpTrapsOid: public Oid {
  62.    public: 
  63.    snmpTrapsOid (void):Oid("1.3.6.1.6.3.1.1.5"){};
  64. }; 
  65. // SMI Enterprose Oid
  66. class snmpTrapEnterpriseOid: public Oid {
  67.    public: 
  68.    snmpTrapEnterpriseOid(void):Oid("1.3.6.1.6.3.1.1.4.3.0"){};
  69. }; 
  70. // SMI Cold Start Oid
  71. class coldStartOid: public snmpTrapsOid {
  72.    public: 
  73.    coldStartOid( void){*this+=".1";};
  74. };
  75. // SMI WarmStart Oid
  76. class warmStartOid: public snmpTrapsOid {
  77.    public: 
  78.    warmStartOid( void){*this+=".2";};
  79. };
  80. // SMI LinkDown Oid
  81. class linkDownOid: public snmpTrapsOid {
  82.    public: 
  83.    linkDownOid( void){*this+=".3";};
  84. }; 
  85. // SMI LinkUp Oid
  86. class linkUpOid: public snmpTrapsOid {
  87.    public: 
  88.    linkUpOid( void){*this+=".4";};
  89. };
  90. // SMI Authentication Failure Oid
  91. class authenticationFailureOid: public snmpTrapsOid {
  92.    public: 
  93.    authenticationFailureOid( void){*this+=".5";};
  94. }; 
  95. // SMI egpneighborloss Oid
  96. class egpNeighborLossOid: public snmpTrapsOid {
  97.    public: 
  98.    egpNeighborLossOid( void){*this+=".6";};
  99. };
  100. const coldStartOid coldStart;
  101. const warmStartOid warmStart;
  102. const linkDownOid linkDown;
  103. const linkUpOid linkUp;
  104. const authenticationFailureOid authenticationFailure;
  105. const egpNeighborLossOid egpNeighborLoss;
  106. const snmpTrapEnterpriseOid snmpTrapEnterprise;
  107. //-----------------------------------------------------------------------
  108. //--------[ extract_from_varbindlist ]-----------------------------------
  109. //-----------------------------------------------------------------------
  110. // loop through all vbs in the VArbind list extracting each
  111. // vb into the SNMP++ Vb ojbects
  112. int extract_from_varbindlist( HSNMP_VBL hRecvVbl,  // handle to winsnmp vbl
  113.                               Pdu &pdu)            // Snmp++ Pdu to extract into
  114. {
  115.    int z;                            // looping variable
  116.    SNMPAPI_STATUS vb_status;         // status of VB extract
  117.    smiVALUE SnmpValue;               // A received value
  118.    smiOID RecvOid;                   // a received oid
  119.    char stroid[MAX_DOTTED_OID_SIZE]; // string oid
  120.    TimeTicks tt;                     // timeticks object
  121.    Counter32 ctr;                    // counter object
  122.    Gauge32 gge;                      // gauge object
  123.    Vb tempvb;                        // temp vb object
  124.    int vb_count;                     // count of pdu vbs
  125.    //-----[ delete existing vblist from pdu ] --------------------------
  126.    pdu.set_vblist(&tempvb, 0);
  127.    //-----[ loop through and extract response vb's] --------------------
  128.    SNMPDEBUG("++ SNMP++, In Extract From Vb List n");
  129.    vb_count = SnmpCountVbl( hRecvVbl);
  130.    for (z=1;z<=vb_count;z++)
  131.    {
  132.       // get the vb
  133.       SNMPDEBUG("++ SNMP++, Get VB n");
  134.       vb_status = SnmpGetVb( hRecvVbl,
  135.                              z,
  136.                              &RecvOid,
  137.                              &SnmpValue);
  138.       // if it is a good status then extract
  139.       // it into the vb object else the
  140.       // error index should point to it
  141.       // so we just skip it
  142.       //
  143.       // if the status was successful,
  144.       // then we need to copy the oid
  145.       // and value portions to the vb object
  146.       // when finished, we need to free the oid
  147.       // and the smivalue portion if its an oid or octet
  148.       if ( vb_status == SNMPAPI_SUCCESS)
  149.       {
  150.          // copy the smivalue data into the vb object
  151.          // to be returned
  152.          SnmpOidToStr( &RecvOid,MAX_DOTTED_OID_SIZE,stroid);
  153.          tempvb.set_oid(stroid);
  154.          // clean up memory created by WinSnmp
  155.          SnmpFreeDescriptor(SNMP_SYNTAX_OID, (smiLPOPAQUE) &RecvOid);
  156.          switch( SnmpValue.syntax)
  157.          {
  158.             // null , do nothing
  159.             case SNMP_SYNTAX_NULL:
  160.             case SNMP_SYNTAX_NOSUCHOBJECT:
  161.             case SNMP_SYNTAX_NOSUCHINSTANCE:
  162.             case SNMP_SYNTAX_ENDOFMIBVIEW:
  163.             break;
  164.             // octects
  165.             case SNMP_SYNTAX_OCTETS:
  166.             case SNMP_SYNTAX_BITS:
  167.             case SNMP_SYNTAX_OPAQUE:
  168.             {
  169.                OctetStr octetstr( (unsigned char far *) SnmpValue.value.string.ptr,
  170.                                   ( size_t) SnmpValue.value.string.len);
  171.                tempvb.set_value( octetstr);
  172.                SnmpFreeDescriptor( SNMP_SYNTAX_OCTETS,
  173.                                    (smiLPOPAQUE)&SnmpValue.value.string );
  174.             }
  175.             break;
  176.             // ip addresses
  177.             case SNMP_SYNTAX_IPADDR:
  178.             {
  179.                IpAddress ipa("0.0.0.0"); // make it valid first
  180.                ipa[0] = SnmpValue.value.string.ptr[0];
  181.                ipa[1] = SnmpValue.value.string.ptr[1];
  182.                ipa[2] = SnmpValue.value.string.ptr[2];
  183.                ipa[3] = SnmpValue.value.string.ptr[3];
  184.                tempvb.set_value( ipa);
  185.    SnmpFreeDescriptor( SNMP_SYNTAX_IPADDR,
  186.    (smiLPIPADDR) &SnmpValue.value.string );
  187.             }
  188.             break;
  189.             // oid
  190.             case SNMP_SYNTAX_OID:
  191.             {
  192.                SnmpOidToStr( &SnmpValue.value.oid,MAX_DOTTED_OID_SIZE,stroid);
  193.                Oid oidvb(stroid);
  194.                tempvb.set_value( oidvb);
  195.                SnmpFreeDescriptor( SNMP_SYNTAX_OID,
  196.                                    (smiLPOPAQUE)&SnmpValue.value.oid );
  197.             }
  198.             break;
  199.             // int 32
  200.             case SNMP_SYNTAX_INT32:
  201.                tempvb.set_value( (signed long int) SnmpValue.value.sNumber);
  202.             break;
  203.             // time ticks
  204.             case SNMP_SYNTAX_TIMETICKS:
  205.                tt =  (unsigned long) SnmpValue.value.uNumber;
  206.                tempvb.set_value( tt);
  207.             break;
  208.             // counter
  209.             case SNMP_SYNTAX_CNTR32:
  210.                ctr = (unsigned long) SnmpValue.value.uNumber;
  211.                tempvb.set_value( ctr);
  212.             break;
  213.             // gauge
  214.             case SNMP_SYNTAX_GAUGE32:
  215.                gge = (unsigned long) SnmpValue.value.uNumber;
  216.                tempvb.set_value( gge);
  217.             break;
  218.             // u int 32
  219.             case SNMP_SYNTAX_UINT32:
  220.                tempvb.set_value( (unsigned long int) SnmpValue.value.uNumber);
  221.             break;
  222.             // 64 bit counter
  223.             case SNMP_SYNTAX_CNTR64:
  224.                Counter64 c64( (unsigned long int) SnmpValue.value.hNumber.hipart,
  225.                               (unsigned long int) SnmpValue.value.hNumber.lopart);
  226.                tempvb.set_value( c64);
  227.             break;
  228.             } // end switch
  229.          }  // end if vb status is good
  230.          pdu += tempvb;
  231.        } // end for all vb's
  232.    SNMPDEBUG("++ SNMP++, End Extract From Vblist n");
  233.    return 0;
  234. }  // end extract_from_varbindlist
  235. //-------------------[ returns error string ]--------------------------
  236. char * Snmp::error_msg( const int c)
  237. {
  238.    return ((c<0)?
  239.            ((c<MAX_NEG_ERROR)?nErrs[-(MAX_NEG_ERROR)+1]:nErrs[-c]):
  240.             ((c>MAX_POS_ERROR)?pErrs[MAX_POS_ERROR+1]:pErrs[c]));
  241. }
  242. //-----------------------------------------------------------------------
  243. //--------------------[ async handler ]----------------------------------
  244. //-----------------------------------------------------------------------
  245. // Prepares the async message to be callled to the
  246. // callback function
  247. void FAR  process_async_event( int reason,
  248.                                long int lnRecvRequestId,
  249.                                HSNMP_SESSION session_handle,
  250.                                smiINT lnErrorStatus,
  251.                                smiINT lnErrorIndex,
  252.                                HSNMP_VBL hRecvVbl,
  253.                                HSNMP_CONTEXT hRecvContext,
  254.                                HSNMP_ENTITY hDstRecvEnt,
  255.                                Snmp* spp_session,
  256.                                snmp_callback callback,
  257.                                void * personality)
  258. {
  259.    int vb_count;                     // number of vbs
  260.    Vb* vbs;                          // vbs, dynamically instantiated
  261.    SNMPAPI_STATUS gen_status;        // status of getting a vb
  262.    unsigned char agent_addr[40];     // agent address space
  263.    smiOCTETS octet_community;        // octet community name
  264.    unsigned char community_name[255]; // community name for async passing
  265.    CTarget v1target;                // v1 target to use
  266.    Pdu pdu;                          // instantiated pdu object
  267.    // get the var bind list from WinSnmp
  268.    // if vb count is zero then nothing to
  269.    // do return out;
  270.    vb_count = (int) SnmpCountVbl( hRecvVbl);
  271.    if ( vb_count == 0)
  272.    {
  273.       SNMPDEBUG("-- SNMP++, Async Handler Vb count = 0n");
  274.   (callback)(   reason,                    // reason
  275.                  (Snmp*) spp_session,          // snmp++ session who own the req
  276.                  (Pdu&) pdu,                   // pdu
  277.                  (SnmpTarget&) v1target,       // target
  278.                  (void*) personality);         // callback data
  279.       return;
  280.    }
  281.    // dynamically instantiate a list of
  282.    // Vb obejcts
  283.    // return if new error
  284.    vbs = new Vb[vb_count];
  285.    if ( vbs == 0)
  286.    {
  287.      SNMPDEBUG("-- SNMP++, Async Handler new Vb Failn");
  288.      return;  // if new error then return
  289.    }
  290.    // stuff them into the pdu
  291.    pdu.set_vblist( (Vb*) vbs, vb_count);
  292.    // extract vbs from WinSNMP var bind list into
  293.    // Snmp++ pdu objects
  294.    extract_from_varbindlist( hRecvVbl, pdu);
  295.    //------[ prepare the agent address ]-------------------------------------
  296.    gen_status = SnmpEntityToStr( hDstRecvEnt,40, (char *) agent_addr);
  297.    if ( gen_status == SNMPAPI_FAILURE)
  298.    {
  299.       delete [] vbs;                    // free the snmp++ vbs
  300.       SNMPDEBUG("-- SNMP++, Async Handler SnmpEntityToStr Failn");
  301.       return;                           // error case, don't call callback
  302.    }
  303.    //-----[ prepare the agents context ]-------------------------------------
  304.    gen_status = SnmpContextToStr( hRecvContext, &octet_community);
  305.    if ( gen_status == SNMPAPI_FAILURE)
  306.    {
  307.       delete [] vbs;                    // free the snmp++ vbs
  308.       SNMPDEBUG("-- SNMP++, Async Handler SnmpContextToStr Failn");
  309.       return;                           // error case, don't call callback
  310.    }
  311.    //----[ copy SMI octet community into an unsigned char community ]
  312.    // protect againt over running the target string
  313.    MEMCPY( community_name,
  314.              octet_community.ptr,
  315.            (size_t) min(octet_community.len,40));
  316.    //------[ make an target object for the callback ]----------------------
  317.    // set the address portion of the target
  318.    IpxAddress ipxaddress( (char*) agent_addr); 
  319.    if ( ipxaddress.valid())
  320.       v1target.set_address( ipxaddress);
  321.    else {
  322.       IpAddress  ipaddress( (char*) agent_addr); 
  323.       if( ipaddress.valid())
  324.          v1target.set_address( ipaddress);
  325.       else
  326.         return;  //unknown address format
  327.    }
  328.    // fill in the community names
  329.    OctetStr rc( (const unsigned char *) octet_community.ptr, octet_community.len);
  330.    v1target.set_readcommunity( rc);
  331.    v1target.set_writecommunity( rc);
  332.    //------[ make up a pdu onject ]------------------------------------------
  333.    set_request_id( &pdu, lnRecvRequestId);     // friend function call
  334.    set_error_status( &pdu, (int) lnErrorStatus);
  335.    set_error_index( &pdu, (int) lnErrorIndex);
  336.    // change the pdu type for responses
  337.    if ( reason == SNMP_CLASS_ASYNC_RESPONSE)
  338.       pdu.set_type( SNMP_PDU_RESPONSE);
  339.    //------[ call into the callback function ]-------------------------------
  340.    (callback)(   reason,                       // reason
  341.                  (Snmp*) spp_session,          // snmp++ session who own the req
  342.                  (Pdu&) pdu,                   // pdu
  343.                  (SnmpTarget&) v1target,       // target
  344.                  (void*) personality);         // callback data
  345.    //------[ free up the vbs ]
  346.    delete [] vbs;
  347.    //------[ free up winsnmp vars ]------------------------------------------
  348.    SnmpFreeDescriptor( SNMP_SYNTAX_OCTETS, (smiLPOPAQUE) &octet_community);
  349. };
  350. //-----------------------------------------------------------------------
  351. //--------------------[ trap handler ]----------------------------------
  352. //-----------------------------------------------------------------------
  353. // Prepares the trap message to be callled to the
  354. // trap callback function
  355. void FAR  process_trap_event( int reason,
  356.                                long int lnRecvRequestId,
  357.                                HSNMP_SESSION session_handle,
  358.                                smiINT lnErrorStatus,
  359.                                smiINT lnErrorIndex,
  360.                                HSNMP_VBL hRecvVbl,
  361.                                HSNMP_CONTEXT hRecvContext,
  362.                                HSNMP_ENTITY hDstRecvEnt,
  363.                                Snmp* spp_session,
  364.                                snmp_callback callback,
  365.                                void * personality)
  366. {
  367.    int vb_count;                     // number of vbs
  368.    Vb* vbs;                          // vbs, dynamically instantiated
  369.    SNMPAPI_STATUS gen_status;        // status of getting a vb
  370.    unsigned char agent_addr[40];     // agent address space
  371.    smiOCTETS octet_community;        // octet community name
  372.    unsigned char community_name[255]; // community name for async passing
  373.    CTarget target;                   // v1 target to use
  374.    Pdu pdu,sendpdu;                  // instantiated pdu object
  375.    TimeTicks timestamp;              // timestamp on trap
  376.    Oid trapid;                       // type of trap
  377.    Oid enterprise;                   // enterprise of a trap
  378.    SNMPDEBUG("++ SNMP++, In Process Trap Eventn");
  379.    // get the var bind list from WinSnmp
  380.    // if vb count is zero then nothing to
  381.    // do return out;
  382.    vb_count = (int) SnmpCountVbl( hRecvVbl);
  383.    if ( vb_count == 0)
  384.    {
  385.       SNMPDEBUG("-- SNMP++, Trap Handler Vb count = 0n");
  386.       return;
  387.    }
  388.    // dynamically instantiate a list of
  389.    // Vb obejcts
  390.    // return if new error
  391.    vbs = new Vb[vb_count];
  392.    if ( vbs == 0)
  393.    {
  394.      SNMPDEBUG("-- SNMP++, Trap Handler new Vb Failn");
  395.      return;  // if new error then return
  396.    }
  397.    // stuff them into the pdu
  398.    pdu.set_vblist( (Vb*) vbs, vb_count);
  399.    // extract vbs from WinSNMP var bind list into
  400.    // Snmp++ pdu objects
  401.    extract_from_varbindlist( hRecvVbl, pdu);
  402.    // build up the timeticks and trapid portions
  403.    Vb tempvb;
  404.    //skip the first two vbs in the list
  405.    for ( int w=2;w<pdu.get_vb_count();w++)
  406.    {
  407.       pdu.get_vb(tempvb,w);
  408.       sendpdu += tempvb;
  409.    }
  410.    // get the timestamp found in vb #1
  411.    pdu.get_vb(tempvb,0);
  412.    tempvb.get_value( timestamp);
  413.    // get the trapid found in vb #2
  414.    pdu.get_vb( tempvb,1);
  415.    tempvb.get_value( trapid);
  416.    // patch for incorrect ".0" on trap is in WinSNMP
  417.    if ( trapid[ (int) (trapid.len()-1)] == (unsigned long) 0)
  418.       trapid.trim(1);
  419.    // try to pull off the enterprise
  420.    // if its there it will the last vb in the pdu
  421.    Vb enterprise_vb;
  422.    Oid e_oid;
  423.    sendpdu.get_vb( enterprise_vb, sendpdu.get_vb_count() -1);
  424.    enterprise_vb.get_oid( e_oid);
  425.    if ( e_oid == "1.3.6.1.6.3.1.1.4.3.0")
  426.    {
  427.    enterprise_vb.get_value( enterprise);
  428.    sendpdu.trim();
  429.    }
  430.    //------[ prepare the agent address ]-------------------------------------
  431.    gen_status = SnmpEntityToStr( hDstRecvEnt,40, (char *) agent_addr);
  432.    if ( gen_status == SNMPAPI_FAILURE)
  433.    {
  434.       delete [] vbs;                    // free the snmp++ vbs
  435.       SNMPDEBUG("-- SNMP++, Trap Handler SnmpEntityToStr Failn");
  436.       return;                           // error case, don't call callback
  437.    }
  438.    //-----[ prepare the agents context ]-------------------------------------
  439.    gen_status = SnmpContextToStr( hRecvContext, &octet_community);
  440.    if ( gen_status == SNMPAPI_FAILURE)
  441.    {
  442.       delete [] vbs;                    // free the snmp++ vbs
  443.       SNMPDEBUG("-- SNMP++, Trap Handler SnmpContextToStr Failn");
  444.       return;                           // error case, don't call callback
  445.    }
  446.    //----[ copy SMI octet community into an unsigned char community ]
  447.    // protect againt over running the target string
  448.    MEMCPY( community_name,
  449.            octet_community.ptr,
  450.            (size_t) min(octet_community.len,40));
  451.    //------[ make an target object for the callback ]----------------------
  452.    // set the address portion of the target
  453.    GenAddress address( (char *) agent_addr);
  454.    if ( !address.valid())
  455.       return;
  456.    target.set_address( address);
  457.    // fill in the community names
  458.    OctetStr rc( (const unsigned char *) octet_community.ptr, octet_community.len);
  459.    target.set_readcommunity( rc);
  460.    target.set_writecommunity( rc);
  461.    //------[ make up a pdu onject ]------------------------------------------
  462.    set_request_id( &pdu, lnRecvRequestId);     // friend function call
  463.    set_error_status( &pdu, (int) lnErrorStatus);
  464.    set_error_index( &pdu, (int) lnErrorIndex);
  465.    // change the pdu type for responses
  466.    if ( reason == SNMP_CLASS_ASYNC_RESPONSE)
  467.       pdu.set_type( SNMP_PDU_RESPONSE);
  468.    //------[ load up the trap id and timestamp ]-----------------------------
  469.    sendpdu.set_notify_id( trapid);
  470.    sendpdu.set_notify_timestamp( timestamp);
  471.    sendpdu.set_notify_enterprise( enterprise);
  472.  
  473.    //------[ determine if we should call into the callback ]-----------------
  474.    OidCollection trapids;
  475.    TargetCollection targets;
  476.    spp_session->get_notify_filter( trapids, targets);
  477.    SNMPDEBUG("++ SNMP++, Trap Handler Fire Callbackn");
  478.    //------[ call into the callback function ]-------------------------------
  479.    if (trapids.size()==0)
  480.    {
  481.       (callback)(  reason,                      // reason
  482.                  (Snmp*) spp_session,          // snmp++ session who own the req
  483.                  (Pdu&) sendpdu,               // pdu
  484.                  (SnmpTarget&) target,         // target
  485.                  (void*) personality);         // callback data
  486.       SNMPDEBUG("++ SNMP++, Empty Collection, Back From Trap Handler Fire Callbackn");
  487.    }
  488.    else
  489.    {
  490.   Oid cur_id;
  491.       int n = trapids.size();
  492.   for (int z=1;z<=n;z++)
  493.   {
  494.      trapids.get_element( cur_id,z-1);
  495.  if ( cur_id.nCompare( cur_id.len(), trapid)==0)
  496.  {
  497.      (callback)(  reason,                      // reason
  498.                  (Snmp*) spp_session,          // snmp++ session who own the req
  499.                  (Pdu&) sendpdu,               // pdu
  500.                  (SnmpTarget&) target,         // target
  501.                  (void*) personality);         // callback data
  502.                  SNMPDEBUG("++ SNMP++, Explict collection Hit,Back From Trap Handler Fire Callbackn");
  503.  z= n+1;  // stop the loop
  504.  } // end if
  505.   }  // end for
  506.    }  // end else
  507.    //------[ free up the vbs ]
  508.    delete [] vbs;
  509.    //------[ free up winsnmp vars ]------------------------------------------
  510.    SnmpFreeDescriptor( SNMP_SYNTAX_OCTETS, (smiLPOPAQUE) &octet_community);
  511. };
  512. //---------------------------------------------------------------------
  513. //----[ pdu receiver ]-------------------------------------------------
  514. //---------------------------------------------------------------------
  515. // - Receives pdus for all sessions
  516. // - When each session is created, the session handle is set into
  517. //   the WndExtra portion of the created instance. When the WinSnmp
  518. //   dll calls this Windproc its session is extracted via GetWindowWord
  519. //   and is then used to read and decode the pdu. The pdu is registered
  520. //   to the container only if a matching Request id is pending.
  521. //
  522. long FAR PASCAL XPORT SnmpWndProc(HWND hWnd,
  523.                                   UINT message,
  524.                                   UINT wParam,
  525.                                   LONG lParam)
  526. {
  527.    HSNMP_SESSION session_handle; // winsnmp session handle
  528.    HSNMP_PDU hRecvPdu;           // received pdu
  529.    HSNMP_ENTITY hDstRecvEnt,     // received destination
  530.                 hSrcRecvEnt;     // received source
  531.    HSNMP_CONTEXT hRecvContext;   // received context
  532.    SNMPAPI_STATUS Wstatus;       // snmp api status
  533.    smiINT lnRecvPduType;         // received pdu type
  534.    smiINT lnRecvRequestId;       // received pcu status
  535.    smiINT lnErrorStatus;         // received error status
  536.    smiINT lnErrorIndex;          // received error index
  537.    HSNMP_VBL hRecvVbl;           // received variable binding list
  538.    snmp_callback callback;       // callback for async calls
  539.    void * personality;           // personality
  540.    Snmp* spp_session;            // snmp++ session handle
  541.    SNMPAPI_STATUS last_error;    // last WinSnmp error to occur
  542.    int status;
  543.    switch (message)
  544.    {
  545.       // called when window is created
  546.       case WM_CREATE:
  547.         return 0;
  548.       break;
  549.       // called when a pdu is received
  550.       // the session handle is in the WndExtra portion
  551.       // and needs to be extracted
  552.       case SNMP_MSG:
  553.       //-------------------------------------------------------------
  554.       // win32 window handles are 32 bits wide, use GetWindowLong()
  555.       // WinSNMP session handle
  556.       session_handle = (HSNMP_SESSION) GetWindowLong( hWnd,0);
  557.       // snmp++ session
  558.       spp_session = ( Snmp*) GetWindowLong( hWnd,
  559.                                             sizeof( HWND));
  560. //--------------------------------------------------------------
  561. // ACE*COMM specific timeout procesing JR-9/18/97
  562. if ( wParam == SNMPAPI_TL_TIMEOUT) 
  563. {
  564. SNMPDEBUG("SNMP++, ACE*COMM DLL Timeoutn");
  565. // rid is in the lParam
  566. SNMP_WAIT;
  567. pdu_container->timeout();
  568. // check to make sure that this was a
  569. // pending async request
  570. status =  pdu_container->get_cb_info( (long int) lParam,
  571.                                            &callback,
  572.                                            &personality);
  573. SNMP_SIGNAL;
  574. if ( status)
  575. {
  576.          SNMPDEBUG("SNMP++, Found Rid for callback Resolutionn");
  577. // inform the users callback of the timeout
  578. // this was the initial request
  579. process_async_event( (int) SNMP_CLASS_TIMEOUT,
  580.                              lParam,
  581.                              session_handle,
  582.                              0,  // error status
  583.                              0,  // error index
  584.                              0,
  585.                              0,
  586.                              0,
  587.                              spp_session,
  588.                              callback,
  589.                              personality);
  590. }
  591. return 0;
  592. }
  593. // end ACE*COMM msg check
  594. //-------------------------------------------------------------
  595.         SNMPDEBUG("++ SNMP++, Receive msg n");
  596.         // recieve the pdu
  597.         Wstatus = SnmpRecvMsg(session_handle,
  598.                               &hSrcRecvEnt,
  599.                               &hDstRecvEnt,
  600.                               &hRecvContext,
  601.                               &hRecvPdu);
  602.         // if successful process it, else throw it away
  603.         if ( Wstatus != SNMPAPI_FAILURE)
  604.         {
  605.             SNMPDEBUG("++ SNMP++, Get PDU Data n");
  606.             Wstatus = SnmpGetPduData( hRecvPdu,
  607.                                       &lnRecvPduType,
  608.                                       &lnRecvRequestId,
  609.                                       &lnErrorStatus,
  610.                                       &lnErrorIndex,
  611.                                       &hRecvVbl );
  612.             // if the decode was successful stuff it
  613.             // into the pdu container else throw it away
  614.             if ( Wstatus == SNMPAPI_SUCCESS)
  615.             {
  616.                 switch( lnRecvPduType)
  617.                 {
  618.                    //----[ response ]-----------------
  619.                    case SNMP_PDU_RESPONSE:
  620.   SNMP_WAIT;
  621.   status = pdu_container->check_if_pending( (long int) lnRecvRequestId, 
  622.                                         &callback);
  623.   SNMP_SIGNAL;
  624.                       if ( status)
  625.                       {
  626.                          if ( callback ==0)
  627.                          {  // blocking response
  628.                             // memory is freed when extracted using get_slot
  629.                             SNMPDEBUG("++ SNMP++, Process Blocked MSG n");
  630. SNMP_WAIT;
  631.                             pdu_container->set_slot( (long int) lnRecvRequestId,
  632.                                                      session_handle,
  633.                                                      hSrcRecvEnt,
  634.                                                      hDstRecvEnt,
  635.                                                      hRecvContext,
  636.                                                      lnRecvPduType,
  637.                                                      lnRecvRequestId,
  638.                                                      lnErrorStatus,
  639.                                                      lnErrorIndex,
  640.                                                      hRecvVbl);
  641.                             SNMPDEBUG("++ SNMP++, Free PDU n");
  642.                             SnmpFreePdu( hRecvPdu);  
  643.                             // update the pdu count
  644.                             pdu_container->pdu_received();
  645. SNMP_SIGNAL;
  646.                          }
  647.                          else
  648.                          {  // async response
  649.                             SNMPDEBUG("++ SNMP++, Process Async Msg n");
  650.                             // if we can find the request in the pdu container
  651.                             // then get the callback information and process it
  652. SNMP_WAIT;
  653. status =  pdu_container->get_cb_info( (long int) lnRecvRequestId,
  654.                                                         &callback,
  655.                                                         &personality);
  656. SNMP_SIGNAL;
  657.                             if ( status)
  658.                                process_async_event( (int) SNMP_CLASS_ASYNC_RESPONSE,
  659.                                                     lnRecvRequestId,
  660.                                                     session_handle,
  661.                                                     lnErrorStatus,
  662.                                                     lnErrorIndex,
  663.                                                     hRecvVbl,
  664.                                                     hRecvContext,
  665.                                                     hSrcRecvEnt,
  666.                                                     spp_session,
  667.                                                     callback,
  668.                                                     personality);
  669.                             else {
  670.   SNMP_WAIT;
  671.                               pdu_container->stray_response();
  672.   SNMP_SIGNAL;
  673. }
  674.                             SNMPDEBUG("++ SNMP++, Free Vars After process_asyncn");
  675.                             SnmpFreeVbl( hRecvVbl);
  676.                             SnmpFreeEntity( hSrcRecvEnt);
  677.                             SnmpFreeContext( hRecvContext);
  678.                             SnmpFreeEntity( hDstRecvEnt);  // don't need
  679.                             SnmpFreePdu( hRecvPdu);        // don't need
  680.                             // update the pdu count
  681. SNMP_WAIT;
  682.                             pdu_container->pdu_received();
  683. SNMP_SIGNAL;
  684.                          }
  685.                       }
  686.                       else   // not a pending response, toss it
  687.                       {
  688.                          SNMPDEBUG("++ SNMP++, Stray Message n");
  689.                          SnmpFreeEntity( hSrcRecvEnt);
  690.                          SnmpFreeEntity( hDstRecvEnt);
  691.                          SnmpFreeContext( hRecvContext);
  692.                          SnmpFreePdu( hRecvPdu);
  693.                          SnmpFreeVbl( hRecvVbl);
  694.  SNMP_WAIT;
  695.                          pdu_container->stray_response();
  696.  SNMP_SIGNAL;
  697.                       }
  698.                    break;
  699.                    //---[ trap ]----------------------
  700.                    case SNMP_PDU_TRAP:
  701.   SNMP_WAIT;
  702.                       pdu_container->trap_received();
  703.   SNMP_SIGNAL;
  704.                       SNMPDEBUG("++ SNMP++, TRAP Received n");
  705.                       if ( spp_session->get_notify_callback() != 0)
  706.                          process_trap_event( (int) SNMP_CLASS_NOTIFICATION,
  707.                                               lnRecvRequestId,
  708.                                               session_handle,
  709.                                               lnErrorStatus,
  710.                                               lnErrorIndex,
  711.                                               hRecvVbl,
  712.                                               hRecvContext,
  713.                                               hSrcRecvEnt,
  714.                                               spp_session,
  715.                                               spp_session->get_notify_callback(),
  716.                                               spp_session->get_notify_callback_data());
  717.                       SNMPDEBUG("++ SNMP++, Free Entity and PDU n");
  718.                       SnmpFreeEntity( hSrcRecvEnt);
  719.                       SnmpFreeEntity( hDstRecvEnt);
  720.                       SnmpFreeContext( hRecvContext);
  721.                       SnmpFreePdu( hRecvPdu);
  722.                       SnmpFreeVbl( hRecvVbl);
  723.                    break;
  724.                    //----[ unidentified message ]---------------
  725.                    default:
  726.                    {
  727.                       SNMPDEBUG("++ SNMP++, unidentified Message n");
  728.   SNMP_WAIT;
  729.                       pdu_container->stray_response();
  730.                       SnmpFreeEntity( hSrcRecvEnt);
  731.                       SnmpFreeEntity( hDstRecvEnt);
  732.                       SnmpFreeContext( hRecvContext);
  733.                       SnmpFreePdu( hRecvPdu);
  734.                       SnmpFreeVbl( hRecvVbl);
  735.                       pdu_container->invalid_resp_pdu();
  736.   SNMP_SIGNAL;
  737.                    }
  738.                 };  // end switch
  739.             }
  740.             else  //error getting pdu data, so we need to free the vars
  741.             {
  742.                SNMPDEBUG("++ SNMP++, GET PDU ERROR n");
  743.    SNMP_WAIT;
  744.                SnmpFreeEntity( hSrcRecvEnt);
  745.                SnmpFreeEntity( hDstRecvEnt);
  746.                SnmpFreeContext( hRecvContext);
  747.                SnmpFreePdu( hRecvPdu);
  748.                pdu_container->decode_err();
  749.    SNMP_SIGNAL;
  750.             }
  751.         }   // end if recv success
  752.         else
  753.         {
  754.            SNMPDEBUG("++ SNMP++, Receive MSG Fail n");
  755.            // receive message fail, look for timeout case
  756.            last_error = SnmpGetLastError( session_handle);
  757.            if ( last_error == SNMPAPI_TL_TIMEOUT)
  758.            {
  759.               SNMPDEBUG("++ SNMP++, WinSNMP TimeOut Notify n");
  760.               // process a async timeout event
  761.               // we only care about async ones
  762.               // handles from receive message are valid
  763.               SNMPDEBUG("++ SNMP++, Get PDU Data n");
  764.               Wstatus = SnmpGetPduData( hRecvPdu,
  765.                                         &lnRecvPduType,
  766.                                         &lnRecvRequestId,
  767.                                         &lnErrorStatus,
  768.                                         &lnErrorIndex,
  769.                                         &hRecvVbl );
  770.               if ( Wstatus == SNMPAPI_SUCCESS)
  771.               {
  772.  SNMP_WAIT;
  773.                  pdu_container->timeout();
  774.                  // check to make sure that this was a
  775.                  // pending async request
  776.  status = pdu_container->get_cb_info( (long int) lnRecvRequestId,
  777.                                                         &callback,
  778.                                                         &personality);
  779.  SNMP_SIGNAL;
  780.                  if ( status)
  781.                  {
  782.                     // clear the request from the pdu container
  783. SNMP_WAIT;
  784.                     pdu_container->clear_request_id( (long int) lnRecvRequestId);
  785. SNMP_SIGNAL;
  786.                     // inform the users callback of the timeout
  787.                     // this was the initial request
  788.                     process_async_event( (int) SNMP_CLASS_TIMEOUT,
  789.                                          lnRecvRequestId,
  790.                                          session_handle,
  791.                                          0,  // error status
  792.                                          0,  // error index
  793.                                          hRecvVbl,
  794.                                          hRecvContext,
  795.                                          hSrcRecvEnt,
  796.                                          spp_session,
  797.                                          callback,
  798.                                          personality);
  799.                  }
  800.                  SnmpFreeVbl( hRecvVbl);
  801.               }
  802.               // free up the get message vars
  803.               // these are valid on a timeout
  804.               SnmpFreeEntity( hSrcRecvEnt);
  805.               SnmpFreeEntity( hDstRecvEnt);
  806.               SnmpFreeContext( hRecvContext);
  807.               SnmpFreePdu( hRecvPdu);
  808.            }
  809.            else {
  810.  SNMP_WAIT;
  811.              pdu_container->receive_err();
  812.  SNMP_SIGNAL;
  813.    }
  814.         }
  815.         return 0;
  816.       break;
  817.       default:
  818.        return DefWindowProc(hWnd, message, wParam, lParam);
  819.    }
  820.    return 0;
  821. };
  822. //----------------------------------------------------------------------
  823. //--------[ transport layer start up ]----------------------------------
  824. //----------------------------------------------------------------------
  825. // Private function, not exposed to the outside
  826. int transport_start_up( )
  827. {
  828.    SNMPAPI_STATUS status;
  829.    WNDCLASS snmpc;
  830. #ifndef _DLL_ATTACH_OPTION
  831. smiUINT32 nMajVer, nMinVer, nLevel, nTrans, nReTrans;
  832. #endif
  833.    SNMPDEBUG("++ SNMP++, Transport Start UP n");
  834.    // set translation mode to v1
  835.    SnmpSetTranslateMode( SNMPAPI_UNTRANSLATED_V1);
  836.    // register the snmp class
  837.    snmpc.style = 0;
  838.    snmpc.lpfnWndProc = SnmpWndProc;
  839.    snmpc.cbClsExtra = 0;
  840.    snmpc.cbWndExtra = sizeof( HWND) +     // WinSnmp Session
  841.                       sizeof( Snmp*);     // Snmp++ session
  842.     
  843.    snmpc.hInstance = NULL;
  844.    snmpc.hIcon = NULL;
  845.    snmpc.hCursor = NULL;
  846.    snmpc.hbrBackground = NULL;
  847.    snmpc.lpszMenuName = NULL;
  848.    snmpc.lpszClassName = SzSnmpClass;
  849.    // register will fail if the class
  850.    // already exists, in this case
  851.    // we don't care
  852.    // This may happen is someone inadvertently
  853.    // calls transport_start_up more than once!
  854.    status = RegisterClass( &snmpc); 
  855.    if ( status == 0)
  856.    {
  857.       SNMPDEBUG("-- SNMP++, CLASS REGISTER FAIL n"); 
  858.       return SNMP_CLASS_RESOURCE_UNAVAIL;
  859.    }   
  860.    SNMPDEBUG("++ SNMP++, Done Xport Start Up n");
  861.    // create the pdu container class
  862.    // here, multiple pdu container objects per app
  863.    // should not be created
  864.    pdu_ref_count++;    // up the ref count
  865.    if ( pdu_ref_count ==1)
  866.    {
  867.          SNMPDEBUG("++ SNMP++, New PDU Container n");
  868.          pdu_container = new Pdu_Container();
  869.          if ( pdu_container == NULL)
  870.          {
  871.             SNMPDEBUG("-- SNMP++, Pdu Container Create Fail n");
  872.             return SNMP_CLASS_RESOURCE_UNAVAIL;
  873.          }   
  874.          else 
  875.          {
  876. #ifndef _DLL_ATTACH_OPTION   
  877.    // start up WinSNMP
  878. status = SnmpStartup(&nMajVer,
  879.                              &nMinVer,
  880.                              &nLevel,
  881.                              &nTrans,
  882.                              &nReTrans);
  883.         if ( status !=  SNMPAPI_SUCCESS ) {
  884. SNMPDEBUG("Unable to Startup WinSNMP!n");
  885. return 0;
  886. }
  887. SNMPDEBUG("Startup WinSNMP OKn");
  888. #endif
  889.             return SNMP_CLASS_SUCCESS;
  890.          }
  891.     }
  892.     else
  893.     {
  894. #ifndef _DLL_ATTACH_OPTION   
  895.    // start up WinSNMP
  896. status = SnmpStartup(&nMajVer,
  897.                              &nMinVer,
  898.                              &nLevel,
  899.                              &nTrans,
  900.                              &nReTrans);
  901.         if ( status !=  SNMPAPI_SUCCESS ) {
  902. SNMPDEBUG("Unable to Startup WinSNMP!n");
  903. return 0;
  904. }
  905. SNMPDEBUG("Startup WinSNMP OKn");
  906. #endif
  907.       return SNMP_CLASS_SUCCESS;    // we already have a good pdu object
  908. }
  909. };
  910. //-----------------------------------------------------------------------
  911. //----------[ transport layer shut down ]--------------------------------
  912. //-----------------------------------------------------------------------
  913. // Private function
  914. int transport_shut_down( )
  915. {
  916.    
  917.    int unreg_status;
  918.    SNMPDEBUG("++ SNMP++, Transport Shut Down n");
  919.   
  920.    // delete the pdu container only when the ref
  921.    // count reaches 0
  922.    pdu_ref_count--;
  923.    if ( pdu_ref_count == 0)
  924.    {
  925.      SNMPDEBUG("++ SNMP++, Destroy PDU Container n");
  926.      delete pdu_container;
  927.    }
  928.    // protect against running counter < 0
  929.    // this allows a new transport_start_up to
  930.    // resume
  931.    if ( pdu_ref_count < 0) pdu_ref_count = 0;
  932.    
  933.    unreg_status = UnregisterClass( SzSnmpClass,NULL);
  934.    if ( unreg_status == FALSE) {
  935.       SNMPDEBUG("-- SNMP++, UnRegister Class Fail n");
  936.    }
  937. #ifndef _DLL_ATTACH_OPTION  
  938.    SnmpCleanup(); 
  939. #endif
  940.    return SNMP_CLASS_SUCCESS;
  941. };
  942. //----------------------------------------------------------------------
  943. //------[ Snmp Class Constructor ]--------------------------------------
  944. //----------------------------------------------------------------------
  945. Snmp::Snmp( int &status, unsigned short agent_port)  // status of construction
  946. {
  947.    SNMPDEBUG("++ SNMP++, SNMP Constructor n");
  948.    SNMPAPI_STATUS WinSnmpStatus;    // return status for snmp calls
  949.    
  950.    SNMP_WAIT;                      
  951.    // call transport start up if it hasn't been called before 
  952.    construct_status = SNMP_CLASS_SUCCESS;
  953.    if ( snmp_ref_count == 0)
  954.    {
  955.        status = transport_start_up();
  956.        construct_status = status;
  957.        if ( status != SNMP_CLASS_SUCCESS)
  958.        {
  959.            SNMPDEBUG("-- SNMP++, Transport Start Up Failure n");
  960.    SNMP_SIGNAL;
  961.            return;
  962.        }    
  963.    }
  964.    snmp_ref_count++;                          // bump up the ref count
  965.    pdu_handler = CreateWindow( SzSnmpClass,   // name of class
  966.                                NULL,          // window text 
  967.                                WS_POPUP,      // window style
  968.                                0,             // xpos
  969.                                0,             // ypos
  970.                                0,             // width
  971.                                0,             // hieght
  972.                                0,             // parent window handle, none for popup
  973.                                0 ,            // window id
  974.                                0,             // parent instance
  975.                                0);            // pointer to construct data
  976.    if ( pdu_handler == NULL)
  977.    {
  978.      status = SNMP_CLASS_RESOURCE_UNAVAIL;
  979.      SNMPDEBUG("-- SNMP++, Hidden Window Create Failure n");
  980.      construct_status = status;
  981.  SNMP_SIGNAL;
  982.      return;
  983.    }
  984.    else
  985.    {
  986.       // create a winsnmp session
  987.       iv_snmp_session = (SNMPHANDLE) SnmpOpen(  pdu_handler , SNMP_MSG);
  988.       if ( iv_snmp_session == SNMPAPI_FAILURE) {
  989.      WinSnmpStatus = SnmpGetLastError( (HSNMP_SESSION) iv_snmp_session);
  990.      if (SNMPAPI_ALLOC_ERROR == WinSnmpStatus) 
  991.         status = SNMP_CLASS_RESOURCE_UNAVAIL; 
  992.      else if (SNMPAPI_OTHER_ERROR == WinSnmpStatus) 
  993.              status = SNMP_CLASS_ERROR;
  994.           else  
  995.              status = SNMP_CLASS_INTERNAL_ERROR; 
  996.      SNMPDEBUG("-- SNMP++, WinSNMP Session Create Failure n");
  997.      construct_status = status;
  998.      SNMP_SIGNAL;
  999.      return;
  1000.       } 
  1001.   else {
  1002.          // set the pdu handler extra data to the session handle value
  1003.          // WinSnmp session
  1004.          SetWindowLong( pdu_handler,
  1005.                         0,
  1006.                         (LONG) iv_snmp_session);
  1007.          // snmp++ session
  1008.          SetWindowLong( pdu_handler,
  1009.                         0 + sizeof( HWND),
  1010.                         (LONG) this);
  1011.            
  1012.          // intialize all the trap receiving member variables
  1013.          notify_targets = 0;
  1014.          notify_ids = 0;
  1015.          listen_addresses = 0;
  1016.          notifycallback = 0;
  1017.          notifycallback_data = 0;
  1018.          // success
  1019.          status = SNMP_CLASS_SUCCESS;
  1020.  SNMP_SIGNAL;
  1021.          return;
  1022.       }
  1023.    }
  1024. };
  1025. //--------------------------------------------------------------------
  1026. //---------[ Snmp Class Destructor ]----------------------------------
  1027. //--------------------------------------------------------------------
  1028. // destroys instance
  1029. Snmp::~Snmp()
  1030. {
  1031.    SNMPAPI_STATUS status;
  1032.    SNMP_WAIT;   
  1033.    // if we failed during construction then don't try 
  1034.    // to free stuff up that was not allocated
  1035.    if ( construct_status != SNMP_CLASS_SUCCESS) {
  1036.   SNMP_SIGNAL;
  1037.       return;
  1038.    }
  1039.    // shut down trap reception if used
  1040.    notify_unregister();
  1041.    // terminate the session
  1042.    pdu_container->search_and_destroy( (HSNMP_SESSION) iv_snmp_session, this);
  1043.    status = SnmpClose( (HSNMP_SESSION) iv_snmp_session);
  1044.    status = DestroyWindow( (HWND) pdu_handler);
  1045.    snmp_ref_count--;
  1046.    if (snmp_ref_count <0) snmp_ref_count = 0;
  1047.    if ( snmp_ref_count == 0)
  1048.       transport_shut_down( );
  1049.    SNMPDEBUG("++ SNMP++, Exit From ~Snmp n");
  1050.    SNMP_SIGNAL;
  1051. };
  1052. //-----------------------[ access the trap reception info ]---------------
  1053. snmp_callback Snmp::get_notify_callback()
  1054. { return notifycallback; };
  1055. void * Snmp::get_notify_callback_data()
  1056. { return notifycallback_data; };
  1057. //-----------------------[ get notify filters ]---------------------------
  1058. // return back the currently set notification filters
  1059. // if they are not defined then return back empty collections
  1060. // 
  1061. int Snmp::get_notify_filter( OidCollection &trapids,
  1062.                              TargetCollection &targets)
  1063. {
  1064.    if (notify_ids != 0)
  1065. trapids = *notify_ids;
  1066.    if ( notify_targets != 0)
  1067.    targets = *notify_targets;
  1068.    return SNMP_CLASS_SUCCESS;
  1069. };
  1070. //-----------------------[ register to get traps]-------------------------
  1071. // alternate form for local listen specification
  1072. int Snmp::notify_register( const OidCollection &trapids,
  1073.                            const TargetCollection &targets,
  1074.                            const AddressCollection &listen_addresses,
  1075.                            const snmp_callback  callback,
  1076.                            const void *callback_data) 
  1077. {
  1078.      return notify_register( trapids,
  1079.                              targets,
  1080.                              callback,
  1081.                              callback_data);
  1082. };
  1083. //-----------------------[ register to get traps]-------------------------
  1084. int Snmp::notify_register( const OidCollection &trapids,
  1085.                            const TargetCollection &targets,
  1086.                            const snmp_callback  callback,
  1087.                            const void *callback_data) 
  1088.    SNMPAPI_STATUS status;
  1089.    SNMPAPI_STATUS WinSnmpStatus; // return status for snmp calls
  1090.    int return_status = 0;
  1091.    int already_on = FALSE;
  1092.    // free up local collections
  1093.    if ( notify_targets != 0)
  1094.       delete notify_targets;
  1095.    if ( notify_ids != 0) {
  1096.       delete notify_ids;
  1097.   already_on = TRUE;
  1098.    }
  1099.    // null out callback information
  1100.    notifycallback = 0;
  1101.    notifycallback_data = 0;
  1102.    //-------------------------------------------------------------------------
  1103.    //-----------[ assign new trap filtering info ]----------------------------
  1104.    //-------------------------------------------------------------------------
  1105.    // create a new collection using param passed in
  1106.    notify_targets = new TargetCollection ( targets);
  1107.    // delete current trapid collection if defined
  1108.   
  1109.    // create a new collection using param passed in
  1110.    notify_ids = new OidCollection( trapids);        
  1111.    // assign callback and callback data info
  1112.    notifycallback = callback;
  1113.    notifycallback_data = (void*) callback_data;
  1114.    //--------------------------------------------------------------------
  1115.    //-----------[ Turn the traps on using new info ]---------------------
  1116.    //--------------------------------------------------------------------
  1117.    if ( !already_on) {
  1118.   // listen for everything
  1119.       status = SnmpRegister( (HSNMP_SESSION)iv_snmp_session,// session to use
  1120.                              NULL,                          // source entity
  1121.                              NULL,                          // destination entity, don't care where its directed
  1122.                              NULL,                          // handle send context, don't care what the community name is
  1123.                              NULL,                          // oid mask
  1124.                              SNMPAPI_ON);
  1125.    }
  1126.    else
  1127.    return SNMP_CLASS_SUCCESS; 
  1128.    if ( status == SNMPAPI_FAILURE) {
  1129.        WinSnmpStatus = SnmpGetLastError( (HSNMP_SESSION) iv_snmp_session);
  1130.        if (SNMPAPI_ALLOC_ERROR == WinSnmpStatus) {
  1131.    return SNMP_CLASS_RESOURCE_UNAVAIL;
  1132.        } else if (SNMPAPI_OTHER_ERROR == WinSnmpStatus) {
  1133.    return SNMP_CLASS_ERROR;
  1134.        } else if (SNMPAPI_TL_IN_USE == WinSnmpStatus) {
  1135.    return SNMP_CLASS_TL_IN_USE;   
  1136.        } else if (SNMPAPI_TL_NOT_AVAILABLE == WinSnmpStatus) {
  1137.    return SNMP_CLASS_TL_UNSUPPORTED;
  1138.        } else {
  1139.    return SNMP_CLASS_INTERNAL_ERROR; 
  1140.        }
  1141.    }
  1142.    return SNMP_CLASS_SUCCESS;
  1143. };
  1144. //-----------------------[ un-register to get traps]----------------------
  1145. int Snmp::notify_unregister() 
  1146.     SNMPAPI_STATUS Wstatus;
  1147.     // free up local collections
  1148.     if ( notify_targets != 0)
  1149.        delete notify_targets;
  1150.     if ( notify_ids != 0)
  1151.        delete notify_ids;
  1152.     // null out callback information
  1153.     notifycallback = 0;
  1154.     notifycallback_data = 0;
  1155.     // invoke WinSNMP register to turn it off
  1156.     Wstatus = SnmpRegister((HSNMP_SESSION)iv_snmp_session,  // session to use
  1157.                            NULL,             // source entity
  1158.                            NULL,             // destination entity, don't care where its directed
  1159.                            NULL,             // handle send context, don't care what the community name is
  1160.                            NULL,             // oid mask
  1161.                            SNMPAPI_OFF);
  1162.     if ( Wstatus == SNMPAPI_FAILURE) {
  1163. Wstatus = SnmpGetLastError( (HSNMP_SESSION) iv_snmp_session);
  1164. if (SNMPAPI_ALLOC_ERROR == Wstatus) {
  1165.     return SNMP_CLASS_RESOURCE_UNAVAIL; 
  1166. } else {
  1167.     return SNMP_CLASS_INTERNAL_ERROR; 
  1168. }
  1169.     }
  1170.     return SNMP_CLASS_SUCCESS; 
  1171. };
  1172. //----------------------[ cancel a pending request ]--------------------
  1173. // cancel a pending request
  1174. // only cancels async requests
  1175. // returns true is canceled and false if nothing to cancel
  1176. int Snmp::cancel( const unsigned long rid)
  1177. {
  1178.    snmpcallback callback;
  1179.    SNMP_WAIT;
  1180.    if ( pdu_container->check_if_pending( (long int) rid, &callback))
  1181.    {
  1182.       if ( callback != 0)
  1183.       {
  1184.          pdu_container->clear_request_id( rid);
  1185.  SNMP_SIGNAL;
  1186.          return SNMP_CLASS_SUCCESS;
  1187.       }
  1188.    }
  1189.    SNMP_SIGNAL;
  1190.    return SNMP_CLASS_INVALID_REQID;  // no requests pending for this rid
  1191. };
  1192. //------------------------[ get ]---------------------------------------
  1193. int Snmp::get( Pdu &pdu,                   // pdu to use
  1194.                SnmpTarget &target)   // get target
  1195. {
  1196.    pdu.set_type( sNMP_PDU_GET);
  1197.    return snmp_engine( pdu,       // get pdu
  1198.                        0,         // max repeaters
  1199.                        0,         // non repeaters
  1200.                        target,    // target
  1201.                        NULL,      // callback for async only
  1202.                        0);        // callback data
  1203. };
  1204. //------------------------[ get async ]----------------------------------
  1205. int Snmp::get( Pdu &pdu,                     // pdu to use
  1206.                SnmpTarget &target,           // destination target
  1207.                const snmp_callback callback, // async callback
  1208.                const void * callback_data)   // callback data
  1209. {
  1210.    if ( ! callback )
  1211.        return SNMP_CLASS_INVALID_CALLBACK;
  1212.    pdu.set_type( sNMP_PDU_GET);
  1213.    return snmp_engine( pdu,            // get async pdu
  1214.                        0,              // max repeaters
  1215.                        0,              // non repeaters
  1216.                        target,         // target
  1217.                        callback,       // callback to use
  1218.                        callback_data); // callback data
  1219. };
  1220. //------------------------[ get next ]-----------------------------------
  1221. int Snmp::get_next( Pdu &pdu,             // pdu to use
  1222.                     SnmpTarget &target)   // get target
  1223. {
  1224.    pdu.set_type( sNMP_PDU_GETNEXT);
  1225.    return snmp_engine( pdu,        // pdu to get next
  1226.                        0,          // max repeaters
  1227.                        0,          // non repeaters
  1228.                        target,     // target
  1229.                        NULL,       // callback for async only
  1230.                        0);         // callback data for async only
  1231. };
  1232. //------------------------[ get next async ]-----------------------------
  1233. int Snmp::get_next( Pdu &pdu,                     // pdu to use
  1234.                     SnmpTarget &target,           // destination target
  1235.                     const snmp_callback callback, // callback to use
  1236.                     const void *callback_data)    // callback data
  1237. {
  1238.    if ( ! callback )
  1239.        return SNMP_CLASS_INVALID_CALLBACK;
  1240.    pdu.set_type( sNMP_PDU_GETNEXT);
  1241.    return snmp_engine( pdu,              // pdu to get next
  1242.                        0,                // max repeaters
  1243.                        0,                // non repeaters
  1244.                        target,           // target
  1245.                        callback,         // callback
  1246.                        callback_data);   // callback data
  1247. };
  1248. //-------------------------[ set ]---------------------------------------
  1249. int Snmp::set( Pdu &pdu,            // pdu to use
  1250.                SnmpTarget &target)  // target address
  1251. {
  1252.    pdu.set_type( sNMP_PDU_SET);
  1253.    return snmp_engine( pdu,         // pdu to set
  1254.                        0,           // max repeaters
  1255.                        0,           // non repeaters
  1256.                        target,      // target
  1257.                        NULL,        // callback for async only
  1258.                        0);          // callback data
  1259. };
  1260. //------------------------[ set async ]----------------------------------
  1261. int Snmp::set( Pdu &pdu,                     // pdu to use
  1262.                SnmpTarget &target,           // destination target
  1263.                const snmp_callback callback, // callback to use
  1264.                const void * callback_data)   // callback data
  1265. {
  1266.    if ( ! callback )
  1267.        return SNMP_CLASS_INVALID_CALLBACK;
  1268.    pdu.set_type( sNMP_PDU_SET);
  1269.    return snmp_engine( pdu,               // pdu to set
  1270.                        0,                 // max repeaters
  1271.                        0,                 // non repeaters
  1272.                        target,            // target
  1273.                        callback,          // callback function
  1274.                        callback_data);    // callback data
  1275. };
  1276. //-----------------------[ get bulk ]------------------------------------
  1277. int Snmp::get_bulk( Pdu &pdu,                // pdu to use
  1278.                     SnmpTarget &target,      // destination target
  1279.                     const int non_repeaters, // number of non repeaters
  1280.                     const int max_reps)      // maximum number of repetitions
  1281. {
  1282.      pdu.set_type( sNMP_PDU_GETBULK);
  1283.      return snmp_engine( pdu,               // pdu to use
  1284.                          non_repeaters,     // # of non repeaters
  1285.                          max_reps,          // max repititions
  1286.                          target,            // target
  1287.                          NULL,              // callback for async only
  1288.                          0);                // callback data
  1289. };
  1290. //-----------------------[ get bulk async ]------------------------------
  1291. int Snmp::get_bulk( Pdu &pdu,                     // pdu to use
  1292.                     SnmpTarget &target,           // destination target
  1293.                     const int non_repeaters,      // number of non repeaters
  1294.                     const int max_reps,           // maximum number of repetitions
  1295.                     const snmp_callback callback, // callback to use
  1296.                     const void *callback_data)    // callback data
  1297. {
  1298.    if ( ! callback )
  1299.        return SNMP_CLASS_INVALID_CALLBACK;
  1300.   pdu.set_type( sNMP_PDU_GETBULK);
  1301.   return snmp_engine( pdu,                    // pdu to use
  1302.                       non_repeaters,          // # of non repeaters
  1303.                       max_reps,               // max repititions
  1304.                       target,                 // target
  1305.                       callback,               // callback function
  1306.                       callback_data);         // callback data
  1307. };
  1308. //----------------------[ blocking inform, V2 only]------------------------
  1309. int Snmp::inform( Pdu &pdu,                // pdu to send
  1310.                   SnmpTarget &target)      // destination target
  1311. {
  1312.    pdu.set_type( sNMP_PDU_INFORM);
  1313.    return snmp_engine( pdu,       // get pdu
  1314.                        0,         // max repeaters
  1315.                        0,         // non repeaters
  1316.                        target,    // target
  1317.                        NULL,      // callback for async only
  1318.                        0);        // callback data
  1319. };
  1320. //----------------------[ asynch inform, V2 only]------------------------
  1321. int Snmp::inform( Pdu &pdu,                     // pdu to send
  1322.                   SnmpTarget &target,           // destination target
  1323.                   const snmp_callback callback, // callback function
  1324.                   const void * callback_data)   // callback data
  1325. {
  1326.    if ( ! callback )
  1327.       return SNMP_CLASS_INVALID_CALLBACK;
  1328.    pdu.set_type( sNMP_PDU_INFORM_ASYNC);
  1329.    return snmp_engine( pdu,               // pdu to set
  1330.                        0,                 // max repeaters
  1331.                        0,                 // non repeaters
  1332.                        target,            // target
  1333.                        callback,          // callback function
  1334.                        callback_data);    // callback data
  1335. };
  1336. //---------------------[ send a trap ]------------------------------------------
  1337. int Snmp::trap( Pdu &pdu,             // pdu to send
  1338.                 SnmpTarget &target)   // destination target
  1339.    int status;
  1340.    long int request_id;          // unique request id
  1341.    
  1342.    SNMPDEBUG("++ SNMP++, Send a Trapn");
  1343.    //---------[ make sure pdu is valid ]--------------------------
  1344.    if ( !pdu.valid())
  1345.      return  SNMP_CLASS_INVALID_PDU;
  1346.    pdu.set_type( sNMP_PDU_TRAP);
  1347.    SNMP_WAIT;
  1348.    //-----[ get a request id to use ]-------------------------
  1349.    request_id = pdu_container->get_request_id();
  1350.    SNMP_SIGNAL;
  1351.        
  1352.    //-----[ send it out ]----------------------------------------------
  1353.    status = sendMsg(target, pdu,0,0,request_id);
  1354.    // verify the send status
  1355.    if (status != SNMP_CLASS_SUCCESS) {
  1356.       SNMPDEBUG("-- SNMP++, Failure Sending Trap Pdun");
  1357.       return status;  // fail on send message
  1358.    }
  1359.    SNMP_WAIT;
  1360.    pdu_container->traps_sent();
  1361.    SNMP_SIGNAL;
  1362.    
  1363.    return SNMP_CLASS_SUCCESS;
  1364. };
  1365. //------------[ convert SNMP++ VB to WinSNMP smiVALUE ]----------------
  1366. int convertVbToSmival( Vb &tempvb, smiVALUE *smival )
  1367. {
  1368.    smival->syntax = tempvb.get_syntax();
  1369.    switch ( smival->syntax ) {
  1370.       
  1371.    //    case sNMP_SYNTAX_INT32:
  1372.       case sNMP_SYNTAX_INT:
  1373.   tempvb.get_value(smival->value.sNumber);
  1374.   break;
  1375.       //    case sNMP_SYNTAX_UINT32:
  1376.       case sNMP_SYNTAX_GAUGE32:
  1377.       case sNMP_SYNTAX_CNTR32:
  1378.       case sNMP_SYNTAX_TIMETICKS:
  1379.   tempvb.get_value(smival->value.uNumber);
  1380.   break;
  1381.   // case Counter64
  1382.       case sNMP_SYNTAX_CNTR64:
  1383.       {
  1384.      Counter64 c64;
  1385.      tempvb.get_value(c64);
  1386.      smival->value.hNumber.hipart = c64.high();
  1387.      smival->value.hNumber.lopart = c64.low();
  1388.   }
  1389.   break;
  1390.       case sNMP_SYNTAX_BITS:
  1391.       case sNMP_SYNTAX_OCTETS:
  1392.       case sNMP_SYNTAX_IPADDR:
  1393.       {
  1394.      OctetStr os;
  1395.      tempvb.get_value(os);
  1396.      smival->value.string.ptr = NULL;
  1397.      smival->value.string.len = os.len();
  1398.      if ( smival->value.string.len > 0 ) 
  1399.  {
  1400. smival->value.string.ptr = (SmiLPBYTE) new  unsigned char [smival->value.string.len];
  1401.         if ( smival->value.string.ptr ) 
  1402.     {
  1403.                for (int i=0; i<(int) smival->value.string.len ; i++)
  1404.           smival->value.string.ptr[i] = os[i];
  1405.         } 
  1406.     else 
  1407.     { 
  1408.            smival->syntax = sNMP_SYNTAX_NULL;  // invalidate the smival
  1409.            return SNMP_CLASS_RESOURCE_UNAVAIL;
  1410.         }
  1411.      }
  1412.       }
  1413.       break;
  1414.       case sNMP_SYNTAX_OID:
  1415.   {
  1416.      Oid oid;
  1417.      tempvb.get_value(oid);
  1418.      smival->value.oid.ptr = NULL;
  1419.      smival->value.oid.len = oid.len();
  1420.      if ( smival->value.oid.len > 0 ) 
  1421.  {
  1422. smival->value.oid.ptr = (SmiLPUINT32) new unsigned long [ smival->value.oid.len];
  1423.         if ( smival->value.oid.ptr ) 
  1424. {
  1425.                for (int i=0; i<(int)smival->value.oid.len ; i++)
  1426.           smival->value.oid.ptr[i] = oid[i];
  1427.         } 
  1428. else 
  1429. {
  1430.             smival->syntax = sNMP_SYNTAX_NULL;  // invalidate the smival
  1431.             return SNMP_CLASS_RESOURCE_UNAVAIL;
  1432.         }
  1433.     }
  1434.   }
  1435.   break;
  1436.       default:
  1437.         return SNMP_CLASS_INTERNAL_ERROR;
  1438.    }
  1439.    return SNMP_CLASS_SUCCESS;
  1440. }
  1441. //------------[ free WinSNMP smiVALUE descriptors ]---------------------
  1442. void freeSmivalDescriptor( smiVALUE *smival )
  1443. {
  1444.    switch ( smival->syntax ) {
  1445.      case SNMP_SYNTAX_OCTETS:
  1446.      case SNMP_SYNTAX_OPAQUE:
  1447.      case SNMP_SYNTAX_IPADDR:
  1448.      case SNMP_SYNTAX_NSAPADDR: // obsoleted in SNMPv2 Draft Std
  1449.      case SNMP_SYNTAX_BITS:     // obsoleted in SNMPv2 Draft Std
  1450.           delete [] smival->value.string.ptr;    
  1451.        break;
  1452.      case SNMP_SYNTAX_OID:
  1453.   delete [] smival->value.oid.ptr;
  1454.        break;
  1455.    }
  1456.    smival->syntax = SNMP_SYNTAX_NULL;
  1457. }
  1458. //----------------------[ load_varbindlist ]----------------------------
  1459. // load the WinSNMP varbind list with the Snmp++ Vb objects
  1460. int load_varbindlist(HSNMP_SESSION session_handle,
  1461.              HSNMP_VBL hvbl,   // handle to WinSNMP vbl
  1462.                      Pdu &pdu)         // pdu to use
  1463. {
  1464.    int z;                  // looping variable
  1465.    Oid current_oid;        // current oid object
  1466.    smiOID smioid;          // winsnmp oid variable
  1467.    smiVALUE smival;        // winsnmp smi value
  1468.    SNMPAPI_STATUS Wstatus; // return status for snmp calls
  1469.    Vb tempvb;              // temp vb to use
  1470.    int vb_count;           // count of vbs in pdu
  1471.    unsigned short action;  // type of pdu
  1472.    int rc;            // snmp++ result code
  1473.    TimeTicks timestamp;    // timestamp for traps
  1474.    SNMPDEBUG("++ SNMP++, In load var bind list n");
  1475.    vb_count = pdu.get_vb_count();
  1476.    action = pdu.get_type();
  1477.    //------------------------------------------------
  1478.    // if its a trap then build up trap timestamp and id
  1479.    if ( action == sNMP_PDU_TRAP) {
  1480.    // timestamp
  1481.    tempvb.set_oid( (Oid) "1.3.6.1.2.1.1.3.0");
  1482.    pdu.get_notify_timestamp( timestamp);
  1483.    if ( timestamp <= 0) 
  1484.            timestamp = ( long) GetTickCount();
  1485.    tempvb.set_value( timestamp);
  1486.        Wstatus = SnmpStrToOid( tempvb.get_printable_oid(),&smioid);
  1487.        if ( Wstatus == SNMPAPI_FAILURE) 
  1488.    {
  1489.      Wstatus = SnmpGetLastError(NULL);
  1490.      if (SNMPAPI_ALLOC_ERROR == Wstatus) 
  1491.          return SNMP_CLASS_RESOURCE_UNAVAIL; 
  1492.  else 
  1493.  if (SNMPAPI_OID_INVALID == Wstatus) 
  1494.             return SNMP_CLASS_INVALID_OID;
  1495.      else 
  1496.             return SNMP_CLASS_INTERNAL_ERROR; 
  1497.    }
  1498.        rc = convertVbToSmival(tempvb, &smival);
  1499.    if ( rc != SNMP_CLASS_SUCCESS ) 
  1500.    {
  1501.          SnmpFreeDescriptor(SNMP_SYNTAX_OID, (smiLPOPAQUE) &smioid);
  1502.      return rc; 
  1503.    }
  1504.        Wstatus = SnmpSetVb( hvbl,0,&smioid,&smival);
  1505.        if ( Wstatus == SNMPAPI_FAILURE) 
  1506.    {
  1507.      Wstatus = SnmpGetLastError(NULL);
  1508.          SnmpFreeDescriptor(SNMP_SYNTAX_OID, (smiLPOPAQUE) &smioid);
  1509.      freeSmivalDescriptor( &smival);
  1510.      if (SNMPAPI_ALLOC_ERROR == Wstatus) 
  1511.    return SNMP_CLASS_RESOURCE_UNAVAIL; 
  1512.  else 
  1513.    return SNMP_CLASS_INTERNAL_ERROR; 
  1514.        }
  1515.    freeSmivalDescriptor(&smival);
  1516.        // free the smioid descriptor
  1517.        SnmpFreeDescriptor(SNMP_SYNTAX_OID, (smiLPOPAQUE) &smioid);
  1518.         
  1519.    // trap id
  1520.    tempvb.set_oid( (Oid) "1.3.6.1.6.3.1.1.4.1.0");
  1521.    pdu.get_notify_id( current_oid);
  1522.    tempvb.set_value( current_oid);
  1523.        Wstatus = SnmpStrToOid( tempvb.get_printable_oid(),&smioid);
  1524.        if ( Wstatus == SNMPAPI_FAILURE) 
  1525.    {
  1526.      Wstatus = SnmpGetLastError(NULL);
  1527.      if (SNMPAPI_ALLOC_ERROR == Wstatus) 
  1528.          return SNMP_CLASS_RESOURCE_UNAVAIL; 
  1529.  else 
  1530.  if (SNMPAPI_OID_INVALID == Wstatus) 
  1531.             return SNMP_CLASS_INVALID_OID;
  1532.      else 
  1533.             return SNMP_CLASS_INTERNAL_ERROR; 
  1534.    }
  1535.        rc = convertVbToSmival(tempvb, &smival);
  1536.    if ( rc != SNMP_CLASS_SUCCESS ) 
  1537.    {
  1538.          SnmpFreeDescriptor(SNMP_SYNTAX_OID, (smiLPOPAQUE) &smioid);
  1539.      return rc; 
  1540.    }
  1541.        Wstatus = SnmpSetVb( hvbl,0,&smioid,&smival);
  1542.        if ( Wstatus == SNMPAPI_FAILURE) 
  1543.    {
  1544.      Wstatus = SnmpGetLastError(NULL);
  1545.          SnmpFreeDescriptor(SNMP_SYNTAX_OID, (smiLPOPAQUE) &smioid);
  1546.      freeSmivalDescriptor( &smival);
  1547.      if (SNMPAPI_ALLOC_ERROR == Wstatus) 
  1548.    return SNMP_CLASS_RESOURCE_UNAVAIL; 
  1549.  else 
  1550.    return SNMP_CLASS_INTERNAL_ERROR; 
  1551.        }
  1552.    freeSmivalDescriptor(&smival);
  1553.        // free the smioid descriptor
  1554.        SnmpFreeDescriptor(SNMP_SYNTAX_OID, (smiLPOPAQUE) &smioid);
  1555.    
  1556.    };
  1557.    //------------------------------------------------
  1558.    // set all vb's into the vbl for all vb objects
  1559.    for (z=0;z<vb_count;z++)
  1560.    {
  1561.       SNMPDEBUG("++ SNMP++, Loading a Var Bind");
  1562.       // get a vb from the pdu
  1563.       pdu.get_vb( tempvb,z);
  1564.       // extract the oid request from the vb object
  1565.       // put it into a smi oid object
  1566.       tempvb.get_oid( current_oid);
  1567.       Wstatus = SnmpStrToOid( current_oid.get_printable(),&smioid);
  1568.       if ( Wstatus == SNMPAPI_FAILURE) 
  1569.   {
  1570.      Wstatus = SnmpGetLastError(NULL);
  1571.      if (SNMPAPI_ALLOC_ERROR == Wstatus) 
  1572.          return SNMP_CLASS_RESOURCE_UNAVAIL; 
  1573.  else 
  1574.  if (SNMPAPI_OID_INVALID == Wstatus) 
  1575.             return SNMP_CLASS_INVALID_OID;
  1576.      else 
  1577.             return SNMP_CLASS_INTERNAL_ERROR; 
  1578.       }
  1579.       // based on the action set the vb into the vbl
  1580.       // differently
  1581.       switch( action)
  1582.       {
  1583.          //-----[ get action ]
  1584.          // for gets we only need to put the oid portion in
  1585.          // we will get the value portion back
  1586.          case sNMP_PDU_GET:
  1587.          case sNMP_PDU_GETNEXT:
  1588.          case sNMP_PDU_GETBULK:
  1589.          SNMPDEBUG("++ SNMP++, Loading a Var Bind Oid portion only");
  1590.          Wstatus = SnmpSetVb( hvbl,0,&smioid,NULL);
  1591.          if ( Wstatus == SNMPAPI_FAILURE) 
  1592.  {
  1593.         Wstatus = SnmpGetLastError(NULL);
  1594.             SnmpFreeDescriptor(SNMP_SYNTAX_OID, (smiLPOPAQUE) &smioid);
  1595.         if (SNMPAPI_ALLOC_ERROR == Wstatus) 
  1596.        return SNMP_CLASS_RESOURCE_UNAVAIL; 
  1597. else 
  1598.        return SNMP_CLASS_INTERNAL_ERROR; 
  1599.      }
  1600.          break;
  1601.          //-----[ set and notification actions ]
  1602.          // for sets and notifications, we need to put the smivalue portion
  1603.      // as well as the oid portion into the varbind
  1604.          case sNMP_PDU_SET:
  1605.          case sNMP_PDU_TRAP:
  1606.          case sNMP_PDU_INFORM:
  1607.          SNMPDEBUG("++ SNMP++, Loading a Var Bind Oid and Value portion");
  1608.      rc = convertVbToSmival(tempvb, &smival);
  1609.      if ( rc != SNMP_CLASS_SUCCESS ) 
  1610.  {
  1611.             SnmpFreeDescriptor(SNMP_SYNTAX_OID, (smiLPOPAQUE) &smioid);
  1612.         return rc; 
  1613.      }
  1614.          Wstatus = SnmpSetVb( hvbl,0,&smioid,&smival);
  1615.          if ( Wstatus == SNMPAPI_FAILURE) 
  1616.  {
  1617.         Wstatus = SnmpGetLastError(NULL);
  1618.             SnmpFreeDescriptor(SNMP_SYNTAX_OID, (smiLPOPAQUE) &smioid);
  1619.         freeSmivalDescriptor( &smival);
  1620.         if (SNMPAPI_ALLOC_ERROR == Wstatus) 
  1621.       return SNMP_CLASS_RESOURCE_UNAVAIL; 
  1622. else 
  1623.       return SNMP_CLASS_INTERNAL_ERROR; 
  1624.          }
  1625.      freeSmivalDescriptor(&smival);
  1626.          break;
  1627.  default: // Internal error
  1628.          SNMPDEBUG("++ SNMP++, Invalid PDU Type loading a Var Bind list");
  1629.          return SNMP_CLASS_INTERNAL_ERROR;
  1630.          break;
  1631.       }  // end switch
  1632.       // free the smioid descriptor
  1633.       SnmpFreeDescriptor(SNMP_SYNTAX_OID, (smiLPOPAQUE) &smioid);
  1634.    }  //end for z
  1635.    //-----------------------------------------------------------------
  1636.    // check for trap enterprise addition
  1637.    if ( action == sNMP_PDU_TRAP) {
  1638.        tempvb.set_oid( snmpTrapEnterprise);
  1639.    pdu.get_notify_enterprise( current_oid);
  1640.    // enterprise has to be valid
  1641.    if ( current_oid.valid() ) {
  1642.       tempvb.set_value( current_oid);
  1643.           Wstatus = SnmpStrToOid( tempvb.get_printable_oid(),&smioid);
  1644.           if ( Wstatus == SNMPAPI_FAILURE) 
  1645.   {
  1646.         Wstatus = SnmpGetLastError(NULL);
  1647.         if (SNMPAPI_ALLOC_ERROR == Wstatus) 
  1648.             return SNMP_CLASS_RESOURCE_UNAVAIL; 
  1649.     else 
  1650.     if (SNMPAPI_OID_INVALID == Wstatus) 
  1651.                return SNMP_CLASS_INVALID_OID;
  1652.         else 
  1653.                return SNMP_CLASS_INTERNAL_ERROR; 
  1654.   }
  1655.           rc = convertVbToSmival(tempvb, &smival);
  1656.       if ( rc != SNMP_CLASS_SUCCESS ) 
  1657.   {
  1658.              SnmpFreeDescriptor(SNMP_SYNTAX_OID, (smiLPOPAQUE) &smioid);
  1659.          return rc; 
  1660.   }
  1661.           Wstatus = SnmpSetVb( hvbl,0,&smioid,&smival);
  1662.           if ( Wstatus == SNMPAPI_FAILURE) 
  1663.   {
  1664.          Wstatus = SnmpGetLastError(NULL);
  1665.              SnmpFreeDescriptor(SNMP_SYNTAX_OID, (smiLPOPAQUE) &smioid);
  1666.          freeSmivalDescriptor( &smival);
  1667.          if (SNMPAPI_ALLOC_ERROR == Wstatus) 
  1668.         return SNMP_CLASS_RESOURCE_UNAVAIL; 
  1669.      else 
  1670.         return SNMP_CLASS_INTERNAL_ERROR; 
  1671.   }
  1672.       freeSmivalDescriptor(&smival);
  1673.           // free the smioid descriptor
  1674.           SnmpFreeDescriptor(SNMP_SYNTAX_OID, (smiLPOPAQUE) &smioid);
  1675.    } // end if enterprise valid
  1676.    }
  1677.    SNMPDEBUG("++ SNMP++, Out Load VarBind List n");
  1678.    return SNMP_CLASS_SUCCESS;
  1679. }; // end function
  1680. //---------------[ yield pump ]-----------------------
  1681. int yield_pump()
  1682. {
  1683.    MSG msg;                      // message var for blocking
  1684.    // while there are messages, pump em
  1685.    // just look at the message without removing it first
  1686.    while ( PeekMessage( &msg, (HWND) NULL,0,0, PM_NOREMOVE   ))
  1687.    {
  1688.       // get the message
  1689.       GetMessage( &msg, (HWND) NULL,0,0);
  1690.   // check for shutdown
  1691.   if ( msg.message == SNMP_SHUTDOWN_MSG)
  1692.   return SNMP_CLASS_SHUTDOWN;
  1693.       // translate it
  1694.       TranslateMessage( &msg);
  1695.       // dispath it
  1696.       DispatchMessage( &msg);
  1697.    } // end while
  1698.    return SNMP_CLASS_SUCCESS;
  1699. };
  1700. //----------------------------------------------------------------------
  1701. //---------[ snmp++ engine ]--------------------------------------------
  1702. //----------------------------------------------------------------------
  1703. // Snmp engine used for all requests, async and blocked
  1704. // build up the request as a WinSNMP request
  1705. // send it out
  1706. // if it was a async request then return out
  1707. // otherwise wait for response while pumping messages
  1708. // while waiting
  1709. // if request arrived then unload request into snmp++ vb format
  1710. //
  1711. int Snmp::snmp_engine( Pdu &pdu,                 // pdu to use
  1712.                        long int non_reps,        // # of non repititions
  1713.                        long int max_reps,        // # of max repititions
  1714.                        SnmpTarget &target,       // from this target
  1715.                        const snmp_callback cb,   // callback for async calls
  1716.                        const void * cbd)         // callback data
  1717. {
  1718.    long int request_id;          // unique request id
  1719.    int blocked;                  // blocking variable
  1720.    unsigned long start_time;     // starting time of wait
  1721.    HSNMP_ENTITY hDstRecvEnt,     // received destination
  1722.                 hSrcRecvEnt;     // received source
  1723.    HSNMP_CONTEXT hRecvContext;   // received context
  1724.    smiINT lnRecvPduType;         // received pdu type
  1725.    smiINT lnRecvRequestId;       // received pcu status
  1726.    smiINT lnErrorStatus;         // received error status
  1727.    smiINT lnErrorIndex;          // received error index
  1728.    HSNMP_VBL hRecvVbl;           // received variable binding list
  1729.    int return_status;            // return status
  1730.    int error_status;             // pdu error status
  1731.    unsigned long my_timeout;     // target specific timeout
  1732.    int my_retry;                 // target specific retry
  1733.    int yield_value;
  1734.    OctetStr my_get_community;
  1735.    OctetStr my_set_community;
  1736.    snmp_callback my_callback;
  1737.    void * my_callback_data;
  1738.    unsigned long wait_time;
  1739.    GenAddress address; 
  1740.    unsigned char version;  
  1741.    int status;
  1742.    //---------[ make sure target is valid ]-------------------------
  1743.    // make sure that the target is valid
  1744.    if ( ! target.valid()) {
  1745.       SNMPDEBUG("-- SNMP++, Target Object Invalidn");
  1746.       return SNMP_CLASS_INVALID_TARGET;
  1747.    }
  1748.    // try to resolve the target as a v1 target instead
  1749.    if ( !target.resolve_to_C( my_get_community,
  1750.                               my_set_community,
  1751.                               address,
  1752.                               my_timeout,
  1753.                               my_retry,
  1754.                               version)) {
  1755.       SNMPDEBUG("-- SNMP++, V1 Resolve Failn");
  1756.       return SNMP_CLASS_INVALID_TARGET;
  1757.    }
  1758.    //---------[ make sure pdu is valid ]--------------------------
  1759.    if ( !pdu.valid())
  1760.      return  SNMP_CLASS_INVALID_PDU;
  1761.    //----[ build a unique request id ]---------------------------------
  1762.    // each rid is unique by querying the pdu container class for an
  1763.    // available slot. Once an id is issued, no other request can use
  1764.    // it until it is removed from the container
  1765.    SNMP_WAIT;
  1766.    request_id = (smiINT) pdu_container->get_request_id( (HSNMP_SESSION) iv_snmp_session,
  1767.                                                     cb,
  1768.                                                         (void *) cbd);
  1769.    SNMP_SIGNAL;
  1770.    if ( request_id == -1) {
  1771.       return SNMP_CLASS_RESOURCE_UNAVAIL;
  1772.    };
  1773.    //-------[ Send out the PDU ]------------------------------------------
  1774.    SNMPDEBUG("++ SNMP++, Send PDU n");
  1775.    return_status = sendMsg( target, pdu, non_reps, max_reps, request_id);
  1776.    // update
  1777.    SNMP_WAIT;
  1778.    pdu_container->pdu_sent();
  1779.    SNMP_SIGNAL;
  1780.    // verify the send status
  1781.    if (return_status != SNMP_CLASS_SUCCESS) {
  1782.   SNMP_WAIT;
  1783.       pdu_container->clear_request_id( (int) request_id);
  1784.       pdu_container->sent_err();
  1785.   SNMP_SIGNAL;
  1786.       return return_status;  // fail on send message
  1787.    }
  1788.    //---------[ if this was an async call then return out ]
  1789.    // presence of a non-null callback function indicates this is async
  1790.    if ( cb )  
  1791.       return SNMP_CLASS_SUCCESS;
  1792.    //---------[ otherwise we sit and wait for the response pdu ]
  1793.    //---------[ peek and loop until response has arrived or timeout]
  1794.    // Note, the WinSNMP timeout notification is ignored because there
  1795.    // is no support for blocking-mode timeout notification in the 
  1796.    // SnmpWndProc.  Therefore, the following loop checks when the
  1797.    // projected timeout would occur.  
  1798.    blocked = TRUE;
  1799.    start_time = GetTickCount();
  1800.    wait_time = ( unsigned int) my_timeout * (my_retry+1) * 10;
  1801.    while (( blocked) && ( (GetTickCount() - start_time) < wait_time))
  1802.    {
  1803.       //--------------[ yield to windows ]---------------------------
  1804.       // allow other windows messages to be processed
  1805.       yield_value = yield_pump();
  1806.       // after processing any messages, look for responce pdu
  1807.       // did the response pdu arrive?
  1808.   SNMP_WAIT;
  1809.   status = pdu_container->check_if_arrived( (int) request_id);
  1810.       SNMP_SIGNAL;
  1811.       if ( status)
  1812.       {
  1813.          SNMPDEBUG("++ SNMP++, Extract From PDU Cont n");
  1814.          blocked = FALSE;  // no longer blocked on this request
  1815.          // pick up the data
  1816.  SNMP_WAIT;
  1817.          pdu_container->get_slot( (int) request_id,  // for this rid
  1818.                                   &hSrcRecvEnt,      // this source entity
  1819.                                   &hDstRecvEnt,      // this dest entity
  1820.                                   &hRecvContext,     // this community
  1821.                                   &lnRecvPduType,    // this pdu type
  1822.                                   &lnRecvRequestId,  // rid returned
  1823.                                   &lnErrorStatus,    // error status
  1824.                                   &lnErrorIndex,     // error index
  1825.                                   &my_callback,      // callback function
  1826.                                   &my_callback_data, // callback data
  1827.                                   &hRecvVbl);        // vbl returned
  1828.          SNMP_SIGNAL;
  1829.          SNMPDEBUG("++ SNMP++, Get VB Count n");
  1830.      
  1831.          // extract the snmp++ vbs from the winsnmp varbindlist
  1832.          extract_from_varbindlist( hRecvVbl, pdu);
  1833.          // set return error status vals
  1834.          error_status = ( int) lnErrorStatus;
  1835.          set_error_status( &pdu, error_status);
  1836.          set_error_index( &pdu, (int) lnErrorIndex);
  1837.          SNMPDEBUG("++ SNMP++, Free Vbl, Ent, Ent, Context n");
  1838.          // free up the receive resources
  1839.          SnmpFreeVbl( hRecvVbl);
  1840.          SnmpFreeEntity( hSrcRecvEnt);
  1841.          SnmpFreeEntity( hDstRecvEnt);
  1842.          SnmpFreeContext( hRecvContext);
  1843.  SNMP_WAIT;
  1844.          pdu_container->clear_request_id( (int) request_id);
  1845.  SNMP_SIGNAL;
  1846.       }   // end if pdu_received
  1847.   
  1848.       //----------[ did the yield find a stop ]----------------
  1849.       if ( yield_value != SNMP_CLASS_SUCCESS)
  1850.       {
  1851.  SNMP_WAIT;
  1852.          pdu_container->clear_request_id( (int) request_id);
  1853.  SNMP_SIGNAL;
  1854.          return yield_value;
  1855.       };
  1856.   Sleep(1);
  1857.    } // end while blocked & ! timeout
  1858.    //------[ determine if blocked ]-----------------------------
  1859.    // if we are blocked then its a timeout; 
  1860.    // otherwise, it a response.  In the response case,
  1861.    // we return a "warning" if pdu.error_status is set 
  1862.    // by the agent.
  1863.    if ( blocked)
  1864.    {
  1865.   SNMP_WAIT;
  1866.       pdu_container->clear_request_id( (int) request_id);
  1867.   SNMP_SIGNAL;
  1868.       return_status = SNMP_CLASS_TIMEOUT;
  1869.    }
  1870.    else
  1871.    {
  1872.        if ( error_status == 0)
  1873.            return_status = SNMP_CLASS_SUCCESS;
  1874.        else
  1875.            return_status = SNMP_CLASS_ERR_STATUS_SET;
  1876.    }
  1877.    return return_status;
  1878. };
  1879. //-----------------------------------------------------------------
  1880. //--------[ sendMsg ]----------------------------------------------
  1881. //-----------------------------------------------------------------
  1882. int Snmp::sendMsg( SnmpTarget &target,         // target of send
  1883.                    Pdu &pdu,                   // the pdu to send
  1884.    long int non_reps,          // # of non repititions
  1885.                    long int max_reps,          // # of max repititions
  1886.              long int request_id)        // unique request id
  1887. {
  1888.     SNMPAPI_STATUS Wstatus;       // return status for snmp calls
  1889.     HSNMP_PDU hSendPdu;
  1890.     HSNMP_ENTITY hDstEntity;      // destination entity
  1891.     HSNMP_ENTITY hSrcEntity;      // source entity
  1892.     HSNMP_CONTEXT hSendContext;   // send context
  1893.     unsigned long my_timeout;     // target specific timeout
  1894.     int my_retry;                 // target specific retry
  1895.     SmiOCTETS my_community_name;  // community name to use
  1896.     int return_status;
  1897.     OctetStr my_get_community, my_set_community;
  1898.     unsigned short action;
  1899.     GenAddress address;
  1900.     HSNMP_VBL hvbl;
  1901.     unsigned char version; 
  1902.     //---------[ make sure pdu is valid ]---------------------------------
  1903.     if ( !pdu.valid()) {
  1904. SNMPDEBUG("-- SNMP++, PDU Object Invalidn");
  1905. return  SNMP_CLASS_INVALID_PDU;
  1906.     }
  1907.     //---------[ make sure target is valid ]-------------------------
  1908.     // make sure that the target is valid
  1909.     if ( ! target.valid()) {
  1910. SNMPDEBUG("-- SNMP++, Target Object Invalidn");
  1911. return SNMP_CLASS_INVALID_TARGET;
  1912.     }
  1913.     //---------[ get the action from the pdu ]---------------------
  1914.     action = pdu.get_type();
  1915.     // try to resolve the target as a community-based target 
  1916.     if ( !target.resolve_to_C(my_get_community,
  1917.                               my_set_community,
  1918.                               address,
  1919.                               my_timeout,
  1920.                               my_retry,
  1921.                               version)) {
  1922. SNMPDEBUG("-- SNMP++, CTarget Resolve Failn");
  1923. return SNMP_CLASS_INVALID_TARGET;
  1924.     }
  1925.     //-----[ set the translation mode to no translation based on the target type ]
  1926.     Wstatus = SnmpSetTranslateMode( version == version1 ? SNMPAPI_UNTRANSLATED_V1 : SNMPAPI_UNTRANSLATED_V2);
  1927.     if ( Wstatus != SNMPAPI_SUCCESS) {
  1928. Wstatus = SnmpGetLastError( (HSNMP_SESSION) iv_snmp_session);
  1929. SNMPDEBUG("-- SNMP++, Failure setting UNTRANSLATED_V1 moden");
  1930. if (SNMPAPI_ALLOC_ERROR == Wstatus) {
  1931.     return SNMP_CLASS_RESOURCE_UNAVAIL;
  1932. } else {
  1933.     return SNMP_CLASS_INTERNAL_ERROR;
  1934. }
  1935.     }
  1936.     SNMPDEBUG("++ SNMP++, Make Entities, Context & PDU n");
  1937.     //-----[ set destination entity ]--------------------------------
  1938.     // Determine set the port or socket that we should be
  1939.     // sending to.
  1940.     unsigned int port = 0xffff;
  1941.     char * addrStr;
  1942.     int addrType = address.get_type();
  1943.     
  1944.     switch (addrType) {
  1945.       case type_udp:
  1946. {
  1947.   UdpAddress udpAddr(address);
  1948.   port = udpAddr.get_port();
  1949.   addrStr = udpAddr.IpAddress::get_printable();
  1950.   break;
  1951.         }
  1952.       case type_ipxsock:
  1953. {
  1954.   IpxSockAddress ipxsockAddr(address);
  1955.   port = ipxsockAddr.get_socket();
  1956.   addrStr = ipxsockAddr.IpxAddress::get_printable();
  1957.   break;
  1958.         }
  1959.       default:
  1960. // Otherwise we will be sending to the default.
  1961.         addrStr = address.get_printable();
  1962. break;
  1963.     }
  1964.     hDstEntity = SnmpStrToEntity( (HSNMP_SESSION) iv_snmp_session, addrStr);
  1965.     if ( hDstEntity == SNMPAPI_FAILURE) {
  1966. Wstatus = SnmpGetLastError( (HSNMP_SESSION) iv_snmp_session);
  1967. SNMPDEBUG("-- SNMP++, Fail Maiking Dest Entityn");
  1968. if (SNMPAPI_ENTITY_UNKNOWN == Wstatus) {
  1969.     return SNMP_CLASS_TL_UNSUPPORTED;
  1970. } else if (SNMPAPI_ALLOC_ERROR == Wstatus) {
  1971.     return SNMP_CLASS_RESOURCE_UNAVAIL;
  1972. } else {
  1973.     return SNMP_CLASS_INTERNAL_ERROR;
  1974. }
  1975.     }
  1976.    if (port != 0xffff) {
  1977. HMODULE hModule;
  1978. functionPortSet portbuilder;
  1979. hModule = GetModuleHandle("WSNMP32");
  1980. portbuilder = (functionPortSet) GetProcAddress( hModule,"SnmpSetPort");
  1981. if ( portbuilder != NULL) {
  1982.    Wstatus = (portbuilder)(hDstEntity, port);
  1983.    if ( Wstatus != SNMPAPI_SUCCESS) {
  1984.        SNMPDEBUG("-- SNMP++, Failure Setting Dest Entity Portn");
  1985.        SnmpFreeEntity ( hDstEntity);
  1986.        return  SNMP_CLASS_INVALID_ADDRESS;  // cannot set alt port
  1987.    }
  1988. }
  1989.     }
  1990.     hSrcEntity = SnmpStrToEntity( (HSNMP_SESSION) iv_snmp_session,  addrStr);
  1991.     if ( hSrcEntity == SNMPAPI_FAILURE) {
  1992. SNMPDEBUG("-- SNMP++, Fail Making Source Entityn");
  1993. SnmpFreeEntity ( hDstEntity);
  1994. if (SNMPAPI_ENTITY_UNKNOWN == Wstatus) {
  1995.     return SNMP_CLASS_TL_UNSUPPORTED;
  1996. } else if (SNMPAPI_ALLOC_ERROR == Wstatus) {
  1997.     return SNMP_CLASS_RESOURCE_UNAVAIL;
  1998. } else {
  1999.     return SNMP_CLASS_INTERNAL_ERROR;
  2000. }
  2001.     }
  2002.     if (action != sNMP_PDU_TRAP ) {
  2003. // set the retransmit mode on
  2004. Wstatus = SnmpSetRetransmitMode( SNMPAPI_ON);
  2005. if ( Wstatus != SNMPAPI_SUCCESS) {
  2006.     Wstatus = SnmpGetLastError( (HSNMP_SESSION) iv_snmp_session);
  2007.     SNMPDEBUG("-- SNMP++, Fail setting RETRANSMIT_MODE=ONn");
  2008.     SnmpFreeEntity ( hDstEntity);
  2009.     SnmpFreeEntity ( hSrcEntity);
  2010.     if (SNMPAPI_ALLOC_ERROR == Wstatus) {
  2011. return SNMP_CLASS_RESOURCE_UNAVAIL;
  2012.     } else {
  2013. return SNMP_CLASS_INTERNAL_ERROR;
  2014.     }
  2015. }
  2016. // set the timeout
  2017. Wstatus = SnmpSetTimeout( hDstEntity, (SmiTIMETICKS) my_timeout);
  2018. if ( Wstatus != SNMPAPI_SUCCESS) {
  2019.     Wstatus = SnmpGetLastError( (HSNMP_SESSION) iv_snmp_session);
  2020.     SNMPDEBUG("-- SNMP++, Fail setting timeout n");
  2021.     SnmpFreeEntity ( hDstEntity);
  2022.     SnmpFreeEntity ( hSrcEntity);
  2023.     if (SNMPAPI_ALLOC_ERROR == Wstatus) {
  2024. return SNMP_CLASS_RESOURCE_UNAVAIL;
  2025.     } else {
  2026. return SNMP_CLASS_INTERNAL_ERROR;
  2027.     }
  2028. }
  2029. // set the retry
  2030. Wstatus = SnmpSetRetry( hDstEntity, (SmiUINT32) my_retry);
  2031. if ( Wstatus != SNMPAPI_SUCCESS) {
  2032.     Wstatus = SnmpGetLastError( (HSNMP_SESSION) iv_snmp_session);
  2033.     SNMPDEBUG("-- SNMP++, Fail setting retry n");
  2034.     SnmpFreeEntity ( hDstEntity);
  2035.     SnmpFreeEntity ( hSrcEntity);
  2036.     if (SNMPAPI_ALLOC_ERROR == Wstatus) {
  2037. return SNMP_CLASS_RESOURCE_UNAVAIL;
  2038.     } else {
  2039. return SNMP_CLASS_INTERNAL_ERROR;
  2040.     }
  2041. }
  2042.     }
  2043.     //------[ build the context ]--------------------------------------
  2044.     // v1 context is the community name in WinSnmp
  2045.     // use the commnuty from the Target ovject
  2046.     // depending on the action use either the get or set
  2047.     // community name
  2048.     //
  2049.     if ( action == sNMP_PDU_SET) {
  2050. my_community_name.ptr = (unsigned char *) my_set_community.data();
  2051. my_community_name.len = my_set_community.len();
  2052.     } else {
  2053. my_community_name.ptr = (unsigned char *) my_get_community.data();
  2054. my_community_name.len = my_get_community.len();
  2055.     }
  2056.     hSendContext = SnmpStrToContext( (HSNMP_SESSION) iv_snmp_session,(smiLPOCTETS)&my_community_name);
  2057.     if ( hSendContext == SNMPAPI_FAILURE) {
  2058. Wstatus = SnmpGetLastError( (HSNMP_SESSION) iv_snmp_session);
  2059. SNMPDEBUG("-- SNMP++, FailMaiking Contextn");
  2060. SnmpFreeEntity ( hDstEntity);
  2061. SnmpFreeEntity ( hSrcEntity);
  2062. if (SNMPAPI_ALLOC_ERROR == Wstatus) {
  2063.     return SNMP_CLASS_RESOURCE_UNAVAIL; 
  2064. } else {
  2065.     return SNMP_CLASS_INTERNAL_ERROR; 
  2066. }
  2067.     }
  2068.     //-------[ make a WinSNMP vbl without the oid ]---------------------
  2069.     hvbl = SnmpCreateVbl( (HSNMP_SESSION) iv_snmp_session, NULL, NULL);
  2070.     if ( hvbl == SNMPAPI_FAILURE) {
  2071. Wstatus = SnmpGetLastError( (HSNMP_SESSION) iv_snmp_session);
  2072. SNMPDEBUG("-- SNMP++, Fail Making Vbln");
  2073. SnmpFreeEntity ( hDstEntity);
  2074. SnmpFreeEntity ( hSrcEntity);
  2075. SnmpFreeContext( hSendContext);
  2076. if (SNMPAPI_ALLOC_ERROR == Wstatus) {
  2077.     return SNMP_CLASS_RESOURCE_UNAVAIL; 
  2078. } else {
  2079.     return SNMP_CLASS_INTERNAL_ERROR; 
  2080. }
  2081.     }
  2082.     //-------[ load WinSNMP varbind list using Snmp++ Vbs ]----------
  2083.     return_status = load_varbindlist( (HSNMP_SESSION) iv_snmp_session, hvbl, pdu);
  2084.     if ( return_status != SNMP_CLASS_SUCCESS) {
  2085. SnmpFreeEntity ( hDstEntity);
  2086. SnmpFreeEntity ( hSrcEntity);
  2087. SnmpFreeContext( hSendContext);
  2088. SnmpFreeVbl( hvbl);
  2089. SNMPDEBUG("-- SNMP++, Fail Loading Vbln");
  2090. return return_status;
  2091.     }
  2092.     //-----[ make the WinSNMP pdu ]---------------------------------------
  2093.     hSendPdu = SnmpCreatePdu( (HSNMP_SESSION) iv_snmp_session,  // for this session
  2094.                              (smiINT) action,   // defined action
  2095.                              request_id,        // request id
  2096.                              (action == sNMP_PDU_GETBULK) ? (smiINT) non_reps : NULL, // non repeaters
  2097.                              (action == sNMP_PDU_GETBULK) ? (smiINT) max_reps :NULL,  // max repetitions
  2098.                              pdu.get_vb_count() ? hvbl : NULL ); // vbl to send
  2099.  
  2100.     if ( hSendPdu == SNMPAPI_FAILURE) {
  2101. Wstatus = SnmpGetLastError( (HSNMP_SESSION) iv_snmp_session);
  2102. SNMPDEBUG("-- SNMP++, Failure Making Pdun");
  2103. SnmpFreeVbl( hvbl);
  2104. SnmpFreeEntity ( hDstEntity);
  2105. SnmpFreeEntity ( hSrcEntity);
  2106. SnmpFreeContext( hSendContext);
  2107. if (SNMPAPI_ALLOC_ERROR == Wstatus) {
  2108.     return SNMP_CLASS_RESOURCE_UNAVAIL; 
  2109. } else {
  2110.     return SNMP_CLASS_INTERNAL_ERROR; 
  2111. }
  2112.     }
  2113.     
  2114.     //-------[ Send out the PDU ]------------------------------------------
  2115.     SNMPDEBUG("++ SNMP++, Send PDU n");
  2116.     Wstatus = SnmpSendMsg( 
  2117.   (HSNMP_SESSION) iv_snmp_session,  // handle to session
  2118.   hSrcEntity,       // handle to source destination
  2119.   hDstEntity,       // handle to destination entity
  2120.   hSendContext,     // handle to context
  2121.   hSendPdu );       // the pdu to send
  2122.   
  2123.     //-----[ free everything up ]---------------------------------------
  2124.     SnmpFreePdu( hSendPdu);
  2125.     SnmpFreeVbl( hvbl);
  2126.     SnmpFreeEntity ( hDstEntity);
  2127.     SnmpFreeEntity ( hSrcEntity);
  2128.     SnmpFreeContext( hSendContext);
  2129.      
  2130.     if (Wstatus == SNMPAPI_FAILURE) {
  2131. Wstatus = SnmpGetLastError( (HSNMP_SESSION) iv_snmp_session);
  2132. SNMPDEBUG("-- SNMP++, Failure Sending Pdun");
  2133. if (SNMPAPI_ALLOC_ERROR == Wstatus) {
  2134.     return SNMP_CLASS_RESOURCE_UNAVAIL;
  2135. } else if (SNMPAPI_TL_NOT_SUPPORTED == Wstatus) {
  2136.     return SNMP_CLASS_TL_UNSUPPORTED;
  2137. } else if (SNMPAPI_OPERATION_INVALID == Wstatus) {
  2138.     return SNMP_CLASS_INVALID_OPERATION;
  2139. } else if (SNMPAPI_OTHER_ERROR == Wstatus) {
  2140.     return SNMP_CLASS_ERROR;
  2141. } else if (SNMPAPI_SESSION_INVALID == Wstatus ||
  2142.    SNMPAPI_ENTITY_INVALID == Wstatus ||
  2143.    SNMPAPI_CONTEXT_INVALID == Wstatus ||
  2144.    SNMPAPI_PDU_INVALID == Wstatus ||
  2145.    SNMPAPI_NOT_INITIALIZED == Wstatus) {
  2146.     return SNMP_CLASS_INTERNAL_ERROR;
  2147. } else {
  2148.     // The rest of the Wstatus codes are pathalogical
  2149.             // transport layer failures
  2150.     return SNMP_CLASS_TL_FAILED;
  2151. }
  2152.     } else {
  2153. return SNMP_CLASS_SUCCESS;
  2154.     }
  2155. }