File Coverage

blib/lib/Net/SNMP/Interfaces.pm
Criterion Covered Total %
statement 18 83 21.6
branch 0 22 0.0
condition 0 13 0.0
subroutine 6 16 37.5
pod 7 7 100.0
total 31 141 21.9


line stmt bran cond sub pod time code
1             #*****************************************************************************
2             #* *
3             #* Gellyfish Software *
4             #* *
5             #* *
6             #*****************************************************************************
7             #* *
8             #* PROGRAM : Net::SNMP::Interfaces. *
9             #* *
10             #* AUTHOR : JNS *
11             #* *
12             #* DESCRIPTION : Simple SNMP stuff for Interfaces. *
13             #* *
14             #* *
15             #*****************************************************************************
16              
17             package Net::SNMP::Interfaces;
18              
19             =head1 NAME
20              
21             Net::SNMP::Interfaces - provide simple methods to gain interface data via
22              
23             SNMP
24              
25             =head1 SYNOPSIS
26              
27             use Net::SNMP::Interfaces;
28              
29             my $interfaces = Net::SNMP::Interfaces->new(Hostname => 'localhost',
30             Community => 'public' );
31              
32             my @ifnames = $interfaces->all_interfaces();
33              
34             =head1 DESCRIPTION
35              
36             Net::SNMP::Interfaces aims to provide simple object methods to obtain
37             information about a host's network interfaces ( be it a server a router
38             or whatever ). The motivation was largely to allow a programmer to use
39             SNMP to obtain this information without needing to know a great deal
40             about the gory details.
41              
42             The module uses Net::SNMP under the hood to do the dirty work although
43             the user shouldn't have to worry about that ( the Net::SNMP object is
44             available though for those who might feel the need ).
45              
46             The actual details for a particular interface are obtained from the methods
47             of Net::SNMP::Interfaces::Details - objects of which type can be obtained
48             for the methods all_interfaces() and interface().
49              
50             Of course the simpler interface has its limitations and there may well
51             be things that you would like to do which you cant do with this module -
52             in which case I would recommend that you get a good book on SNMP and
53             use Net::SNMP :)
54              
55             The module uses blocking SNMP requests at the current time so if some
56             of the methods are taking too long you may want to time them out
57             yourself using alarm().
58              
59             =cut
60              
61              
62              
63 1     1   895 use strict;
  1         2  
  1         39  
64 1     1   1348 use Net::SNMP;
  1         465034  
  1         114  
65 1     1   19 use Carp;
  1         2  
  1         58  
66              
67              
68 1     1   724 use Net::SNMP::Interfaces::Details;
  1         2  
  1         35  
69              
70 1         786 use vars qw(
71             @ISA
72             $VERSION
73             $AUTOLOAD
74 1     1   5 );
  1         1  
75            
76              
77              
78             ($VERSION) = q$Revision: 1.4 $ =~ /([\d.]+)/;
79              
80             =head2 METHODS
81              
82             =over
83              
84             =item new( HASH %args )
85              
86             The constructor of the class. It takes several arguments that are passed
87             to Net::SNMP :
88              
89             =over
90              
91             =item Hostname
92              
93             The name of the host which you want to connect to. Defaults to 'localhost'.
94              
95             =item Community
96              
97             The SNMP community string which you want to use for this session. The default
98             is 'public'.
99              
100             =item Port
101              
102             The UDP port that the SNMP service is listening on. The default is 161.
103              
104             =item Version
105              
106             The SNMP version (as described in the L documentation) to be
107             used. The default is 'snmpv1'. Support for SNMPv3 is currently somehwat
108             limited.
109              
110             =back
111              
112             There is a also an optional argument 'RaiseError' which determines
113             the behaviour of the module in the event there is an error while creating
114             the SNMP. Normally new() will return undef if there was an error but if
115             RaiseError is set to a true value it will die() printing the error string
116             to STDERR. If this is not set and an error occurs undef will be return
117             and the variable $Net::SNMP::Interfaces::error will contain the test of
118             the error.
119              
120             Because the interfaces are discovered in the constructor, if the module
121             is to be used in a long running program to monitor a host where
122             interfaces might be added or removed it is recommended that the object
123             returned by new() is periodically destroyed and a new one constructed.
124              
125             =cut
126              
127              
128             sub new
129             {
130 0     0 1   my ( $proto , %args ) = @_;
131            
132 0           my $self = {};
133              
134 0   0       $self->{_hostname} = $args{Hostname} || 'localhost';
135 0   0       $self->{_community} = $args{Community} || 'public';
136 0   0       $self->{_port} = $args{Port} || 161;
137 0   0       $self->{_version} = $args{Version} || 'snmpv1',
      0        
138             $self->{_raise} = $args{RaiseError} || 0;
139              
140              
141 0           my ($session, $error) = Net::SNMP->session(
142             -hostname => $self->{_hostname},
143             -community => $self->{_community},
144             -port => $self->{_port},
145             -version => $self->{_version},
146             );
147              
148 0 0         if (!defined($session))
149             {
150 0 0         if ( $self->{_raise} )
151             {
152 0           croak sprintf("%s: %s", __PACKAGE__, $error);
153             }
154             else
155             {
156 0           $Net::SNMP::Interfaces::error = $error;
157 0           return undef;
158             }
159             }
160              
161 0           $self->{_snmp_session} = $session;
162              
163 0           my $ifIndex = '1.3.6.1.2.1.2.2.1.1';
164 0           my $ifDescr = '1.3.6.1.2.1.2.2.1.2';
165              
166 0           my $response;
167              
168 0 0         if (!defined($response = $session->get_table($ifIndex)))
169             {
170 0 0         if ( $self->{_raise} )
171             {
172 0           $session->close;
173 0           croak sprintf("%s: %s",__PACKAGE__, $session->error);
174             }
175             else
176             {
177 0           $Net::SNMP::Interfaces::error = $session->error();
178 0           return undef;
179             }
180             }
181              
182              
183 0           foreach my $index ( values %{$response} )
  0            
184             {
185 0           my $this_desc = "$ifDescr.$index";
186              
187 0           my $description;
188              
189 0 0         if ( defined( $description = $session->get_request($this_desc)) )
190             {
191 0           $self->{_desc2index}->{$description->{$this_desc}} = $index;
192 0           $self->{_index2desc}->{$index} = $description->{$this_desc};
193             }
194             else
195             {
196 0           $self->{_lasterror} = $session->error();
197             }
198             }
199              
200 0           return bless $self, $proto;
201             }
202              
203             =item if_names()
204              
205             Returns a list of the interface names.
206              
207             =cut
208              
209             sub if_names
210             {
211 0     0 1   my ( $self ) = @_;
212              
213 0           return keys %{$self->{_desc2index}};
  0            
214             }
215              
216              
217             =item if_indices()
218              
219             Returns a list of the indices of the interfaces - this probably shouldn't
220             be necessary but is here for completeness anyway. If you dont know what
221             the index is for you are safe to ignore this.
222              
223             =cut
224              
225             sub if_indices
226             {
227 0     0 1   my ( $self ) = @_;
228              
229 0           return keys %{$self->{_index2desc}};
  0            
230             }
231              
232             =item error()
233              
234             Returns the text of the last Net::SNMP error. This method only makes sense
235             if the previous method call indicated an error by a false return.
236              
237             =cut
238              
239             sub error
240             {
241 0     0 1   my ($self ) = @_;
242              
243 0   0       return $self->{_lasterror} || $self->session()->error();
244             }
245              
246             =item session()
247              
248             Returns the Net::SNMP session object for this instance. Or a false value
249             if there is no open session. This might be used to call methods on the
250             Net::SNMP object if some facility is needed that isnt supplied by this
251             module.
252              
253             =cut
254              
255             sub session
256             {
257 0     0 1   my ( $self ) = @_;
258              
259 0 0         return exists $self->{_snmp_session} ? $self->{_snmp_session} : undef;
260             }
261              
262             =item all_interfaces()
263              
264             Returns a list of Net::SNMP::Interface::Details objects corresponding to
265             the interfaces discovered on this host. In scalar context it will return
266             a reference to an array.
267              
268             =cut
269              
270             sub all_interfaces
271             {
272 0     0 1   my ( $self ) = @_;
273              
274 0           my @interfaces;
275              
276            
277 0           for my $index ( sort $self->if_indices() )
278             {
279 0           my %args = (
280             Index => $index,
281             Name => $self->{_index2desc}->{$index},
282             Session => $self->session()
283             );
284              
285 0           push @interfaces, Net::SNMP::Interfaces::Details->new(%args);
286             }
287              
288 0 0         return wantarray ? @interfaces : \@interfaces;
289             }
290              
291             =item interface( SCALAR $name )
292              
293             Returns a Net::SNMP::Interfaces::Details object for the named interface.
294             Returns undef if the supplied name is not a known interface.
295              
296             =cut
297              
298             sub interface
299             {
300 0     0 1   my ( $self, $name ) = @_;
301              
302 0           my $index = $self->{_desc2index}->{$name};
303              
304 0 0         if ( defined $index )
305             {
306 0           return Net::SNMP::Interfaces::Details->new(
307             Name => $name,
308             Index => $index,
309             Session => $self->session()
310             );
311             }
312             else
313             {
314 0           return undef;
315             }
316             }
317              
318             =for pod
319              
320             In addition to the methods above, you can also use the methods from
321             Net::SNMP::Interfaces::Details but with the addition of the interface
322             name as an argument. e.g:
323              
324             $in_octs = $self->ifInOctets('eth0');
325              
326             Please see the documentation for Net::SNMP::Interfaces::Details for more
327             on these methods.
328              
329             =cut
330              
331             sub AUTOLOAD
332             {
333 0     0     my ( $self, $name ) = @_;
334              
335 0 0         return if $AUTOLOAD =~ /DESTROY$/;
336              
337 0 0         croak "No name" unless $name;
338 0 0         return undef unless exists $self->{_desc2index}->{$name};
339              
340 0           my ($meth) = $AUTOLOAD =~ /::([^:]+)$/;
341              
342 1     1   5 no strict 'refs';
  1         2  
  1         106  
343              
344 0           *{$AUTOLOAD} = sub {
345 0     0     my ( $self, $name ) = @_;
346 0           return $self->interface($name)->$meth() ;
347 0           };
348              
349 0           goto &{$AUTOLOAD};
  0            
350              
351             }
352              
353              
354             sub DESTROY
355             {
356 0     0     my ( $self ) = @_;
357              
358 0           $self->session()->close();
359             }
360              
361             1;
362             __END__