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

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.   SNMP++ S N M P M E S S A G E . C P P   
  15.       
  16.   SNMPMESSAGE CLASS DEFINITION
  17.        
  18.   VERSION:
  19.   2.8
  20.   
  21.   RCS INFO:
  22.   $Header: Exp $
  23.        
  24.   DESIGN:
  25.   Peter E Mellquist
  26.                 
  27.   AUTHOR:      
  28.   Peter E Mellquist
  29.               
  30.   LANGUAGE:
  31.   ANSI C++ 
  32.       
  33.   OPERATING SYSTEMS:
  34.   Win 32
  35.   BSD UNIX
  36.       
  37.   DESCRIPTION:
  38.   ASN.1 encoding / decoding class
  39.         
  40. =====================================================================*/ 
  41. #include "snmpmsg.h"                 // header file for SnmpMessage
  42. #include "asn1.h"                       // ASN.1 header file
  43. #include "stdio.h"                      // standard io file 
  44. //--------------[ well known trap ids ]-----------------------------------
  45. // SMI trap oid def
  46. class snmpTrapsOid: public Oid {
  47.    public: 
  48.    snmpTrapsOid (void):Oid("1.3.6.1.6.3.1.1.5"){};
  49. }; 
  50. // SMI Enterprise Oid
  51. class snmpTrapEnterpriseOid: public Oid {
  52.    public: 
  53.    snmpTrapEnterpriseOid(void):Oid("1.3.6.1.6.3.1.1.4.3.0"){};
  54. }; 
  55. // SMI Cold Start Oid
  56. class coldStartOid: public snmpTrapsOid {
  57.    public: 
  58.    coldStartOid( void){*this+=".1";};
  59. };
  60. // SMI WarmStart Oid
  61. class warmStartOid: public snmpTrapsOid {
  62.    public: 
  63.    warmStartOid( void){*this+=".2";};
  64. };
  65. // SMI LinkDown Oid
  66. class linkDownOid: public snmpTrapsOid {
  67.    public: 
  68.    linkDownOid( void){*this+=".3";};
  69. }; 
  70. // SMI LinkUp Oid
  71. class linkUpOid: public snmpTrapsOid {
  72.    public: 
  73.    linkUpOid( void){*this+=".4";};
  74. };
  75. // SMI Authentication Failure Oid
  76. class authenticationFailureOid: public snmpTrapsOid {
  77.    public: 
  78.    authenticationFailureOid( void){*this+=".5";};
  79. }; 
  80. // SMI egpneighborloss Oid
  81. class egpNeighborLossOid: public snmpTrapsOid {
  82.    public: 
  83.    egpNeighborLossOid( void){*this+=".6";};
  84. };
  85. const coldStartOid coldStart;
  86. const warmStartOid warmStart;
  87. const linkDownOid linkDown;
  88. const linkUpOid linkUp;
  89. const authenticationFailureOid authenticationFailure;
  90. const egpNeighborLossOid egpNeighborLoss;
  91. const snmpTrapEnterpriseOid snmpTrapEnterprise;
  92. //------------[ convert SNMP++ VB to WinSNMP smiVALUE ]----------------
  93. int convertVbToSmival( Vb &tempvb, SmiVALUE *smival )
  94. {
  95.    smival->syntax = tempvb.get_syntax();
  96.    switch ( smival->syntax ) {
  97.   // case sNMP_SYNTAX_NULL
  98.   case sNMP_SYNTAX_NULL:
  99.       break;
  100.   // case sNMP_SYNTAX_INT32:
  101.       case sNMP_SYNTAX_INT:
  102.   tempvb.get_value(smival->value.sNumber);
  103.   break;
  104.       //    case sNMP_SYNTAX_UINT32:
  105.       case sNMP_SYNTAX_GAUGE32:
  106.       case sNMP_SYNTAX_CNTR32:
  107.       case sNMP_SYNTAX_TIMETICKS:
  108.   case sNMP_SYNTAX_UINT32:
  109.   tempvb.get_value(smival->value.uNumber);
  110.   break;
  111.   // case Counter64
  112.       case sNMP_SYNTAX_CNTR64:
  113.       {
  114.      Counter64 c64;
  115.      tempvb.get_value(c64);
  116.      smival->value.hNumber.hipart = c64.high();
  117.      smival->value.hNumber.lopart = c64.low();
  118.   }
  119.   break;
  120.       case sNMP_SYNTAX_BITS:
  121.       case sNMP_SYNTAX_OCTETS:
  122.       case sNMP_SYNTAX_IPADDR:
  123.       {
  124.      OctetStr os;
  125.      tempvb.get_value(os);
  126.      smival->value.string.ptr = NULL;
  127.      smival->value.string.len = os.len();
  128.      if ( smival->value.string.len > 0 ) 
  129.  {
  130. smival->value.string.ptr = (SmiLPBYTE) new  unsigned char [smival->value.string.len];
  131.         if ( smival->value.string.ptr ) 
  132.     {
  133.                for (int i=0; i<(int) smival->value.string.len ; i++)
  134.           smival->value.string.ptr[i] = os[i];
  135.         } 
  136.     else 
  137.     { 
  138.            smival->syntax = sNMP_SYNTAX_NULL;  // invalidate the smival
  139.            return SNMP_CLASS_RESOURCE_UNAVAIL;
  140.         }
  141.      }
  142.       }
  143.       break;
  144.       case sNMP_SYNTAX_OID:
  145.   {
  146.      Oid oid;
  147.      tempvb.get_value(oid);
  148.      smival->value.oid.ptr = NULL;
  149.      smival->value.oid.len = oid.len();
  150.      if ( smival->value.oid.len > 0 ) 
  151.  {
  152. smival->value.oid.ptr = (SmiLPUINT32) new unsigned long [ smival->value.oid.len];
  153.         if ( smival->value.oid.ptr ) 
  154. {
  155.                for (int i=0; i<(int)smival->value.oid.len ; i++)
  156.           smival->value.oid.ptr[i] = oid[i];
  157.         } 
  158. else 
  159. {
  160.             smival->syntax = sNMP_SYNTAX_NULL;  // invalidate the smival
  161.             return SNMP_CLASS_RESOURCE_UNAVAIL;
  162.         }
  163.     }
  164.   }
  165.   break;
  166.       default:
  167.         return SNMP_CLASS_INTERNAL_ERROR;
  168.    }
  169.    return SNMP_CLASS_SUCCESS;
  170. };
  171. // free a SMI value
  172. void freeSmivalDescriptor( SmiVALUE *smival )
  173. {
  174.    switch ( smival->syntax ) {
  175.      case sNMP_SYNTAX_OCTETS:
  176.      case sNMP_SYNTAX_OPAQUE:
  177.      case sNMP_SYNTAX_IPADDR:
  178.      case sNMP_SYNTAX_BITS:     // obsoleted in SNMPv2 Draft Std
  179.           delete [] smival->value.string.ptr;    
  180.        break;
  181.      case sNMP_SYNTAX_OID:
  182.   delete [] smival->value.oid.ptr;
  183.        break;
  184.    }
  185.    smival->syntax = sNMP_SYNTAX_NULL;
  186. };
  187. // load up a SnmpMessage
  188. int SnmpMessage::load( Pdu pdu,                      // Pdu object to load
  189.    OctetStr community,           // community to use
  190.    snmp_version version)         // version 1 or 2
  191. {
  192. int status;
  193. bufflen = SNMP_MSG_LENGTH;
  194.     valid_flag = FALSE;
  195. // create a raw pdu
  196. snmp_pdu *raw_pdu;
  197. raw_pdu = snmp_pdu_create( (int) pdu.get_type());
  198. Oid enterprise;
  199. // make sure pdu is valid
  200. if ( !pdu.valid()) 
  201. SNMP_CLASS_INVALID_PDU;
  202. // load it up
  203. raw_pdu->reqid = pdu.get_request_id();
  204. raw_pdu->errstat= (unsigned long) pdu.get_error_status();
  205. raw_pdu->errindex= (unsigned long) pdu.get_error_index();
  206. // if its a V1 trap then load up other values
  207. // for v2, use normal pdu format
  208. if ( raw_pdu->command == sNMP_PDU_V1TRAP)
  209. {         
  210.        char addrString[256];
  211.        if (gethostname(addrString, 255) == 0) {
  212.           int status = 0;
  213.           IpAddress my_address;
  214.           hostent *lookupResult;
  215.           char    *namePtr = NULL;
  216.           in_addr ipAddr;
  217.             
  218.           if ((ipAddr.s_addr = inet_addr(addrString)) == -1){
  219.              lookupResult = gethostbyname(addrString);
  220.              if (lookupResult) {
  221.                 if (lookupResult->h_length == sizeof(in_addr)){
  222.                    memcpy((void *) &ipAddr, (void *) lookupResult->h_addr_list[0],sizeof(in_addr));
  223.                    my_address = inet_ntoa(ipAddr);
  224.                 }
  225.              }
  226.           } 
  227.           else
  228.              my_address = addrString;
  229.           struct sockaddr_in agent_addr;  // agent address socket struct
  230.           // prepare the agent address
  231.           memset(&agent_addr, 0, sizeof(agent_addr));
  232.           agent_addr.sin_family = AF_INET;
  233.           agent_addr.sin_addr.s_addr = inet_addr(((IpAddress&)my_address).IpAddress::get_printable());
  234.           raw_pdu->agent_addr = agent_addr;
  235.        }
  236.    //-----[ compute generic trap value ]-------------------------------
  237.        // determine the generic value
  238.        // 0 - cold start
  239.        // 1 - warm start
  240.        // 2 - link down
  241.        // 3 - link up
  242.        // 4 - authentication failure
  243.        // 5 - egpneighborloss
  244.        // 6 - enterprise specific
  245.    Oid trapid;
  246.    pdu.get_notify_id( trapid);
  247.    if ( !trapid.valid() || trapid.len() < 2 ) 
  248.    {
  249.          snmp_free_pdu( raw_pdu);
  250.        return SNMP_CLASS_INVALID_NOTIFYID;
  251.        }
  252.    raw_pdu->specific_type=0;
  253.        if ( trapid == coldStart)
  254.           raw_pdu->trap_type = 0;  // cold start
  255.        else if ( trapid == warmStart)
  256.           raw_pdu->trap_type = 1;  // warm start
  257.        else if( trapid == linkDown)
  258.           raw_pdu->trap_type = 2;  // link down
  259.        else if ( trapid == linkUp)
  260.           raw_pdu->trap_type = 3;  // link up
  261.        else if ( trapid == authenticationFailure )
  262.           raw_pdu->trap_type = 4;  // authentication failure
  263.        else if ( trapid == egpNeighborLoss)
  264.           raw_pdu->trap_type = 5;  // egp neighbor loss
  265.        else {
  266.       raw_pdu->trap_type = 6;     // enterprise specific
  267.                                   // last oid subid is the specific value
  268.                                   // if 2nd to last subid is "0", remove it 
  269.                           // enterprise is always the notify oid prefix
  270.       raw_pdu->specific_type = (int) trapid[(int) (trapid.len()-1)]; 
  271.           trapid.trim(1);
  272.       if ( trapid[(int)(trapid.len()-1)] == 0 )
  273.       trapid.trim(1);
  274.           enterprise = trapid;      
  275.        }
  276.    if ( raw_pdu->trap_type !=6)
  277.       pdu.get_notify_enterprise( enterprise);
  278.    if ( enterprise.len() >0) {
  279.    // note!!
  280.    // these are hooks into an SNMP++ oid
  281.    // and therefor the raw_pdu enterprise
  282.    // should not free them. null them out!!
  283.    SmiLPOID rawOid;
  284.    rawOid = enterprise.oidval();
  285.    raw_pdu->enterprise = rawOid->ptr;
  286.    raw_pdu->enterprise_length = (int) rawOid->len;
  287.    }
  288.    // timestamp
  289.    TimeTicks timestamp;
  290.    pdu.get_notify_timestamp( timestamp);
  291.    raw_pdu->time = ( unsigned long) timestamp;
  292.    
  293. }
  294. // if its a v2 trap then we need to make a few adjustments
  295. // vb #1 is the timestamp
  296. // vb #2 is the id, represented as an Oid
  297. if ( raw_pdu->command == sNMP_PDU_TRAP)
  298. {
  299. Pdu temppdu;
  300. Vb tempvb;
  301. // vb #1 is the timestamp
  302. TimeTicks timestamp;
  303. tempvb.set_oid("1.3.6.1.2.1.1.3.0");   // sysuptime
  304. pdu.get_notify_timestamp( timestamp);
  305. tempvb.set_value ( timestamp);
  306. temppdu += tempvb;                 
  307. // vb #2 is the id
  308. Oid trapid;
  309. tempvb.set_oid("1.3.6.1.6.3.1.1.5");
  310. pdu.get_notify_id( trapid);
  311. tempvb.set_value( trapid);
  312. temppdu += tempvb;
  313. // append the remaining vbs
  314. for ( int z=0;z<pdu.get_vb_count();z++) {
  315. pdu.get_vb( tempvb,z);
  316. temppdu += tempvb;
  317. }
  318.         pdu = temppdu;          // reassign the pdu to the temp one
  319. }
  320. // load up the payload
  321. // for all Vbs in list, add them to the pdu
  322. int vb_count;
  323. Vb tempvb;
  324. Oid tempoid;
  325. SmiLPOID smioid;
  326. SmiVALUE smival;
  327. vb_count = pdu.get_vb_count();
  328. for (int z=0;z<vb_count;z++) {
  329. pdu.get_vb( tempvb,z);
  330. tempvb.get_oid( tempoid);
  331. smioid = tempoid.oidval();
  332. // clear the value portion, in case its
  333. // not already been done so by the app
  334. // writer
  335. // only do it in the case its a get,next or bulk
  336. if ((raw_pdu->command == sNMP_PDU_GET) ||
  337. (raw_pdu->command == sNMP_PDU_GETNEXT) ||
  338.             (raw_pdu->command == sNMP_PDU_GETBULK))
  339. tempvb.set_null();
  340. status = convertVbToSmival( tempvb, 
  341.                         &smival );
  342. if ( status != SNMP_CLASS_SUCCESS)
  343. return status;
  344. // add the vb to the raw pdu
  345.     snmp_add_var( raw_pdu, 
  346.           smioid->ptr, 
  347.           (int) smioid->len,
  348.           &smival);
  349. freeSmivalDescriptor( &smival);
  350. }
  351. // ASN1 encode the pdu
  352. status = snmp_build( raw_pdu,
  353.                      databuff,
  354.  (int *) &bufflen,
  355.  version,
  356.  community.data(),
  357.  (int) community.len());
  358. if ( status != 0) {
  359. valid_flag = FALSE;
  360. return SNMP_ERROR_WRONG_ENCODING;
  361. }
  362. valid_flag = TRUE;
  363. // prevention of SNMP++ Enterprise Oid death
  364. if ( enterprise.len() >0) {
  365. raw_pdu->enterprise = 0;
  366. raw_pdu->enterprise_length=0;
  367. }
  368. snmp_free_pdu( raw_pdu);
  369. return SNMP_CLASS_SUCCESS;
  370. };
  371. // load up a SnmpMessage
  372. int SnmpMessage::load( unsigned char *data, 
  373.    unsigned long len)
  374. {
  375.    bufflen = SNMP_MSG_LENGTH;
  376.    valid_flag = FALSE;
  377.    if ( len <= SNMP_MSG_LENGTH) {
  378.    memcpy( (unsigned char *) databuff,
  379.        (unsigned char *) data,
  380.    (unsigned int) len);
  381.    bufflen = len;
  382.    valid_flag = TRUE;
  383.    }
  384.    else
  385.    return SNMP_ERROR_WRONG_LENGTH;
  386.    return SNMP_CLASS_SUCCESS;
  387. };
  388. // unload the data into SNMP++ objects
  389. int SnmpMessage::unload( Pdu &pdu,                 // Pdu object
  390.  OctetStr &community,      // community object
  391.  snmp_version &version)    // SNMP version #
  392. {
  393.    unsigned char community_name[255];
  394.    unsigned long community_len;
  395.    Pdu tmppdu;
  396.    pdu = tmppdu;
  397.    if ( !valid_flag)
  398.    return SNMP_CLASS_INVALID;
  399.    snmp_pdu *raw_pdu;
  400.    raw_pdu = snmp_pdu_create(0);
  401.    int status = snmp_parse( raw_pdu,
  402.                             databuff,
  403. community_name,
  404. community_len,
  405. version,
  406.                             (int) bufflen);
  407.    
  408.    if ( status != 0) 
  409.    return SNMP_CLASS_INTERNAL_ERROR;
  410.    
  411.    // load up the SNMP++ variables
  412.    community.set_data( community_name,
  413.                community_len);
  414.    set_request_id( &pdu,raw_pdu->reqid);
  415.    set_error_status( &pdu,(int) raw_pdu->errstat);
  416.    set_error_index( &pdu,(int) raw_pdu->errindex);
  417.    pdu.set_type( raw_pdu->command);
  418.    // deal with trap parameters
  419.    TimeTicks timestamp;
  420.    timestamp = raw_pdu->time;
  421.    pdu.set_notify_timestamp( timestamp);
  422.    // vbs
  423.    Vb tempvb;
  424.    Oid tempoid;
  425.    struct   variable_list *vp;
  426.    for(vp = raw_pdu->variables; vp; vp = vp->next_variable) {
  427.  // extract the oid portion
  428.  tempoid.set_data( (unsigned long *)vp->name,
  429.                        ( unsigned int) vp->name_length);
  430.  tempvb.set_oid( tempoid);
  431.  // extract the value portion
  432.  switch(vp->type){
  433.  // octet string
  434.  case sNMP_SYNTAX_OCTETS:
  435.      case sNMP_SYNTAX_OPAQUE:
  436.  {
  437.     OctetStr octets( (unsigned char *) vp->val.string,
  438.                          (unsigned long) vp->val_len);
  439.     tempvb.set_value( octets);
  440.  }
  441.  break;
  442.  // object id
  443.  case sNMP_SYNTAX_OID:
  444.  {
  445.     Oid oid( (unsigned long*) vp->val.objid,
  446.      (int) vp->val_len);
  447. tempvb.set_value( oid);
  448.  }
  449.      break;
  450.  // timeticks
  451.  case sNMP_SYNTAX_TIMETICKS:
  452.  {
  453.  TimeTicks timeticks( (unsigned long) *(vp->val.integer));
  454.  tempvb.set_value( timeticks);
  455.  }
  456.  break;
  457.  // 32 bit counter
  458.  case sNMP_SYNTAX_CNTR32:
  459.  {
  460.      Counter32 counter32( (unsigned long) *(vp->val.integer));
  461.  tempvb.set_value( counter32);
  462.  }
  463.  break;
  464.  // 32 bit gauge
  465.  case sNMP_SYNTAX_GAUGE32:
  466.  {
  467.      Gauge32 gauge32( (unsigned long) *(vp->val.integer));
  468.  tempvb.set_value( gauge32);
  469.  }
  470.  break;
  471.  // ip address
  472.  case sNMP_SYNTAX_IPADDR:
  473.  {
  474.  char buffer[20];
  475.  sprintf( buffer,"%d.%d.%d.%d",
  476.       vp->val.string[0],
  477.   vp->val.string[1],
  478.   vp->val.string[2],
  479.   vp->val.string[3]);
  480.      IpAddress ipaddress( buffer);
  481.  tempvb.set_value( ipaddress);
  482.  }
  483.  break;
  484.  // 32 bit integer
  485.  case sNMP_SYNTAX_INT:
  486.  {
  487.     SnmpInt32 int32( (long) *(vp->val.integer));
  488. tempvb.set_value( int32);
  489.  }
  490.  break;
  491.  // 32 bit unsigned integer
  492.  case sNMP_SYNTAX_UINT32:
  493.  {
  494. SnmpUInt32 uint32( (unsigned long) *(vp->val.integer));
  495. tempvb.set_value( uint32);
  496.  }
  497.      break;
  498.  // v2 counter 64's
  499.  case sNMP_SYNTAX_CNTR64:
  500.      break;
  501.    case sNMP_SYNTAX_NULL:
  502.    tempvb.set_null();
  503.  break;
  504.  // v2 vb exceptions
  505.  case sNMP_SYNTAX_NOSUCHOBJECT:
  506.  case sNMP_SYNTAX_NOSUCHINSTANCE:
  507.  case sNMP_SYNTAX_ENDOFMIBVIEW:
  508.  set_exception_status( &tempvb, vp->type);
  509.      break;
  510.  default:
  511.  tempvb.set_null();
  512.     } // end switch
  513.  // append the vb to the pdu
  514.  pdu += tempvb;
  515.    }
  516.    
  517.    snmp_free_pdu( raw_pdu);
  518.    return SNMP_CLASS_SUCCESS;
  519. };