File Coverage

blib/lib/Net/SNMP/Mixin/IfInfo.pm
Criterion Covered Total %
statement 46 71 64.7
branch 12 20 60.0
condition 3 9 33.3
subroutine 12 12 100.0
pod 1 1 100.0
total 74 113 65.4


line stmt bran cond sub pod time code
1             package Net::SNMP::Mixin::IfInfo;
2              
3 4     4   394362 use strict;
  4         10  
  4         124  
4 4     4   28 use warnings;
  4         8  
  4         142  
5              
6             #
7             # store this package name in a handy variable,
8             # used for unambiguous prefix of mixin attributes
9             # storage in object hash
10             #
11             my $prefix = __PACKAGE__;
12              
13             #
14             # this module import config
15             #
16 4     4   22 use Carp ();
  4         8  
  4         110  
17 4     4   557 use Net::SNMP::Mixin::Util qw/idx2val hex2octet normalize_mac push_error get_init_slot/;
  4         94506  
  4         31  
18              
19             #
20             # this module export config
21             #
22             my @mixin_methods;
23              
24             BEGIN {
25 4     4   2685 @mixin_methods = (qw/ get_if_entries /);
26             }
27              
28 4         37 use Sub::Exporter -setup => {
29             exports => [@mixin_methods],
30             groups => { default => [@mixin_methods], },
31 4     4   33 };
  4         8  
32              
33             #
34             # SNMP oid constants used in this module
35             #
36             use constant {
37 4         1612 IF_DESCR => '1.3.6.1.2.1.2.2.1.2',
38             IF_TYPE => '1.3.6.1.2.1.2.2.1.3',
39             IF_MTU => '1.3.6.1.2.1.2.2.1.4',
40             IF_SPEED => '1.3.6.1.2.1.2.2.1.5',
41             IF_PHYS_ADDRESS => '1.3.6.1.2.1.2.2.1.6',
42             IF_ADMIN_STATUS => '1.3.6.1.2.1.2.2.1.7',
43             IF_OPER_STATUS => '1.3.6.1.2.1.2.2.1.8',
44             IF_X_NAME => '1.3.6.1.2.1.31.1.1.1.1',
45             IF_X_HIGHSPEED => '1.3.6.1.2.1.31.1.1.1.15',
46             IF_X_ALIAS => '1.3.6.1.2.1.31.1.1.1.18',
47 4     4   2166 };
  4         12  
48              
49             =head1 NAME
50              
51             Net::SNMP::Mixin::IfInfo - mixin class for interface related infos
52              
53             =head1 VERSION
54              
55             Version 1.01
56              
57             =cut
58              
59             our $VERSION = '1.01';
60              
61             =head1 SYNOPSIS
62              
63             use Net::SNMP;
64             use Net::SNMP::Mixin;
65              
66             my $session = Net::SNMP->session( -hostname => 'foo.bar.com' );
67              
68             $session->mixer('Net::SNMP::Mixin::IfInfo');
69             $session->init_mixins;
70             snmp_dispatcher();
71             $session->init_ok();
72             die $session->errors if $session->errors;
73              
74             my $if_entries = $session->get_if_entries;
75             foreach my $if_index ( sort { $a <=> $b } keys %$if_entries ) {
76             my $ifAdminStatus = $if_entries->{$if_index}->{ifAdminStatus} // 0;
77             my $ifOperStatus = $if_entries->{$if_index}->{ifOperStatus} // 0;
78             my $ifType = $if_entries->{$if_index}->{ifType} // 0;
79             my $ifName = $if_entries->{$if_index}->{ifName} // '';
80             my $ifDescr = $if_entries->{$if_index}->{ifDescr} // '';
81             my $ifAlias = $if_entries->{$if_index}->{ifAlias} // '';
82              
83             printf "%5d %1d/%1d %-10.10s %-25.25s %-26.26s\n",
84             $if_index, $ifAdminStatus, $ifOperStatus, $ifName, $ifDescr, $ifAlias;
85             }
86              
87             =head1 DESCRIPTION
88              
89             A mixin class for basic interface related infos from the ifTable and ifXTable.
90              
91             This mixin supports the quasi static information from both tables together in one hash, see below.
92              
93             =head1 MIXIN METHODS
94              
95             =head2 B<< OBJ->get_if_entries >>
96              
97             Returns parts ot the ifTable and ifXTable as a hash reference. The key is the common ifIndex into the ifTable and ifXtable:
98              
99             {
100             INTEGER => { # ifIndex as key
101              
102             ifName => DisplayString, # ifXTable entries
103             ifAlias => DisplayString,
104             ifHighspeed => GAUGE,
105              
106             ifDescr => DisplayString, # ifTable entries
107             ifType => IANAifType,
108             ifMtu => INTEGER,
109             ifSpeed => GAUGE,
110             ifPhysAddress => PhysAddress,
111             ifAdminStatus => INTEGER,
112             ifOperStatus => INTEGER,
113             }
114              
115             ...,
116             }
117              
118             =cut
119              
120             sub get_if_entries {
121 1     1 1 29203 my $session = shift;
122 1         5 my $agent = $session->hostname;
123              
124 1 50       9 Carp::croak "$agent: '$prefix' not initialized,"
125             unless $session->init_ok($prefix);
126              
127             # hash for return values
128 0         0 my $result = {};
129              
130             # the MIB tables are stored in {col}{idx}=value order but we return {idx}{col}=value
131             #
132             # grab all if indexes from one random choosen col
133 0         0 my @indexes = keys %{ $session->{$prefix}{ifInfo}{ifDescr} };
  0         0  
134              
135             # side effect: make a shallow copy for shallow values
136 0         0 foreach my $idx (@indexes) {
137 0         0 foreach my $col ( keys %{ $session->{$prefix}{ifInfo} } ) {
  0         0  
138 0         0 my $value = $session->{$prefix}{ifInfo}{$col}{$idx};
139              
140             # convert back to OCTET-STRING, maybe already translated by Net::SNMP
141 0 0       0 if ( $col eq 'ifPhysAddress' ) {
142 0         0 $value = hex2octet($value);
143 0   0     0 $value = normalize_mac($value) // $value;
144             }
145 0         0 $result->{$idx}{$col} = $value;
146             }
147             }
148              
149 0         0 return $result;
150             }
151              
152             =head1 INITIALIZATION
153              
154             =head2 B<< OBJ->_init($reload) >>
155              
156             Fetch basic interface related snmp values from the host. Don't call this method direct!
157              
158             =cut
159              
160             #
161             # due to the asynchron nature, we don't know what init job is really the last, we decrement
162             # the value after each callback
163             #
164 4     4   44 use constant THIS_INIT_JOBS => 1;
  4         11  
  4         2712  
165              
166             sub _init {
167 4     4   9235 my ( $session, $reload ) = @_;
168 4         13 my $agent = $session->hostname;
169              
170             die "$agent: $prefix already initialized and reload not forced.\n"
171             if exists get_init_slot($session)->{$prefix}
172 4 50 66     29 && get_init_slot($session)->{$prefix} == 0
      33        
173             && not $reload;
174              
175             # set number of async init jobs for proper initialization
176 4         108 get_init_slot($session)->{$prefix} = THIS_INIT_JOBS;
177              
178             # populate the object with needed mib values
179             #
180             # map between ifIndexes -> ifDescr, ...
181 4         44 _fetch_if_entries($session);
182 4 100       22 return if $session->error;
183              
184 2         12 return 1;
185             }
186              
187             =head1 PRIVATE METHODS
188              
189             Only for developers or maintainers.
190              
191             =head2 B<< _fetch_if_entries($session) >>
192              
193             Get selected MIB values from the ifTable and ifXTable.
194              
195             =cut
196              
197             sub _fetch_if_entries {
198 4     4   11 my $session = shift;
199 4         16 my $result;
200              
201             # fetch selected entries from ifTable and ifXTable
202 4 100       33 $result = $session->get_entries(
203             -columns => [
204             IF_DESCR, IF_TYPE, IF_MTU, IF_SPEED, IF_PHYS_ADDRESS, IF_ADMIN_STATUS, IF_OPER_STATUS,
205             IF_X_NAME, IF_X_HIGHSPEED, IF_X_ALIAS,
206             ],
207              
208             # define callback if in nonblocking mode
209             $session->nonblocking ? ( -callback => \&_if_entries_cb ) : (),
210             );
211              
212 4 100       2015890 unless ( defined $result ) {
213              
214             # Net::SNMP looses sometimes error messages in nonblocking
215             # mode, so we save them in an extra buffer
216 2         16 my $err_msg = $session->error;
217 2 50       57 push_error( $session, "$prefix: $err_msg" ) if $err_msg;
218 2         104 return;
219             }
220              
221             # in nonblocking mode the callback will be called asynchronously
222 2 50       8 return 1 if $session->nonblocking;
223              
224             # ok we are in synchronous mode, call the result mangling function
225             # by hand
226 0         0 _if_entries_cb($session);
227              
228             }
229              
230             =head2 B<< _if_entries_cb($session) >>
231              
232             The callback for _fetch_if_entries
233              
234             =cut
235              
236             sub _if_entries_cb {
237 2     2   2005381 my $session = shift;
238 2         10 my $vbl = $session->var_bind_list;
239              
240 2 50       26 unless ( defined $vbl ) {
241              
242             # Net::SNMP looses sometimes error messages in nonblocking
243             # mode, so we save them in an extra buffer
244 2         12 my $err_msg = $session->error;
245 2 50       33 push_error( $session, "$prefix: $err_msg" ) if $err_msg;
246 2         69 return;
247             }
248              
249             # mangle result table to get plain idx->value
250 0           $session->{$prefix}{ifInfo}{ifDescr} = idx2val( $vbl, IF_DESCR );
251 0           $session->{$prefix}{ifInfo}{ifType} = idx2val( $vbl, IF_TYPE );
252 0           $session->{$prefix}{ifInfo}{ifMtu} = idx2val( $vbl, IF_MTU );
253 0           $session->{$prefix}{ifInfo}{ifSpeed} = idx2val( $vbl, IF_SPEED );
254 0           $session->{$prefix}{ifInfo}{ifPhysAddress} = idx2val( $vbl, IF_PHYS_ADDRESS );
255 0           $session->{$prefix}{ifInfo}{ifAdminStatus} = idx2val( $vbl, IF_ADMIN_STATUS );
256 0           $session->{$prefix}{ifInfo}{ifOperStatus} = idx2val( $vbl, IF_OPER_STATUS );
257 0           $session->{$prefix}{ifInfo}{ifName} = idx2val( $vbl, IF_X_NAME );
258 0           $session->{$prefix}{ifInfo}{ifHighspeed} = idx2val( $vbl, IF_X_HIGHSPEED );
259 0           $session->{$prefix}{ifInfo}{ifAlias} = idx2val( $vbl, IF_X_ALIAS );
260              
261             # this init job is finished
262 0           get_init_slot($session)->{$prefix}--;
263              
264 0           return 1;
265             }
266              
267             =head1 SEE ALSO
268              
269             L<< Net::SNMP::Mixin::Dot1dBase >> for a mapping between ifIndexes and dot1dBasePorts.
270              
271             =head1 REQUIREMENTS
272              
273             L<< Net::SNMP >>, L<< Net::SNMP::Mixin >>
274              
275             =head1 BUGS, PATCHES & FIXES
276              
277             There are no known bugs at the time of this release. However, if you spot a bug or are experiencing difficulties that are not explained within the POD documentation, please submit a bug to the RT system (see link below). However, it would help greatly if you are able to pinpoint problems or even supply a patch.
278              
279             Fixes are dependant upon their severity and my availablity. Should a fix not be forthcoming, please feel free to (politely) remind me by sending an email to gaissmai@cpan.org .
280              
281             RT: http://rt.cpan.org/Public/Dist/Display.html?Name=Net-SNMP-Mixin-IfInfo
282              
283             =head1 AUTHOR
284              
285             Karl Gaissmaier
286              
287             =head1 COPYRIGHT & LICENSE
288              
289             Copyright 2008-2021 Karl Gaissmaier, all rights reserved.
290              
291             This program is free software; you can redistribute it and/or modify it
292             under the same terms as Perl itself.
293              
294             =cut
295              
296             unless ( caller() ) {
297             print __PACKAGE__ . " compiles and initializes successful.\n";
298             }
299              
300             1;
301              
302             # vim: sw=2