File Coverage

blib/lib/Net/SNMP/Mixin/Util.pm
Criterion Covered Total %
statement 57 57 100.0
branch 27 28 96.4
condition 6 9 66.6
subroutine 8 8 100.0
pod 4 4 100.0
total 102 106 96.2


line stmt bran cond sub pod time code
1             package Net::SNMP::Mixin::Util;
2              
3 5     5   133808 use strict;
  5         11  
  5         240  
4 5     5   30 use warnings;
  5         11  
  5         190  
5              
6             #
7             # this module import config
8             #
9 5     5   1533 use Net::SNMP ();
  5         119975  
  5         191  
10              
11             #
12             # this module export config
13             #
14 5         80 use Sub::Exporter -setup =>
15 5     5   6879 { exports => [qw/idx2val hex2octet normalize_mac push_error/], };
  5         21081  
16              
17             =head1 NAME
18              
19             Net::SNMP::Mixin::Util - helper class for Net::SNMP mixins
20              
21             =head1 VERSION
22              
23             Version 0.12
24              
25             =cut
26              
27             our $VERSION = '0.12';
28              
29             =head1 SYNOPSIS
30              
31             A helper class for Net::SNMP mixins.
32              
33             use Net::SNMP::Mixin::Util qw/idx2val hex2octet normalize_mac/;
34              
35             =head1 EXPORTS
36              
37             The following routines are exported by request:
38              
39             =over 2
40              
41             =item B<< idx2val($var_bind_list, $base_oid, [$pre], [$tail]) >>
42              
43             convert a var_bind_list into a index => value form,
44             removing the base_oid from oid.
45              
46             e.g. if base_oid is '1.3.6.1.2.1.17.1.4.1.2',
47             convert from:
48            
49             '1.3.6.1.2.1.17.1.4.1.2.1' => 'foo'
50             '1.3.6.1.2.1.17.1.4.1.2.2' => 'bar'
51              
52             to:
53              
54             '1' => 'foo'
55             '2' => 'bar'
56            
57             or if base_oid is '1.0.8802.4.1.1.12' and pre == 1 and tail == 2,
58             convert from:
59              
60             '1.0.8802.4.1.1.12.0.10.0.0.2.99.185' => 'foo',
61             '1.0.8802.4.1.1.12.0.10.0.0.3.99.186' => 'bar',
62             '1.0.8802.4.1.1.12.0.10.0.0.4.99.187' => 'baz',
63             ^ ^ ^ ^ ^ ^ ^
64             |.....base_oid....|.|.index..|.tail.| |value|
65             ^
66             pre ---------------|
67              
68             to:
69              
70             '10.0.0.2' => 'foo',
71             '10.0.0.3' => 'bar',
72             '10.0.0.4' => 'baz',
73              
74             Returns the hash reference with index => value. Dies on error.
75              
76             =cut
77              
78             sub idx2val {
79 10     10 1 1461 my ( $var_bind_list, $base_oid, $pre, $tail ) = @_;
80              
81 10 100       41 die "missing attribute 'var_bind_list'," unless defined $var_bind_list;
82 9 100       9669 die "missing attribute 'base_oid'," unless defined $base_oid;
83              
84 8   100     38 $pre ||= 0;
85 8   100     26 $tail ||= 0;
86              
87 8 100       35 die "wrong format for 'pre'," if $pre < 0;
88 7 100       25 die "wrong format for 'tail'," if $tail < 0;
89              
90 6         12 my $idx;
91 6         16 my $idx2val = {};
92 6         27 foreach my $oid ( keys %$var_bind_list ) {
93 23 100       80 next unless Net::SNMP::oid_base_match( $base_oid, $oid );
94              
95 18         818 $idx = $oid;
96              
97             # cutoff leading and trailing whitespace, bloody SNMP agents!
98 18         74 $idx =~ s/^\s*//;
99 18         108 $idx =~ s/\s*$//;
100              
101             # cutoff the basoid, get the idx
102 18         152 $idx =~ s/^$base_oid//;
103              
104             # if the idx isn't at the front of the index
105             # cut off the n fold pre
106 18 100       541 $idx =~ s/^\.?(\d+\.?){$pre}// if $pre > 0;
107              
108             # if the idx isn't at the end of the oid
109             # cut off the n fold tail
110 18 100       182 $idx =~ s/(\d+\.?){$tail}$// if $tail > 0;
111              
112             # cut off remaining dangling '.'
113 18         38 $idx =~ s/^\.//;
114 18         43 $idx =~ s/\.$//;
115              
116 18         73 $idx2val->{$idx} = $var_bind_list->{$oid};
117             }
118 6         154 return $idx2val;
119             }
120              
121             =item B<< hex2octet($hex_string) >>
122              
123             Sometimes it's importend that the returned SNMP values were untranslated by Net::SNMP. If already translated, we must reconvert it to pure OCTET_STRINGs for some calculations. Returns the input parameter untranslated if it's no string in the form /^0x[0-9a-f]+$/i .
124              
125             =cut
126              
127             sub hex2octet {
128 3     3 1 7 my $hex_string = shift;
129              
130             # don't touch, it's no hex_string
131 3 100       121 return $hex_string unless $hex_string =~ m/^0x[0-9a-f]+$/i;
132              
133             # remove '0x' in front
134 1         3 $hex_string = substr( $hex_string, 2 );
135              
136             # return octet_string
137 1         11 return pack 'H*', $hex_string;
138             }
139              
140             =item B<< normalize_mac($mac_address) >>
141              
142             normalize MAC addresses to the IEEE form XX:XX:XX:XX:XX:XX
143              
144             normalize the different formats like,
145              
146             x:xx:x:xx:Xx:xx to XX:XX:XX:XX:XX:XX
147             or xxxxxx-xxxxxx to XX:XX:XX:XX:XX:XX
148             or xx-xx-xx-xx-xx-xx to XX:XX:XX:XX:XX:XX
149             or xxxx.xxxx.xxxx to XX:XX:XX:XX:XX:XX
150             or 0x xxxxxxxxxxxx to XX:XX:XX:XX:XX:XX
151             or plain packed '6C' to XX:XX:XX:XX:XX:XX
152              
153             or returns undef for format errors.
154              
155             =cut
156              
157             sub normalize_mac {
158 20     20 1 8473 my ($mac) = @_;
159 20 100       61 return unless defined $mac;
160              
161             # translate this OCTET_STRING to hexadecimal, unless already translated
162 19 100       56 if ( length $mac == 6 ) {
163 1         8 $mac = unpack 'H*', $mac;
164             }
165              
166             # to upper case
167 19         39 my $norm_address = uc($mac);
168              
169             # remove '-' in bloody Microsoft format
170 19         38 $norm_address =~ s/-//g;
171              
172             # remove '.' in bloody Cisco format
173 19         30 $norm_address =~ s/\.//g;
174              
175             # remove '0X' in front of, we are already upper case
176 19         30 $norm_address =~ s/^0X//;
177              
178             # we are already upper case
179 19         142 my $hex_digit = qr/[A-F,0-9]/;
180              
181             # insert leading 0 in bloody Sun format
182 19         192 $norm_address =~ s/\b($hex_digit)\b/0$1/g;
183              
184             # insert ':' aabbccddeeff -> aa:bb:cc:dd:ee:ff
185 19         225 $norm_address =~ s/($hex_digit{2})(?=$hex_digit)/$1:/g;
186              
187             # wrong format
188 19 100       201 return unless $norm_address =~ m /^($hex_digit{2}:){5}$hex_digit{2}$/;
189              
190 12         104 return $norm_address;
191             }
192              
193             =item B<< push_error($session, $error_msg) >>
194              
195             Net::SNMP has only one slot for errors. During nonblocking calls it's possible that an error followed by a successful transaction is cleared before the user gets the chance to see the error. At least for the mixin modules we use an array buffer for all seen errors until they are explicit cleared.
196              
197             This utility routine helps the mixin authors to push an error into the buffer without the knowledge of the buffer internas.
198              
199             Dies if session isn't a Net::SNMP object or error_msg is missing.
200              
201             =back
202              
203             =cut
204              
205             sub push_error {
206 3     3 1 5384 my ( $session, $error_msg ) = @_;
207              
208 3 100       25 die "missing attribute 'session'," unless defined $session;
209 2 100       16 die "missing attribute 'error_msg'," unless defined $error_msg;
210              
211 1 50 33     22 die "'session' isn't a Net::SNMP object,"
212             unless ref $session && $session->isa('Net::SNMP');
213              
214             # prepare the error buffer if not already done
215 1   50     10 $session->{'Net::SNMP::Mixin'}{errors} ||= [];
216              
217             # store the error_msg at the buffer end
218 1         2 push @{ $session->{'Net::SNMP::Mixin'}{errors} }, $error_msg;
  1         7  
219             }
220              
221             unless ( caller() ) {
222             print __PACKAGE__ . " compiles and initializes successful.\n";
223             }
224              
225             =head1 REQUIREMENTS
226              
227             L, L
228              
229             =head1 BUGS, PATCHES & FIXES
230              
231             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.
232              
233             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 .
234              
235             RT: http://rt.cpan.org/Public/Dist/Display.html?Name=Net-SNMP-Mixin
236              
237             =head1 AUTHOR
238              
239             Karl Gaissmaier
240              
241             =head1 COPYRIGHT & LICENSE
242              
243             Copyright 2008 Karl Gaissmaier, all rights reserved.
244              
245             This program is free software; you can redistribute it and/or modify it
246             under the same terms as Perl itself.
247              
248             =cut
249              
250             1;
251              
252             # vim: sw=2