line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
1
|
|
|
1
|
|
549
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
51
|
|
2
|
|
|
|
|
|
|
package NSNMP::Simple; |
3
|
|
|
|
|
|
|
# Copyright (c) 2003-2004 AirWave Wireless, Inc. |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
# Redistribution and use in source and binary forms, with or without |
6
|
|
|
|
|
|
|
# modification, are permitted provided that the following conditions |
7
|
|
|
|
|
|
|
# are met: |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
# 1. Redistributions of source code must retain the above |
10
|
|
|
|
|
|
|
# copyright notice, this list of conditions and the following |
11
|
|
|
|
|
|
|
# disclaimer. |
12
|
|
|
|
|
|
|
# 2. Redistributions in binary form must reproduce the above |
13
|
|
|
|
|
|
|
# copyright notice, this list of conditions and the following |
14
|
|
|
|
|
|
|
# disclaimer in the documentation and/or other materials provided |
15
|
|
|
|
|
|
|
# with the distribution. |
16
|
|
|
|
|
|
|
# 3. The name of the author may not be used to endorse or |
17
|
|
|
|
|
|
|
# promote products derived from this software without specific |
18
|
|
|
|
|
|
|
# prior written permission. |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS |
21
|
|
|
|
|
|
|
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
22
|
|
|
|
|
|
|
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
23
|
|
|
|
|
|
|
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
24
|
|
|
|
|
|
|
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
25
|
|
|
|
|
|
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE |
26
|
|
|
|
|
|
|
# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
27
|
|
|
|
|
|
|
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
28
|
|
|
|
|
|
|
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
29
|
|
|
|
|
|
|
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
30
|
|
|
|
|
|
|
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
31
|
1
|
|
|
1
|
|
952
|
use IO::Socket; |
|
1
|
|
|
|
|
35310
|
|
|
1
|
|
|
|
|
41
|
|
32
|
1
|
|
|
1
|
|
643
|
use NSNMP; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
25
|
|
33
|
1
|
|
|
1
|
|
7
|
use NSNMP::Mapper; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
25
|
|
34
|
1
|
|
|
1
|
|
5
|
use vars qw($error $error_status $socket); |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
66
|
|
35
|
|
|
|
|
|
|
# these are negative so as not to collide with SNMP protocol error numbers, |
36
|
|
|
|
|
|
|
# which count up from 1 |
37
|
1
|
|
|
1
|
|
6
|
use constant noResponse => -1; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
61
|
|
38
|
1
|
|
|
1
|
|
28
|
use constant badHostName => -2; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
1415
|
|
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
=head1 NAME |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
NSNMP::Simple - simple interface to get and set synchronously |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
=head1 SYNOPSIS |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
my $sysnameoid = '1.3.6.1.2.1.1.5.0'; |
47
|
|
|
|
|
|
|
my $hostname = NSNMP::Simple->get('127.0.0.1', $sysnameoid); |
48
|
|
|
|
|
|
|
die $NSNMP::Simple::error unless defined $hostname; |
49
|
|
|
|
|
|
|
NSNMP::Simple->set('127.0.0.1', $sysnameoid, NSNMP::OCTET_STRING, |
50
|
|
|
|
|
|
|
'thor.cs.cmu.edu', community => 'CMUprivate') |
51
|
|
|
|
|
|
|
or die $NSNMP::Simple::error; |
52
|
|
|
|
|
|
|
my %sysoids = NSNMP::Simple->get_table('127.0.0.1', '1.3.6.1.2.1'); |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
=head1 DESCRIPTION |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
NSNMP::Simple lets you get or set a single OID via SNMP with a single |
57
|
|
|
|
|
|
|
line of code. It's easier to use, and roughly an order of magnitude |
58
|
|
|
|
|
|
|
faster, than L 4.1.2, but Net::SNMP is still much |
59
|
|
|
|
|
|
|
more mature and complete. I don't presently recommend using |
60
|
|
|
|
|
|
|
NSNMP::Simple in production code. |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
=head1 MODULE CONTENTS |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
=cut |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
# some speed costs on my 500MHz PIII laptop: |
67
|
|
|
|
|
|
|
# it takes: |
68
|
|
|
|
|
|
|
# 3 microseconds to do a function call and return |
69
|
|
|
|
|
|
|
# 2 microseconds to do a hash lookup on a 20char string |
70
|
|
|
|
|
|
|
# 50 microseconds in the kernel to send a packet and receive a response |
71
|
|
|
|
|
|
|
# 600 microseconds to encode the packet, send it, and receive and |
72
|
|
|
|
|
|
|
# decode the response (in user time) (getsysname-lots.pl) |
73
|
|
|
|
|
|
|
# 150 microseconds to do the socket, address, timeout, and error-status |
74
|
|
|
|
|
|
|
# checking |
75
|
|
|
|
|
|
|
# this module does |
76
|
|
|
|
|
|
|
# another 40 microseconds to do the request_id handling (in the normal case: |
77
|
|
|
|
|
|
|
# request ID matches) |
78
|
|
|
|
|
|
|
# a negligible amount of time to handle retry logic |
79
|
|
|
|
|
|
|
# encoding and decoding of non-OCTET_STRING values |
80
|
|
|
|
|
|
|
# all in all: about 1250 microseconds per request-response pair with this |
81
|
|
|
|
|
|
|
# module |
82
|
|
|
|
|
|
|
# although I still haven't implemented traps, v2 and v3, and handling of |
83
|
|
|
|
|
|
|
# failure to socket; all of these will slow this module down more. |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
# XXX refactor this a little more |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
my ($nfound, $timeleft); |
88
|
|
|
|
|
|
|
sub _read_timeout { |
89
|
717
|
|
|
717
|
|
977
|
my ($fh, $timeout) = @_; |
90
|
717
|
|
|
|
|
840
|
my $rin = ''; |
91
|
717
|
|
|
|
|
3088
|
vec($rin, fileno($fh), 1) = 1; |
92
|
717
|
|
|
|
|
12696625
|
return select($rin, undef, undef, $timeout); |
93
|
|
|
|
|
|
|
} |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
sub _remember_error { |
96
|
13
|
|
|
13
|
|
22
|
my ($response_decoded) = @_; |
97
|
13
|
|
|
|
|
38
|
$error_status = $response_decoded->error_status; |
98
|
13
|
|
|
|
|
104
|
my $error_name = NSNMP->error_description($error_status); |
99
|
13
|
|
|
|
|
76
|
$error = "Received $error_name($error_status) error-status at error-index " |
100
|
|
|
|
|
|
|
. $response_decoded->error_index; |
101
|
13
|
|
|
|
|
102
|
return undef; |
102
|
|
|
|
|
|
|
} |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
my $request_id = 'aaaa'; |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
my $response; |
107
|
|
|
|
|
|
|
sub _synchronous_request_response { |
108
|
705
|
|
|
705
|
|
2736
|
my ($host, %args) = @_; |
109
|
705
|
|
66
|
|
|
1810
|
$socket ||= IO::Socket::INET->new(Proto => 'udp'); # XXX error check |
110
|
705
|
|
|
|
|
1571
|
my $port = 161; # XXX test |
111
|
705
|
100
|
|
|
|
5337
|
$port = $1 if $host =~ s/:(\d+)\z//; |
112
|
705
|
|
|
|
|
153210
|
my $iaddr = Socket::inet_aton($host); |
113
|
705
|
100
|
|
|
|
2523
|
if (not defined $iaddr) { |
114
|
2
|
|
|
|
|
31
|
$error = "Unable to resolve destination address '$host'"; |
115
|
2
|
|
|
|
|
19
|
$error_status = badHostName; |
116
|
2
|
|
|
|
|
14
|
return undef; |
117
|
|
|
|
|
|
|
} |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
# This method of picking request IDs has the following nice properties: |
120
|
|
|
|
|
|
|
# - there are 450 000 request IDs available |
121
|
|
|
|
|
|
|
# - they're always positive, so if they get sign-extended, it's always |
122
|
|
|
|
|
|
|
# with 0s |
123
|
|
|
|
|
|
|
# - they can never be represented in less than 4 bytes |
124
|
|
|
|
|
|
|
# - it's relatively fast |
125
|
703
|
|
|
|
|
1177
|
$request_id++; |
126
|
703
|
50
|
|
|
|
1857
|
$request_id = substr($request_id, 1) if length($request_id) > 4; |
127
|
|
|
|
|
|
|
|
128
|
703
|
100
|
|
|
|
2112
|
my $tries = 1 + (exists $args{retries} ? $args{retries} : 1); |
129
|
703
|
|
|
|
|
1856
|
try: while ($tries--) { |
130
|
709
|
|
|
|
|
4120
|
send $socket, NSNMP->encode(request_id => $request_id, %args), 0, |
131
|
|
|
|
|
|
|
scalar Socket::sockaddr_in($port, $iaddr); # XXX err handling: bad port? |
132
|
|
|
|
|
|
|
|
133
|
709
|
100
|
|
|
|
142983
|
my $timeout = (exists $args{timeout} ? $args{timeout} : 5); |
134
|
709
|
|
|
|
|
949
|
for (;;) { |
135
|
|
|
|
|
|
|
# perldoc -f select says, "Most systems do not bother to return |
136
|
|
|
|
|
|
|
# anything useful in $timeleft." Well, Linux 2.4 does; so if |
137
|
|
|
|
|
|
|
# you're using something that doesn't, upgrade. |
138
|
717
|
|
|
|
|
1852
|
((my $success), $timeout) = _read_timeout($socket, $timeout); |
139
|
717
|
100
|
|
|
|
2395
|
next try unless $success; |
140
|
|
|
|
|
|
|
|
141
|
704
|
|
|
|
|
3101
|
$socket->recv($response, 65536, 0); # XXX error handling? |
142
|
704
|
|
|
|
|
18670
|
my $resp_decoded = NSNMP->decode($response); |
143
|
704
|
100
|
100
|
|
|
9661
|
if (not $resp_decoded or $resp_decoded->request_id ne $request_id |
|
|
|
66
|
|
|
|
|
144
|
|
|
|
|
|
|
and $resp_decoded->request_id !~ /\A\0+\Q$request_id\E\z/) { |
145
|
|
|
|
|
|
|
# ignore it |
146
|
8
|
|
|
|
|
41
|
next; |
147
|
|
|
|
|
|
|
} |
148
|
696
|
100
|
|
|
|
1984
|
return _remember_error($resp_decoded) if $resp_decoded->error_status; |
149
|
683
|
|
|
|
|
1096
|
($error, $error_status) = (undef, undef); |
150
|
683
|
|
|
|
|
2584
|
return $resp_decoded; |
151
|
|
|
|
|
|
|
} |
152
|
|
|
|
|
|
|
} |
153
|
7
|
|
|
|
|
85
|
($error, $error_status) = |
154
|
|
|
|
|
|
|
("No response from remote host '$host'", noResponse); |
155
|
7
|
|
|
|
|
210
|
return undef; |
156
|
|
|
|
|
|
|
} |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
sub decode_int { |
159
|
40
|
|
|
40
|
0
|
80
|
my ($intstr) = @_; |
160
|
40
|
100
|
|
|
|
153
|
my $padchar = ("\0" eq ($intstr & "\x80")) ? "\0" : "\377"; |
161
|
40
|
100
|
|
|
|
129
|
$intstr = substr($intstr, length($intstr) - 4) if length($intstr) > 4; |
162
|
40
|
|
|
|
|
103
|
my $padded = $padchar x (4 - length($intstr)) . $intstr; |
163
|
40
|
|
|
|
|
820
|
my $num = unpack "N", $padded; |
164
|
40
|
100
|
|
|
|
153
|
$num -= 4294967296 if $padchar ne "\0"; # unpack gave us unsigned |
165
|
40
|
|
|
|
|
424
|
return $num; |
166
|
|
|
|
|
|
|
} |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
my %decoders = ( |
169
|
|
|
|
|
|
|
NSNMP::INTEGER => \&decode_int, |
170
|
|
|
|
|
|
|
NSNMP::Counter32 => \&decode_int, |
171
|
|
|
|
|
|
|
NSNMP::Gauge32 => \&decode_int, |
172
|
|
|
|
|
|
|
NSNMP::TimeTicks => \&decode_int, |
173
|
|
|
|
|
|
|
NSNMP::OCTET_STRING => sub { $_[0] }, |
174
|
|
|
|
|
|
|
NSNMP::IpAddress => sub { join '.', unpack "C*", $_[0] }, |
175
|
|
|
|
|
|
|
NSNMP::OBJECT_IDENTIFIER => sub { NSNMP->decode_oid($_[0]) }, |
176
|
|
|
|
|
|
|
); |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
sub encode_int { |
179
|
11
|
|
|
11
|
0
|
158
|
my ($int) = @_; |
180
|
11
|
|
|
|
|
29
|
my $rv = pack "N", $int; |
181
|
11
|
100
|
100
|
|
|
517
|
return "\0$rv" if $int >= 0 and (($rv & "\x80") ne "\00"); |
182
|
10
|
|
|
|
|
361
|
return $rv; |
183
|
|
|
|
|
|
|
} |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
my %encoders = ( |
186
|
|
|
|
|
|
|
NSNMP::INTEGER => \&encode_int, |
187
|
|
|
|
|
|
|
NSNMP::Counter32 => \&encode_int, # XXX test |
188
|
|
|
|
|
|
|
NSNMP::Gauge32 => \&encode_int, |
189
|
|
|
|
|
|
|
NSNMP::TimeTicks => \&encode_int, # XXX test |
190
|
|
|
|
|
|
|
NSNMP::OCTET_STRING => sub { $_[0] }, |
191
|
|
|
|
|
|
|
NSNMP::IpAddress => sub { pack "C*", split /\./, $_[0] }, |
192
|
|
|
|
|
|
|
NSNMP::OBJECT_IDENTIFIER => sub { NSNMP->encode_oid($_[0]) }, # XXX test |
193
|
|
|
|
|
|
|
); |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
=head2 NSNMP::Simple->get($agent, $oid, %args) |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
Returns the value of C<$oid> on the SNMP agent at C<$agent>, which can |
198
|
|
|
|
|
|
|
be a hostname or an IP address, optionally followed by a colon and a |
199
|
|
|
|
|
|
|
numeric port number, which defaults to 161, the default SNMP port. |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
C<%args> can contain any or all of the following: |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
=over |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
=item C $ver> |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
$ver is an SNMP version number (1 or 2 --- 3 isn't yet supported --- |
208
|
|
|
|
|
|
|
see L). Default is 1. |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
=item C $comm> |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
Specifies the community string. Default is C. |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
=item C $retries> |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
Specifies retries. Default is 1 --- that is, two tries. Retries are |
217
|
|
|
|
|
|
|
evenly spaced. |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
=item C $timeout> |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
Specifies a timeout in (possibly fractional) seconds. Default is 5.0. |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
=back |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
Translates the value of C<$oid> into a Perlish value, so, for example, |
226
|
|
|
|
|
|
|
an INTEGER OID whose value is 1 will be returned as "1", not "\001". |
227
|
|
|
|
|
|
|
IpAddresses are translated to dotted-quad notation, integer-like types |
228
|
|
|
|
|
|
|
are translated to integers, and OCTET STRINGS, OPAQUES, and |
229
|
|
|
|
|
|
|
NsapAddresses are left alone. |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
It doesn't return the type of the value at all. |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
In case of failure, it returns C and sets |
234
|
|
|
|
|
|
|
C<$NSNMP::Simple::error> to a string describing the error in English, |
235
|
|
|
|
|
|
|
in the same format as Net::SNMP's error messages. |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
=cut |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
# Note that I wanted to put that list of %args first in the text, as a |
240
|
|
|
|
|
|
|
# bulleted list. But pod2html barfed on the required blank line after |
241
|
|
|
|
|
|
|
# the =item * line, so I gave up on bulleted lists in POD. Yick. |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
sub get { |
244
|
52
|
|
|
52
|
1
|
18664
|
my ($class, $host, $oid, %args) = @_; |
245
|
52
|
|
|
|
|
1831
|
my $response_decoded = |
246
|
|
|
|
|
|
|
_synchronous_request_response($host, |
247
|
|
|
|
|
|
|
type => NSNMP::GET_REQUEST, |
248
|
|
|
|
|
|
|
varbindlist => [[NSNMP->encode_oid($oid), |
249
|
|
|
|
|
|
|
NSNMP::NULL, '']], |
250
|
|
|
|
|
|
|
%args); |
251
|
52
|
100
|
|
|
|
681
|
return undef unless $response_decoded; |
252
|
44
|
|
|
|
|
163
|
my $varbind = ($response_decoded->varbindlist)[0]; |
253
|
44
|
|
|
|
|
246
|
return $decoders{$varbind->[1]}->($varbind->[2]); |
254
|
|
|
|
|
|
|
} |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
=head2 NSNMP::Simple->set($agent, $oid, $type, $value, %args) |
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
Sets the value of C<$oid> on the SNMP agent at C<$agent> to the value |
259
|
|
|
|
|
|
|
C<$value>, as BER-encoded type C<$type>. Returns true on success, |
260
|
|
|
|
|
|
|
false on failure, and also sets C<$NSNMP::Simple::error> on failure. |
261
|
|
|
|
|
|
|
Accepts the same C<%args> as C<-Eget>. |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
=cut |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
sub set { |
266
|
16
|
|
|
16
|
1
|
319
|
my ($class, $host, $oid, $type, $value, %args) = @_; |
267
|
16
|
|
|
|
|
76
|
return !!_synchronous_request_response($host, |
268
|
|
|
|
|
|
|
type => NSNMP::SET_REQUEST, |
269
|
|
|
|
|
|
|
varbindlist => [[NSNMP->encode_oid($oid), |
270
|
|
|
|
|
|
|
$type, $encoders{$type}->($value)]], |
271
|
|
|
|
|
|
|
%args); |
272
|
|
|
|
|
|
|
} |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
=head2 NSNMP::Simple->get_table($agent, $oid, %args) |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
Gets the values of all OIDs under C<$oid> on the SNMP agent at |
277
|
|
|
|
|
|
|
C<$agent>. Returns a list of alternating OIDs and values, in OID |
278
|
|
|
|
|
|
|
lexical order; you can stuff it into a hash if you don't care about |
279
|
|
|
|
|
|
|
the order. If there are no OIDs under C<$oid>, returns an empty list |
280
|
|
|
|
|
|
|
and clears C<$NSNMP::Simple::error>. Note that this can be caused |
281
|
|
|
|
|
|
|
either by misspelling the OID or by actually having an empty table, |
282
|
|
|
|
|
|
|
and there's no way to tell which. (See the note in L about |
283
|
|
|
|
|
|
|
the SNMP protocol design.) |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
If any of the component SNMP requests returns an unexpected error, |
286
|
|
|
|
|
|
|
C returns an empty list and sets C<$NSNMP::Simple::error>. |
287
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
Note for Net::SNMP users: C does not set |
289
|
|
|
|
|
|
|
C<$NSNMP::Simple::error> on an empty table, but Net::SNMP's |
290
|
|
|
|
|
|
|
C does. |
291
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
Accepts the same C<%args> as C<-Eget>. |
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
The OIDs in the returned list are spelled in ASCII with or without a |
295
|
|
|
|
|
|
|
leading dot, depending on whether or not C<$oid> has a leading dot. |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
=cut |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
sub get_table { |
300
|
13
|
|
|
13
|
1
|
5169
|
my ($class, $host, $oid, %args) = @_; |
301
|
13
|
|
|
|
|
69
|
my @rv; |
302
|
|
|
|
|
|
|
my $response; |
303
|
13
|
|
|
|
|
120
|
my $mapper = NSNMP::Mapper->new($oid => 1); |
304
|
13
|
|
|
|
|
266
|
my $initial_dot = $oid =~ /\A\./; |
305
|
13
|
|
|
|
|
169
|
my $encoded_oid = NSNMP->encode_oid($oid); |
306
|
13
|
|
|
|
|
20
|
for (;;) { |
307
|
637
|
|
|
|
|
2691
|
$response = _synchronous_request_response($host, |
308
|
|
|
|
|
|
|
type => NSNMP::GET_NEXT_REQUEST, |
309
|
|
|
|
|
|
|
varbindlist => [[$encoded_oid, NSNMP::NULL, '']], |
310
|
|
|
|
|
|
|
%args, |
311
|
|
|
|
|
|
|
); |
312
|
637
|
100
|
|
|
|
4702
|
if (not defined $response) { |
313
|
12
|
100
|
|
|
|
40
|
if ($error_status eq NSNMP::noSuchName) { |
314
|
|
|
|
|
|
|
# end of MIB |
315
|
10
|
|
|
|
|
26
|
($error_status, $error) = (undef, undef); |
316
|
10
|
|
|
|
|
1455
|
return @rv; |
317
|
|
|
|
|
|
|
} |
318
|
2
|
|
|
|
|
45
|
return (); |
319
|
|
|
|
|
|
|
} |
320
|
625
|
|
|
|
|
1630
|
my @varbindlist = $response->varbindlist; |
321
|
625
|
|
|
|
|
1594
|
$encoded_oid = $varbindlist[0][0]; |
322
|
625
|
|
|
|
|
1841
|
$oid = NSNMP->decode_oid($varbindlist[0][0]); |
323
|
625
|
100
|
|
|
|
1911
|
return @rv unless ($mapper->map($oid))[0]; |
324
|
624
|
100
|
|
|
|
3026
|
push @rv, ($initial_dot ? ".$oid" : $oid), |
325
|
|
|
|
|
|
|
$decoders{$varbindlist[0][1]}->($varbindlist[0][2]); |
326
|
|
|
|
|
|
|
} |
327
|
|
|
|
|
|
|
} |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
=head2 $error |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
C<$NSNMP::Simple::error> is undef after any successful subroutine |
332
|
|
|
|
|
|
|
call on this module, and an English string describing the error after |
333
|
|
|
|
|
|
|
any unsuccessful subroutine call. |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
C<$NSNMP::Simple::error_status> is undef when C<$error> is undef, |
336
|
|
|
|
|
|
|
and when C<$error> is defined, C<$error_status> contains an integer |
337
|
|
|
|
|
|
|
describing the type of error. This may be a raw SNMP C |
338
|
|
|
|
|
|
|
code, such as NSNMP::noSuchName, or it may be one of the following |
339
|
|
|
|
|
|
|
values: |
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
=over |
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
=item NSNMP::Simple::noResponse |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
This code means that the remote host sent no response, or at least, no |
346
|
|
|
|
|
|
|
response we could decode, so we timed out. (The timeout value is |
347
|
|
|
|
|
|
|
configurable, as described earlier.) |
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
=item NSNMP::Simple::badHostName |
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
This code means that C couldn't resolve the hostname |
352
|
|
|
|
|
|
|
given. It might be malformed or a nonexistent DNS name, or it might |
353
|
|
|
|
|
|
|
be an existing DNS name, but DNS might be broken for some other |
354
|
|
|
|
|
|
|
reason. |
355
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
=back |
357
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
=head1 FILES |
359
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
None. |
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
=head1 AUTHOR |
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
Kragen Sitaker Ekragen@pobox.comE |
365
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
=head1 BUGS |
367
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
This module uses L, so it inherits most of the |
369
|
|
|
|
|
|
|
bugs of that module. |
370
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
It's still too slow. On my 500MHz laptop, it can SNMP-walk 5675 OIDs |
372
|
|
|
|
|
|
|
in about 7.2 CPU seconds, for less than 800 OIDs per second. ucd-snmp |
373
|
|
|
|
|
|
|
(now confusingly called net-snmp, not to be confused with Net::SNMP) |
374
|
|
|
|
|
|
|
takes 1.8 CPU seconds to perform the same task. That's four times as |
375
|
|
|
|
|
|
|
fast. On the other hand, Net::SNMP manages about 110 OIDs per second, |
376
|
|
|
|
|
|
|
seven times slower still. |
377
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
=cut |
379
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
1; |