pdu.cpp
上传用户:cnryan
上传日期:2008-12-15
资源大小:260k
文件大小:14k
- /*_############################################################################
- _##
- _## pdu.cpp
- _##
- _## SNMP++v3.2.21
- _## -----------------------------------------------
- _## Copyright (c) 2001-2006 Jochen Katz, Frank Fock
- _##
- _## This software is based on SNMP++2.6 from Hewlett Packard:
- _##
- _## Copyright (c) 1996
- _## Hewlett-Packard Company
- _##
- _## ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS.
- _## Permission to use, copy, modify, distribute and/or sell this software
- _## and/or its documentation is hereby granted without fee. User agrees
- _## to display the above copyright notice and this license notice in all
- _## copies of the software and any documentation of the software. User
- _## agrees to assume all liability for the use of the software;
- _## Hewlett-Packard and Jochen Katz make no representations about the
- _## suitability of this software for any purpose. It is provided
- _## "AS-IS" without warranty of any kind, either express or implied. User
- _## hereby grants a royalty-free license to any and all derivatives based
- _## upon this software code base.
- _##
- _## Stuttgart, Germany, Fri Jun 16 17:48:57 CEST 2006
- _##
- _##########################################################################*/
- /*===================================================================
- Copyright (c) 1999
- Hewlett-Packard Company
- ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS.
- Permission to use, copy, modify, distribute and/or sell this software
- and/or its documentation is hereby granted without fee. User agrees
- to display the above copyright notice and this license notice in all
- copies of the software and any documentation of the software. User
- agrees to assume all liability for the use of the software; Hewlett-Packard
- makes no representations about the suitability of this software for any
- purpose. It is provided "AS-IS" without warranty of any kind,either express
- or implied. User hereby grants a royalty-free license to any and all
- derivatives based upon this software code base.
- P D U . C P P
- PDU CLASS IMPLEMENTATION
- DESIGN + AUTHOR: Peter E Mellquist
- DESCRIPTION:
- Pdu class implementation. Encapsulation of an SMI Protocol
- Data Unit (PDU) in C++.
- =====================================================================*/
- char pdu_cpp_version[]="@(#) SNMP++ $Id: pdu.cpp,v 1.13 2006/01/07 20:02:34 katz Exp $";
- #include "snmp_pp/pdu.h" // include Pdu class definition
- #include "snmp_pp/usm_v3.h"
- #include "snmp_pp/vb.h"
- #include "snmp_pp/v3.h"
- #ifdef SNMP_PP_NAMESPACE
- namespace Snmp_pp {
- #endif
- #define PDU_INITIAL_SIZE 25
- //=====================[ constructor no args ]=========================
- Pdu::Pdu()
- : vbs(0), vbs_size(0), vb_count(0), error_status(0), error_index(0),
- validity(true), request_id(0), pdu_type(0), notify_timestamp(0),
- v1_trap_address_set(false)
- #ifdef _SNMPv3
- , security_level(SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV),
- message_id(0), maxsize_scopedpdu(0)
- #endif
- {
- }
- //=====================[ constructor with vbs and count ]==============
- Pdu::Pdu(Vb* pvbs, const int pvb_count)
- : vbs(0), vbs_size(0), vb_count(0), error_status(0), error_index(0),
- validity(true), request_id(0), pdu_type(0), notify_timestamp(0),
- v1_trap_address_set(false)
- #ifdef _SNMPv3
- , security_level(SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV),
- message_id(0), maxsize_scopedpdu(0)
- #endif
- {
- if (pvb_count == 0) return; // zero is ok
- vbs = new Vb*[pvb_count];
- if (vbs)
- vbs_size = pvb_count;
- else
- {
- vbs_size = 0;
- validity = false;
- return;
- }
- // loop through and assign internal vbs
- for (int z = 0; z < pvb_count; ++z)
- {
- if (pvbs[z].valid())
- vbs[z] = new Vb(pvbs[z]);
- else
- vbs[z] = 0;
- if ((vbs[z]) && !vbs[z]->valid())
- {
- delete vbs[z];
- vbs[z] = 0;
- }
- if (vbs[z] == 0) // check for new fail
- {
- for (int y = 0; y < z; ++y) delete vbs[y]; // free vbs
- validity = false;
- return;
- }
- }
- vb_count = pvb_count; // assign the vb count
- }
- //=====================[ destructor ]====================================
- Pdu::~Pdu()
- {
- for (int z = 0; z < vb_count; ++z)
- {
- delete vbs[z];
- vbs[z] = 0;
- }
- if (vbs)
- {
- delete [] vbs;
- vbs = 0;
- vbs_size = 0;
- }
- }
- //=====================[ assignment to another Pdu object overloaded ]===
- Pdu& Pdu::operator=(const Pdu &pdu)
- {
- if (this == &pdu) return *this; // check for self assignment
- // Initialize all mv's
- error_status = pdu.error_status;
- error_index = pdu.error_index;
- request_id = pdu.request_id;
- pdu_type = pdu.pdu_type;
- notify_id = pdu.notify_id;
- notify_timestamp = pdu.notify_timestamp;
- notify_enterprise = pdu.notify_enterprise;
- #ifdef _SNMPv3
- security_level = pdu.security_level;
- message_id = pdu.message_id;
- context_name = pdu.context_name;
- context_engine_id = pdu.context_engine_id;
- maxsize_scopedpdu = pdu.maxsize_scopedpdu;
- #endif
- if (pdu.v1_trap_address_set)
- {
- v1_trap_address = pdu.v1_trap_address;
- v1_trap_address_set = true;
- }
- else
- v1_trap_address_set = false;
- validity = true;
- // free up old vbs
- for (int z = 0; z < vb_count; ++z) delete vbs[z];
- vb_count = 0;
- // check for zero case
- if (pdu.vb_count == 0) return *this;
- // allocate array
- if (vbs_size < pdu.vb_count)
- {
- delete [] vbs;
- vbs = new Vb*[pdu.vb_count];
- if (vbs)
- vbs_size = pdu.vb_count;
- else
- {
- vbs_size = 0;
- validity = false;
- return *this;
- }
- }
- // loop through and fill em up
- for (int y = 0; y < pdu.vb_count; ++y)
- {
- vbs[y] = new Vb(*(pdu.vbs[y]));
- if ((vbs[y]) && !vbs[y]->valid())
- {
- delete vbs[y];
- vbs[y] = 0;
- }
- if (!vbs[y])
- {
- for (int x = 0; x < y; ++x) delete vbs[x]; // free vbs
- validity = false;
- return *this;
- }
- }
- vb_count = pdu.vb_count;
- return *this;
- }
- // append operator, appends a variable binding
- Pdu& Pdu::operator+=(const Vb &vb)
- {
- if (!vb.valid()) return *this; // dont add invalid Vbs
- if (vb_count + 1 > vbs_size)
- {
- if (!extend_vbs()) return *this;
- }
- vbs[vb_count] = new Vb(vb); // add the new one
- if (vbs[vb_count]) // up the vb count on success
- {
- if (vbs[vb_count]->valid())
- {
- ++vb_count;
- validity = true; // set up validity
- }
- else
- {
- delete vbs[vb_count];
- vbs[vb_count] = 0;
- }
- }
- return *this; // return self reference
- }
- //=====================[ extract Vbs from Pdu ]==========================
- int Pdu::get_vblist(Vb* pvbs, const int pvb_count) const
- {
- if ((!pvbs) || (pvb_count < 0) || (pvb_count > vb_count))
- return false;
- // loop through all vbs and assign to params
- for (int z = 0; z < pvb_count; ++z)
- {
- pvbs[z] = *vbs[z];
- if (!pvbs[z].valid())
- return false;
- }
- return true;
- }
- //=====================[ deposit Vbs ]===================================
- int Pdu::set_vblist(Vb* pvbs, const int pvb_count)
- {
- // if invalid then don't destroy
- if (((!pvbs) && (pvb_count > 0)) ||
- (pvb_count < 0))
- return false;
- // free up current vbs
- for (int z = 0; z < vb_count; ++z) delete vbs[z];
- vb_count = 0;
- // check for zero case
- if (pvb_count == 0)
- {
- validity = true;
- error_status = 0;
- error_index = 0;
- request_id = 0;
- return false;
- }
- // allocate array
- if (vbs_size < pvb_count)
- {
- delete [] vbs;
- vbs = new Vb*[pvb_count];
- if (vbs)
- vbs_size = pvb_count;
- else
- {
- vbs_size = 0;
- validity = false;
- return false;
- }
- }
- // loop through all vbs and reassign them
- for (int y = 0; y < pvb_count; ++y)
- {
- if (pvbs[y].valid())
- {
- vbs[y] = new Vb(pvbs[y]);
- if ((vbs[y]) && !vbs[y]->valid())
- {
- delete vbs[y];
- vbs[y] = 0;
- }
- }
- else
- vbs[y] = 0;
- // check for errors
- if (!vbs[y])
- {
- for (int x = 0; x < y; ++x) delete vbs[x]; // free vbs
- validity = false;
- return false;
- }
- }
- vb_count = pvb_count;
- // clear error status and index since no longer valid
- // request id may still apply so don't reassign it
- error_status = 0;
- error_index = 0;
- validity = true;
- return true;
- }
- //===================[ get a particular vb ]=============================
- // here the caller has already instantiated a vb object
- // index is zero based
- int Pdu::get_vb(Vb &vb, const int index) const
- {
- if (index < 0) return false; // can't have an index less than 0
- if (index >= vb_count) return false; // can't ask for something not there
- vb = *vbs[index]; // asssign it
- return vb.valid();
- }
- //===================[ set a particular vb ]=============================
- int Pdu::set_vb(Vb &vb, const int index)
- {
- if (index < 0) return false; // can't have an index less than 0
- if (index >= vb_count) return false; // can't ask for something not there
- if (!vb.valid()) return false; // don't set invalid vbs
- Vb *victim = vbs[index]; // save in case new fails
- vbs[index] = new Vb(vb);
- if (vbs[index])
- {
- if (vbs[index]->valid())
- {
- delete victim;
- }
- else
- {
- delete vbs[index];
- vbs[index] = victim;
- return false;
- }
- }
- else
- {
- vbs[index] = victim;
- return false;
- }
- return true;
- }
- // trim off the last vb
- int Pdu::trim(const int count)
- {
- // verify that count is legal
- if ((count < 0) || (count > vb_count)) return false;
- int lp = count;
- while (lp != 0)
- {
- if (vb_count > 0)
- {
- delete vbs[vb_count-1];
- vbs[vb_count-1] = 0;
- vb_count--;
- }
- lp--;
- }
- return true;
- }
- // delete a Vb anywhere within the Pdu
- int Pdu::delete_vb(const int p)
- {
- // position has to be in range
- if ((p<0) || (p > vb_count - 1)) return false;
- delete vbs[p]; // safe to remove it
- for (int z = p; z < vb_count - 1; ++z)
- vbs[z] = vbs[z+1];
- vb_count--;
- return true;
- }
- // Get the SNMPv1 trap address
- int Pdu::get_v1_trap_address(GenAddress &address) const
- {
- if (v1_trap_address_set == false)
- return false;
- address = v1_trap_address;
- return true;
- }
- // Set the SNMPv1 trap address
- int Pdu::set_v1_trap_address(const Address &address)
- {
- v1_trap_address = address;
- v1_trap_address_set = (v1_trap_address.valid() == true);
- return v1_trap_address_set;
- }
- int Pdu::get_asn1_length() const
- {
- int length = 0;
- // length for all vbs
- for (int i = 0; i < vb_count; ++i)
- length += vbs[i]->get_asn1_length();
- // header for vbs
- if (length < 0x80) length += 2;
- else if (length <= 0xFF) length += 3;
- else if (length <= 0xFFFF) length += 4;
- else if (length <= 0xFFFFFF) length += 5;
- else length += 6;
- // req id, error status, error index
- SnmpInt32 i32(request_id ? request_id : PDU_MAX_RID);
- length += i32.get_asn1_length();
- i32 = error_status;
- length += i32.get_asn1_length();
- i32 = error_index;
- length += i32.get_asn1_length();
-
- // header for data_pdu
- if (length < 0x80) length += 2;
- else if (length <= 0xFF) length += 3;
- else if (length <= 0xFFFF) length += 4;
- else if (length <= 0xFFFFFF) length += 5;
- else length += 6;
- #ifdef _SNMPv3
- // now the scopedpdu part sequence (4), context engine, id context name
- length += 4 + 2 + context_engine_id.len() + 2 + context_name.len();
- // An encrypted message is transported as an octet string
- if (security_level == SNMP_SECURITY_LEVEL_AUTH_PRIV)
- {
- // assume that encryption increases the data to a multiple of 16
- int mod = length % 16;
- if (mod) length += 16 - mod;
- length += 4;
- }
- #endif
- return length;
- }
- // extend the vbs array
- bool Pdu::extend_vbs()
- {
- if (vbs_size == 0)
- {
- vbs = new Vb*[PDU_INITIAL_SIZE];
- if (vbs)
- {
- vbs_size = PDU_INITIAL_SIZE;
- return true;
- }
- else
- return false;
- }
- Vb **tmp = vbs;
- vbs = new Vb*[vbs_size * 2];
- if (!vbs)
- {
- vbs = tmp;
- return false;
- }
- for (int y = 0; y < vb_count; ++y)
- vbs[y] = tmp[y];
- vbs_size *= 2;
- delete [] tmp;
- return true;
- }
- // Clear all members of the object
- void Pdu::clear()
- {
- error_status = 0;
- error_index = 0;
- request_id = 0;
- pdu_type = 0;
- notify_timestamp = 0;
- notify_id.clear();
- notify_enterprise.clear();
- v1_trap_address_set = false;
- validity = true;
- for (int z = 0; z < vb_count; ++z) delete vbs[z];
- vb_count = 0;
- #ifdef _SNMPv3
- security_level = SNMP_SECURITY_LEVEL_NOAUTH_NOPRIV;
- message_id = 0;
- maxsize_scopedpdu = 0;
- context_name.clear();
- context_engine_id.clear();
- #endif // _SNMPv3
- }
- // Does the type of response match the type of request
- bool Pdu::match_type(const int request, const int response)
- {
- switch (request)
- {
- case sNMP_PDU_GET:
- case sNMP_PDU_GETNEXT:
- case sNMP_PDU_SET:
- case sNMP_PDU_GETBULK:
- case sNMP_PDU_INFORM:
- {
- if ((response == sNMP_PDU_RESPONSE) ||
- (response == sNMP_PDU_REPORT))
- return true;
- if ((response == sNMP_PDU_GET) ||
- (response == sNMP_PDU_GETNEXT) ||
- (response == sNMP_PDU_SET) ||
- (response == sNMP_PDU_GETBULK) ||
- (response == sNMP_PDU_INFORM) ||
- (response == sNMP_PDU_V1TRAP) ||
- (response == sNMP_PDU_TRAP))
- {
- debugprintf(0, "Unknown response pdu type (%d).", response);
- }
- return false;
- }
- case sNMP_PDU_REPORT:
- case sNMP_PDU_RESPONSE:
- case sNMP_PDU_V1TRAP:
- case sNMP_PDU_TRAP:
- {
- return false;
- }
- default:
- {
- debugprintf(0, "Unknown request pdu type (%d).", request);
- return false;
- }
- }
- }
- #ifdef SNMP_PP_NAMESPACE
- }; // end of namespace Snmp_pp
- #endif