📄 snmp.pm
字号:
%$this = @_; $this->{ErrorStr} = ''; # if methods return undef check for expln. $this->{ErrorNum} = 0; # contains SNMP error return $this->{Version} ||= NetSNMP::default_store::netsnmp_ds_get_int(NetSNMP::default_store::NETSNMP_DS_LIBRARY_ID, NetSNMP::default_store::NETSNMP_DS_LIB_SNMPVERSION) || SNMP::SNMP_DEFAULT_VERSION(); if ($this->{Version} eq 128) { # special handling of the bogus v1 definition. $this->{Version} = 1; } # allow override of local SNMP port $this->{LocalPort} ||= 0; # destination host defaults to localhost $this->{DestHost} ||= 'localhost'; # community defaults to public $this->{Community} ||= NetSNMP::default_store::netsnmp_ds_get_string(NetSNMP::default_store::NETSNMP_DS_LIBRARY_ID(), NetSNMP::default_store::NETSNMP_DS_LIB_COMMUNITY()) || 'public'; # number of retries before giving up, defaults to SNMP_DEFAULT_RETRIES $this->{Retries} = SNMP::SNMP_DEFAULT_RETRIES() unless defined($this->{Retries}); # timeout before retry, defaults to SNMP_DEFAULT_TIMEOUT $this->{Timeout} = SNMP::SNMP_DEFAULT_TIMEOUT() unless defined($this->{Timeout}); # flag to enable fixing pdu and retrying with a NoSuch error $this->{RetryNoSuch} ||= 0; # backwards compatibility. Make host = host:port if ($this->{RemotePort} && $this->{DestHost} !~ /:/) { $this->{DestHost} = $this->{DestHost} . ":" . $this->{RemotePort}; } if ($this->{Version} eq '1' or $this->{Version} eq '2' or $this->{Version} eq '2c') { $this->{SessPtr} = SNMP::_new_session($this->{Version}, $this->{Community}, $this->{DestHost}, $this->{LocalPort}, $this->{Retries}, $this->{Timeout}, ); } elsif ($this->{Version} eq '3' ) { $this->{SecName} ||= NetSNMP::default_store::netsnmp_ds_get_string(NetSNMP::default_store::NETSNMP_DS_LIBRARY_ID(), NetSNMP::default_store::NETSNMP_DS_LIB_SECNAME()) || 'initial'; if (!$this->{SecLevel}) { $this->{SecLevel} = NetSNMP::default_store::netsnmp_ds_get_int(NetSNMP::default_store::NETSNMP_DS_LIBRARY_ID(), NetSNMP::default_store::NETSNMP_DS_LIB_SECLEVEL()) || $SNMP::V3_SEC_LEVEL_MAP{'noAuthNoPriv'}; } elsif ($this->{SecLevel} !~ /^\d+$/) { $this->{SecLevel} = $SNMP::V3_SEC_LEVEL_MAP{$this->{SecLevel}}; } $this->{SecEngineId} ||= ''; $this->{ContextEngineId} ||= $this->{SecEngineId}; $this->{Context} ||= NetSNMP::default_store::netsnmp_ds_get_string(NetSNMP::default_store::NETSNMP_DS_LIBRARY_ID(), NetSNMP::default_store::NETSNMP_DS_LIB_CONTEXT()) || ''; $this->{AuthProto} ||= 'DEFAULT'; # defaults to the library's default $this->{AuthPass} ||= NetSNMP::default_store::netsnmp_ds_get_string(NetSNMP::default_store::NETSNMP_DS_LIBRARY_ID(), NetSNMP::default_store::NETSNMP_DS_LIB_AUTHPASSPHRASE()) || NetSNMP::default_store::netsnmp_ds_get_string(NetSNMP::default_store::NETSNMP_DS_LIBRARY_ID(), NetSNMP::default_store::NETSNMP_DS_LIB_PASSPHRASE()) || ''; $this->{AuthMasterKey} ||= ''; $this->{PrivMasterKey} ||= ''; $this->{AuthLocalizedKey} ||= ''; $this->{PrivLocalizedKey} ||= ''; $this->{PrivProto} ||= 'DEFAULT'; # defaults to hte library's default $this->{PrivPass} ||= NetSNMP::default_store::netsnmp_ds_get_string(NetSNMP::default_store::NETSNMP_DS_LIBRARY_ID(), NetSNMP::default_store::NETSNMP_DS_LIB_PRIVPASSPHRASE()) || NetSNMP::default_store::netsnmp_ds_get_string(NetSNMP::default_store::NETSNMP_DS_LIBRARY_ID(), NetSNMP::default_store::NETSNMP_DS_LIB_PASSPHRASE()) || ''; $this->{EngineBoots} = 0 if not defined $this->{EngineBoots}; $this->{EngineTime} = 0 if not defined $this->{EngineTime}; $this->{SessPtr} = SNMP::_new_v3_session($this->{Version}, $this->{DestHost}, $this->{Retries}, $this->{Timeout}, $this->{SecName}, $this->{SecLevel}, $this->{SecEngineId}, $this->{ContextEngineId}, $this->{Context}, $this->{AuthProto}, $this->{AuthPass}, $this->{PrivProto}, $this->{PrivPass}, $this->{EngineBoots}, $this->{EngineTime}, $this->{AuthMasterKey}, length($this->{AuthMasterKey}), $this->{PrivMasterKey}, length($this->{PrivMasterKey}), $this->{AuthLocalizedKey}, length($this->{AuthLocalizedKey}), $this->{PrivLocalizedKey}, length($this->{PrivLocalizedKey}), ); } unless ($this->{SessPtr}) { warn("unable to create session") if $SNMP::verbose; return undef; } SNMP::initMib($SNMP::auto_init_mib); # ensures that *some* mib is loaded $this->{UseLongNames} = $SNMP::use_long_names unless exists $this->{UseLongNames}; $this->{UseSprintValue} = $SNMP::use_sprint_value unless exists $this->{UseSprintValue}; $this->{BestGuess} = $SNMP::best_guess unless exists $this->{BestGuess}; $this->{NonIncreasing} ||= $SNMP::non_increasing; $this->{UseEnums} = $SNMP::use_enums unless exists $this->{UseEnums}; $this->{UseNumeric} = $SNMP::use_numeric unless exists $this->{UseNumeric}; # Force UseLongNames if UseNumeric is in use. $this->{UseLongNames}++ if $this->{UseNumeric}; bless $this, $type;}sub update {# *Not Implemented*# designed to update the fields of session to allow retargetting to different# host, community name change, timeout, retry changes etc. Unfortunately not# working yet because some updates (the address in particular) need to be# done on the internal session pointer which cannot be fetched w/o touching# globals at this point which breaks win32. A patch to the net-snmp toolkit# is needed my $this = shift; my ($name, $aliases, $host_type, $len, $thisaddr); my %new_fields = @_; @$this{keys %new_fields} = values %new_fields; $this->{UseLongNames} = $SNMP::use_long_names unless exists $this->{UseLongNames}; $this->{UseSprintValue} = $SNMP::use_sprint_value unless exists $this->{UseSprintValue}; $this->{BestGuess} = $SNMP::best_guess unless exists $this->{BestGuess}; $this->{NonIncreasing} ||= $SNMP::non_increasing; $this->{UseEnums} = $SNMP::use_enums unless exists $this->{UseEnums}; $this->{UseNumeric} = $SNMP::use_numeric unless exists $this->{UseNumeric}; # Force UseLongNames if UseNumeric is in use. $this->{UseLongNames}++ if $this->{UseNumeric}; SNMP::_update_session($this->{Version}, $this->{Community}, $this->{DestHost}, $this->{RemotePort}, $this->{LocalPort}, $this->{Retries}, $this->{Timeout}, );}sub set { my $this = shift; my $vars = shift; my $varbind_list_ref; my $res = 0; if (ref($vars) =~ /SNMP::VarList/) { $varbind_list_ref = $vars; } elsif (ref($vars) =~ /SNMP::Varbind/) { $varbind_list_ref = [$vars]; } elsif (ref($vars) =~ /ARRAY/) { $varbind_list_ref = [$vars]; $varbind_list_ref = $vars if ref($$vars[0]) =~ /ARRAY/; } else { #$varbind_list_ref = [[$tag, $iid, $val]]; my $split_vars = SNMP::split_vars($vars); my $val = shift; push @$split_vars,$val; $varbind_list_ref = [$split_vars]; } my $cb = shift; $res = SNMP::_set($this, $varbind_list_ref, $cb);}sub get { my $this = shift; my $vars = shift; my ($varbind_list_ref, @res); if (ref($vars) =~ /SNMP::VarList/) { $varbind_list_ref = $vars; } elsif (ref($vars) =~ /SNMP::Varbind/) { $varbind_list_ref = [$vars]; } elsif (ref($vars) =~ /ARRAY/) { $varbind_list_ref = [$vars]; $varbind_list_ref = $vars if ref($$vars[0]) =~ /ARRAY/; } else { $varbind_list_ref = [SNMP::split_vars($vars)]; } my $cb = shift; @res = SNMP::_get($this, $this->{RetryNoSuch}, $varbind_list_ref, $cb); return(wantarray() ? @res : $res[0]);}use strict;my $have_netsnmp_oid = eval { require NetSNMP::OID; };sub gettable { # # getTable # -------- # # Get OIDs starting at $table_oid, and continue down the tree # until we get to an OID which does not start with $table_oid, # i.e. we have reached the end of this table. # my $state; my ($this, $root_oid, @options) = @_; $state->{'options'} = {@options}; my ($textnode, $varbinds, $vbl, $res, $repeat); # translate the OID into numeric form if its not if ($root_oid !~ /^[\.0-9]+$/) { $textnode = $root_oid; $root_oid = SNMP::translateObj($root_oid); } else { $textnode = SNMP::translateObj($root_oid); } # bail if we don't have a valid oid. return if (!$root_oid); # deficed if we're going to parse indexes my $parse_indexes = (defined($state->{'options'}{'noindexes'})) ? 0 : $have_netsnmp_oid; # get the list of columns we should look at. my @columns; if (!$state->{'options'}{'columns'}) { if ($textnode) { my %indexes; if ($parse_indexes) { # get indexes my @indexes = @{$SNMP::MIB{$textnode}{'children'}[0]{'indexes'}}; # quick translate into a hash map { $indexes{$_} = 1; } @indexes; } # calculate the list of accessible columns that aren't indexes my $children = $SNMP::MIB{$textnode}{'children'}[0]{'children'}; foreach my $c (@$children) { push @{$state->{'columns'}}, $root_oid . ".1." . $c->{'subID'} if (!$indexes{$c->{'label'}}); } if ($#{$state->{'columns'}} == -1) { # some tables are only indexes, and we need to walk at # least one column. We pick the last. push @{$state->{'columns'}}, $root_oid . ".1." . $children->[$#$children]{'subID'}; } } } else { # XXX: requires specification in numeric OID... ack.! @{$state->{'columns'}} = @{$state->{'options'}{'columns'}}; # if the columns aren't numeric, we need to turn them into # numeric columns... map { if ($_ !~ /\.1\.3/) { $_ = $SNMP::MIB{$_}{'objectID'}; } } @{$state->{'columns'}}; } # create the initial walking info. foreach my $c (@{$state->{'columns'}}) { push @{$state->{'varbinds'}}, [$c]; push @{$state->{'stopconds'}}, $c; } if ($#{$state->{'varbinds'}} == -1) { print STDERR "ack: gettable failed to find any columns to look for.\n"; return; } $vbl = $state->{'varbinds'}; my $repeatcount; if ($this->{Version} == 1 || $state->{'options'}{nogetbulk}) { $state->{'repeatcount'} = 1; } elsif ($state->{'options'}{'repeat'}) { $state->{'repeatcount'} = $state->{'options'}{'repeat'}; } elsif ($#{$state->{'varbinds'}} == -1) { $state->{'repeatcount'} = 1; } else { # experimentally determined maybe guess at a best repeat value # 1000 bytes max (safe), 30 bytes average for encoding of the # varbind (experimentally determined to be closer to # 26. Again, being safe. Then devide by the number of # varbinds. $state->{'repeatcount'} = int(1000 / 36 / ($#{$state->{'varbinds'}} + 1)); } # # if we've been configured with a callback, then call the # sub-functions with a callback to our own "next" processing # function (_gettable_do_it). or else call the blocking method and # call the next processing function ourself. # if ($state->{'options'}{'callback'}) { if ($this->{Version} > 1 && !$state->{'options'}{'nogetbulk'}) { $res = $this->getbulk(0, $state->{'repeatcount'}, $vbl, [\&_gettable_do_it, $this, $vbl, $parse_indexes, $textnode, $state]); } else { $res = $this->getnext($vbl, [\&_gettable_do_it, $this, $vbl, $parse_indexes, $textnode, $state]); } } else { if ($this->{Version} > 1 && !$state->{'options'}{'nogetbulk'}) { $res = $this->getbulk(0, $state->{'repeatcount'}, $vbl); } else { $res = $this->getnext($vbl); } return $this->_gettable_do_it($vbl, $parse_indexes, $textnode, $state); } return 0;}sub _gettable_do_it() { my ($this, $vbl, $parse_indexes, $textnode, $state) = @_; my ($res); $vbl = $_[$#_] if ($state->{'options'}{'callback'}); while ($#$vbl > -1 && !$this->{ErrorNum}) { if (($#$vbl + 1) % ($#{$state->{'stopconds'}} + 1) != 0) { if ($vbl->[$#$vbl][2] ne 'ENDOFMIBVIEW') { # unless it's an end of mib view we didn't get the # proper number of results back. print STDERR "ack: gettable results not appropriate\n"; } my @k = keys(%{$state->{'result_hash'}}); last if ($#k > -1); # bail with what we have return; } $state->{'varbinds'} = []; my $newstopconds; my $lastsetstart = ($state->{'repeatcount'}-1) * ($#{$state->{'stopconds'}}+1); for (my $i = 0; $i <= $#$vbl; $i++) { my $row_oid = SNMP::translateObj($vbl->[$i][0]); my $row_text = $vbl->[$i][0]; my $row_index = $vbl->[$i][1]; my $row_value = $vbl->[$i][2]; my $row_type = $vbl->[$i][3]; if ($row_oid =~ /^$state->{'stopconds'}[$i % ($#{$state->{'stopconds'}}+1)]/ && $row_value ne 'ENDOFMIBVIEW' ){ if ($row_type eq "OBJECTID") { # If the value returned is an OID, translate this # back in to a textual OID $row_value = SNMP::translateObj($row_value); } # Place the results in a hash $state->{'result_hash'}{$row_index}{$row_text} = $row_value; # continue past this next time if ($i >= $lastsetstart) { push @$newstopconds, $state->{'stopconds'}->[$i%($#{$state->{'stopconds'}}+1)]; push @{$state->{'varbinds'}},[$vbl->[$i][0],$vbl->[$i][1]]; } } } if ($#$newstopconds == -1) { last; } if ($#{$state->{'varbinds'}} == -1) { print "gettable ack. shouldn't get here\n"; } $vbl = $state->{'varbinds'}; $state->{'stopconds'} = $newstopconds; # # if we've been configured with a callback, then call the # sub-functions with a callback to our own "next" processing # function (_gettable_do_it). or else call the blocking method and # call the next processing function ourself. #
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -