File Coverage

blib/lib/Cisco/SNMP/ProxyPing.pm
Criterion Covered Total %
statement 21 120 17.5
branch 0 46 0.0
condition 0 19 0.0
subroutine 7 14 50.0
pod 6 6 100.0
total 34 205 16.5


line stmt bran cond sub pod time code
1             package Cisco::SNMP::ProxyPing;
2              
3             ##################################################
4             # AUTHOR = Michael Vincent
5             # www.VinsWorld.com
6             ##################################################
7              
8 1     1   98841 use strict;
  1         5  
  1         55  
9 1     1   12 use warnings;
  1         3  
  1         180  
10              
11 1     1   1441 use Net::SNMP qw(:asn1);
  1         88845  
  1         267  
12 1     1   447 use Cisco::SNMP;
  1         3  
  1         52  
13              
14             our $VERSION = $Cisco::SNMP::VERSION;
15              
16             our @ISA = qw(Cisco::SNMP);
17              
18 1     1   5 use Sys::Hostname;
  1         2  
  1         42  
19 1     1   4 use Socket qw(AF_INET);
  1         2  
  1         1091  
20              
21             # use Net::IPv6Addr;
22             my $HAVE_Net_IPv6Addr = 0;
23             if ($Socket::VERSION >= 1.94) {
24 1     1   482 eval "use Net::IPv6Addr 0.2";
  1         25240  
  1         71  
25             if(!$@) {
26             $HAVE_Net_IPv6Addr = 1
27             }
28             }
29              
30             my $AF_INET6 = eval { Socket::AF_INET6() };
31              
32             ##################################################
33             # Start Public Module
34             ##################################################
35              
36             sub _ppOID {
37 0     0     return '1.3.6.1.4.1.9.9.16.1.1.1'
38             }
39              
40             sub proxy_ping {
41 0     0 1   my $self = shift;
42 0   0       my $class = ref($self) || $self;
43              
44 0           my $session = $self->{_SESSION_};
45              
46 0           my %params = (
47             count => 1,
48             size => 64,
49             wait => 1
50             );
51              
52 0           my %args;
53 0 0         if (@_ == 1) {
54 0           ($params{host}) = @_
55             } else {
56 0           %args = @_;
57 0           for (keys(%args)) {
58 0 0 0       if ((/^-?host(?:name)?$/i) || (/^-?dest(?:ination)?$/i)) {
    0 0        
    0          
    0          
    0          
    0          
59 0           $params{host} = $args{$_}
60             } elsif (/^-?size$/i) {
61 0 0         if ($args{$_} =~ /^\d+$/) {
62 0           $params{size} = $args{$_}
63             } else {
64 0           $Cisco::SNMP::LASTERROR = "Invalid size `$args{$_}'";
65             return undef
66 0           }
67             } elsif (/^-?family$/i) {
68 0 0         if ($args{$_} =~ /^(?:(?:(:?ip)?v?(?:4|6))|${\AF_INET}|$AF_INET6)$/) {
  0            
69 0 0         if ($args{$_} =~ /^(?:(?:(:?ip)?v?4)|${\AF_INET})$/) {
  0            
70 0           $params{family} = AF_INET
71             } else {
72 0           $params{family} = $AF_INET6
73             }
74             } else {
75 0           $Cisco::SNMP::LASTERROR = "Invalid family `$args{$_}'";
76             return undef
77 0           }
78             } elsif (/^-?count$/i) {
79 0 0         if ($args{$_} =~ /^\d+$/) {
80 0           $params{count} = $args{$_}
81             } else {
82 0           $Cisco::SNMP::LASTERROR = "Invalid count `$args{$_}'";
83             return undef
84 0           }
85             } elsif ((/^-?wait$/i) || (/^-?timeout$/i)) {
86 0 0         if ($args{$_} =~ /^\d+$/) {
87 0           $params{wait} = $args{$_}
88             } else {
89 0           $Cisco::SNMP::LASTERROR = "Invalid wait time `$args{$_}'";
90             return undef
91 0           }
92             } elsif (/^-?vrf(?:name)?$/i) {
93 0           $params{vrf} = $args{$_}
94             }
95             }
96             }
97 0           my $pp;
98 0           $pp->{_params_} = \%params;
99              
100             # host must be defined
101 0 0         if (!defined $params{host}) {
102 0           $params{host} = hostname
103             }
104              
105             # inherit from new()
106 0 0         if (!defined $params{family}) {
107             $params{family} = $self->{family}
108 0           }
109              
110             # resolve host our way
111 0 0         if (defined(my $ret = Cisco::SNMP::_resolv($params{host}, $params{family}))) {
112 0           $params{host} = $ret->{addr};
113             $params{family} = $ret->{family}
114 0           } else {
115             return undef
116 0           }
117              
118 0           my $instance = int(rand(1024)+1024);
119             # Prepare object by clearing row
120 0           my $response = $session->set_request(_ppOID() . '.16.' . $instance, INTEGER, 6);
121 0 0         if (!defined $response) {
122 0           $Cisco::SNMP::LASTERROR = "proxy ping NOT SUPPORTED";
123             return undef
124 0           }
125              
126             # Convert destination to Hex equivalent
127 0           my $dest;
128 0 0         if ($params{family} == AF_INET) {
129 0           for (split(/\./, $params{host})) {
130 0           $dest .= sprintf("%02x",$_)
131             }
132             } else {
133 0 0         if ($HAVE_Net_IPv6Addr) {
134 0           my $addr = Net::IPv6Addr->new($params{host});
135 0           my @dest = $addr->to_array;
136 0           $dest .= join '', $_ for (@dest)
137             } else {
138 0           $Cisco::SNMP::LASTERROR = "Socket > 1.94 and Net::IPv6Addr required";
139             return undef
140 0           }
141             }
142              
143             # ciscoPingEntryStatus (5 = createAndWait, 6 = destroy)
144 0           $response = $session->set_request(_ppOID() . '.16.' . $instance, INTEGER, 6);
145 0           $response = $session->set_request(_ppOID() . '.16.' . $instance, INTEGER, 5);
146             # ciscoPingEntryOwner ()
147 0           $response = $session->set_request(_ppOID() . '.15.' . $instance, OCTET_STRING, __PACKAGE__);
148             # ciscoPingProtocol (1 = IP, 20 = IPv6)
149 0 0         $response = $session->set_request(_ppOID() . '.2.' . $instance, INTEGER, ($params{family} == AF_INET) ? 1 : 20);
150 0 0         if (!defined $response) {
151 0           $Cisco::SNMP::LASTERROR = "Device does not support ciscoPingProtocol 20 (IPv6)";
152             return undef
153 0           }
154             # ciscoPingAddress (NOTE: hex string, not regular IP)
155 0           $response = $session->set_request(_ppOID() . '.3.' . $instance, OCTET_STRING, pack('H*', $dest));
156             # ciscoPingPacketTimeout (in ms)
157 0           $response = $session->set_request(_ppOID() . '.6.' . $instance, INTEGER32, $params{wait}*100);
158             # ciscoPingDelay (Set gaps (in ms) between successive pings)
159 0           $response = $session->set_request(_ppOID() . '.7.' . $instance, INTEGER32, $params{wait}*100);
160             # ciscoPingPacketCount
161 0           $response = $session->set_request(_ppOID() . '.4.' . $instance, INTEGER, $params{count});
162             # ciscoPingPacketSize (protocol dependent)
163 0           $response = $session->set_request(_ppOID() . '.5.' . $instance, INTEGER, $params{size});
164              
165 0 0         if (exists $params{vrf}) {
166             # ciscoPingVrfName ()
167             $response = $session->set_request(_ppOID() . '.17.' . $instance, OCTET_STRING, $params{vrf})
168 0           }
169             # Verify ping is ready (ciscoPingEntryStatus = 2)
170 0           $response = $session->get_request(_ppOID() . '.16.' . $instance);
171 0 0         if (defined $response->{_ppOID() . '.16.' . $instance}) {
172 0 0         if ($response->{_ppOID() . '.16.' . $instance} != 2) {
173 0           $Cisco::SNMP::LASTERROR = "Ping not ready";
174             return undef
175 0           }
176             } else {
177 0           $Cisco::SNMP::LASTERROR = "proxy ping NOT SUPPORTED (after setup)";
178             return undef
179 0           }
180              
181             # ciscoPingEntryStatus (1 = activate)
182 0           $response = $session->set_request(_ppOID() . '.16.' . $instance, INTEGER, 1);
183              
184             # Wait sample interval
185 0           sleep $params{wait};
186              
187             # Get results
188 0           $response = $session->get_table(_ppOID());
189 0   0       $pp->{Sent} = $response->{_ppOID() . '.9.' . $instance} || 0;
190 0   0       $pp->{Received} = $response->{_ppOID() . '.10.' . $instance} || 0;
191 0   0       $pp->{Minimum} = $response->{_ppOID() . '.11.' . $instance} || 0;
192 0   0       $pp->{Average} = $response->{_ppOID() . '.12.' . $instance} || 0;
193 0   0       $pp->{Maximum} = $response->{_ppOID() . '.13.' . $instance} || 0;
194              
195             # destroy entry
196 0           $response = $session->set_request(_ppOID() . '.16.' . $instance, INTEGER, 6);
197 0           return bless $pp, $class
198             }
199              
200             sub ppSent {
201 0     0 1   my $self = shift;
202             return $self->{Sent}
203 0           }
204              
205             sub ppReceived {
206 0     0 1   my $self = shift;
207             return $self->{Received}
208 0           }
209              
210             sub ppMinimum {
211 0     0 1   my $self = shift;
212             return $self->{Minimum}
213 0           }
214              
215             sub ppAverage {
216 0     0 1   my $self = shift;
217             return $self->{Average}
218 0           }
219              
220             sub ppMaximum {
221 0     0 1   my $self = shift;
222             return $self->{Maximum}
223 0           }
224              
225             ##################################################
226             # End Public Module
227             ##################################################
228              
229             1;
230              
231             __END__