?? snmp_session.pm
字號:
sub index_compare ($$) { my ($i1, $i2) = @_; $i1 = '' unless defined $i1; $i2 = '' unless defined $i2; if ($i1 eq '') { return $i2 eq '' ? 0 : 1; } elsif ($i2 eq '') { return 1; } elsif (!$i1) { return $i2 eq '' ? 1 : !$i2 ? 0 : 1; } elsif (!$i2) { return -1; } else { my ($f1,$r1) = split('\.',$i1,2); my ($f2,$r2) = split('\.',$i2,2); if ($f1 < $f2) { return -1; } elsif ($f1 > $f2) { return 1; } else { return index_compare ($r1,$r2); } }}sub oid_diff ($$) { my($base, $full) = @_; my $base_dotnot = join ('.',@{$base}); my $full_dotnot = BER::pretty_oid ($full); return undef unless substr ($full_dotnot, 0, length $base_dotnot) eq $base_dotnot && substr ($full_dotnot, length $base_dotnot, 1) eq '.'; substr ($full_dotnot, length ($base_dotnot)+1);}sub pretty_address{ my($addr) = shift; my($port,$ipaddr) = unpack_sockaddr_in($addr); return sprintf ("[%s].%d",inet_ntoa($ipaddr),$port);}sub version { $VERSION; }package SNMPv1_Session;use strict qw(vars subs); # see aboveuse vars qw(@ISA);use SNMP_Session;use Socket;use BER;@ISA = qw(SNMP_Session);sub snmp_version { 0 }sub open{ my($this,$remote_hostname,$community,$port, $max_pdu_len,$bind_to_port,$max_repetitions) = @_; my($name,$aliases,$remote_addr,$socket); my $udp_proto = 0; $community = 'public' unless defined $community; $port = SNMP_Session::standard_udp_port unless defined $port; $max_pdu_len = 8000 unless defined $max_pdu_len; $max_repetitions = $default_max_repetitions unless defined $max_repetitions; $remote_addr = inet_aton ($remote_hostname) || return $this->error_return ("can't resolve \"$remote_hostname\" to IP address"); $socket = 'SNMP'.sprintf ("%s:%d", inet_ntoa ($remote_addr), $port); (($name,$aliases,$udp_proto) = getprotobyname('udp')) unless $udp_proto; $udp_proto=17 unless $udp_proto; socket ($socket, PF_INET, SOCK_DGRAM, $udp_proto) || return $this->error_return ("creating socket: $!"); if (defined $bind_to_port) { my $sockaddr = sockaddr_in ($bind_to_port, INADDR_ANY); bind ($socket, $sockaddr) || return $this->error_return ("binding to port $bind_to_port: $!"); } $remote_addr = pack_sockaddr_in ($port, $remote_addr); bless { 'sock' => $socket, 'sockfileno' => fileno ($socket), 'community' => $community, 'remote_hostname' => $remote_hostname, 'remote_addr' => $remote_addr, 'max_pdu_len' => $max_pdu_len, 'pdu_buffer' => '\0' x $max_pdu_len, 'request_id' => int (rand 0x80000000 + rand 0xffff), 'timeout' => $default_timeout, 'retries' => $default_retries, 'backoff' => $default_backoff, 'debug' => $default_debug, 'error_status' => 0, 'error_index' => 0, 'default_max_repetitions' => $max_repetitions, };}sub open_trap_session (@) { my ($this, $port) = @_; $port = 162 unless defined $port; return $this->open ("0.0.0.0", "", 161, undef, $port);}sub sock { $_[0]->{sock} }sub sockfileno { $_[0]->{sockfileno} }sub remote_addr { $_[0]->{remote_addr} }sub pdu_buffer { $_[0]->{pdu_buffer} }sub max_pdu_len { $_[0]->{max_pdu_len} }sub default_max_repetitions { $_[0]->{default_max_repetitions} }sub close{ my($this) = shift; close ($this->sock) || $this->error ("close: $!");}sub wrap_request{ my($this) = shift; my($request) = shift; encode_sequence (encode_int ($this->snmp_version), encode_string ($this->{community}), $request) || return $this->ber_error ("wrapping up request PDU");}my @error_status_code = qw(noError tooBig noSuchName badValue readOnly genErr noAccess wrongType wrongLength wrongEncoding wrongValue noCreation inconsistentValue resourceUnavailable commitFailed undoFailed authorizationError notWritable inconsistentName);sub unwrap_response_5b{ my ($this,$response,$tag,$oids,$errorp) = @_; my ($community,$request_id,@rest,$snmpver); ($snmpver,$community,$request_id, $this->{error_status}, $this->{error_index}, @rest) = decode_by_template ($response, "%{%i%s%*{%i%i%i%{%@", $tag); return $this->ber_error ("Error decoding response PDU") unless defined $snmpver; return $this->error ("Received SNMP response with unknown snmp-version field $snmpver") unless $snmpver == $this->snmp_version; if ($this->{error_status} != 0) { if ($errorp) { my ($oid, $errmsg); $errmsg = $error_status_code[$this->{error_status}] || $this->{error_status}; $oid = $oids->[$this->{error_index}-1] if $this->{error_index} > 0 && $this->{error_index}-1 <= $#{$oids}; $oid = $oid->[0] if ref($oid) eq 'ARRAY'; return ($community, $request_id, $this->error ("Received SNMP response with error code\n" ." error status: $errmsg\n" ." index ".$this->{error_index} .(defined $oid ? " (OID: ".&BER::pretty_oid($oid).")" : ""))); } else { if ($this->{error_index} == 1) { @rest[$this->{error_index}-1..$this->{error_index}] = (); } } } ($community, $request_id, @rest);}sub send_query ($$){ my ($this,$query) = @_; send ($this->sock,$query,0,$this->remote_addr);}sub receive_response_3{ my ($this, $response_tag, $oids, $errorp) = @_; my ($remote_addr); $remote_addr = recv ($this->sock,$this->{'pdu_buffer'},$this->max_pdu_len,0); return $this->error ("receiving response PDU: $!") unless defined $remote_addr; return $this->error ("short (".length $this->{'pdu_buffer'} ." bytes) response PDU") unless length $this->{'pdu_buffer'} > 2; my $response = $this->{'pdu_buffer'}; ## ## Check whether the response came from the address we've sent the ## request to. If this is not the case, we should probably ignore ## it, as it may relate to another request. ## if ($this->{'debug'} && $remote_addr ne $this->{'remote_addr'}) { warn "Response came from ".&SNMP_Session::pretty_address($remote_addr) .", not ".&SNMP_Session::pretty_address($this->{'remote_addr'}) unless $SNMP_Session::suppress_warnings; } $this->{'last_sender_addr'} = $remote_addr; my ($response_community, $response_id, @unwrapped) = $this->unwrap_response_5b ($response, $response_tag, $oids, $errorp); if ($response_community ne $this->{community} || $response_id ne $this->{request_id}) { if ($this->{'debug'}) { warn "$response_community != $this->{community}" unless $SNMP_Session::suppress_warnings || $response_community eq $this->{community}; warn "$response_id != $this->{request_id}" unless $SNMP_Session::suppress_warnings || $response_id == $this->{request_id}; } return 0; } if (!defined $unwrapped[0]) { $this->{'unwrapped'} = undef; return undef; } $this->{'unwrapped'} = \@unwrapped; return length $this->pdu_buffer;}sub receive_trap{ my ($this) = @_; my ($remote_addr, $iaddr, $port, $trap); $remote_addr = recv ($this->sock,$this->{'pdu_buffer'},$this->max_pdu_len,0); return undef unless $remote_addr; ($port, $iaddr) = sockaddr_in($remote_addr); $trap = $this->{'pdu_buffer'}; return ($trap, $iaddr, $port);}sub describe{ my($this) = shift; print $this->to_string (),"\n";}sub to_string{ my($this) = shift; my ($class,$prefix); $class = ref($this); $prefix = ' ' x (length ($class) + 2); ($class." (remote host: \"".$this->{remote_hostname} ."\" ".&SNMP_Session::pretty_address ($this->remote_addr)."\n" .$prefix." community: \"".$this->{'community'}."\"\n" .$prefix." request ID: ".$this->{'request_id'}."\n" .$prefix."PDU bufsize: ".$this->{'max_pdu_len'}." bytes\n" .$prefix." timeout: ".$this->{timeout}."s\n" .$prefix." retries: ".$this->{retries}."\n" .$prefix." backoff: ".$this->{backoff}.")");## sprintf ("SNMP_Session: %s (size %d timeout %g)",## &SNMP_Session::pretty_address ($this->remote_addr),$this->max_pdu_len,## $this->timeout);}### SNMP Agent support### contributed by Mike McCauley <mikem@open.com.au>###sub receive_request{ my ($this) = @_; my ($remote_addr, $iaddr, $port, $request); $remote_addr = recv($this->sock, $this->{'pdu_buffer'}, $this->{'max_pdu_len'}, 0); return undef unless $remote_addr; ($port, $iaddr) = sockaddr_in($remote_addr); $request = $this->{'pdu_buffer'}; return ($request, $iaddr, $port);}sub decode_request{ my ($this, $request) = @_; my ($snmp_version, $community, $requestid, $errorstatus, $errorindex, $bindings); ($snmp_version, $community, $requestid, $errorstatus, $errorindex, $bindings) = decode_by_template ($request, "%{%i%s%*{%i%i%i%@", SNMP_Session::get_request); if (defined $snmp_version) { # Its a valid get_request return(SNMP_Session::get_request, $requestid, $bindings, $community); } ($snmp_version, $community, $requestid, $errorstatus, $errorindex, $bindings) = decode_by_template ($request, "%{%i%s%*{%i%i%i%@", SNMP_Session::getnext_request); if (defined $snmp_version) { # Its a valid getnext_request return(SNMP_Session::getnext_request, $requestid, $bindings, $community); } ($snmp_version, $community, $requestid, $errorstatus, $errorindex, $bindings) = decode_by_template ($request, "%{%i%s%*{%i%i%i%@", SNMP_Session::set_request); if (defined $snmp_version) { # Its a valid set_request return(SNMP_Session::set_request, $requestid, $bindings, $community); } # Something wrong with this packet # Decode failed return undef;}package SNMPv2c_Session;use strict qw(vars subs); # see aboveuse vars qw(@ISA);use SNMP_Session;use BER;@ISA = qw(SNMPv1_Session);sub snmp_version { 1 }sub open{ my $session = SNMPv1_Session::open (@_); return bless $session;}sub map_table_start_end ($$$$$$) { my ($session, $columns, $mapfn, $start, $end, $max_repetitions) = @_; my @encoded_oids; my $call_counter = 0; my $base_index = $start; $max_repetitions = $session->default_max_repetitions unless defined $max_repetitions; do { foreach (@encoded_oids = @{$columns}) { $_=encode_oid (@{$_},split '\.',$base_index) || return $session->ber_error ("encoding OID $base_index"); } if ($session->getbulk_request_response (0, $max_repetitions, @encoded_oids)) { my $response = $session->pdu_buffer; my ($bindings) = $session->decode_get_response ($response); my $smallest_index = undef; my @collected_values = (); my @bases = @{$columns}; my $n_bindings = 0; while ($bindings ne '') { my ($binding, $oid, $value); unless (defined $bases[0]) { @bases = @{$columns}; (++$call_counter, &$mapfn ($smallest_index, @collected_values)) if defined $smallest_index; $base_index = $smallest_index; $smallest_index = undef; @collected_values = (); } my $base = shift @bases; ($binding, $bindings) = decode_sequence ($bindings); ($oid, $value) = decode_by_template ($binding, "%O%@"); my $out_index; ++$n_bindings; $out_index = SNMP_Session::oid_diff ($base, $oid); my $cmp; if (!defined $smallest_index || ($cmp = SNMP_Session::index_compare ($out_index,$smallest_index)) == -1) { $smallest_index = $out_index; grep ($_=undef, @collected_values); push @collected_values, $value; } elsif ($cmp == 1) { push @collected_values, undef; } else { push @collected_values, $value; } } @bases = @{$columns}; (++$call_counter, &$mapfn ($smallest_index, @collected_values)) if defined $smallest_index; $base_index = $smallest_index; $smallest_index = undef; @collected_values = (); } else { return undef; } } while (defined $base_index && (!defined $end || index_compare ($base_index, $end) < 0)); $call_counter;}1;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -