#! /usr/bin/perl # # backupConfig.pl is a PERL script intended to copy the current running config # of an IOS Cisco device to a specified TFTP server. The name of the config is # constructed using the IP address of the device, and appending the string # "-config" to it. The username, password and enable password must be supplied # for each device specified as an IP address. The script is adapted from the # examples at http://nettelnetcisco.sourceforge.net/docs.html # # Versions # -------- # 0.1 - Initial version # 0.2 - Uses only just-in-time processing for devices from config file # 0.3 - Performs local write to file of running config # # Note: The TFTP component of the script has not been tested and has been # commented out. The file only performs a write to a local file of the running # config and displays the running confirm to STDOUT. # use Net::Telnet::Cisco; use strict; use warnings; # # Global variables # my $tftp_server = "192.168.1.1"; my $config = "backupConfig.txt"; my $DEBUG = 0; my $INFO = 0; # # backupConfig sub-routine opens the config tile and parses it to constucts a list # of devices together with the login and enable credentials. Each line in the # config file must specify the IP address of the device, the type of the device, # the IOS version of the device, the logon username, the logon password and the # enable password. Each field must be separated by a sequence of ~~~ characters # e.g.; # "192.168.1.254"~~~"router"~~~"12"~~~"noc"~~~"password"~~~"en-password" # "192.168.1.253"~~~"switch"~~~"12"~~~"noc"~~~"password"~~~"en-password" # sub backupConfig { # debug code trace if ( $DEBUG ) { printf( "DEBUG: backupConfig()\n" ); } # open the config file or die trying :) open( CONFIG, "<".$config ) or die( "DIE: Unable to open config file : " . $config ); while( ) { # read the line my $lineRead = $_; chomp( $lineRead ); if ( $DEBUG ) { printf( "DEBUG: backupConfig - $lineRead\n" ); } # split the line into fields my @splitFields = split( "~~~", $lineRead ); if ( $DEBUG ) { printf( "DEBUG: backupConfig - @splitFields\n" ); } my $ipAddress = $splitFields[0]; my $deviceType = $splitFields[1]; my $iosVersion = $splitFields[2]; my $username = $splitFields[3]; my $password = $splitFields[4]; my $enPassword = $splitFields[5]; # attempt to get the config for the device processDevice( $ipAddress, $deviceType, $iosVersion, $username, $password, $enPassword ); } # close the file close( CONFIG ); } # # executeCmd is a sub-routine to execute a specified command on the Cisco # device specified. The command, the device IP address, and the login credentials # must be supplied # # @param cmd - the command to be executed on the device # @param host - the IP address of the Cisco device # @param username - the initial device login username # @param password - the initial device login password # @param enablePass - the enable/privilege device login password # # @returns Array - array of Strings representing the output of the command # sub executeCmd { # debug code trace if ($DEBUG) { printf( "DEBUG: executeCmd()\n" ); } # get function paramaters my $cmd = shift; my $host = shift; my $username = shift; my $password = shift; my $enablePass = shift; # validate parameters if ( !defined( $cmd )) { printf( "ERROR: executeCmd() - Command not defined\n" ); return; } if ( !defined( $host )) { printf( "ERROR: executeCmd() - Host not defined\n" ); return; } if ( !defined( $username )) { printf("ERROR: executeCmd() - Username not defined\n"); return; } if ( !defined( $password )) { printf("ERROR: executeCmd() - Password not defined\n"); return; } if ( !defined( $enablePass )) { printf("ERROR: executeCmd() - Enable password not defined\n"); return; } if ( $INFO ) { printf( "INFO: executeCmd( $cmd, $host, $username, $password, $enablePass )\n" ); } # connect to cisco device my $session = Net::Telnet::Cisco->new( Host => $host ); $session->login( $username, $password ); # escalate privilege my @output; if ( $session->enable( $enablePass )) { # execute the command and capture output @output = $session->cmd( $cmd ); if ( $INFO ) { foreach ( @output ) { print "$_"; } } } else { printf( "ERROR: executeCmd() - Unable to escalate privileges\n" ); warn "WARN : Unable to escalate privileges : " . $session->errmsg; } # close session to cisco device $session->close; return \@output; } # # getTFTPCmd is a sub-routine to construct the appropriate command string for # the host supplied. The type of device and the IOS version must also be supplied # # @param host - the IP address of the Cisco device # @param ver - the major IOS version number, {12,11,10} # @param type - the Cisco device type, {"router","switch"} # # @returns String - the command string to copy the config to the tftp server # sub getTFTPCmd { # debug code trace if ( $DEBUG ) { printf( "DEBUG: getTFTPCmd()\n" ); } # get function parameters my $host = shift; my $type = shift; my $ver = shift; my $cmd = ""; # validate parameters if ( !defined( $host )) { printf( "ERROR: getTFTPCmd() - Host not defined\n" ); return undef; } if ( !defined( $type )) { printf( "ERROR: getTFTPCmd() - Device type not defined\n" ); return; } if ( !defined( $ver )) { printf( "ERROR: getTFTPCmd() - IOS version not defined\n" ); return; } if ( $INFO ) { printf( "INFO: getTFTPCmd( $host, $type, $ver )\n" ); } # determine type of device if ( $type eq "router" ) { # check ios version and construct command if ( $ver >= 12 ) { $cmd = "copy system:/running-config tftp://$tftp_server/$host-config\n\n\n"; } elsif ( $ver >= 11 ) { $cmd = "copy running-config tftp\n$tftp_server\n$host-config\n"; } elsif ( $ver >= 10 ) { $cmd = "write net\n$tftp_server\n$host-config\n\n"; } } elsif ( $type eq "switch" ) { $cmd = "copy system:/running-config tftp://$tftp_server/$host-config\n\n\n"; } # return the TFTP command as a string if ( $INFO ) { printf( "INFO: getTFTPCmd() - \"$cmd\"\n" ); } return $cmd } # # processDevice sub-routine performs the backup of the config on the on the Cisco # device specified. The IP address of the host, the type of device, the version # of the IOS, the logon username and password, and the enable password must be # supplied. The TFTP command is executed on the device, along with a write of the # current running config to the backup file. The backup filename is constructed # using the IP address of the device, and appending the string "-config" to it. # # @param ipAddress - the IP address of the Cisco device # @param deviceType - the Cisco device type, {"router","switch"} # @param iosVersion - the major IOS version number, {12,11,10} # @param username - the logon username # @param password - the logon password # @param enPassword - the enable password # sub processDevice { # debug code trace if ( $DEBUG ) { printf( "DEBUG: processDevice()\n" ); } # get function paramaters my $ipAddress = shift; my $deviceType = shift; my $iosVersion = shift; my $username = shift; my $password = shift; my $enPassword = shift; # validate paramaters if ( !defined( $ipAddress )) { printf( "ERROR: processDevice() - Host not defined\n" ); return; } if ( !defined( $deviceType )) { printf( "ERROR: processDevice() - Device type not defined\n" ); return; } if ( !defined( $iosVersion )) { printf( "ERROR: processDevice() - IOS version not defined\n" ); return; } if ( !defined( $username )) { printf( "ERROR: processDevice() - Username not defined\n" ); return; } if ( !defined( $password )) { printf( "ERROR: processDevice() - Password not defined\n" ); return; } if ( !defined( $enPassword )) { printf( "ERROR: processDevice() - Enable password not defined\n" ); return; } if ( $INFO ) { printf( "INFO: processDevice( $ipAddress, $deviceType, $iosVersion, $username, $password, $enPassword )\n" ); } # get the TFTP command and execute on the cisco device #my $cmd = getTFTPCmd( $ipAddress, $deviceType, $iosVersion ); #executeCmd( $cmd, $ipAddress, $username, $password, $enPassword ); # get a running config and write to a local file $cmd = "show run"; my $running_config = executeCmd( $cmd, $ipAddress, $username, $password, $enPassword ); foreach my $dataLine ( @{$running_config} ) { printf("%s", $dataLine ); } writeToFile( $ipAddress."-config", $running_config ); } # # writeToFile sub-routine writes the data supplied as an array of String to the # file created using the filename supplied # # @param $filename - String representing the name of the file to write to # @param @data - array of Strings # sub writeToFile { # debug code trace if ( $DEBUG ) { printf( "DEBUG: writeToFile()\n" ); } # get function parameters my $filename = shift; my $data_ref = shift; # validate function paramaters if ( !defined( $data_ref )) { printf( "ERROR: writeToFile() - Data not defined\n" ); return; } if ( !defined( $filename )) { printf( "ERROR: writeToFile() - Filename not defined\n" ); return; } # create file with filename open( DATA, ">$filename" ); foreach ( @{$data_ref} ) { print DATA "$_"; } close( DATA ); } backupConfig();