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

SNMP编程

开发平台:

Visual C++

  1. /*_############################################################################
  2.   _## 
  3.   _##  pdu.cpp  
  4.   _##
  5.   _##  SNMP++v3.2.22
  6.   _##  -----------------------------------------------
  7.   _##  Copyright (c) 2001-2007 Jochen Katz, Frank Fock
  8.   _##
  9.   _##  This software is based on SNMP++2.6 from Hewlett Packard:
  10.   _##  
  11.   _##    Copyright (c) 1996
  12.   _##    Hewlett-Packard Company
  13.   _##  
  14.   _##  ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS.
  15.   _##  Permission to use, copy, modify, distribute and/or sell this software 
  16.   _##  and/or its documentation is hereby granted without fee. User agrees 
  17.   _##  to display the above copyright notice and this license notice in all 
  18.   _##  copies of the software and any documentation of the software. User 
  19.   _##  agrees to assume all liability for the use of the software; 
  20.   _##  Hewlett-Packard and Jochen Katz make no representations about the 
  21.   _##  suitability of this software for any purpose. It is provided 
  22.   _##  "AS-IS" without warranty of any kind, either express or implied. User 
  23.   _##  hereby grants a royalty-free license to any and all derivatives based
  24.   _##  upon this software code base. 
  25.   _##  
  26.   _##  Stuttgart, Germany, Wed May  2 23:22:30 CEST 2007 
  27.   _##  
  28.   _##########################################################################*/
  29. /*===================================================================
  30.   Copyright (c) 1999
  31.   Hewlett-Packard Company
  32.   ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS.
  33.   Permission to use, copy, modify, distribute and/or sell this software
  34.   and/or its documentation is hereby granted without fee. User agrees
  35.   to display the above copyright notice and this license notice in all
  36.   copies of the software and any documentation of the software. User
  37.   agrees to assume all liability for the use of the software; Hewlett-Packard
  38.   makes no representations about the suitability of this software for any
  39.   purpose. It is provided "AS-IS" without warranty of any kind,either express
  40.   or implied. User hereby grants a royalty-free license to any and all
  41.   derivatives based upon this software code base.
  42.   P D U . C P P
  43.   PDU CLASS IMPLEMENTATION
  44.   DESIGN + AUTHOR:  Peter E Mellquist
  45.   DESCRIPTION:
  46.   Pdu class implementation. Encapsulation of an SMI Protocol
  47.   Data Unit (PDU) in C++.
  48. =====================================================================*/
  49. char pdu_cpp_version[]="@(#) SNMP++ $Id: pdu.cpp 208 2006-01-07 20:02:34Z katz $";
  50. #include "snmp_pp/pdu.h"       // include Pdu class definition
  51. #include "snmp_pp/usm_v3.h"
  52. #include "snmp_pp/vb.h"
  53. #include "snmp_pp/v3.h"
  54. #ifdef SNMP_PP_NAMESPACE
  55. namespace Snmp_pp {
  56. #endif
  57. #define PDU_INITIAL_SIZE 25
  58. //=====================[ constructor no args ]=========================
  59. Pdu::Pdu()
  60.   : vbs(0), vbs_size(0), vb_count(0), error_status(0), error_index(0),
  61.     validity(true), request_id(0), pdu_type(0), notify_timestamp(0),
  62.     v1_trap_address_set(false)
  63. #ifdef _SNMPv3
  64.     , security_level(SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV),
  65.     message_id(0), maxsize_scopedpdu(0)
  66. #endif
  67. {
  68. }
  69. //=====================[ constructor with vbs and count ]==============
  70. Pdu::Pdu(Vb* pvbs, const int pvb_count)
  71.   : vbs(0), vbs_size(0), vb_count(0), error_status(0), error_index(0),
  72.     validity(true), request_id(0), pdu_type(0), notify_timestamp(0),
  73.     v1_trap_address_set(false)
  74. #ifdef _SNMPv3
  75.     , security_level(SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV),
  76.     message_id(0), maxsize_scopedpdu(0)
  77. #endif
  78. {
  79.   if (pvb_count == 0) return;    // zero is ok
  80.   vbs = new Vb*[pvb_count];
  81.   if (vbs)
  82.     vbs_size = pvb_count;
  83.   else
  84.   {
  85.     vbs_size = 0;
  86.     validity = false;
  87.     return;
  88.   }
  89.   // loop through and assign internal vbs
  90.   for (int z = 0; z < pvb_count; ++z)
  91.   {
  92.     if (pvbs[z].valid())
  93.       vbs[z] = new Vb(pvbs[z]);
  94.     else
  95.       vbs[z] = 0;
  96.     if ((vbs[z]) && !vbs[z]->valid())
  97.     {
  98.       delete vbs[z];
  99.       vbs[z] = 0;
  100.     }
  101.     if (vbs[z] == 0)     // check for new fail
  102.     {
  103.       for (int y = 0; y < z; ++y) delete vbs[y]; // free vbs
  104.       validity = false;
  105.       return;
  106.     }
  107.   }
  108.   vb_count = pvb_count;   // assign the vb count
  109. }
  110. //=====================[ destructor ]====================================
  111. Pdu::~Pdu()
  112. {
  113.   for (int z = 0; z < vb_count; ++z)
  114.   {
  115.     delete vbs[z];
  116.     vbs[z] = 0;
  117.   }
  118.   if (vbs)
  119.   {
  120.     delete [] vbs;
  121.     vbs = 0;
  122.     vbs_size = 0;
  123.   }
  124. }
  125. //=====================[ assignment to another Pdu object overloaded ]===
  126. Pdu& Pdu::operator=(const Pdu &pdu)
  127. {
  128.   if (this == &pdu) return *this; // check for self assignment
  129.   // Initialize all mv's
  130.   error_status      = pdu.error_status;
  131.   error_index       = pdu.error_index;
  132.   request_id        = pdu.request_id;
  133.   pdu_type          = pdu.pdu_type;
  134.   notify_id         = pdu.notify_id;
  135.   notify_timestamp  = pdu.notify_timestamp;
  136.   notify_enterprise = pdu.notify_enterprise;
  137. #ifdef _SNMPv3
  138.   security_level    = pdu.security_level;
  139.   message_id        = pdu.message_id;
  140.   context_name      = pdu.context_name;
  141.   context_engine_id = pdu.context_engine_id;
  142.   maxsize_scopedpdu = pdu.maxsize_scopedpdu;
  143. #endif
  144.   if (pdu.v1_trap_address_set)
  145.   {
  146.     v1_trap_address = pdu.v1_trap_address;
  147.     v1_trap_address_set = true;
  148.   }
  149.   else
  150.     v1_trap_address_set = false;
  151.   validity = true;
  152.   // free up old vbs
  153.   for (int z = 0; z < vb_count; ++z)  delete vbs[z];
  154.   vb_count = 0;
  155.   // check for zero case
  156.   if (pdu.vb_count == 0) return *this;
  157.   // allocate array
  158.   if (vbs_size < pdu.vb_count)
  159.   {
  160.     delete [] vbs;
  161.     vbs = new Vb*[pdu.vb_count];
  162.     if (vbs)
  163.       vbs_size = pdu.vb_count;
  164.     else
  165.     {
  166.       vbs_size = 0;
  167.       validity = false;
  168.       return *this;
  169.     }
  170.   }
  171.   // loop through and fill em up
  172.   for (int y = 0; y < pdu.vb_count; ++y)
  173.   {
  174.     vbs[y] = new Vb(*(pdu.vbs[y]));
  175.     if ((vbs[y]) && !vbs[y]->valid())
  176.     {
  177.       delete vbs[y];
  178.       vbs[y] = 0;
  179.     }
  180.     if (!vbs[y])
  181.     {
  182.       for (int x = 0; x < y; ++x) delete vbs[x]; // free vbs
  183.       validity = false;
  184.       return *this;
  185.     }
  186.   }
  187.   vb_count = pdu.vb_count;
  188.   return *this;
  189. }
  190. // append operator, appends a variable binding
  191. Pdu& Pdu::operator+=(const Vb &vb)
  192. {
  193.   if (!vb.valid())                return *this; // dont add invalid Vbs
  194.   if (vb_count + 1 > vbs_size)
  195.   {
  196.     if (!extend_vbs()) return *this;
  197.   }
  198.   vbs[vb_count] = new Vb(vb);  // add the new one
  199.   if (vbs[vb_count])   // up the vb count on success
  200.   {
  201.     if (vbs[vb_count]->valid())
  202.     {
  203.       ++vb_count;
  204.       validity = true;   // set up validity
  205.     }
  206.     else
  207.     {
  208.       delete vbs[vb_count];
  209.       vbs[vb_count] = 0;
  210.     }
  211.   }
  212.   return *this;        // return self reference
  213. }
  214. //=====================[ extract Vbs from Pdu ]==========================
  215. int Pdu::get_vblist(Vb* pvbs, const int pvb_count) const
  216. {
  217.   if ((!pvbs) || (pvb_count < 0) || (pvb_count > vb_count))
  218.     return false;
  219.   // loop through all vbs and assign to params
  220.   for (int z = 0; z < pvb_count; ++z)
  221.   {
  222.     pvbs[z] = *vbs[z];
  223.     if (!pvbs[z].valid())
  224.       return false;
  225.   }
  226.   return true;
  227. }
  228. //=====================[ deposit Vbs ]===================================
  229. int Pdu::set_vblist(Vb* pvbs, const int pvb_count)
  230. {
  231.   // if invalid then don't destroy
  232.   if (((!pvbs) && (pvb_count > 0)) ||
  233.       (pvb_count < 0))
  234.     return false;
  235.   // free up current vbs
  236.   for (int z = 0; z < vb_count; ++z)  delete vbs[z];
  237.   vb_count = 0;
  238.   // check for zero case
  239.   if (pvb_count == 0)
  240.   {
  241.     validity = true;
  242.     error_status = 0;
  243.     error_index = 0;
  244.     request_id = 0;
  245.     return false;
  246.   }
  247.   // allocate array
  248.   if (vbs_size < pvb_count)
  249.   {
  250.     delete [] vbs;
  251.     vbs = new Vb*[pvb_count];
  252.     if (vbs)
  253.       vbs_size = pvb_count;
  254.     else
  255.     {
  256.       vbs_size = 0;
  257.       validity = false;
  258.       return false;
  259.     }
  260.   }
  261.   // loop through all vbs and reassign them
  262.   for (int y = 0; y < pvb_count; ++y)
  263.   {
  264.     if (pvbs[y].valid())
  265.     {
  266.       vbs[y] = new Vb(pvbs[y]);
  267.       if ((vbs[y]) && !vbs[y]->valid())
  268.       {
  269. delete vbs[y];
  270. vbs[y] = 0;
  271.       }
  272.     }
  273.     else
  274.       vbs[y] = 0;
  275.     // check for errors
  276.     if (!vbs[y])
  277.     {
  278.       for (int x = 0; x < y; ++x) delete vbs[x]; // free vbs
  279.       validity = false;
  280.       return false;
  281.     }
  282.   }
  283.   vb_count = pvb_count;
  284.   // clear error status and index since no longer valid
  285.   // request id may still apply so don't reassign it
  286.   error_status = 0;
  287.   error_index = 0;
  288.   validity = true;
  289.   return true;
  290. }
  291. //===================[ get a particular vb ]=============================
  292. // here the caller has already instantiated a vb object
  293. // index is zero based
  294. int Pdu::get_vb(Vb &vb, const int index) const
  295. {
  296.    if (index < 0)         return false; // can't have an index less than 0
  297.    if (index >= vb_count) return false; // can't ask for something not there
  298.    vb = *vbs[index];   // asssign it
  299.    return vb.valid();
  300. }
  301. //===================[ set a particular vb ]=============================
  302. int Pdu::set_vb(Vb &vb, const int index)
  303. {
  304.   if (index < 0)         return false; // can't have an index less than 0
  305.   if (index >= vb_count) return false; // can't ask for something not there
  306.   if (!vb.valid())       return false; // don't set invalid vbs
  307.   Vb *victim = vbs[index]; // save in case new fails
  308.   vbs[index] = new Vb(vb);
  309.   if (vbs[index])
  310.   {
  311.     if (vbs[index]->valid())
  312.     {
  313.       delete victim;
  314.     }
  315.     else
  316.     {
  317.       delete vbs[index];
  318.       vbs[index] = victim;
  319.       return false;
  320.     }
  321.   }
  322.   else
  323.   {
  324.     vbs[index] = victim;
  325.     return false;
  326.   }
  327.   return true;
  328. }
  329. // trim off the last vb
  330. int Pdu::trim(const int count)
  331. {
  332.   // verify that count is legal
  333.   if ((count < 0) || (count > vb_count)) return false;
  334.   int lp = count;
  335.   while (lp != 0)
  336.   {
  337.     if (vb_count > 0)
  338.     {
  339.       delete vbs[vb_count-1];
  340.       vbs[vb_count-1] = 0;
  341.       vb_count--;
  342.     }
  343.     lp--;
  344.   }
  345.   return true;
  346. }
  347. // delete a Vb anywhere within the Pdu
  348. int Pdu::delete_vb(const int p)
  349. {
  350.   // position has to be in range
  351.   if ((p<0) || (p > vb_count - 1)) return false;
  352.   delete vbs[p];   // safe to remove it
  353.   for (int z = p; z < vb_count - 1; ++z)
  354.     vbs[z] = vbs[z+1];
  355.   vb_count--;
  356.   return true;
  357. }
  358. // Get the SNMPv1 trap address
  359. int Pdu::get_v1_trap_address(GenAddress &address) const
  360. {
  361.   if (v1_trap_address_set == false)
  362.     return false;
  363.   address = v1_trap_address;
  364.   return true;
  365. }
  366. // Set the SNMPv1 trap address
  367. int Pdu::set_v1_trap_address(const Address &address)
  368. {
  369.   v1_trap_address = address;
  370.   v1_trap_address_set = (v1_trap_address.valid() == true);
  371.   return v1_trap_address_set;
  372. }
  373. int Pdu::get_asn1_length() const
  374. {
  375.   int length = 0;
  376.   // length for all vbs
  377.   for (int i = 0; i < vb_count; ++i)
  378.     length += vbs[i]->get_asn1_length();
  379.   // header for vbs
  380.   if      (length < 0x80)      length += 2;
  381.   else if (length <= 0xFF)     length += 3;
  382.   else if (length <= 0xFFFF)   length += 4;
  383.   else if (length <= 0xFFFFFF) length += 5;
  384.   else                         length += 6;
  385.   // req id, error status, error index
  386.   SnmpInt32 i32(request_id ? request_id : PDU_MAX_RID);
  387.   length += i32.get_asn1_length();
  388.   i32 = error_status;
  389.   length += i32.get_asn1_length();
  390.   i32 = error_index;
  391.   length += i32.get_asn1_length();
  392.     
  393.   // header for data_pdu
  394.   if      (length < 0x80)      length += 2;
  395.   else if (length <= 0xFF)     length += 3;
  396.   else if (length <= 0xFFFF)   length += 4;
  397.   else if (length <= 0xFFFFFF) length += 5;
  398.   else                         length += 6;
  399. #ifdef _SNMPv3
  400.   // now the scopedpdu part sequence (4), context engine, id context name
  401.   length += 4 + 2 + context_engine_id.len() + 2 + context_name.len();
  402.   // An encrypted message is transported as an octet string 
  403.   if (security_level == SNMP_SECURITY_LEVEL_AUTH_PRIV)
  404.   {
  405.     // assume that encryption increases the data to a multiple of 16
  406.     int mod = length % 16;
  407.     if (mod) length += 16 - mod;
  408.     length += 4;
  409.   }
  410. #endif
  411.   return length;
  412. }
  413. // extend the vbs array
  414. bool Pdu::extend_vbs()
  415. {
  416.   if (vbs_size == 0)
  417.   {
  418.     vbs = new Vb*[PDU_INITIAL_SIZE];
  419.     if (vbs)
  420.     {
  421.       vbs_size = PDU_INITIAL_SIZE;
  422.       return true;
  423.     }
  424.     else
  425.        return false;
  426.   }
  427.   Vb **tmp = vbs;
  428.   vbs = new Vb*[vbs_size * 2];
  429.   if (!vbs)
  430.   {
  431.     vbs = tmp;
  432.     return false;
  433.   }
  434.   for (int y = 0; y < vb_count; ++y)
  435.     vbs[y] = tmp[y];
  436.   vbs_size *= 2;
  437.   delete [] tmp;
  438.   return true;
  439. }
  440. // Clear all members of the object
  441. void Pdu::clear()
  442. {
  443.   error_status        = 0;
  444.   error_index         = 0;
  445.   request_id          = 0;
  446.   pdu_type            = 0;
  447.   notify_timestamp    = 0;
  448.   notify_id.clear();
  449.   notify_enterprise.clear();
  450.   v1_trap_address_set = false;
  451.   validity            = true;
  452.   for (int z = 0; z < vb_count; ++z)  delete vbs[z];
  453.   vb_count = 0;
  454. #ifdef _SNMPv3
  455.   security_level    = SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV;
  456.   message_id        = 0;
  457.   maxsize_scopedpdu = 0;
  458.   context_name.clear();
  459.   context_engine_id.clear();
  460. #endif // _SNMPv3
  461. }
  462. // Does the type of response match the type of request
  463. bool Pdu::match_type(const int request, const int response)
  464. {
  465.   switch (request)
  466.   {
  467.     case sNMP_PDU_GET:
  468.     case sNMP_PDU_GETNEXT:
  469.     case sNMP_PDU_SET:
  470.     case sNMP_PDU_GETBULK:
  471.     case sNMP_PDU_INFORM:
  472.     {
  473.       if ((response == sNMP_PDU_RESPONSE) ||
  474.   (response == sNMP_PDU_REPORT))
  475. return true;
  476.       if ((response == sNMP_PDU_GET) ||
  477.   (response == sNMP_PDU_GETNEXT) ||
  478.   (response == sNMP_PDU_SET) ||
  479.   (response == sNMP_PDU_GETBULK) ||
  480.   (response == sNMP_PDU_INFORM) ||
  481.   (response == sNMP_PDU_V1TRAP) ||
  482.   (response == sNMP_PDU_TRAP))
  483.       {
  484. debugprintf(0, "Unknown response pdu type (%d).", response);
  485.       }
  486.       return false;
  487.     }
  488.     case sNMP_PDU_REPORT:
  489.     case sNMP_PDU_RESPONSE:
  490.     case sNMP_PDU_V1TRAP:
  491.     case sNMP_PDU_TRAP:
  492.     {
  493.       return false;
  494.     }
  495.     default:
  496.     {
  497.       debugprintf(0, "Unknown request pdu type (%d).", request);
  498.       return false;
  499.     }
  500.   }
  501. }
  502. #ifdef SNMP_PP_NAMESPACE
  503. }; // end of namespace Snmp_pp
  504. #endif