Below is a piece of code that I wrote a while ago when setting up a backup mechanism to automatically retrieve (and put) configuration files from (or to) Cisco Catalyst switches (running CatOS).
Usually, as a perl programmer with a new challenge, you will first do a search on CPAN and almost probably find the answer or at least a hint. But at that time I decided not to go for the Cisco::Conf module that uses telnet instead of SNMP commands and operates in writeNet mode. Today, the more recent Cisco::CopyConfig should be the module of choice, but it uses ccCopy mode and works for IOS devices only.
My example uses tftpGrp mode, a third variant, that has not yet been packed in a module.
Short explanation: Subroutine, give it your Catalyst’s hostname or IP address ($Host) and SNMP write community string ($Cty), the TFTP server’s hostname or IP address ($Server) and the filename on TFTP server ($Filename). The action ($Action) to be performed by Catalyst is given in clear text, see %Actions for allowed values. Module number ($Module) and timeout in seconds ($Timeout) are optional arguments and default to standard values if omitted. Returns result in clear text, see %Results for possible values.
Don’t forget to touch and chmod 666 file on TFTP server before transfer and remove it afterwards. Have fun!
use Convert::BER;
use Net::SNMP;
sub tftpGrp {
my($Host,$Cty,$Server,$Filename,
$Action,$Module,$Timeout) = @_;
################################
my %OIDs = (
'tftpHost' => '1.3.6.1.4.1.9.5.1.5.1.0',
'tftpFile' => '1.3.6.1.4.1.9.5.1.5.2.0',
'tftpModule' => '1.3.6.1.4.1.9.5.1.5.3.0',
'tftpAction' => '1.3.6.1.4.1.9.5.1.5.4.0',
'tftpResult' => '1.3.6.1.4.1.9.5.1.5.5.0',
);
my %Actions = (
'other' => 1,
'downloadConfig' => 2,
'uploadConfig' => 3,
'downloadSw' => 4,
'uploadSw' => 5,
'downloadFw' => 6,
'uploadFw' => 7,
);
my %Results = (
1 => 'inProgress',
2 => 'success',
3 => 'noResponse',
4 => 'tooManyRetries',
5 => 'noBuffers',
6 => 'noProcesses',
7 => 'badChecksum',
8 => 'badLength',
9 => 'badFlash',
10 => 'serverError',
11 => 'userCanceled',
12 => 'wrongCode',
13 => 'fileNotFound',
14 => 'invalidTftpHost',
15 => 'invalidTftpModule',
16 => 'accessViolation',
17 => 'unknownStatus',
18 => 'invalidStorageDevice',
19 => 'insufficientSpaceOnStorageDevice',
20 => 'insufficientDramSize',
21 => 'incompatibleImage',
);
################################
$Action = $Actions{$Action} or return(undef);
$Module = 1 unless(int($Module));
$Timeout = 10 unless(int($Timeout));
my($Session,$Error) = Net::SNMP->session(
-version => 'snmpv2c',
-hostname => $Host,
-community => $Cty
);
return($Error) unless(defined($Session));
$Session->timeout($Timeout);
$Session->set_request($OIDs{'tftpHost'},OCTET_STRING,$Server);
$Session->set_request($OIDs{'tftpFile'},OCTET_STRING,$Filename);
$Session->set_request($OIDs{'tftpModule'},INTEGER,$Module);
$Session->set_request($OIDs{'tftpAction'},INTEGER,$Action);
$Error = $Session->error();
if($Error) { $Session->close(); return($Error); }
for(my $Time = time(); time() <= $Time + $Timeout;) {
sleep(1);
my $Result = $Session->get_request($OIDs{'tftpResult'});
my $Value = $Result->{$OIDs{'tftpResult'}};
$Error = $Results{$Value};
$Timeout++ if($Error eq 'inProgress');
last if($Error eq 'success');
}
$Session->close();
return($Error);
}