| 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 |  | 45585 | use strict; | 
|  | 1 |  |  |  |  | 10 |  | 
|  | 1 |  |  |  |  | 26 |  | 
| 9 | 1 |  |  | 1 |  | 5 | use warnings; | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 25 |  | 
| 10 |  |  |  |  |  |  |  | 
| 11 | 1 |  |  | 1 |  | 562 | use Net::SNMP qw(:asn1); | 
|  | 1 |  |  |  |  | 59470 |  | 
|  | 1 |  |  |  |  | 223 |  | 
| 12 | 1 |  |  | 1 |  | 379 | use Cisco::SNMP; | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 54 |  | 
| 13 |  |  |  |  |  |  |  | 
| 14 |  |  |  |  |  |  | our $VERSION = $Cisco::SNMP::VERSION; | 
| 15 |  |  |  |  |  |  |  | 
| 16 |  |  |  |  |  |  | our @ISA = qw(Cisco::SNMP); | 
| 17 |  |  |  |  |  |  |  | 
| 18 | 1 |  |  | 1 |  | 7 | use Sys::Hostname; | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 41 |  | 
| 19 | 1 |  |  | 1 |  | 5 | use Socket qw(AF_INET); | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 1620 |  | 
| 20 |  |  |  |  |  |  |  | 
| 21 |  |  |  |  |  |  | my $AF_INET6 = eval { Socket::AF_INET6() }; | 
| 22 |  |  |  |  |  |  |  | 
| 23 |  |  |  |  |  |  | my %PROTO = ( | 
| 24 |  |  |  |  |  |  | tftp => 1, | 
| 25 |  |  |  |  |  |  | ftp  => 2, | 
| 26 |  |  |  |  |  |  | rcp  => 3, | 
| 27 |  |  |  |  |  |  | scp  => 4, | 
| 28 |  |  |  |  |  |  | sftp => 5 | 
| 29 |  |  |  |  |  |  | ); | 
| 30 |  |  |  |  |  |  |  | 
| 31 |  |  |  |  |  |  | ################################################## | 
| 32 |  |  |  |  |  |  | # Start Public Module | 
| 33 |  |  |  |  |  |  | ################################################## | 
| 34 |  |  |  |  |  |  |  | 
| 35 |  |  |  |  |  |  | sub config_copy { | 
| 36 | 0 |  |  | 0 | 1 |  | my $self = shift; | 
| 37 | 0 |  | 0 |  |  |  | my $class = ref($self) || $self; | 
| 38 |  |  |  |  |  |  |  | 
| 39 | 0 |  |  |  |  |  | my $session = $self->{_SESSION_}; | 
| 40 |  |  |  |  |  |  |  | 
| 41 | 0 |  |  |  |  |  | my %params = ( | 
| 42 |  |  |  |  |  |  | op       => 'wr', | 
| 43 |  |  |  |  |  |  | catos    => 0, | 
| 44 |  |  |  |  |  |  | timeout  => 10, | 
| 45 |  |  |  |  |  |  | source   => 4, | 
| 46 |  |  |  |  |  |  | dest     => 3, | 
| 47 |  |  |  |  |  |  | protocol => 'tftp', | 
| 48 |  |  |  |  |  |  | username => 'cisco', | 
| 49 |  |  |  |  |  |  | password => 'cisco' | 
| 50 |  |  |  |  |  |  | ); | 
| 51 |  |  |  |  |  |  |  | 
| 52 | 0 |  |  |  |  |  | my %args; | 
| 53 | 0 | 0 |  |  |  |  | if ( @_ == 1 ) { | 
| 54 | 0 |  |  |  |  |  | $Cisco::SNMP::LASTERROR = "Insufficient number of args"; | 
| 55 | 0 |  |  |  |  |  | return undef; | 
| 56 |  |  |  |  |  |  | } else { | 
| 57 | 0 |  |  |  |  |  | %args = @_; | 
| 58 | 0 |  |  |  |  |  | for ( keys(%args) ) { | 
| 59 | 0 | 0 | 0 |  |  |  | if ( (/^-?(?:tftp)?server$/i) || (/^-?tftp$/) ) { | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 60 | 0 |  |  |  |  |  | $params{server} = $args{$_}; | 
| 61 |  |  |  |  |  |  | } elsif (/^-?catos$/i) { | 
| 62 | 0 | 0 |  |  |  |  | if ( $args{$_} == 1 ) { | 
| 63 | 0 |  |  |  |  |  | $params{catos} = 1; | 
| 64 |  |  |  |  |  |  | } | 
| 65 |  |  |  |  |  |  | } elsif (/^-?user(?:name)?$/i) { | 
| 66 | 0 |  |  |  |  |  | $params{username} = $args{$_}; | 
| 67 |  |  |  |  |  |  | } elsif (/^-?pass(?:word)?$/i) { | 
| 68 | 0 |  |  |  |  |  | $params{password} = $args{$_}; | 
| 69 |  |  |  |  |  |  | } elsif (/^-?timeout$/i) { | 
| 70 | 0 |  |  |  |  |  | $params{timeout} = $args{$_}; | 
| 71 |  |  |  |  |  |  | } elsif (/^-?proto(?:col)?$/i) { | 
| 72 | 0 | 0 |  |  |  |  | if ( exists( $PROTO{lc( $args{$_} )} ) ) { | 
| 73 | 0 |  |  |  |  |  | $params{protocol} = lc( $args{$_} ); | 
| 74 |  |  |  |  |  |  | } else { | 
| 75 | 0 |  |  |  |  |  | $Cisco::SNMP::LASTERROR = "Invalid protocol `$args{$_}'"; | 
| 76 | 0 |  |  |  |  |  | return undef; | 
| 77 |  |  |  |  |  |  | } | 
| 78 |  |  |  |  |  |  | } elsif (/^-?family$/i) { | 
| 79 | 0 | 0 |  |  |  |  | if ( $args{$_} | 
| 80 | 0 |  |  |  |  |  | =~ /^(?:(?:(:?ip)?v?(?:4|6))|${\AF_INET}|$AF_INET6)$/ ) { | 
| 81 | 0 | 0 |  |  |  |  | if ( $args{$_} =~ /^(?:(?:(:?ip)?v?4)|${\AF_INET})$/ ) { | 
|  | 0 |  |  |  |  |  |  | 
| 82 | 0 |  |  |  |  |  | $params{family} = AF_INET; | 
| 83 |  |  |  |  |  |  | } else { | 
| 84 | 0 |  |  |  |  |  | $params{family} = $AF_INET6; | 
| 85 |  |  |  |  |  |  | } | 
| 86 |  |  |  |  |  |  | } else { | 
| 87 | 0 |  |  |  |  |  | $Cisco::SNMP::LASTERROR = "Invalid family `$args{$_}'"; | 
| 88 | 0 |  |  |  |  |  | return undef; | 
| 89 |  |  |  |  |  |  | } | 
| 90 |  |  |  |  |  |  | } elsif (/^-?source$/i) { | 
| 91 | 0 | 0 |  |  |  |  | if ( $args{$_} =~ /^run(?:ning)?(?:-config)?$/i ) { | 
|  |  | 0 |  |  |  |  |  | 
| 92 | 0 |  |  |  |  |  | $params{source} = 4; | 
| 93 |  |  |  |  |  |  | } elsif ( $args{$_} =~ /^start(?:up)?(?:-config)?$/i ) { | 
| 94 | 0 |  |  |  |  |  | $params{source} = 3; | 
| 95 |  |  |  |  |  |  | } else { | 
| 96 | 0 |  |  |  |  |  | $params{source} = 1; | 
| 97 | 0 |  |  |  |  |  | $params{op}     = 'put'; | 
| 98 | 0 |  |  |  |  |  | $params{file}   = $args{$_}; | 
| 99 |  |  |  |  |  |  | } | 
| 100 |  |  |  |  |  |  | } elsif (/^-?dest(?:ination)?$/i) { | 
| 101 | 0 | 0 |  |  |  |  | if ( $args{$_} =~ /^run(?:ning)?(?:-config)?$/i ) { | 
|  |  | 0 |  |  |  |  |  | 
| 102 | 0 |  |  |  |  |  | $params{dest} = 4; | 
| 103 |  |  |  |  |  |  | } elsif ( $args{$_} =~ /^start(?:up)?(?:-config)?$/i ) { | 
| 104 | 0 |  |  |  |  |  | $params{dest} = 3; | 
| 105 |  |  |  |  |  |  | } else { | 
| 106 | 0 |  |  |  |  |  | $params{dest} = 1; | 
| 107 | 0 |  |  |  |  |  | $params{op}   = 'get'; | 
| 108 | 0 |  |  |  |  |  | $params{file} = $args{$_}; | 
| 109 |  |  |  |  |  |  | } | 
| 110 |  |  |  |  |  |  | } | 
| 111 |  |  |  |  |  |  | } | 
| 112 |  |  |  |  |  |  | } | 
| 113 | 0 |  |  |  |  |  | my $cc; | 
| 114 | 0 |  |  |  |  |  | $cc->{_params_} = \%params; | 
| 115 |  |  |  |  |  |  |  | 
| 116 | 0 | 0 |  |  |  |  | if ( $params{source} == $params{dest} ) { | 
| 117 | 0 |  |  |  |  |  | $Cisco::SNMP::LASTERROR = "Source and destination cannot be same"; | 
| 118 | 0 |  |  |  |  |  | return undef; | 
| 119 |  |  |  |  |  |  | } | 
| 120 |  |  |  |  |  |  |  | 
| 121 |  |  |  |  |  |  | # server must be defined if put/get | 
| 122 | 0 | 0 | 0 |  |  |  | if ( ( $params{op} ne 'wr' ) and not defined $params{server} ) { | 
| 123 | 0 |  |  |  |  |  | $params{server} = hostname; | 
| 124 |  |  |  |  |  |  | } | 
| 125 |  |  |  |  |  |  |  | 
| 126 |  |  |  |  |  |  | # inherit from new() | 
| 127 | 0 | 0 |  |  |  |  | if ( not defined $params{family} ) { | 
| 128 | 0 |  |  |  |  |  | $params{family} = $self->{family}; | 
| 129 |  |  |  |  |  |  | } | 
| 130 |  |  |  |  |  |  |  | 
| 131 | 0 | 0 | 0 |  |  |  | if ( $params{catos} and $params{protocol} ne 'tftp' ) { | 
| 132 | 0 |  |  |  |  |  | $Cisco::SNMP::LASTERROR = "CatOS only supports tftp"; | 
| 133 | 0 |  |  |  |  |  | return undef; | 
| 134 |  |  |  |  |  |  | } | 
| 135 |  |  |  |  |  |  |  | 
| 136 |  |  |  |  |  |  | # resolve server our way | 
| 137 | 0 | 0 |  |  |  |  | if ( defined $params{server} ) { | 
| 138 | 0 | 0 |  |  |  |  | if (defined( | 
| 139 |  |  |  |  |  |  | my $ret | 
| 140 |  |  |  |  |  |  | = Cisco::SNMP::_resolv( $params{server}, $params{family} ) | 
| 141 |  |  |  |  |  |  | ) | 
| 142 |  |  |  |  |  |  | ) { | 
| 143 | 0 |  |  |  |  |  | $params{server} = $ret->{addr}; | 
| 144 | 0 |  |  |  |  |  | $params{family} = $ret->{family}; | 
| 145 |  |  |  |  |  |  | } else { | 
| 146 | 0 |  |  |  |  |  | return undef; | 
| 147 |  |  |  |  |  |  | } | 
| 148 | 0 | 0 | 0 |  |  |  | if ( $params{catos} and $params{family} == $AF_INET6 ) { | 
| 149 | 0 |  |  |  |  |  | $Cisco::SNMP::LASTERROR = "CatOS does not support IPv6"; | 
| 150 | 0 |  |  |  |  |  | return undef; | 
| 151 |  |  |  |  |  |  | } | 
| 152 |  |  |  |  |  |  | } | 
| 153 |  |  |  |  |  |  |  | 
| 154 | 0 |  |  |  |  |  | my $response; | 
| 155 | 0 |  |  |  |  |  | my $instance = int( rand(1024) + 1024 ); | 
| 156 | 0 |  |  |  |  |  | my %ioserr   = ( | 
| 157 |  |  |  |  |  |  | 1 => "Unknown", | 
| 158 |  |  |  |  |  |  | 2 => "Bad file name", | 
| 159 |  |  |  |  |  |  | 3 => "Timeout", | 
| 160 |  |  |  |  |  |  | 4 => "No memory", | 
| 161 |  |  |  |  |  |  | 5 => "No config", | 
| 162 |  |  |  |  |  |  | 6 => "Unsupported protocol", | 
| 163 |  |  |  |  |  |  | 7 => "Config apply fail", | 
| 164 |  |  |  |  |  |  | 8 => "System not ready", | 
| 165 |  |  |  |  |  |  | 9 => "Request abort" | 
| 166 |  |  |  |  |  |  | ); | 
| 167 |  |  |  |  |  |  |  | 
| 168 |  |  |  |  |  |  | # wr mem | 
| 169 | 0 | 0 |  |  |  |  | if ( $params{op} eq 'wr' ) { | 
| 170 | 0 | 0 |  |  |  |  | if ( $params{catos} ) { | 
| 171 | 0 |  |  |  |  |  | $Cisco::SNMP::LASTERROR | 
| 172 |  |  |  |  |  |  | = "CatOS does not support `copy run start'"; | 
| 173 | 0 |  |  |  |  |  | return undef; | 
| 174 |  |  |  |  |  |  | } | 
| 175 |  |  |  |  |  |  |  | 
| 176 |  |  |  |  |  |  | # ccCopyEntryRowStatus (5 = createAndWait, 6 = destroy) | 
| 177 |  |  |  |  |  |  | $response | 
| 178 | 0 |  |  |  |  |  | = $session->set_request( | 
| 179 |  |  |  |  |  |  | '1.3.6.1.4.1.9.9.96.1.1.1.1.14.' . $instance, | 
| 180 |  |  |  |  |  |  | INTEGER, 6 ); | 
| 181 |  |  |  |  |  |  |  | 
| 182 | 0 | 0 |  |  |  |  | if ( not defined $response ) { | 
| 183 |  |  |  |  |  |  |  | 
| 184 |  |  |  |  |  |  | # copy run start NOT SUPPORTED - trying old way | 
| 185 | 0 |  |  |  |  |  | $response | 
| 186 |  |  |  |  |  |  | = $session->set_request( '1.3.6.1.4.1.9.2.1.54.0', INTEGER, 1 ); | 
| 187 | 0 | 0 |  |  |  |  | if ( defined $response ) { | 
| 188 | 0 |  |  |  |  |  | return bless $cc, $class; | 
| 189 |  |  |  |  |  |  | } else { | 
| 190 | 0 |  |  |  |  |  | $Cisco::SNMP::LASTERROR | 
| 191 |  |  |  |  |  |  | = "`copy run start' FAILED (new and old)"; | 
| 192 | 0 |  |  |  |  |  | return undef; | 
| 193 |  |  |  |  |  |  | } | 
| 194 |  |  |  |  |  |  | } | 
| 195 |  |  |  |  |  |  |  | 
| 196 |  |  |  |  |  |  | # ccCopySourceFileType (1 = networkFile, 3 = startupConfig, 4 = runningConfig) | 
| 197 |  |  |  |  |  |  | $response | 
| 198 |  |  |  |  |  |  | = $session->set_request( | 
| 199 |  |  |  |  |  |  | '1.3.6.1.4.1.9.9.96.1.1.1.1.3.' . $instance, | 
| 200 | 0 |  |  |  |  |  | INTEGER, $params{source} ); | 
| 201 |  |  |  |  |  |  |  | 
| 202 |  |  |  |  |  |  | # ccCopyDestFileType (1 = networkFile, 3 = startupConfig, 4 = runningConfig) | 
| 203 |  |  |  |  |  |  | $response | 
| 204 |  |  |  |  |  |  | = $session->set_request( | 
| 205 |  |  |  |  |  |  | '1.3.6.1.4.1.9.9.96.1.1.1.1.4.' . $instance, | 
| 206 |  |  |  |  |  |  | INTEGER, $params{dest} ) | 
| 207 |  |  |  |  |  |  |  | 
| 208 |  |  |  |  |  |  | # TFTP PUT/GET (to/from device) | 
| 209 | 0 |  |  |  |  |  | } else { | 
| 210 | 0 |  |  |  |  |  | $response = _config_copy( \%params, $session, $instance ); | 
| 211 | 0 | 0 |  |  |  |  | if ( $response == 0 ) { | 
|  |  | 0 |  |  |  |  |  | 
| 212 | 0 |  |  |  |  |  | return bless $cc, $class; | 
| 213 |  |  |  |  |  |  | } elsif ( $response == -1 ) { | 
| 214 | 0 |  |  |  |  |  | return undef; | 
| 215 |  |  |  |  |  |  | } | 
| 216 |  |  |  |  |  |  |  | 
| 217 |  |  |  |  |  |  | # $response == 1, continue ... | 
| 218 |  |  |  |  |  |  | } | 
| 219 |  |  |  |  |  |  |  | 
| 220 |  |  |  |  |  |  | # ccCopyEntryRowStatus (4 = createAndGo, 6 = destroy) | 
| 221 | 0 |  |  |  |  |  | $response | 
| 222 |  |  |  |  |  |  | = $session->set_request( '1.3.6.1.4.1.9.9.96.1.1.1.1.14.' . $instance, | 
| 223 |  |  |  |  |  |  | INTEGER, 1 ); | 
| 224 |  |  |  |  |  |  |  | 
| 225 |  |  |  |  |  |  | # Check status, wait done | 
| 226 | 0 |  |  |  |  |  | $response | 
| 227 |  |  |  |  |  |  | = $session->get_request( '1.3.6.1.4.1.9.9.96.1.1.1.1.10.' . $instance ); | 
| 228 | 0 | 0 |  |  |  |  | if ( not defined $response ) { | 
| 229 | 0 |  |  |  |  |  | $Cisco::SNMP::LASTERROR | 
| 230 |  |  |  |  |  |  | = "$params{protocol} NOT SUPPORTED (after setup)"; | 
| 231 | 0 |  |  |  |  |  | return undef; | 
| 232 |  |  |  |  |  |  | } | 
| 233 |  |  |  |  |  |  |  | 
| 234 |  |  |  |  |  |  | # loop and check response - error if timeout | 
| 235 | 0 |  |  |  |  |  | my $loop = 0; | 
| 236 | 0 |  |  |  |  |  | while ( $response->{'1.3.6.1.4.1.9.9.96.1.1.1.1.10.' . $instance} <= 2 ) { | 
| 237 | 0 |  |  |  |  |  | $response = $session->get_request( | 
| 238 |  |  |  |  |  |  | '1.3.6.1.4.1.9.9.96.1.1.1.1.10.' . $instance ); | 
| 239 | 0 | 0 |  |  |  |  | if ( not defined $response ) { | 
| 240 | 0 |  |  |  |  |  | $Cisco::SNMP::LASTERROR | 
| 241 |  |  |  |  |  |  | = "IOS $params{protocol} `$params{op}' FAILED - cannot verify completion"; | 
| 242 | 0 |  |  |  |  |  | return undef; | 
| 243 |  |  |  |  |  |  | } | 
| 244 | 0 | 0 |  |  |  |  | if ( $loop++ == $params{timeout} ) { | 
| 245 | 0 |  |  |  |  |  | $Cisco::SNMP::LASTERROR | 
| 246 |  |  |  |  |  |  | = "IOS $params{protocol} `$params{op}' FAILED - timeout during completion verification"; | 
| 247 | 0 |  |  |  |  |  | return undef; | 
| 248 |  |  |  |  |  |  | } | 
| 249 | 0 |  |  |  |  |  | sleep 1; | 
| 250 |  |  |  |  |  |  | } | 
| 251 |  |  |  |  |  |  |  | 
| 252 |  |  |  |  |  |  | # Success | 
| 253 | 0 | 0 |  |  |  |  | if ( $response->{'1.3.6.1.4.1.9.9.96.1.1.1.1.10.' . $instance} == 3 ) { | 
|  |  | 0 |  |  |  |  |  | 
| 254 | 0 |  |  |  |  |  | $response = $session->get_request( | 
| 255 |  |  |  |  |  |  | '1.3.6.1.4.1.9.9.96.1.1.1.1.11.' . $instance ); | 
| 256 |  |  |  |  |  |  | $cc->{StartTime} | 
| 257 | 0 |  |  |  |  |  | = $response->{'1.3.6.1.4.1.9.9.96.1.1.1.1.11.' . $instance}; | 
| 258 | 0 |  |  |  |  |  | $response = $session->get_request( | 
| 259 |  |  |  |  |  |  | '1.3.6.1.4.1.9.9.96.1.1.1.1.12.' . $instance ); | 
| 260 |  |  |  |  |  |  | $cc->{EndTime} | 
| 261 | 0 |  |  |  |  |  | = $response->{'1.3.6.1.4.1.9.9.96.1.1.1.1.12.' . $instance}; | 
| 262 | 0 |  |  |  |  |  | $session->set_request( '1.3.6.1.4.1.9.9.96.1.1.1.1.14.' . $instance, | 
| 263 |  |  |  |  |  |  | INTEGER, 6 ); | 
| 264 | 0 |  |  |  |  |  | return bless $cc, $class | 
| 265 |  |  |  |  |  |  |  | 
| 266 |  |  |  |  |  |  | # Error | 
| 267 |  |  |  |  |  |  | } elsif ( $response->{'1.3.6.1.4.1.9.9.96.1.1.1.1.10.' . $instance} == 4 ) | 
| 268 |  |  |  |  |  |  | { | 
| 269 | 0 |  |  |  |  |  | $response = $session->get_request( | 
| 270 |  |  |  |  |  |  | '1.3.6.1.4.1.9.9.96.1.1.1.1.13.' . $instance ); | 
| 271 | 0 |  |  |  |  |  | $session->set_request( '1.3.6.1.4.1.9.9.96.1.1.1.1.14.' . $instance, | 
| 272 |  |  |  |  |  |  | INTEGER, 6 ); | 
| 273 |  |  |  |  |  |  | $Cisco::SNMP::LASTERROR | 
| 274 |  |  |  |  |  |  | = "IOS $params{protocol} `$params{op}' FAILED - " | 
| 275 | 0 |  |  |  |  |  | . $ioserr{$response->{'1.3.6.1.4.1.9.9.96.1.1.1.1.13.' . $instance} | 
| 276 |  |  |  |  |  |  | }; | 
| 277 | 0 |  |  |  |  |  | return undef; | 
| 278 |  |  |  |  |  |  | } else { | 
| 279 | 0 |  |  |  |  |  | $Cisco::SNMP::LASTERROR = "Cannot determine success or failure"; | 
| 280 | 0 |  |  |  |  |  | return undef; | 
| 281 |  |  |  |  |  |  | } | 
| 282 |  |  |  |  |  |  | } | 
| 283 |  |  |  |  |  |  |  | 
| 284 |  |  |  |  |  |  | sub ccStartTime { | 
| 285 | 0 |  |  | 0 | 1 |  | my $self = shift; | 
| 286 | 0 |  |  |  |  |  | return $self->{StartTime}; | 
| 287 |  |  |  |  |  |  | } | 
| 288 |  |  |  |  |  |  |  | 
| 289 |  |  |  |  |  |  | sub ccEndTime { | 
| 290 | 0 |  |  | 0 | 1 |  | my $self = shift; | 
| 291 | 0 |  |  |  |  |  | return $self->{EndTime}; | 
| 292 |  |  |  |  |  |  | } | 
| 293 |  |  |  |  |  |  |  | 
| 294 |  |  |  |  |  |  | ################################################## | 
| 295 |  |  |  |  |  |  | # End Public Module | 
| 296 |  |  |  |  |  |  | ################################################## | 
| 297 |  |  |  |  |  |  |  | 
| 298 |  |  |  |  |  |  | ################################################## | 
| 299 |  |  |  |  |  |  | # Start Private subs | 
| 300 |  |  |  |  |  |  | ################################################## | 
| 301 |  |  |  |  |  |  |  | 
| 302 |  |  |  |  |  |  | # Return: | 
| 303 |  |  |  |  |  |  | # -1 = error | 
| 304 |  |  |  |  |  |  | #  0 = DONE | 
| 305 |  |  |  |  |  |  | #  1 = continue | 
| 306 |  |  |  |  |  |  | sub _config_copy { | 
| 307 |  |  |  |  |  |  |  | 
| 308 | 0 |  |  | 0 |  |  | my ( $params, $session, $instance ) = @_; | 
| 309 |  |  |  |  |  |  |  | 
| 310 | 0 |  |  |  |  |  | my $response; | 
| 311 | 0 |  |  |  |  |  | my %caterr = ( | 
| 312 |  |  |  |  |  |  | 1  => "In Progress", | 
| 313 |  |  |  |  |  |  | 2  => "Success", | 
| 314 |  |  |  |  |  |  | 3  => "No Response", | 
| 315 |  |  |  |  |  |  | 4  => "Too Many Retries", | 
| 316 |  |  |  |  |  |  | 5  => "No Buffers", | 
| 317 |  |  |  |  |  |  | 6  => "No Processes", | 
| 318 |  |  |  |  |  |  | 7  => "Bad Checksum", | 
| 319 |  |  |  |  |  |  | 8  => "Bad Length", | 
| 320 |  |  |  |  |  |  | 9  => "Bad Flash", | 
| 321 |  |  |  |  |  |  | 10 => "Server Error", | 
| 322 |  |  |  |  |  |  | 11 => "User Cancelled", | 
| 323 |  |  |  |  |  |  | 12 => "Wrong Code", | 
| 324 |  |  |  |  |  |  | 13 => "File Not Found", | 
| 325 |  |  |  |  |  |  | 14 => "Invalid TFTP Host", | 
| 326 |  |  |  |  |  |  | 15 => "Invalid TFTP Module", | 
| 327 |  |  |  |  |  |  | 16 => "Access Violation", | 
| 328 |  |  |  |  |  |  | 17 => "Unknown Status", | 
| 329 |  |  |  |  |  |  | 18 => "Invalid Storage Device", | 
| 330 |  |  |  |  |  |  | 19 => "Insufficient Space On Storage Device", | 
| 331 |  |  |  |  |  |  | 20 => "Insufficient Dram Size", | 
| 332 |  |  |  |  |  |  | 21 => "Incompatible Image" | 
| 333 |  |  |  |  |  |  | ); | 
| 334 |  |  |  |  |  |  |  | 
| 335 | 0 | 0 |  |  |  |  | if ( $params->{catos} ) { | 
| 336 |  |  |  |  |  |  | $response | 
| 337 |  |  |  |  |  |  | = $session->set_request( '1.3.6.1.4.1.9.5.1.5.1.0', OCTET_STRING, | 
| 338 | 0 |  |  |  |  |  | $params->{server} ); | 
| 339 |  |  |  |  |  |  | $response | 
| 340 |  |  |  |  |  |  | = $session->set_request( '1.3.6.1.4.1.9.5.1.5.2.0', OCTET_STRING, | 
| 341 | 0 |  |  |  |  |  | $params->{file} ); | 
| 342 | 0 |  |  |  |  |  | $response | 
| 343 |  |  |  |  |  |  | = $session->set_request( '1.3.6.1.4.1.9.5.1.5.3.0', INTEGER, 1 ); | 
| 344 | 0 | 0 |  |  |  |  | if ( $params->{op} eq 'put' ) { | 
| 345 | 0 |  |  |  |  |  | $response | 
| 346 |  |  |  |  |  |  | = $session->set_request( '1.3.6.1.4.1.9.5.1.5.4.0', INTEGER, | 
| 347 |  |  |  |  |  |  | 2 ); | 
| 348 |  |  |  |  |  |  | } else { | 
| 349 | 0 |  |  |  |  |  | $response | 
| 350 |  |  |  |  |  |  | = $session->set_request( '1.3.6.1.4.1.9.5.1.5.4.0', INTEGER, | 
| 351 |  |  |  |  |  |  | 3 ); | 
| 352 |  |  |  |  |  |  | } | 
| 353 |  |  |  |  |  |  |  | 
| 354 |  |  |  |  |  |  | # loop and check response - error if timeout | 
| 355 | 0 | 0 |  |  |  |  | if (defined( | 
| 356 |  |  |  |  |  |  | $response = $session->get_request('1.3.6.1.4.1.9.5.1.5.5.0') | 
| 357 |  |  |  |  |  |  | ) | 
| 358 |  |  |  |  |  |  | ) { | 
| 359 | 0 |  |  |  |  |  | my $loop = 0; | 
| 360 | 0 |  |  |  |  |  | while ( $response->{'1.3.6.1.4.1.9.5.1.5.5.0'} == 1 ) { | 
| 361 | 0 |  |  |  |  |  | $response = $session->get_request('1.3.6.1.4.1.9.5.1.5.5.0'); | 
| 362 | 0 | 0 |  |  |  |  | if ( $loop++ == $params->{timeout} ) { | 
| 363 | 0 |  |  |  |  |  | $Cisco::SNMP::LASTERROR | 
| 364 |  |  |  |  |  |  | = "CatOS TFTP `$params->{op}' FAILED - timeout during completion verification"; | 
| 365 | 0 |  |  |  |  |  | return -1; | 
| 366 |  |  |  |  |  |  | } | 
| 367 | 0 |  |  |  |  |  | sleep 1; | 
| 368 |  |  |  |  |  |  | } | 
| 369 |  |  |  |  |  |  | } else { | 
| 370 | 0 |  |  |  |  |  | $Cisco::SNMP::LASTERROR | 
| 371 |  |  |  |  |  |  | = "CatOS TFTP `$params->{op}' FAILED - can't get initial response"; | 
| 372 | 0 |  |  |  |  |  | return -1; | 
| 373 |  |  |  |  |  |  | } | 
| 374 |  |  |  |  |  |  |  | 
| 375 | 0 | 0 |  |  |  |  | if ( $response->{'1.3.6.1.4.1.9.5.1.5.5.0'} == 2 ) { | 
| 376 | 0 |  |  |  |  |  | return 0; | 
| 377 |  |  |  |  |  |  | } else { | 
| 378 |  |  |  |  |  |  | $Cisco::SNMP::LASTERROR = "CatOS TFTP `$params->{op}' FAILED - " | 
| 379 | 0 |  |  |  |  |  | . $caterr{$response->{'1.3.6.1.4.1.9.5.1.5.5.0'}}; | 
| 380 | 0 |  |  |  |  |  | return -1; | 
| 381 |  |  |  |  |  |  | } | 
| 382 |  |  |  |  |  |  |  | 
| 383 |  |  |  |  |  |  | # IOS | 
| 384 |  |  |  |  |  |  | } else { | 
| 385 |  |  |  |  |  |  |  | 
| 386 |  |  |  |  |  |  | # ccCopyEntryRowStatus (5 = createAndWait, 6 = destroy) | 
| 387 | 0 |  |  |  |  |  | $response | 
| 388 |  |  |  |  |  |  | = $session->set_request( | 
| 389 |  |  |  |  |  |  | '1.3.6.1.4.1.9.9.96.1.1.1.1.14.' . $instance, | 
| 390 |  |  |  |  |  |  | INTEGER, 6 ); | 
| 391 | 0 |  |  |  |  |  | $response | 
| 392 |  |  |  |  |  |  | = $session->set_request( | 
| 393 |  |  |  |  |  |  | '1.3.6.1.4.1.9.9.96.1.1.1.1.14.' . $instance, | 
| 394 |  |  |  |  |  |  | INTEGER, 5 ); | 
| 395 |  |  |  |  |  |  |  | 
| 396 |  |  |  |  |  |  | # ccCopyProtocol | 
| 397 |  |  |  |  |  |  | $response | 
| 398 |  |  |  |  |  |  | = $session->set_request( | 
| 399 |  |  |  |  |  |  | '1.3.6.1.4.1.9.9.96.1.1.1.1.2.' . $instance, | 
| 400 | 0 |  |  |  |  |  | INTEGER, $PROTO{$params->{protocol}} ); | 
| 401 |  |  |  |  |  |  |  | 
| 402 | 0 | 0 |  |  |  |  | if ( not defined $response ) { | 
| 403 | 0 |  |  |  |  |  | $Cisco::SNMP::LASTERROR | 
| 404 |  |  |  |  |  |  | = "IOS TFTP `$params->{op}' NOT SUPPORTED - trying old way"; | 
| 405 | 0 | 0 |  |  |  |  | if ( $params->{protocol} ne 'tftp' ) { | 
| 406 | 0 |  |  |  |  |  | $Cisco::SNMP::LASTERROR | 
| 407 |  |  |  |  |  |  | = "Old way does not support `$params->{protocol}'"; | 
| 408 | 0 |  |  |  |  |  | return -1; | 
| 409 |  |  |  |  |  |  | } | 
| 410 | 0 | 0 |  |  |  |  | if ( $params->{family} == $AF_INET6 ) { | 
| 411 | 0 |  |  |  |  |  | $Cisco::SNMP::LASTERROR | 
| 412 |  |  |  |  |  |  | = "IOS TFTP `$params->{op}' old way does not support IPv6"; | 
| 413 | 0 |  |  |  |  |  | return -1; | 
| 414 |  |  |  |  |  |  | } | 
| 415 | 0 | 0 |  |  |  |  | if ( $params->{op} eq 'put' ) { | 
| 416 |  |  |  |  |  |  | $response | 
| 417 |  |  |  |  |  |  | = $session->set_request( | 
| 418 |  |  |  |  |  |  | '1.3.6.1.4.1.9.2.1.50.' . $params->{server}, | 
| 419 | 0 |  |  |  |  |  | OCTET_STRING, $params->{file} ); | 
| 420 |  |  |  |  |  |  | } else { | 
| 421 |  |  |  |  |  |  | $response | 
| 422 |  |  |  |  |  |  | = $session->set_request( | 
| 423 |  |  |  |  |  |  | '1.3.6.1.4.1.9.2.1.55.' . $params->{server}, | 
| 424 | 0 |  |  |  |  |  | OCTET_STRING, $params->{file} ); | 
| 425 |  |  |  |  |  |  | } | 
| 426 | 0 | 0 |  |  |  |  | if ( defined $response ) { | 
| 427 | 0 |  |  |  |  |  | return 0; | 
| 428 |  |  |  |  |  |  | } else { | 
| 429 | 0 |  |  |  |  |  | $Cisco::SNMP::LASTERROR | 
| 430 |  |  |  |  |  |  | = "IOS TFTP `$params->{op}' FAILED (new and old)"; | 
| 431 | 0 |  |  |  |  |  | return -1; | 
| 432 |  |  |  |  |  |  | } | 
| 433 |  |  |  |  |  |  | } | 
| 434 |  |  |  |  |  |  |  | 
| 435 | 0 | 0 |  |  |  |  | if ( $params->{protocol} ne 'tftp' ) { | 
| 436 |  |  |  |  |  |  | $response | 
| 437 |  |  |  |  |  |  | = $session->set_request( | 
| 438 |  |  |  |  |  |  | '1.3.6.1.4.1.9.9.96.1.1.1.1.7.' . $instance, | 
| 439 | 0 |  |  |  |  |  | OCTET_STRING, $params->{username} ); | 
| 440 | 0 | 0 |  |  |  |  | if ( $params->{protocol} ne 'rcp' ) { | 
| 441 |  |  |  |  |  |  | $response | 
| 442 |  |  |  |  |  |  | = $session->set_request( | 
| 443 |  |  |  |  |  |  | '1.3.6.1.4.1.9.9.96.1.1.1.1.8.' . $instance, | 
| 444 | 0 |  |  |  |  |  | OCTET_STRING, $params->{password} ); | 
| 445 |  |  |  |  |  |  | } | 
| 446 |  |  |  |  |  |  | } | 
| 447 |  |  |  |  |  |  |  | 
| 448 |  |  |  |  |  |  | # ccCopySourceFileType [.3] (1 = networkFile, 3 = startupConfig, 4 = runningConfig) | 
| 449 |  |  |  |  |  |  | # ccCopyDestFileType [.4] (1 = networkFile, 3 = startupConfig, 4 = runningConfig) | 
| 450 | 0 | 0 |  |  |  |  | if ( $params->{op} eq 'put' ) { | 
| 451 | 0 |  |  |  |  |  | $response | 
| 452 |  |  |  |  |  |  | = $session->set_request( | 
| 453 |  |  |  |  |  |  | '1.3.6.1.4.1.9.9.96.1.1.1.1.3.' . $instance, | 
| 454 |  |  |  |  |  |  | INTEGER, 1 ); | 
| 455 |  |  |  |  |  |  | $response | 
| 456 |  |  |  |  |  |  | = $session->set_request( | 
| 457 |  |  |  |  |  |  | '1.3.6.1.4.1.9.9.96.1.1.1.1.4.' . $instance, | 
| 458 | 0 |  |  |  |  |  | INTEGER, $params->{dest} ); | 
| 459 |  |  |  |  |  |  | } else { | 
| 460 |  |  |  |  |  |  | $response | 
| 461 |  |  |  |  |  |  | = $session->set_request( | 
| 462 |  |  |  |  |  |  | '1.3.6.1.4.1.9.9.96.1.1.1.1.3.' . $instance, | 
| 463 | 0 |  |  |  |  |  | INTEGER, $params->{source} ); | 
| 464 | 0 |  |  |  |  |  | $response | 
| 465 |  |  |  |  |  |  | = $session->set_request( | 
| 466 |  |  |  |  |  |  | '1.3.6.1.4.1.9.9.96.1.1.1.1.4.' . $instance, | 
| 467 |  |  |  |  |  |  | INTEGER, 1 ); | 
| 468 |  |  |  |  |  |  | } | 
| 469 |  |  |  |  |  |  |  | 
| 470 |  |  |  |  |  |  | # New way | 
| 471 |  |  |  |  |  |  | # ccCopyServerAddressType (1 = IPv4, 2 = IPv6) | 
| 472 |  |  |  |  |  |  | $response | 
| 473 |  |  |  |  |  |  | = $session->set_request( | 
| 474 |  |  |  |  |  |  | '1.3.6.1.4.1.9.9.96.1.1.1.1.15.' . $instance, | 
| 475 | 0 | 0 |  |  |  |  | INTEGER, ( $params->{family} == AF_INET ) ? 1 : 2 ); | 
| 476 |  |  |  |  |  |  |  | 
| 477 | 0 | 0 |  |  |  |  | if ( defined $response ) { | 
| 478 |  |  |  |  |  |  |  | 
| 479 |  |  |  |  |  |  | # ccCopyServerAddressRev1 | 
| 480 |  |  |  |  |  |  | $response | 
| 481 |  |  |  |  |  |  | = $session->set_request( | 
| 482 |  |  |  |  |  |  | '1.3.6.1.4.1.9.9.96.1.1.1.1.16.' . $instance, | 
| 483 | 0 |  |  |  |  |  | OCTET_STRING, $params->{server} ); | 
| 484 |  |  |  |  |  |  | } else { | 
| 485 |  |  |  |  |  |  |  | 
| 486 |  |  |  |  |  |  | # Deprecated | 
| 487 |  |  |  |  |  |  | # ccCopyServerAddress | 
| 488 | 0 | 0 |  |  |  |  | if ( $params->{family} == $AF_INET6 ) { | 
| 489 | 0 |  |  |  |  |  | $Cisco::SNMP::LASTERROR | 
| 490 |  |  |  |  |  |  | = "ccCopyServerAddressRev1 not supported (requried for IPv6)"; | 
| 491 | 0 |  |  |  |  |  | return -1; | 
| 492 |  |  |  |  |  |  | } | 
| 493 |  |  |  |  |  |  | $response | 
| 494 |  |  |  |  |  |  | = $session->set_request( | 
| 495 |  |  |  |  |  |  | '1.3.6.1.4.1.9.9.96.1.1.1.1.5.' . $instance, | 
| 496 | 0 |  |  |  |  |  | IPADDRESS, $params->{server} ); | 
| 497 |  |  |  |  |  |  | } | 
| 498 |  |  |  |  |  |  |  | 
| 499 |  |  |  |  |  |  | # ccCopyFileName | 
| 500 |  |  |  |  |  |  | $response | 
| 501 |  |  |  |  |  |  | = $session->set_request( | 
| 502 |  |  |  |  |  |  | '1.3.6.1.4.1.9.9.96.1.1.1.1.6.' . $instance, | 
| 503 | 0 |  |  |  |  |  | OCTET_STRING, $params->{file} ); | 
| 504 |  |  |  |  |  |  | } | 
| 505 | 0 |  |  |  |  |  | return 1; | 
| 506 |  |  |  |  |  |  | } | 
| 507 |  |  |  |  |  |  |  | 
| 508 |  |  |  |  |  |  | ################################################## | 
| 509 |  |  |  |  |  |  | # End Private subs | 
| 510 |  |  |  |  |  |  | ################################################## | 
| 511 |  |  |  |  |  |  |  | 
| 512 |  |  |  |  |  |  | 1; | 
| 513 |  |  |  |  |  |  |  | 
| 514 |  |  |  |  |  |  | __END__ |