File Coverage

blib/lib/Cisco/SNMP/Config.pm
Criterion Covered Total %
statement 18 173 10.4
branch 0 86 0.0
condition 0 12 0.0
subroutine 6 10 60.0
pod 3 3 100.0
total 27 284 9.5


line stmt bran cond sub pod time code
1             package Cisco::SNMP::Config;
2              
3             ##################################################
4             # AUTHOR = Michael Vincent
5             # www.VinsWorld.com
6             ##################################################
7              
8 1     1   13717 use strict;
  1         2  
  1         40  
9 1     1   7 use warnings;
  1         3  
  1         50  
10              
11 1     1   905 use Net::SNMP qw(:asn1);
  1         70443  
  1         400  
12 1     1   567 use Cisco::SNMP;
  1         3  
  1         63  
13              
14             our $VERSION = $Cisco::SNMP::VERSION;
15              
16             our @ISA = qw(Cisco::SNMP);
17              
18 1     1   6 use Sys::Hostname;
  1         1  
  1         58  
19 1     1   12 use Socket qw(AF_INET);
  1         1  
  1         1580  
20              
21             my $AF_INET6 = eval { Socket::AF_INET6() };
22              
23             ##################################################
24             # Start Public Module
25             ##################################################
26              
27             sub config_copy {
28 0     0 1   my $self = shift;
29 0   0       my $class = ref($self) || $self;
30              
31 0           my $session = $self->{_SESSION_};
32              
33 0           my %params = (
34             op => 'wr',
35             catos => 0,
36             timeout => 10,
37             source => 4,
38             dest => 3
39             );
40              
41 0           my %args;
42 0 0         if (@_ == 1) {
43 0           $Cisco::SNMP::LASTERROR = "Insufficient number of args";
44             return undef
45 0           } else {
46 0           %args = @_;
47 0           for (keys(%args)) {
48 0 0 0       if ((/^-?(?:tftp)?server$/i) || (/^-?tftp$/)) {
    0          
    0          
    0          
    0          
    0          
49 0           $params{tftpserver} = $args{$_}
50             } elsif (/^-?catos$/i) {
51 0 0         if ($args{$_} == 1) {
52 0           $params{catos} = 1
53             }
54             } elsif (/^-?timeout$/i) {
55 0           $params{timeout} = $args{$_}
56             } elsif (/^-?family$/i) {
57 0 0         if ($args{$_} =~ /^(?:(?:(:?ip)?v?(?:4|6))|${\AF_INET}|$AF_INET6)$/) {
  0            
58 0 0         if ($args{$_} =~ /^(?:(?:(:?ip)?v?4)|${\AF_INET})$/) {
  0            
59 0           $params{family} = AF_INET
60             } else {
61 0           $params{family} = $AF_INET6
62             }
63             } else {
64 0           $Cisco::SNMP::LASTERROR = "Invalid family `$args{$_}'";
65             return undef
66 0           }
67             } elsif (/^-?source$/i) {
68 0 0         if ($args{$_} =~ /^run(?:ning)?(?:-config)?$/i) {
    0          
69 0           $params{source} = 4
70             } elsif ($args{$_} =~ /^start(?:up)?(?:-config)?$/i) {
71 0           $params{source} = 3
72             } else {
73 0           $params{source} = 1;
74 0           $params{op} = 'put';
75 0           $params{file} = $args{$_}
76             }
77             } elsif (/^-?dest(?:ination)?$/i) {
78 0 0         if ($args{$_} =~ /^run(?:ning)?(?:-config)?$/i) {
    0          
79 0           $params{dest} = 4
80             } elsif ($args{$_} =~ /^start(?:up)?(?:-config)?$/i) {
81 0           $params{dest} = 3
82             } else {
83 0           $params{dest} = 1;
84 0           $params{op} = 'get';
85 0           $params{file} = $args{$_}
86             }
87             }
88             }
89             }
90 0           my $cc;
91 0           $cc->{_params_} = \%params;
92              
93 0 0         if ($params{source} == $params{dest}) {
94 0           $Cisco::SNMP::LASTERROR = "Source and destination cannot be same";
95             return undef
96 0           }
97              
98             # tftpserver must be defined if put/get
99 0 0 0       if (($params{op} ne 'wr') && !defined $params{tftpserver}) {
100 0           $params{tftpserver} = hostname
101             }
102              
103             # inherit from new()
104 0 0         if (!defined $params{family}) {
105             $params{family} = $self->{family}
106 0           }
107              
108             # resolve tftpserver our way
109 0 0         if (defined $params{tftpserver}) {
110 0 0         if (defined(my $ret = Cisco::SNMP::_resolv($params{tftpserver}, $params{family}))) {
111 0           $params{tftpserver} = $ret->{addr};
112             $params{family} = $ret->{family}
113 0           } else {
114             return undef
115 0           }
116 0 0 0       if ($params{catos} && ($params{family} == $AF_INET6)) {
117 0           $Cisco::SNMP::LASTERROR = "CatOS does not support IPv6";
118             return undef
119 0           }
120             }
121              
122 0           my $response;
123 0           my $instance = int(rand(1024)+1024);
124 0           my %ioserr = (
125             1 => "Unknown",
126             2 => "Bad file name",
127             3 => "Timeout",
128             4 => "No memory",
129             5 => "No config",
130             6 => "Unsupported protocol",
131             7 => "Config apply fail",
132             8 => "System not ready",
133             9 => "Request abort"
134             );
135              
136             # wr mem
137 0 0         if ($params{op} eq 'wr') {
138 0 0         if ($params{catos}) {
139 0           $Cisco::SNMP::LASTERROR = "CatOS does not support `copy run start'";
140             return undef
141 0           }
142             # ccCopyEntryRowStatus (5 = createAndWait, 6 = destroy)
143 0           $response = $session->set_request('1.3.6.1.4.1.9.9.96.1.1.1.1.14.' . $instance, INTEGER, 6);
144              
145 0 0         if (!defined $response) {
146             # copy run start NOT SUPPORTED - trying old way
147 0           $response = $session->set_request('1.3.6.1.4.1.9.2.1.54.0', INTEGER, 1);
148 0 0         if (defined $response) {
149 0           return bless $cc, $class
150             } else {
151 0           $Cisco::SNMP::LASTERROR = "`copy run start' FAILED (new and old)";
152             return undef
153 0           }
154             }
155              
156             # ccCopySourceFileType (1 = networkFile, 3 = startupConfig, 4 = runningConfig)
157 0           $response = $session->set_request('1.3.6.1.4.1.9.9.96.1.1.1.1.3.' . $instance, INTEGER, $params{source});
158             # ccCopyDestFileType (1 = networkFile, 3 = startupConfig, 4 = runningConfig)
159             $response = $session->set_request('1.3.6.1.4.1.9.9.96.1.1.1.1.4.' . $instance, INTEGER, $params{dest})
160              
161             # TFTP PUT/GET (to/from device)
162 0           } else {
163 0           $response = _config_copy(\%params, $session, $instance);
164 0 0         if ($response == 0) {
    0          
165 0           return bless $cc, $class
166             } elsif ($response == -1) {
167             return undef
168 0           }
169             # $response == 1, continue ...
170             }
171              
172             # ccCopyEntryRowStatus (4 = createAndGo, 6 = destroy)
173 0           $response = $session->set_request('1.3.6.1.4.1.9.9.96.1.1.1.1.14.' . $instance, INTEGER, 1);
174              
175             # Check status, wait done
176 0           $response = $session->get_request('1.3.6.1.4.1.9.9.96.1.1.1.1.10.' . $instance);
177 0 0         if (!defined $response) {
178 0           $Cisco::SNMP::LASTERROR = "tftp NOT SUPPORTED (after setup)";
179             return undef
180 0           }
181              
182             # loop and check response - error if timeout
183 0           my $loop = 0;
184 0           while ($response->{'1.3.6.1.4.1.9.9.96.1.1.1.1.10.' . $instance} <= 2) {
185 0           $response = $session->get_request('1.3.6.1.4.1.9.9.96.1.1.1.1.10.' . $instance);
186 0 0         if (!defined $response) {
187 0           $Cisco::SNMP::LASTERROR = "IOS TFTP `$params{op}' FAILED - cannot verify completion";
188             return undef
189 0           }
190 0 0         if ($loop++ == $params{timeout}) {
191 0           $Cisco::SNMP::LASTERROR = "IOS TFTP `$params{op}' FAILED - timeout during completion verification";
192             return undef
193 0           }
194 0           sleep 1
195             }
196              
197             # Success
198 0 0         if ($response->{'1.3.6.1.4.1.9.9.96.1.1.1.1.10.' . $instance} == 3) {
    0          
199 0           $response = $session->get_request('1.3.6.1.4.1.9.9.96.1.1.1.1.11.' . $instance);
200 0           $cc->{StartTime} = $response->{'1.3.6.1.4.1.9.9.96.1.1.1.1.11.' . $instance};
201 0           $response = $session->get_request('1.3.6.1.4.1.9.9.96.1.1.1.1.12.' . $instance);
202 0           $cc->{EndTime} = $response->{'1.3.6.1.4.1.9.9.96.1.1.1.1.12.' . $instance};
203 0           $session->set_request('1.3.6.1.4.1.9.9.96.1.1.1.1.14.' . $instance, INTEGER, 6);
204 0           return bless $cc, $class
205             # Error
206             } elsif ($response->{'1.3.6.1.4.1.9.9.96.1.1.1.1.10.' . $instance} == 4) {
207 0           $response = $session->get_request('1.3.6.1.4.1.9.9.96.1.1.1.1.13.' . $instance);
208 0           $session->set_request('1.3.6.1.4.1.9.9.96.1.1.1.1.14.' . $instance, INTEGER, 6);
209 0           $Cisco::SNMP::LASTERROR = "IOS TFTP `$params{op}' FAILED - " . $ioserr{$response->{'1.3.6.1.4.1.9.9.96.1.1.1.1.13.' . $instance}};
210             return undef
211 0           } else {
212 0           $Cisco::SNMP::LASTERROR = "Cannot determine success or failure";
213             return undef
214 0           }
215             }
216              
217             sub ccStartTime {
218 0     0 1   my $self = shift;
219             return $self->{StartTime}
220 0           }
221              
222             sub ccEndTime {
223 0     0 1   my $self = shift;
224             return $self->{EndTime}
225 0           }
226              
227             ##################################################
228             # End Public Module
229             ##################################################
230              
231             ##################################################
232             # Start Private subs
233             ##################################################
234              
235             # Return:
236             # -1 = error
237             # 0 = DONE
238             # 1 = continue
239             sub _config_copy {
240              
241 0     0     my ($params, $session, $instance) = @_;
242              
243 0           my $response;
244 0           my %caterr = (
245             1 => "In Progress",
246             2 => "Success",
247             3 => "No Response",
248             4 => "Too Many Retries",
249             5 => "No Buffers",
250             6 => "No Processes",
251             7 => "Bad Checksum",
252             8 => "Bad Length",
253             9 => "Bad Flash",
254             10 => "Server Error",
255             11 => "User Cancelled",
256             12 => "Wrong Code",
257             13 => "File Not Found",
258             14 => "Invalid TFTP Host",
259             15 => "Invalid TFTP Module",
260             16 => "Access Violation",
261             17 => "Unknown Status",
262             18 => "Invalid Storage Device",
263             19 => "Insufficient Space On Storage Device",
264             20 => "Insufficient Dram Size",
265             21 => "Incompatible Image"
266             );
267              
268 0 0         if ($params->{catos}) {
269 0           $response = $session->set_request('1.3.6.1.4.1.9.5.1.5.1.0', OCTET_STRING, $params->{tftpserver});
270 0           $response = $session->set_request('1.3.6.1.4.1.9.5.1.5.2.0', OCTET_STRING, $params->{file});
271 0           $response = $session->set_request('1.3.6.1.4.1.9.5.1.5.3.0', INTEGER, 1);
272 0 0         if ($params->{op} eq 'put') {
273 0           $response = $session->set_request('1.3.6.1.4.1.9.5.1.5.4.0', INTEGER, 2)
274             } else {
275 0           $response = $session->set_request('1.3.6.1.4.1.9.5.1.5.4.0', INTEGER, 3)
276             }
277              
278             # loop and check response - error if timeout
279 0           $response = $session->get_request('1.3.6.1.4.1.9.5.1.5.5.0');
280 0           my $loop = 0;
281 0           while ($response->{'1.3.6.1.4.1.9.5.1.5.5.0'} == 1) {
282 0           $response = $session->get_request('1.3.6.1.4.1.9.5.1.5.5.0');
283 0 0         if ($loop++ == $params->{timeout}) {
284 0           $Cisco::SNMP::LASTERROR = "CatOS TFTP `$params->{op}' FAILED - timeout during completion verification";
285 0           return -1
286             }
287 0           sleep 1
288             }
289              
290 0 0         if ($response->{'1.3.6.1.4.1.9.5.1.5.5.0'} == 2) {
291 0           return 0
292             } else {
293 0           $Cisco::SNMP::LASTERROR = "CatOS TFTP `$params->{op}' FAILED - " . $caterr{$response->{'1.3.6.1.4.1.9.5.1.5.5.0'}};
294 0           return -1
295             }
296              
297             # IOS
298             } else {
299             # ccCopyEntryRowStatus (5 = createAndWait, 6 = destroy)
300 0           $response = $session->set_request('1.3.6.1.4.1.9.9.96.1.1.1.1.14.' . $instance, INTEGER, 6);
301 0           $response = $session->set_request('1.3.6.1.4.1.9.9.96.1.1.1.1.14.' . $instance, INTEGER, 5);
302              
303             # ccCopyProtocol (1 = TFTP)
304 0           $response = $session->set_request('1.3.6.1.4.1.9.9.96.1.1.1.1.2.' . $instance, INTEGER, 1);
305              
306 0 0         if (!defined $response) {
307 0           $Cisco::SNMP::LASTERROR = "IOS TFTP `$params->{op}' NOT SUPPORTED - trying old way";
308 0 0         if ($params->{family} == $AF_INET6) {
309 0           $Cisco::SNMP::LASTERROR = "IOS TFTP `$params->{op}' old way does not support IPv6";
310 0           return -1
311             }
312 0 0         if ($params->{op} eq 'put') {
313             $response = $session->set_request('1.3.6.1.4.1.9.2.1.50.' . $params->{tftpserver}, OCTET_STRING, $params->{file})
314 0           } else {
315             $response = $session->set_request('1.3.6.1.4.1.9.2.1.55.' . $params->{tftpserver}, OCTET_STRING, $params->{file})
316 0           }
317 0 0         if (defined $response) {
318 0           return 0
319             } else {
320 0           $Cisco::SNMP::LASTERROR = "IOS TFTP `$params->{op}' FAILED (new and old)";
321 0           return -1
322             }
323             }
324             # ccCopySourceFileType [.3] (1 = networkFile, 3 = startupConfig, 4 = runningConfig)
325             # ccCopyDestFileType [.4] (1 = networkFile, 3 = startupConfig, 4 = runningConfig)
326 0 0         if ($params->{op} eq 'put') {
327 0           $response = $session->set_request('1.3.6.1.4.1.9.9.96.1.1.1.1.3.' . $instance, INTEGER, 1);
328             $response = $session->set_request('1.3.6.1.4.1.9.9.96.1.1.1.1.4.' . $instance, INTEGER, $params->{dest})
329 0           } else {
330 0           $response = $session->set_request('1.3.6.1.4.1.9.9.96.1.1.1.1.3.' . $instance, INTEGER, $params->{source});
331 0           $response = $session->set_request('1.3.6.1.4.1.9.9.96.1.1.1.1.4.' . $instance, INTEGER, 1)
332             }
333             # New way
334             # ccCopyServerAddressType (1 = IPv4, 2 = IPv6)
335 0 0         $response = $session->set_request('1.3.6.1.4.1.9.9.96.1.1.1.1.15.' . $instance, INTEGER, ($params->{family} == AF_INET) ? 1 : 2);
336              
337 0 0         if (defined $response) {
338             # ccCopyServerAddressRev1
339             $response = $session->set_request('1.3.6.1.4.1.9.9.96.1.1.1.1.16.' . $instance, OCTET_STRING, $params->{tftpserver})
340 0           } else {
341             # Deprecated
342             # ccCopyServerAddress
343 0 0         if ($params->{family} == $AF_INET6) {
344 0           $Cisco::SNMP::LASTERROR = "ccCopyServerAddressRev1 not supported (requried for IPv6)";
345 0           return -1
346             }
347             $response = $session->set_request('1.3.6.1.4.1.9.9.96.1.1.1.1.5.' . $instance, IPADDRESS, $params->{tftpserver})
348 0           }
349             # ccCopyFileName
350             $response = $session->set_request('1.3.6.1.4.1.9.9.96.1.1.1.1.6.' . $instance, OCTET_STRING, $params->{file})
351 0           }
352 0           return 1
353             }
354              
355             ##################################################
356             # End Private subs
357             ##################################################
358              
359             1;
360              
361             __END__