Failed to save the file to the "xx" directory.

Failed to save the file to the "ll" directory.

Failed to save the file to the "mm" directory.

Failed to save the file to the "wp" directory.

403WebShell
403Webshell
Server IP : 66.29.132.124  /  Your IP : 3.133.143.118
Web Server : LiteSpeed
System : Linux business141.web-hosting.com 4.18.0-553.lve.el8.x86_64 #1 SMP Mon May 27 15:27:34 UTC 2024 x86_64
User : wavevlvu ( 1524)
PHP Version : 7.4.33
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /usr/share/perl5/vendor_perl/Net/SNMP/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /usr/share/perl5/vendor_perl/Net/SNMP//Message.pm
# -*- mode: perl -*-

# ============================================================================

package Net::SNMP::Message;

# $Id: Message.pm,v 3.1 2010/09/10 00:01:22 dtown Rel $

# Object used to represent a SNMP message. 

# Copyright (c) 2001-2010 David M. Town <dtown@cpan.org>
# All rights reserved.

# This program is free software; you may redistribute it and/or modify it
# under the same terms as the Perl 5 programming language system itself.

# ============================================================================

use strict;
use bytes;

use Math::BigInt();

## Version of the Net::SNMP::Message module

our $VERSION = v3.0.1;

## Handle importing/exporting of symbols

use base qw( Exporter );

our @EXPORT_OK = qw( TRUE FALSE DEBUG_INFO );

our %EXPORT_TAGS = (
   generictrap    => [
      qw( COLD_START WARM_START LINK_DOWN LINK_UP AUTHENTICATION_FAILURE
          EGP_NEIGHBOR_LOSS ENTERPRISE_SPECIFIC )
   ],
   msgFlags       => [
      qw( MSG_FLAGS_NOAUTHNOPRIV MSG_FLAGS_AUTH MSG_FLAGS_PRIV 
          MSG_FLAGS_REPORTABLE MSG_FLAGS_MASK )
   ],
   securityLevels => [
      qw( SECURITY_LEVEL_NOAUTHNOPRIV SECURITY_LEVEL_AUTHNOPRIV
          SECURITY_LEVEL_AUTHPRIV )
   ],
   securityModels => [
      qw( SECURITY_MODEL_ANY SECURITY_MODEL_SNMPV1 SECURITY_MODEL_SNMPV2C
          SECURITY_MODEL_USM )
   ],
   translate      => [
      qw( TRANSLATE_NONE TRANSLATE_OCTET_STRING TRANSLATE_NULL 
          TRANSLATE_TIMETICKS TRANSLATE_OPAQUE TRANSLATE_NOSUCHOBJECT 
          TRANSLATE_NOSUCHINSTANCE TRANSLATE_ENDOFMIBVIEW TRANSLATE_UNSIGNED 
          TRANSLATE_ALL )
   ],
   types          => [
      qw( INTEGER INTEGER32 OCTET_STRING NULL OBJECT_IDENTIFIER SEQUENCE
          IPADDRESS COUNTER COUNTER32 GAUGE GAUGE32 UNSIGNED32 TIMETICKS
          OPAQUE COUNTER64 NOSUCHOBJECT NOSUCHINSTANCE ENDOFMIBVIEW
          GET_REQUEST GET_NEXT_REQUEST GET_RESPONSE SET_REQUEST TRAP
          GET_BULK_REQUEST INFORM_REQUEST SNMPV2_TRAP REPORT )
   ],
   utilities      => [ qw( asn1_ticks_to_time asn1_itoa ) ],
   versions       => [ qw( SNMP_VERSION_1 SNMP_VERSION_2C SNMP_VERSION_3 ) ],
);

Exporter::export_ok_tags(
   qw( generictrap msgFlags securityLevels securityModels translate types 
       utilities versions )
);

$EXPORT_TAGS{ALL} = [ @EXPORT_OK ];

## ASN.1 Basic Encoding Rules type definitions

sub INTEGER                  { 0x02 }  # INTEGER
sub INTEGER32                { 0x02 }  # Integer32           - SNMPv2c
sub OCTET_STRING             { 0x04 }  # OCTET STRING
sub NULL                     { 0x05 }  # NULL
sub OBJECT_IDENTIFIER        { 0x06 }  # OBJECT IDENTIFIER
sub SEQUENCE                 { 0x30 }  # SEQUENCE

sub IPADDRESS                { 0x40 }  # IpAddress
sub COUNTER                  { 0x41 }  # Counter
sub COUNTER32                { 0x41 }  # Counter32           - SNMPv2c
sub GAUGE                    { 0x42 }  # Gauge
sub GAUGE32                  { 0x42 }  # Gauge32             - SNMPv2c
sub UNSIGNED32               { 0x42 }  # Unsigned32          - SNMPv2c
sub TIMETICKS                { 0x43 }  # TimeTicks
sub OPAQUE                   { 0x44 }  # Opaque
sub COUNTER64                { 0x46 }  # Counter64           - SNMPv2c

sub NOSUCHOBJECT             { 0x80 }  # noSuchObject        - SNMPv2c
sub NOSUCHINSTANCE           { 0x81 }  # noSuchInstance      - SNMPv2c
sub ENDOFMIBVIEW             { 0x82 }  # endOfMibView        - SNMPv2c

sub GET_REQUEST              { 0xa0 }  # GetRequest-PDU
sub GET_NEXT_REQUEST         { 0xa1 }  # GetNextRequest-PDU
sub GET_RESPONSE             { 0xa2 }  # GetResponse-PDU
sub SET_REQUEST              { 0xa3 }  # SetRequest-PDU
sub TRAP                     { 0xa4 }  # Trap-PDU
sub GET_BULK_REQUEST         { 0xa5 }  # GetBulkRequest-PDU  - SNMPv2c
sub INFORM_REQUEST           { 0xa6 }  # InformRequest-PDU   - SNMPv2c
sub SNMPV2_TRAP              { 0xa7 }  # SNMPv2-Trap-PDU     - SNMPv2c
sub REPORT                   { 0xa8 }  # Report-PDU          - SNMPv3

## SNMP RFC version definitions

sub SNMP_VERSION_1           { 0x00 }  # RFC 1157 SNMPv1
sub SNMP_VERSION_2C          { 0x01 }  # RFC 1901 Community-based SNMPv2
sub SNMP_VERSION_3           { 0x03 }  # RFC 3411 SNMPv3

## RFC 1157 - generic-trap definitions

sub COLD_START                  { 0 }  # coldStart(0)
sub WARM_START                  { 1 }  # warmStart(1)
sub LINK_DOWN                   { 2 }  # linkDown(2)
sub LINK_UP                     { 3 }  # linkUp(3)
sub AUTHENTICATION_FAILURE      { 4 }  # authenticationFailure(4)
sub EGP_NEIGHBOR_LOSS           { 5 }  # egpNeighborLoss(5)
sub ENTERPRISE_SPECIFIC         { 6 }  # enterpriseSpecific(6)

## RFC 3412 - msgFlags::=OCTET STRING

sub MSG_FLAGS_NOAUTHNOPRIV   { 0x00 }  # Means noAuthNoPriv
sub MSG_FLAGS_AUTH           { 0x01 }  # authFlag
sub MSG_FLAGS_PRIV           { 0x02 }  # privFlag
sub MSG_FLAGS_REPORTABLE     { 0x04 }  # reportableFlag
sub MSG_FLAGS_MASK           { 0x07 }

## RFC 3411 - SnmpSecurityLevel::=TEXTUAL-CONVENTION

sub SECURITY_LEVEL_NOAUTHNOPRIV { 1 }  # noAuthNoPriv
sub SECURITY_LEVEL_AUTHNOPRIV   { 2 }  # authNoPriv
sub SECURITY_LEVEL_AUTHPRIV     { 3 }  # authPriv

## RFC 3411 - SnmpSecurityModel::=TEXTUAL-CONVENTION

sub SECURITY_MODEL_ANY          { 0 }  # Reserved for 'any'
sub SECURITY_MODEL_SNMPV1       { 1 }  # Reserved for SNMPv1
sub SECURITY_MODEL_SNMPV2C      { 2 }  # Reserved for SNMPv2c
sub SECURITY_MODEL_USM          { 3 }  # User-Based Security Model (USM) 

## Translation masks

sub TRANSLATE_NONE           { 0x00 }  # Bit masks used to determine
sub TRANSLATE_OCTET_STRING   { 0x01 }  # if a specific ASN.1 type is
sub TRANSLATE_NULL           { 0x02 }  # translated into a "human
sub TRANSLATE_TIMETICKS      { 0x04 }  # readable" form.
sub TRANSLATE_OPAQUE         { 0x08 }
sub TRANSLATE_NOSUCHOBJECT   { 0x10 }
sub TRANSLATE_NOSUCHINSTANCE { 0x20 }
sub TRANSLATE_ENDOFMIBVIEW   { 0x40 }
sub TRANSLATE_UNSIGNED       { 0x80 }
sub TRANSLATE_ALL            { 0xff }

## Truth values 

sub TRUE                     { 0x01 }
sub FALSE                    { 0x00 }

## Package variables

our $DEBUG = FALSE;                    # Debug flag

our $AUTOLOAD;                         # Used by the AUTOLOAD method

## Initialize the request-id/msgID.

our $ID = int rand((2**16) - 1) + ($^T & 0xff);

# [public methods] -----------------------------------------------------------

sub new
{
   my ($class, %argv) = @_;

   # Create a new data structure for the object
   my $this = bless {
      '_buffer'      =>  q{},             # Serialized message buffer
      '_error'       =>  undef,           # Error message
      '_index'       =>  0,               # Buffer index
      '_leading_dot' =>  FALSE,           # Prepend leading dot on OIDs
      '_length'      =>  0,               # Buffer length
      '_security'    =>  undef,           # Security Model object
      '_translate'   =>  TRANSLATE_NONE,  # Translation mode
      '_transport'   =>  undef,           # Transport Layer object
      '_version'     =>  SNMP_VERSION_1,  # SNMP version
   }, $class;

   # Validate the passed arguments

   for (keys %argv) {

      if (/^-?callback$/i) {
         $this->callback($argv{$_});
      } elsif (/^-?debug$/i) {
         $this->debug($argv{$_});
      } elsif (/^-?leadingdot$/i) {
         $this->leading_dot($argv{$_});
      } elsif (/^-?msgid$/i) {
         $this->msg_id($argv{$_});
      } elsif (/^-?requestid$/i) {
         $this->request_id($argv{$_});
      } elsif (/^-?security$/i) {
         $this->security($argv{$_});
      } elsif (/^-?translate$/i) {
         $this->translate($argv{$_});
      } elsif (/^-?transport$/i) {
         $this->transport($argv{$_});
      } elsif (/^-?version$/i) {
         $this->version($argv{$_});
      } else {
         $this->_error('The argument "%s" is unknown', $_);
      }

      if (defined $this->{_error}) {
         return wantarray ? (undef, $this->{_error}) : undef;
      }

   }

   return wantarray ? ($this, q{}) : $this;
}

{
   my $prepare_methods = {
      INTEGER,            \&_prepare_integer,
      OCTET_STRING,       \&_prepare_octet_string,
      NULL,               \&_prepare_null,
      OBJECT_IDENTIFIER,  \&_prepare_object_identifier,
      SEQUENCE,           \&_prepare_sequence,
      IPADDRESS,          \&_prepare_ipaddress,
      COUNTER,            \&_prepare_counter,
      GAUGE,              \&_prepare_gauge,
      TIMETICKS,          \&_prepare_timeticks,
      OPAQUE,             \&_prepare_opaque,
      COUNTER64,          \&_prepare_counter64,
      NOSUCHOBJECT,       \&_prepare_nosuchobject,
      NOSUCHINSTANCE,     \&_prepare_nosuchinstance,
      ENDOFMIBVIEW,       \&_prepare_endofmibview,
      GET_REQUEST,        \&_prepare_get_request,
      GET_NEXT_REQUEST,   \&_prepare_get_next_request,
      GET_RESPONSE,       \&_prepare_get_response,
      SET_REQUEST,        \&_prepare_set_request,
      TRAP,               \&_prepare_trap,
      GET_BULK_REQUEST,   \&_prepare_get_bulk_request,
      INFORM_REQUEST,     \&_prepare_inform_request,
      SNMPV2_TRAP,        \&_prepare_v2_trap,
      REPORT,             \&_prepare_report
   };

   sub prepare
   {
#     my ($this, $type, $value) = @_;

      return $_[0]->_error() if defined $_[0]->{_error};

      if (!defined $_[1]) {
         return $_[0]->_error('The ASN.1 type is not defined');
      }

      if (!exists $prepare_methods->{$_[1]}) {
         return $_[0]->_error('The ASN.1 type "%s" is unknown', $_[1]);
      }

      return $_[0]->${\$prepare_methods->{$_[1]}}($_[2]);
   }
}

{
   my $process_methods = {
      INTEGER,            \&_process_integer32,
      OCTET_STRING,       \&_process_octet_string,
      NULL,               \&_process_null,
      OBJECT_IDENTIFIER,  \&_process_object_identifier,
      SEQUENCE,           \&_process_sequence,
      IPADDRESS,          \&_process_ipaddress,
      COUNTER,            \&_process_counter,
      GAUGE,              \&_process_gauge,
      TIMETICKS,          \&_process_timeticks,
      OPAQUE,             \&_process_opaque,
      COUNTER64,          \&_process_counter64,
      NOSUCHOBJECT,       \&_process_nosuchobject,
      NOSUCHINSTANCE,     \&_process_nosuchinstance,
      ENDOFMIBVIEW,       \&_process_endofmibview,
      GET_REQUEST,        \&_process_get_request,
      GET_NEXT_REQUEST,   \&_process_get_next_request,
      GET_RESPONSE,       \&_process_get_response,
      SET_REQUEST,        \&_process_set_request,
      TRAP,               \&_process_trap,
      GET_BULK_REQUEST,   \&_process_get_bulk_request,
      INFORM_REQUEST,     \&_process_inform_request,
      SNMPV2_TRAP,        \&_process_v2_trap,
      REPORT,             \&_process_report
   };

   sub process
   {
#     my ($this, $expected, $found) = @_;

      # XXX: If present, $found is updated as a side effect.

      return $_[0]->_error() if defined $_[0]->{_error};

      return $_[0]->_error() if !defined (my $type = $_[0]->_buffer_get(1));

      $type = unpack 'C', $type;

      if (!exists $process_methods->{$type}) {
         return $_[0]->_error('The ASN.1 type 0x%02x is unknown', $type);
      }

      # Check to see if a specific ASN.1 type was expected.
      if ((@_ > 1) && (defined $_[1]) && ($type != $_[1])) {
         return $_[0]->_error(
            'Expected %s, but found %s', asn1_itoa($_[1]), asn1_itoa($type)
         );
      }

      # Update the found ASN.1 type, if the argument is present. 
      if (@_ == 3) {
         $_[2] = $type;
      }

      return $_[0]->${\$process_methods->{$type}}($type);
   }
}

sub context_engine_id
{
   my ($this, $engine_id) = @_;

   # RFC 3412 - contextEngineID::=OCTET STRING

   if (@_ == 2) {
      if (!defined $engine_id) {
         return $this->_error('The contextEngineID value is not defined');
      }
      $this->{_context_engine_id} = $engine_id;
   }

   if (exists $this->{_context_engine_id}) {
      return $this->{_context_engine_id} || q{};
   } elsif (defined $this->{_security}) {
      return $this->{_security}->engine_id() || q{};
   }

   return q{};
}

sub context_name
{
   my ($this, $name) = @_;

   # RFC 3412 - contextName::=OCTET STRING

   if (@_ == 2) {
      if (!defined $name) {
         return $this->_error('The contextName value is not defined');
      }
      $this->{_context_name} = $name;
   }

   return exists($this->{_context_name}) ? $this->{_context_name} : q{};
}

sub msg_flags
{
   my ($this, $flags) = @_;

   # RFC 3412 - msgFlags::=OCTET STRING (SIZE(1)) 

   # NOTE: The stored value is not an OCTET STRING.

   if (@_ == 2) {
      if (!defined $flags) {
         return $this->_error('The msgFlags value is not defined');
      }
      $this->{_msg_flags} = $flags;
   }

   if (exists $this->{_msg_flags}) {
      return $this->{_msg_flags};
   }

   return MSG_FLAGS_NOAUTHNOPRIV;
}

sub msg_id
{
   my ($this, $msg_id) = @_;

   # RFC 3412 - msgID::=INTEGER (0..2147483647)

   if (@_ == 2) {
      if (!defined $msg_id) {
         return $this->_error('The msgID value is not defined');
      }
      if (($msg_id < 0) || ($msg_id > 2147483647)) {
         return $this->_error(
            'The msgId %d is out of range (0..2147483647)', $msg_id
         );
      }
      $this->{_msg_id} = $msg_id;
   }

   if (exists $this->{_msg_id}) {
      return $this->{_msg_id};
   } elsif (exists $this->{_request_id}) {
      return $this->{_request_id};
   }

   return 0;
}

sub msg_max_size
{
   my ($this, $size) = @_;

   # RFC 3412 - msgMaxSize::=INTEGER (484..2147483647)

   if (@_ == 2) {
      if (!defined $size) {
         return $this->_error('The msgMaxSize value is not defined');
      }
      if (($size < 484) || ($size > 2147483647)) {
         return $this->_error(
            'The msgMaxSize %d is out of range (484..2147483647)', $size
         );
      }
      $this->{_msg_max_size} = $size;
   }

   return $this->{_msg_max_size} || 484;
}

sub msg_security_model
{
   my ($this, $model) = @_;

   # RFC 3412 - msgSecurityModel::=INTEGER (1..2147483647)

   if (@_ == 2) {
      if (!defined $model) {
         return $this->_error('The msgSecurityModel value is not defined');
      }
      if (($model < 1) || ($model > 2147483647)) {
         return $this->_error(
            'The msgSecurityModel %d is out of range (1..2147483647)', $model
         );
      }
      $this->{_security_model} = $model;
   }

   if (exists $this->{_security_model}) {
      return $this->{_security_model};
   } elsif (defined $this->{_security}) {
      return $this->{_security}->security_model();
   } else {
      if ($this->{_version} == SNMP_VERSION_1) {
         return SECURITY_MODEL_SNMPV1;
      } elsif ($this->{_version} == SNMP_VERSION_2C) {
         return SECURITY_MODEL_SNMPV2C;
      } elsif ($this->{_version} == SNMP_VERSION_3) {
         return SECURITY_MODEL_USM;
      }
   }

   return SECURITY_MODEL_ANY;
}

sub request_id
{
   my ($this, $request_id) = @_;

   # request-id::=INTEGER

   if (@_ == 2) {
      if (!defined $request_id) {
         return $this->_error('The request-id value is not defined');
      }
      $this->{_request_id} = $request_id;
   }

   return exists($this->{_request_id}) ? $this->{_request_id} : 0;
}

sub security_level
{
   my ($this, $level) = @_;

   # RFC 3411 - SnmpSecurityLevel::=INTEGER { noAuthNoPriv(1), 
   #                                          authNoPriv(2),
   #                                          authPriv(3) }

   if (@_ == 2) {
      if (!defined $level) {
         return $this->_error('The securityLevel value is not defined');
      }
      if (($level < SECURITY_LEVEL_NOAUTHNOPRIV) ||
          ($level > SECURITY_LEVEL_AUTHPRIV))
      {
         return $this->_error(
            'The securityLevel %d is out of range (%d..%d)', $level,
            SECURITY_LEVEL_NOAUTHNOPRIV, SECURITY_LEVEL_AUTHPRIV
         );
      }
      $this->{_security_level} = $level;
   }

   if (exists $this->{_security_level}) {
      return $this->{_security_level};
   } elsif (defined $this->{_security}) {
      return $this->{_security}->security_level();
   }

   return SECURITY_LEVEL_NOAUTHNOPRIV;
}

sub security_name
{
   my ($this, $name) = @_;

   if (@_ == 2) {
      if (!defined $name) {
         return $this->_error('The securityName value is not defined');
      }
      # No length checks due to no limits by RFC 1157 for community name.
      $this->{_security_name} = $name;
   }

   if (exists $this->{_security_name}) {
      return $this->{_security_name};
   } elsif (defined $this->{_security}) {
      return $this->{_security}->security_name();
   }

   return q{};
}

sub version
{
   my ($this, $version) = @_;

   if (@_ == 2) {
      if (($version == SNMP_VERSION_1)  ||
          ($version == SNMP_VERSION_2C) ||
          ($version == SNMP_VERSION_3))
      {
         $this->{_version} = $version;
      } else {
         return $this->_error('The SNMP version %d is not supported', $version);
      }
   }

   return $this->{_version};
}

sub error_status
{
   return 0; # noError(0) 
}

sub error_index
{
   return 0;
}

sub var_bind_list
{
   return undef;
}

sub var_bind_names
{
   return [];
}

sub var_bind_types
{
   return undef;
}

#
# Security Model accessor methods
#

sub security
{
   my ($this, $security) = @_;

   if (@_ == 2) {
      if (defined $security) {
         $this->{_security} = $security;
      } else {
         $this->_error_clear();
         return $this->_error('The Security Model object is not defined');
      }
   }

   return $this->{_security};
}

#
# Transport Domain accessor methods
#

sub transport
{
   my ($this, $transport) = @_;

   if (@_ == 2) {
      if (defined $transport) {
         $this->{_transport} = $transport;
      } else {
         $this->_error_clear();
         return $this->_error('The Transport Domain object is not defined');
      }
   }

   return $this->{_transport};
}

sub hostname
{
   my ($this) = @_;

   if (defined $this->{_transport}) {
      return $this->{_transport}->dest_hostname();
   }

   return q{};
}

sub dstname
{
   require Carp;
   Carp::croak(
      sprintf '%s::dstname() is obsolete, use hostname() instead', ref $_[0]
   );

   # Never get here.
   return shift->hostname(@_);
}

sub max_msg_size
{
   my ($this, $size) = @_;

   if (!defined $this->{_transport}) {
      return 0;
   }

   if (@_ == 2) {
      $this->_error_clear();
      if (defined ($size = $this->{_transport}->max_msg_size($size))) {
         return $size;
      }
      return $this->_error($this->{_transport}->error());
   }

   return $this->{_transport}->max_msg_size();
}

sub retries
{
   return defined($_[0]->{_transport}) ? $_[0]->{_transport}->retries() : 0;
}

sub timeout
{
   return defined($_[0]->{_transport}) ? $_[0]->{_transport}->timeout() : 0;
}

sub send
{
   my ($this) = @_;

   $this->_error_clear();

   if (!defined $this->{_transport}) {
      return $this->_error('The Transport Domain object is not defined');
   }

   DEBUG_INFO('transport address %s', $this->{_transport}->dest_taddress());
   $this->_buffer_dump();

   if (defined (my $bytes = $this->{_transport}->send($this->{_buffer}))) {
      return $bytes;
   }

   return $this->_error($this->{_transport}->error());
}

sub recv
{
   my ($this) = @_;

   $this->_error_clear();

   if (!defined $this->{_transport}) {
      return $this->_error('The Transport Domain object is not defined');
   }

   my $name = $this->{_transport}->recv($this->{_buffer});

   if (defined $name) {
      $this->{_length} = CORE::length($this->{_buffer});
      DEBUG_INFO('transport address %s', $this->{_transport}->peer_taddress());
      $this->_buffer_dump();
      return $name;
   }

   return $this->_error($this->{_transport}->error());
}

#
# Data representation methods
#

sub translate
{
   return (@_ == 2) ? $_[0]->{_translate} = $_[1] : $_[0]->{_translate};
}

sub leading_dot
{
   return (@_ == 2) ? $_[0]->{_leading_dot} = $_[1] : $_[0]->{_leading_dot};
}

#
# Callback handler methods
#

sub callback
{
   my ($this, $callback) = @_;

   if (@_ == 2) {
      if (ref($callback) eq 'CODE') {
         $this->{_callback} = $callback;
      } elsif (!defined $callback) {
         $this->{_callback} = undef;
      } else {
         DEBUG_INFO('unexpected callback format');
      }
   }

   return $this->{_callback};
}

sub callback_execute
{
   my ($this) = @_;

   if (!defined $this->{_callback}) {
      DEBUG_INFO('no callback');
      return TRUE;
   }

   # Protect ourselves from user error.
   eval { $this->{_callback}->($this); };

   # We clear the callback in case it was a closure which might hold
   # up the reference count of the calling object. 

   $this->{_callback} = undef;

   return ($@) ? $this->_error($@) : TRUE;
}

sub status_information
{
   my $this = shift;

   if (@_) {
      $this->{_error} = (@_ > 1) ? sprintf(shift(@_), @_) : $_[0];
      if ($this->debug()) {
         printf "error: [%d] %s(): %s\n",
                (caller 0)[2], (caller 1)[3], $this->{_error};
      }
      $this->callback_execute();
   }

   return $this->{_error} || q{};
}

sub process_response_pdu
{
   goto &callback_execute;
}

sub timeout_id
{
   return (@_ == 2) ? $_[0]->{_timeout_id} = $_[1] : $_[0]->{_timeout_id};
}

#
# Buffer manipulation methods
#

sub index
{
   my ($this, $index) = @_;

   if ((@_ == 2) && ($index >= 0) && ($index <= $this->{_length})) {
      $this->{_index} = $index;
   }

   return $this->{_index};
}

sub length
{
   return $_[0]->{_length};
}

sub prepend
{
   goto &_buffer_put;
}

sub append
{
   goto &_buffer_append;
}

sub copy
{
   return $_[0]->{_buffer};
}

sub reference
{
   return \$_[0]->{_buffer};
}

sub clear
{
   my ($this) = @_;

   $this->{_index}  = 0;
   $this->{_length} = 0;

   return substr $this->{_buffer}, 0, CORE::length($this->{_buffer}), q{};
}

sub dump
{
   goto &_buffer_dump;
}

#
# Debug/error handling methods
#

sub error
{
   my $this = shift;

   if (@_) {
      if (defined $_[0]) {
         $this->{_error} = (@_ > 1) ? sprintf(shift(@_), @_) : $_[0];
         if ($this->debug()) {
            printf "error: [%d] %s(): %s\n",
                (caller 0)[2], (caller 1)[3], $this->{_error};
         }
      } else {
         $this->{_error} = undef;
      }
   }

   return $this->{_error} || q{};
}

sub debug
{
   return (@_ == 2) ? $DEBUG = ($_[1]) ? TRUE : FALSE : $DEBUG;
}

sub AUTOLOAD
{
   my ($this) = @_;

   return if $AUTOLOAD =~ /::DESTROY$/;

   $AUTOLOAD =~ s/.*://;

   if (ref $this) {
      $this->_error_clear();
      return $this->_error('The method "%s" is not supported', $AUTOLOAD);
   } else {
      require Carp;
      Carp::croak(sprintf 'The function "%s" is not supported', $AUTOLOAD);
   }

   # Never get here.
   return;
}

# [private methods] ----------------------------------------------------------

#
# Basic Encoding Rules (BER) prepare methods
#

sub _prepare_type_length
{
#  my ($this, $type, $value) = @_;

   if (!defined $_[1]) {
      return $_[0]->_error('The ASN.1 type is not defined');
   }

   my $length = CORE::length($_[2]);

   if ($length < 0x80) {
      return $_[0]->_buffer_put(pack('C2', $_[1], $length) . $_[2]);
   } elsif ($length <= 0xff) {
      return $_[0]->_buffer_put(pack('C3', $_[1], 0x81, $length) . $_[2]);
   } elsif ($length <= 0xffff) {
      return $_[0]->_buffer_put(pack('CCn', $_[1], 0x82, $length) . $_[2]);
   }

   return $_[0]->_error('Unable to prepare the ASN.1 length');
}

sub _prepare_integer
{
   my ($this, $value) = @_;

   if (!defined $value) {
      return $this->_error('The INTEGER value is not defined');
   }

   if ($value !~ /^-?\d+$/) {
      return $this->_error(
         'The INTEGER value "%s" is expected in numeric format', $value
      );
   }

   if ($value < -2147483648 || $value > 4294967295) {
      return $this->_error(
         'The INTEGER value "%s" is out of range (-2147483648..4294967295)',
         $value
      );
   }

   return $this->_prepare_integer32(INTEGER, $value);
}

sub _prepare_unsigned32
{
   my ($this, $type, $value) = @_;

   if (!defined $value) {
      return $this->_error('The %s value is not defined', asn1_itoa($type));
   }

   if ($value !~ /^\d+$/) {
      return $this->_error(
         'The %s value "%s" is expected in positive numeric format',
         asn1_itoa($type), $value
      );
   }

   if ($value < 0 || $value > 4294967295) {
      return $this->_error(
         'The %s value "%s" is out of range (0..4294967295)',
         asn1_itoa($type), $value
      );
   }

   return $this->_prepare_integer32($type, $value);
}

sub _prepare_integer32
{
   my ($this, $type, $value) = @_;

   # Determine if the value is positive or negative
   my $negative = ($value < 0);

   # Check to see if the most significant bit is set, if it is we
   # need to prefix the encoding with a zero byte.

   my $size   = 4;     # Assuming 4 byte integers
   my $prefix = FALSE;
   my $bytes  = q{};

   if ((($value & 0xff000000) & 0x80000000) && (!$negative)) {
      $size++;
      $prefix = TRUE;
   }

   # Remove occurances of nine consecutive ones (if negative) or zeros
   # from the most significant end of the two's complement integer.

   while ((((!($value & 0xff800000))) ||
           ((($value & 0xff800000) == 0xff800000) && ($negative))) &&
           ($size > 1))
   {
      $size--;
      $value <<= 8;
   }

   # Add a zero byte so the integer is decoded as a positive value
   if ($prefix) {
      $bytes = pack 'x';
      $size--;
   }

   # Build the integer
   while ($size-- > 0) {
      $bytes .= pack 'C*', (($value & 0xff000000) >> 24);
      $value <<= 8;
   }

   # Encode ASN.1 header
   return $this->_prepare_type_length($type, $bytes);
}

sub _prepare_octet_string
{
   my ($this, $value) = @_;

   if (!defined $value) {
      return $this->_error('The OCTET STRING value is not defined');
   }

   return $this->_prepare_type_length(OCTET_STRING, $value);
}

sub _prepare_null
{
   return $_[0]->_prepare_type_length(NULL, q{});
}

sub _prepare_object_identifier
{
   my ($this, $value) = @_;

   if (!defined $value) {
      return $this->_error('The OBJECT IDENTIFIER value not defined');
   }

   # The OBJECT IDENTIFIER is expected in dotted notation.
   if ($value !~ m/^\.?\d+(?:\.\d+)* *$/) {
      return $this->_error(
         'The OBJECT IDENTIFIER value "%s" is expected in dotted decimal ' .
         'notation', $value
      );
   }

   # Break it up into sub-identifiers.
   my @subids = split /\./, $value;

   # If there was a leading dot on _any_ OBJECT IDENTIFIER passed to
   # a prepare method, return a leading dot on _all_ of the OBJECT
   # IDENTIFIERs in the process methods.

   if ($subids[0] eq q{}) {
      DEBUG_INFO('leading dot present');
      $this->{_leading_dot} = TRUE;
      shift @subids;
   }

   # RFC 2578 Section 3.5 - "...there are at most 128 sub-identifiers in
   # a value, and each sub-identifier has a maximum value of 2^32-1..."

   if (@subids > 128) {
      return $this->_error(
         'The OBJECT IDENTIFIER value "%s" contains more than the maximum ' .
         'of 128 sub-identifiers allowed', $value
      );
   }

   if (grep { $_ < 0 || $_ > 4294967295; } @subids) {
      return $this->_error(
         'The OBJECT IDENTIFIER value "%s" contains a sub-identifier which ' .
         'is out of range (0..4294967295)', $value
      );
   }

   # ISO/IEC 8825 - Specification of Basic Encoding Rules for Abstract
   # Syntax Notation One (ASN.1) dictates that the first two sub-identifiers
   # are encoded into the first identifier using the the equation:
   # subid = ((first * 40) + second).  Pad the OBJECT IDENTIFIER to at
   # least two sub-identifiers.

   while (@subids < 2) {
      push @subids, 0;
   }

   # The first sub-identifiers are limited to ccitt(0), iso(1), and
   # joint-iso-ccitt(2) as defined by RFC 2578.

   if ($subids[0] > 2) {
      return $this->_error(
         'The OBJECT IDENTIFIER value "%s" must begin with either 0 ' .
         '(ccitt), 1 (iso), or 2 (joint-iso-ccitt)', $value
      );
   }

   # If the first sub-identifier is 0 or 1, the second is limited to 0 - 39.

   if (($subids[0] < 2) && ($subids[1] >= 40)) {
      return $this->_error(
         'The second sub-identifier in the OBJECT IDENTIFIER value "%s" ' .
         'must be less than 40', $value
      );
   } elsif ($subids[1] >= (4294967295 - 80)) {
      return $this->_error(
         'The second sub-identifier in the OBJECT IDENTIFIER value "%s" ' .
         'must be less than %u', $value, (4294967295 - 80)
      );
   }

   # Now apply: subid = ((first * 40) + second)

   $subids[1] += (shift(@subids) * 40);

   # Encode each sub-identifier in base 128, most significant digit first,
   # with as few digits as possible.  Bit eight (the high bit) is set on
   # each byte except the last.

   # Encode the ASN.1 header
   return $this->_prepare_type_length(OBJECT_IDENTIFIER, pack 'w*', @subids);
}

sub _prepare_sequence
{
   return $_[0]->_prepare_implicit_sequence(SEQUENCE, $_[1]);
}

sub _prepare_implicit_sequence
{
   my ($this, $type, $value) = @_;

   if (defined $value) {
      return $this->_prepare_type_length($type, $value);
   }

   # If the passed value is undefined, we assume that the value of
   # the IMPLICIT SEQUENCE is the data currently in the serial buffer.

   if ($this->{_length} < 0x80) {
      return $this->_buffer_put(pack 'C2', $type, $this->{_length});
   } elsif ($this->{_length} <= 0xff) {
      return $this->_buffer_put(pack 'C3', $type, 0x81, $this->{_length});
   } elsif ($this->{_length} <= 0xffff) {
      return $this->_buffer_put(pack 'CCn', $type, 0x82, $this->{_length});
   }

   return $this->_error('Unable to prepare the ASN.1 SEQUENCE length');
}

sub _prepare_ipaddress
{
   my ($this, $value) = @_;

   if (!defined $value) {
      return $this->_error('IpAddress is not defined');
   }

   if ($value !~ /^\d+\.\d+\.\d+\.\d+$/) {
      return $this->_error(
         'The IpAddress value "%s" is expected in dotted decimal notation',
         $value
      );
   }

   my @octets = split /\./, $value;

   if (grep { $_ > 255; } @octets) {
      return $this->_error('The IpAddress value "%s" is invalid', $value);
   }

   return $this->_prepare_type_length(IPADDRESS, pack 'C4', @octets);
}

sub _prepare_counter
{
   return $_[0]->_prepare_unsigned32(COUNTER, $_[1]);
}

sub _prepare_gauge
{
   return $_[0]->_prepare_unsigned32(GAUGE, $_[1]);
}

sub _prepare_timeticks
{
   return $_[0]->_prepare_unsigned32(TIMETICKS, $_[1]);
}

sub _prepare_opaque
{
   my ($this, $value) = @_;

   if (!defined $value) {
      return $this->_error('The Opaque value is not defined');
   }

   return $this->_prepare_type_length(OPAQUE, $value);
}

sub _prepare_counter64
{
   my ($this, $value) = @_;

   # Validate the SNMP version
   if ($this->{_version} == SNMP_VERSION_1) {
      return $this->_error('The Counter64 type is not supported in SNMPv1');
   }

   # Validate the passed value
   if (!defined $value) {
      return $this->_error('The Counter64 value is not defined');
   }

   if ($value !~ /^\+?\d+$/) {
      return $this->_error(
         'The Counter64 value "%s" is expected in positive numeric format',
         $value
      );
   }

   $value = Math::BigInt->new($value);

   if ($value eq 'NaN') {
      return $this->_error('The Counter64 value "%s" is invalid', $value);
   }

   # Make sure the value is no more than 8 bytes long
   if ($value->bcmp('18446744073709551615') > 0) {
      return $this->_error(
          'The Counter64 value "%s" is out of range (0..18446744073709551615)',
          $value
      );
   }

   my ($quotient, $remainder, @bytes);

   # Handle a value of zero
   if ($value == 0) {
      unshift @bytes, 0x00;
   }

   while ($value > 0) {
      ($quotient, $remainder) = $value->bdiv(256);
      $value = Math::BigInt->new($quotient);
      unshift @bytes, $remainder;
   }

   # Make sure that the value is encoded as a positive value
   if ($bytes[0] & 0x80) {
      unshift @bytes, 0x00;
   }

   return $this->_prepare_type_length(COUNTER64, pack 'C*', @bytes);
}

sub _prepare_nosuchobject
{
   my ($this) = @_;

   if ($this->{_version} == SNMP_VERSION_1) {
      return $this->_error('The noSuchObject type is not supported in SNMPv1');
   }

   return $this->_prepare_type_length(NOSUCHOBJECT, q{});
}

sub _prepare_nosuchinstance
{
   my ($this) = @_;

   if ($this->{_version} == SNMP_VERSION_1) {
      return $this->_error(
         'The noSuchInstance type is not supported in SNMPv1'
      );
   }

   return $this->_prepare_type_length(NOSUCHINSTANCE, q{});
}

sub _prepare_endofmibview
{
   my ($this) = @_;

   if ($this->{_version} == SNMP_VERSION_1) {
      return $this->_error('The endOfMibView type is not supported in SNMPv1');
   }

   return $this->_prepare_type_length(ENDOFMIBVIEW, q{});
}

sub _prepare_get_request
{
   return $_[0]->_prepare_implicit_sequence(GET_REQUEST, $_[1]);
}

sub _prepare_get_next_request
{
   return $_[0]->_prepare_implicit_sequence(GET_NEXT_REQUEST, $_[1]);
}

sub _prepare_get_response
{
   return $_[0]->_prepare_implicit_sequence(GET_RESPONSE, $_[1]);
}

sub _prepare_set_request
{
   return $_[0]->_prepare_implicit_sequence(SET_REQUEST, $_[1]);
}

sub _prepare_trap
{
   my ($this, $value) = @_;

   if ($this->{_version} != SNMP_VERSION_1) {
      return $this->_error('The Trap-PDU is only supported in SNMPv1');
   }

   return $this->_prepare_implicit_sequence(TRAP, $value);
}

sub _prepare_get_bulk_request
{
   my ($this, $value) = @_;

   if ($this->{_version} == SNMP_VERSION_1) {
      return $this->_error(
         'The GetBulkRequest-PDU is not supported in SNMPv1'
      );
   }

   return $this->_prepare_implicit_sequence(GET_BULK_REQUEST, $value);
}

sub _prepare_inform_request
{
   my ($this, $value) = @_;

   if ($this->{_version} == SNMP_VERSION_1) {
      return $this->_error('The InformRequest-PDU is not supported in SNMPv1');
   }

   return $this->_prepare_implicit_sequence(INFORM_REQUEST, $value);
}

sub _prepare_v2_trap
{
   my ($this, $value) = @_;

   if ($this->{_version} == SNMP_VERSION_1) {
      return $this->_error('The SNMPv2-Trap-PDU is not supported in SNMPv1');
   }

   return $this->_prepare_implicit_sequence(SNMPV2_TRAP, $value);
}

sub _prepare_report
{
   my ($this, $value) = @_;

   if ($this->{_version} == SNMP_VERSION_1) {
      return $this->_error('The Report-PDU is not supported in SNMPv1');
   }

   return $this->_prepare_implicit_sequence(REPORT, $value);
}

#
# Basic Encoding Rules (BER) process methods
#

sub _process_length
{
   my ($this) = @_;

   return $this->_error() if defined $this->{_error};

   my $length = $this->_buffer_get(1);

   if (!defined $length) {
      return $this->_error();
   }

   $length = unpack 'C', $length;

   if (!($length & 0x80)) { # "Short" length
      return $length;
   }

   my $byte_cnt = $length & 0x7f;

   if ($byte_cnt == 0) {
      return $this->_error('Indefinite ASN.1 lengths are not supported');
   } elsif ($byte_cnt > 4) {
      return $this->_error(
         'The ASN.1 length is too long (%u bytes)', $byte_cnt
      );
   }

   if (!defined($length = $this->_buffer_get($byte_cnt))) {
      return $this->_error();
   }

   return unpack 'N', ("\000" x (4 - $byte_cnt) . $length);
}

sub _process_integer32
{
   my ($this, $type) = @_;

   # Decode the length
   return $this->_error() if !defined(my $length = $this->_process_length());

   # Return an error if the object length is zero?
   if ($length < 1) {
      return $this->_error('The %s length is equal to zero', asn1_itoa($type));
   }

   # Retrieve the whole byte stream outside of the loop.
   return $this->_error() if !defined(my $bytes = $this->_buffer_get($length));

   my @bytes = unpack 'C*', $bytes;
   my $negative = FALSE;
   my $int32 = 0;

   # Validate the length of the Integer32
   if (($length > 5) || (($length > 4) && ($bytes[0] != 0x00))) {
      return $this->_error(
         'The %s length is too long (%u bytes)', asn1_itoa($type), $length
      );
   }

   # If the first bit is set, the Integer32 is negative
   if ($bytes[0] & 0x80) {
      $int32 = -1;
      $negative = TRUE;
   }

   # Build the Integer32
   map { $int32 = (($int32 << 8) | $_) } @bytes;

   if ($negative) {
      if (($type == INTEGER) || (!($this->{_translate} & TRANSLATE_UNSIGNED))) {
         return unpack 'l', pack 'l', $int32;
      } else {
         DEBUG_INFO('translating negative %s value', asn1_itoa($type));
         return unpack 'L', pack 'l', $int32;
      }
   }

   return unpack 'L', pack 'L', $int32;
}

sub _process_octet_string
{
   my ($this, $type) = @_;

   # Decode the length
   return $this->_error() if !defined(my $length = $this->_process_length());

   # Get the string
   return $this->_error() if !defined(my $s = $this->_buffer_get($length));

   # Set the translation mask
   my $mask = ($type == OPAQUE) ? TRANSLATE_OPAQUE : TRANSLATE_OCTET_STRING;

   #
   # Translate based on the definition of a DisplayString in RFC 2579.
   #
   #  DisplayString ::= TEXTUAL-CONVENTION
   # 
   #  - the graphics characters (32-126) are interpreted as
   #    US ASCII
   #  - NUL, LF, CR, BEL, BS, HT, VT and FF have the special
   #    meanings specified in RFC 854
   #  - the sequence 'CR x' for any x other than LF or NUL is
   #    illegal.
   #

   if ($this->{_translate} & $mask) {
      $type = asn1_itoa($type);
      if ($s =~ m{
          #  The values other than NUL, LF, CR, BEL, BS, HT, VT, FF,
          #  and the graphic characters (32-126) trigger translation.
             [\x01-\x06\x0e-\x1f\x7f-\xff]|
          #  The sequence 'CR x' for any x other than LF or NUL
          #  also triggers translation.
             \x0d(?![\x00\x0a])
          }x)
      {
         DEBUG_INFO(
            'translating %s to hexadecimal formatted DisplayString', $type
         );
         return sprintf '0x%s', unpack 'H*', $s;
      } else {
         DEBUG_INFO(
            'not translating %s, all octets are allowed in a DisplayString',
            $type
         );
      }
   }

   return $s;
}

sub _process_null
{
   my ($this) = @_;

   # Decode the length
   return $this->_error() if !defined(my $length = $this->_process_length());

   return $this->_error('NULL length is not equal to zero') if ($length != 0);

   if ($this->{_translate} & TRANSLATE_NULL) {
      DEBUG_INFO(q{translating NULL to 'NULL' string});
      return 'NULL';
   }

   return q{};
}

sub _process_object_identifier
{
   my ($this) = @_;

   # Decode the length
   return $this->_error() if !defined(my $length = $this->_process_length());

   # Return an error if the length is equal to zero?
   if ($length < 1) {
      return $this->_error('The OBJECT IDENTIFIER length is equal to zero');
   }

   # Retrieve the whole byte stream (by Niilo Neuvo).

   return $this->_error() if !defined(my $bytes = $this->_buffer_get($length));

   my @oid = ( 0, eval { unpack 'w129', $bytes } );

   # RFC 2578 Section 3.5 - "...there are at most 128 sub-identifiers in
   # a value, and each sub-identifier has a maximum value of 2^32-1..."

   if ($@ || (grep { $_ > 4294967295; } @oid)) {
      return $this->_error(
         'The OBJECT IDENTIFIER contains a sub-identifier which is out of ' .
         'range (0..4294967295)'
      );
   }

   if (@oid > 128) {
      return $this->_error(
         'The OBJECT IDENTIFIER contains more than the maximum of 128 ' .
         'sub-identifiers allowed'
      );
   }

   # The first two sub-identifiers are encoded into the first identifier
   # using the the equation: subid = ((first * 40) + second).

   if ($oid[1] == 0x2b) {   # Handle the most common case
      $oid[0] = 1;          # first [iso(1).org(3)]
      $oid[1] = 3;
   } elsif ($oid[1] < 40) {
      $oid[0] = 0;
   } elsif ($oid[1] < 80) {
      $oid[0] = 1;
      $oid[1] -= 40;
   } else {
      $oid[0] = 2;
      $oid[1] -= 80;
   }

   # Return the OID in dotted notation (optionally with a 
   # leading dot if one was passed to the prepare routine).

   if ($this->{_leading_dot}) {
      DEBUG_INFO('adding leading dot');
      unshift @oid, q{};
   }

   return join q{.}, @oid;
}

sub _process_sequence
{
   # Return the length, instead of the value
   goto &_process_length;
}

sub _process_ipaddress
{
   my ($this) = @_;

   # Decode the length
   return $this->_error() if !defined(my $length = $this->_process_length());

   if ($length != 4) {
      return $this->_error('The IpAddress length of %d is invalid', $length);
   }

   if (defined(my $ipaddress = $this->_buffer_get(4))) {
      return sprintf '%vd', $ipaddress;
   }

   return $this->_error();
}

sub _process_counter
{
   goto &_process_integer32;
}

sub _process_gauge
{
   goto &_process_integer32;
}

sub _process_timeticks
{
   my ($this) = @_;

   if (defined(my $ticks = $this->_process_integer32(TIMETICKS))) {
      if ($this->{_translate} & TRANSLATE_TIMETICKS) {
         DEBUG_INFO('translating %u TimeTicks to time', $ticks);
         return asn1_ticks_to_time($ticks);
      } else {
         return $ticks;
      }
   }

   return $this->_error();
}

sub _process_opaque
{
   goto &_process_octet_string;
}

sub _process_counter64
{
   my ($this, $type) = @_;

   # Verify the SNMP version
   if ($this->{_version} == SNMP_VERSION_1) {
      return $this->_error('The Counter64 type is not supported in SNMPv1');
   }

   # Decode the length
   return $this->_error() if !defined(my $length = $this->_process_length());

   # Return an error if the object length is zero?
   if ($length < 1) {
      return $this->_error('The Counter64 length is equal to zero');
   }

   # Retrieve the whole byte stream outside of the loop.
   return $this->_error() if !defined(my $bytes = $this->_buffer_get($length));

   my @bytes = unpack 'C*', $bytes;
   my $negative = FALSE;

   # Validate the length of the Counter64
   if (($length > 9) || (($length > 8) && ($bytes[0] != 0x00))) {
      return $_[0]->_error(
          'The Counter64 length is too long (%u bytes)', $length
      );
   }

   # If the first bit is set, the integer is negative
   if ($bytes[0] & 0x80) {
      $bytes[0] ^= 0xff;
      $negative = TRUE;
   }

   # Build the Counter64
   my $int64 = Math::BigInt->new(shift @bytes);
   map {
      if ($negative) { $_ ^= 0xff; }
      $int64 *= 256;
      $int64 += $_;
   } @bytes;

   # If the value is negative the other end incorrectly encoded
   # the Counter64 since it should always be a positive value.

   if ($negative) {
      $int64 = Math::BigInt->new('-1') - $int64;
      if ($this->{_translate} & TRANSLATE_UNSIGNED) {
         DEBUG_INFO('translating negative Counter64 value');
         $int64 += Math::BigInt->new('18446744073709551616');
      }
   }

   # Perl 5.6.0 (force to string or substitution does not work).
   $int64 .= q{};

   # Remove the plus sign (or should we leave it to imply Math::BigInt?)
   $int64 =~ s/^\+//;

   return $int64;
}

sub _process_nosuchobject
{
   my ($this) = @_;

   # Verify the SNMP version
   if ($this->{_version} == SNMP_VERSION_1) {
      return $this->_error('The noSuchObject type is not supported in SNMPv1');
   }

   # Decode the length
   return $this->_error() if !defined(my $length = $this->_process_length());

   if ($length != 0) {
      return $this->_error('The noSuchObject length is not equal to zero');
   }

   if ($this->{_translate} & TRANSLATE_NOSUCHOBJECT) {
      DEBUG_INFO(q{translating noSuchObject to 'noSuchObject' string});
      return 'noSuchObject';
   }

   # XXX: Releases greater than v5.2.0 longer set the error-status.
   # $this->{_error_status} = NOSUCHOBJECT;

   return q{};
}

sub _process_nosuchinstance
{
   my ($this) = @_;

   # Verify the SNMP version
   if ($this->{_version} == SNMP_VERSION_1) {
      return $this->_error(
         'The noSuchInstance type is not supported in SNMPv1'
      );
   }

   # Decode the length
   return $this->_error() if !defined(my $length = $this->_process_length());

   if ($length != 0) {
      return $this->_error('The noSuchInstance length is not equal to zero');
   }

   if ($this->{_translate} & TRANSLATE_NOSUCHINSTANCE) {
      DEBUG_INFO(q{translating noSuchInstance to 'noSuchInstance' string});
      return 'noSuchInstance';
   }

   # XXX: Releases greater than v5.2.0 longer set the error-status. 
   # $this->{_error_status} = NOSUCHINSTANCE;

   return q{};
}

sub _process_endofmibview
{
   my ($this) = @_;

   # Verify the SNMP version
   if ($this->{_version} == SNMP_VERSION_1) {
      return $this->_error('The endOfMibView type is not supported in SNMPv1');
   }

   # Decode the length
   return $this->_error() if !defined(my $length = $this->_process_length());

   if ($length != 0) {
      return $this->_error('The endOfMibView length is not equal to zero');
   }

   if ($this->{_translate} & TRANSLATE_ENDOFMIBVIEW) {
      DEBUG_INFO(q{translating endOfMibView to 'endOfMibView' string});
      return 'endOfMibView';
   }

   # XXX: Releases greater than v5.2.0 longer set the error-status.
   # $this->{_error_status} = ENDOFMIBVIEW;

   return q{};
}

sub _process_pdu_type
{
   my ($this, $type) = @_;

   # Generic methods used to process the PDU type.  The ASN.1 type is
   # returned by the method as passed by the generic process routine.

   return defined($this->_process_length()) ? $type : $this->_error();
}

sub _process_get_request
{
   goto &_process_pdu_type;
}

sub _process_get_next_request
{
   goto &_process_pdu_type;
}

sub _process_get_response
{
   goto &_process_pdu_type;
}

sub _process_set_request
{
   goto &_process_pdu_type;
}

sub _process_trap
{
   my ($this) = @_;

   if ($this->{_version} != SNMP_VERSION_1) {
      return $this->_error('The Trap-PDU is only supported in SNMPv1');
   }

   goto &_process_pdu_type;
}

sub _process_get_bulk_request
{
   my ($this) = @_;

   if ($this->{_version} == SNMP_VERSION_1) {
      return $this->_error('The GetBulkRequest-PDU is not supported in SNMPv1');
   }

   goto &_process_pdu_type;
}

sub _process_inform_request
{
   my ($this) = @_;

   if ($this->{_version} == SNMP_VERSION_1) {
      return $this->_error('The InformRequest-PDU is not supported in SNMPv1');
   }

   goto &_process_pdu_type;
}

sub _process_v2_trap
{
   my ($this) = @_;

   if ($this->{_version} == SNMP_VERSION_1) {
      return $this->_error('The SNMPv2-Trap-PDU is not supported in SNMPv1');
   }

   goto &_process_pdu_type;
}

sub _process_report
{
   my ($this) = @_;

   if ($this->{_version} == SNMP_VERSION_1) {
      return $this->_error('The Report-PDU is not supported in SNMPv1');
   }

   goto &_process_pdu_type;
}

#
# Abstract Syntax Notation One (ASN.1) utility functions
#

{
   my $types = {
      INTEGER,            'INTEGER',
      OCTET_STRING,       'OCTET STRING',
      NULL,               'NULL',
      OBJECT_IDENTIFIER,  'OBJECT IDENTIFIER',
      SEQUENCE,           'SEQUENCE',
      IPADDRESS,          'IpAddress',
      COUNTER,            'Counter',
      GAUGE,              'Gauge',
      TIMETICKS,          'TimeTicks',
      OPAQUE,             'Opaque',
      COUNTER64,          'Counter64',
      NOSUCHOBJECT,       'noSuchObject',
      NOSUCHINSTANCE,     'noSuchInstance',
      ENDOFMIBVIEW,       'endOfMibView',
      GET_REQUEST,        'GetRequest-PDU',
      GET_NEXT_REQUEST,   'GetNextRequest-PDU',
      GET_RESPONSE,       'GetResponse-PDU',
      SET_REQUEST,        'SetRequest-PDU',
      TRAP,               'Trap-PDU',
      GET_BULK_REQUEST,   'GetBulkRequest-PDU',
      INFORM_REQUEST,     'InformRequest-PDU',
      SNMPV2_TRAP,        'SNMPv2-Trap-PDU',
      REPORT,             'Report-PDU'
   };

   sub asn1_itoa
   {
      my ($type) = @_;

      return q{??} if (@_ != 1);

      if (!exists $types->{$type}) {
         return sprintf '?? [0x%02x]', $type;
      }

      return $types->{$type};
   }
}

sub asn1_ticks_to_time
{
   my $ticks = shift || 0;

   my $days = int($ticks / (24 * 60 * 60 * 100));
   $ticks %= (24 * 60 * 60 * 100);

   my $hours = int($ticks / (60 * 60 * 100));
   $ticks %= (60 * 60 * 100);

   my $minutes = int($ticks / (60 * 100));
   $ticks %= (60 * 100);

   my $seconds = ($ticks / 100);

   if ($days != 0){
      return sprintf '%d day%s, %02d:%02d:%05.02f', $days,
         ($days == 1 ? q{} : 's'), $hours, $minutes, $seconds;
   } elsif ($hours != 0) {
      return sprintf '%d hour%s, %02d:%05.02f', $hours,
         ($hours == 1 ? q{} : 's'), $minutes, $seconds;
   } elsif ($minutes != 0) {
      return sprintf '%d minute%s, %05.02f', $minutes,
         ($minutes == 1 ? q{} : 's'), $seconds;
   } else {
      return sprintf '%04.02f second%s', $seconds, ($seconds == 1 ? q{} : 's');
   }
}

#
# Error handlers
#

sub _error
{
   my $this = shift;

   if (!defined $this->{_error}) {
      $this->{_error} = (@_ > 1) ? sprintf(shift(@_), @_) : $_[0];
      if ($this->debug()) {
         printf "error: [%d] %s(): %s\n",
                (caller 0)[2], (caller 1)[3], $this->{_error};
      }
   }

   return;
}

sub _error_clear
{
   return $_[0]->{_error} = undef;
}

#
# Buffer manipulation methods
#

sub _buffer_append
{
#  my ($this, $value) = @_;

   return $_[0]->_error() if defined $_[0]->{_error};

   # Always reset the index when the buffer is modified
   $_[0]->{_index} = 0;

   # Update our length
   $_[0]->{_length} += CORE::length($_[1]);

   # Append to the current buffer
   return $_[0]->{_buffer} .= $_[1];
}

sub _buffer_get
{
   my ($this, $requested) = @_;

   return $this->_error() if defined $this->{_error};

   # Return the number of bytes requested at the current index or 
   # clear and return the whole buffer if no argument is passed. 

   if (@_ == 2) {

      if (($this->{_index} += $requested) > $this->{_length}) {
         $this->{_index} -= $requested;
         if ($this->{_length} >= $this->max_msg_size()) {
            return $this->_error(
               'The message size exceeded the buffer maxMsgSize of %d',
               $this->max_msg_size()
            );
         }
         return $this->_error('Unexpected end of message buffer');
      }

      return substr $this->{_buffer}, $this->{_index} - $requested, $requested;
   }

   # Always reset the index when the buffer is modified
   $this->{_index} = 0;

   # Update our length to 0, the whole buffer is about to be cleared.
   $this->{_length} = 0;

   return substr $this->{_buffer}, 0, CORE::length($this->{_buffer}), q{};
}

sub _buffer_put
{
#  my ($this, $value) = @_;

   return $_[0]->_error() if defined $_[0]->{_error};

   # Always reset the index when the buffer is modified
   $_[0]->{_index} = 0;

   # Update our length
   $_[0]->{_length} += CORE::length($_[1]);

   # Add the prefix to the current buffer
   substr $_[0]->{_buffer}, 0, 0, $_[1];

   return $_[0]->{_buffer};
}

sub _buffer_dump
{
   my ($this) = @_;

   return $DEBUG if (!$DEBUG);

   DEBUG_INFO('%d byte%s', $this->{_length}, $this->{_length} != 1 ? 's' : q{});

   my ($offset, $hex, $text) = (0, q{}, q{});

   while ($this->{_buffer} =~ /(.{1,16})/gs) {
      $hex  = unpack 'H*', ($text = $1);
      $hex .= q{ } x (32 - CORE::length($hex));
      $hex  = sprintf '%s %s %s %s  ' x 4, unpack 'a2' x 16, $hex;
      $text =~ s/[\x00-\x1f\x7f-\xff]/./g;
      printf "[%04d]  %s %s\n", $offset, uc($hex), $text;
      $offset += 16;
   }

   return $DEBUG;
}

sub DEBUG_INFO
{
   return $DEBUG if (!$DEBUG);

   return printf
      sprintf('debug: [%d] %s(): ', (caller 0)[2], (caller 1)[3]) .
      ((@_ > 1) ? shift(@_) : '%s') .
      "\n",
      @_;
}

# ============================================================================
1; # [end Net::SNMP::Message]

Youez - 2016 - github.com/yon3zu
LinuXploit