Okay, here it is! My first attempt at a piece of open source scripting to give to the world. You can see by its revision, its at 0.x so no formal release yet. Since I am less than 6 months old in the perl world, I can't help but ask for review from my big brothers. Regardless of its level, or lack thereof, in maturity, I was only able to write this script because of my membership here.
Thanks! -
c
#!/usr/bin/perl -w
# $Id: pancho,v 0.41 2001/08/27 18:48:18 charles Exp $
## module calls
use strict;
use Net::SNMP;
use Getopt::Long;
my $community = ''; # your RW snmp community string
my $tftpserver = ""; # ip address of your tftpserver
my @routers = qw(); # list of routers
############ NO FURTHER EDITING SHOULD BE REQUIRED. ############
############ DOING SO IS AT YOUR OWN RISK. ############
## development variables
my $rcs = (qw$Revision: 0.41 $)[-1];
## ensure some arguments are given
if ($#ARGV < 0) {
print "\nPancho requires some flags to be specified.\nPlease try run
+ning ./pan
cho --help\n\n";
exit(1);
}
## command line options
my $upload;
my $download;
my $filename;
my $commit;
my $list;
my $host;
my $string;
my $version;
my $old;
my $server;
my $regex;
my $help;
GetOptions ( 'upload' => \$upload,
'download' => \$download,
'filename=s' => \$filename,
'commit' => \$commit,
'list=s' => \$list,
'host=s' => \$host,
'server=s' => \$server,
'string=s' => \$string,
'version' => \$version,
'old' => \$old,
'regex' => \$regex,
'help' => \$help,
);
## set up oids
my $wrnet;
my $confnet;
my $wrmem;
my $starttotftp;
my $tftptostart;
my $reload;
my $flashtotftp;
my $tftptoflash;
my $eraseflash;
## for now there is no difference between the old oids
## and new used by cisco. cisco is stating that the older
## versions may no longer be valid in ios revisions 12.1
## and greater with some 11.2 and 12.0 revisions also
## showing problems.
## updated oids will be put into place with a future revsion
## of pancho.
if ($old) {
## deprecated oids
$wrnet = ".1.3.6.1.4.1.9.2.1.55.0";
$confnet = ".1.3.6.1.4.1.9.2.1.53.0";
$wrmem = ".1.3.6.1.4.1.9.2.1.54.0";
$flashtotftp = ".1.3.6.1.4.1.9.2.10.9.0";
$tftptoflash = ".1.3.6.1.4.1.9.2.10.12.0";
$eraseflash = ".1.3.6.1.4.1.9.2.10.6.0";
} else {
## oids
$wrnet = ".1.3.6.1.4.1.9.2.1.55.0";
$confnet = ".1.3.6.1.4.1.9.2.1.53.0";
$wrmem = ".1.3.6.1.4.1.9.2.1.54.0";
$flashtotftp = ".1.3.6.1.4.1.9.2.10.9.0";
$tftptoflash = ".1.3.6.1.4.1.9.2.10.12.0";
$eraseflash = ".1.3.6.1.4.1.9.2.10.6.0";
}
## show version and exit
if ($version) {
&version;
exit(0);
}
## show the help menu and exit
if ($help) {
&usage;
exit(0);
}
## build out count for error checking
my $count = 0;
$count++ if ($upload);
$count++ if ($download);
## ensure that we have a node or list of nodes
if ($host) {
push(@routers, $host);
} elsif ($list) {
open(FH, $list);
@routers = <FH>;
close(FH);
} elsif ( $#routers < 0 ) {
print "\nYou have not specified a node or list of nodes to act upon!
+\n\n"
unless ($count == 0);
exit(1);
}
## determine if we are using the default server or another
if ($server) {
$tftpserver = $server;
}
## determine if we are using the default community string or another
if ($string) {
$community = $string;
}
## check to ensure that we have the information required
if (!$community) {
print "\nYou have not specified an SNMP community.\n\n";
exit(1);
} elsif (!$tftpserver and $upload or $download) {
print "\nYou have not specified a tftp server.\n\n";
exit(1);
}
if ($upload && $count == 1) {
if (!$filename) {
print "\nIn order to tftp a configuration to a remote device\nyou
+must indic
ate a specific filename using -f.\n\n";
exit(1);
} else {
©_tftp_run;
exit(0);
}
} elsif ($download && $count == 1) {
©_run_tftp;
exit(0);
} elsif ($commit) {
©_run_start;
exit(0);
} else {
print "\nYou cannot upload and download at the same time.\n\n"
unless ($count == 0);
}
## subroutines
sub version { print "\n This is Pancho version $rcs\n\n"; }
sub copy_run_start {
if ($regex) {
my $mib = "$wrmem";
for my $host(@routers) {
next unless /$regex/;
$filename = "$host.cfg";
my $s = Net::SNMP->session( -hostname => $host,
-community => $community );
$s->set_request($mib, INTEGER, "1");
$s->close;
print "\nSuccessfully wrote config to memory on $host.\n\n"
}
} else {
my $mib = "$wrmem";
for my $host(@routers) {
my $s = Net::SNMP->session( -hostname => $host,
-community => $community );
$s->set_request($mib, INTEGER, "1");
$s->close;
print "\nSuccessfully wrote config to memory on $host.\n\n"
}
}
}
sub copy_run_tftp {
if ($regex) {
my $mib = "$wrnet$tftpserver";
for my $host(@routers) {
next unless /$regex/;
$filename = "$host.cfg";
my $s = Net::SNMP->session( -hostname => $host,
-community => $community );
$s->set_request($mib, OCTET_STRING, $filename);
my $error = $s->error;
$s->close;
if ($error) {
print "\n$error\n\n";
} else {
print "\nSuccessfully wrote config to tftpserver for $host.\n\
+n"
}
}
} else {
my $mib = "$wrnet$tftpserver";
for my $host(@routers) {
$filename = "$host.cfg";
my $s = Net::SNMP->session( -hostname => $host,
-community => $community );
$s->set_request($mib, OCTET_STRING, $filename);
my $error = $s->error;
$s->close;
if ($error) {
print "\n$error\n\n";
} else {
print "\nSuccessfully wrote config to tftpserver for $host.\n\
+n"
}
}
}
}
sub copy_tftp_run {
if ($regex) {
my $mib = "$confnet$tftpserver";
for my $host(@routers) {
next unless /$regex/;
my $s = Net::SNMP->session( -hostname => $host,
-community => $community );
$s->set_request($mib, OCTET_STRING, $filename);
my $error = $s->error;
$s->set_request($wrmem, INTEGER, "1") if ($commit);
$s->close;
if ($error) {
print "\n$error\n\n"
} else {
print "\nSuccessfully sent config to $host.\n\n"
}
}
} else {
my $mib = "$confnet$tftpserver";
for my $host(@routers) {
my $s = Net::SNMP->session( -hostname => $host,
-community => $community );
$s->set_request($mib, OCTET_STRING, $filename);
my $error = $s->error;
$s->set_request($wrmem, INTEGER, "1") if ($commit);
$s->close;
if ($error) {
print"\n$error\n\n";
} else {
print "\nSuccessfully sent config to $host.\n\n"
}
}
}
}
sub usage {
print <<USAGE;
NAME
pancho
SYNOPSIS
options [ --upload | --download | --commit ]
[ --filename <filename> ]
[ --list <list> ]
[ --host <hostname> ]
[ --server <tftp server ip> ]
[ --string <snmp community> ]
[ --regex <regular expression> ]
[ --version ]
[ --help ]
requires perl, net::snmp
DESCRIPTION
this utility provides a front end to managing
cisco(c) router configurations and administration.
pancho currently supports the following cisco(c)
command line options:
copy tftp run
copy run tftp
copy run start
pancho in conjunction with a text file following
standard cisco ios(c) options allows an administrator
to make the same changes to a group of routers or
a single host through a single command line string.
in addition, pancho can be used to archive router
configurations through automated or manual runs.
OPTIONS
-u, --upload
specify that pancho send a configuration
file TO the remote device(s).
-d, --download
specify that pancho retrieve a configuration
file FROM the remote device(s).
-c. --commit
specify that pancho perform a 'write memory'
or 'copy run start' on the remote device(s).
-f, --filename
specify the local filename that pancho should
send to the remote device.
-l, --list
specify a local file that hold a list of device
hostnames or ip addresses that pancho should
perform actions against.
--host
specify an individual host on which pancho
will perform actions.
--server
specify a tftp server that pancho will push
or pull configurations to and from.
--string
specify a snmp read-write string.
-r, --regex
specify a regular expression that pancho can
use to filter out specific hosts from the
host file that actions should be taken against.
--version
display the current version of pancho.
--help
this display.
pancho gives a network administrator the power to make
tedious work very simple when configuring a group of
cisco routers. through a single command line statement,
a change that is needed to be made on a large number of
routers can be done without having to manually log into
any remote devices. pancho also provide the flexibility
to allow administrators to use its function against a
single host, a select group or the entire whole.
at first glance, pancho appears to have a significantly
long command line. however, many of the option flags
seen above can be set as default such that the flags
themselves would only be called to override the default
settings. for example a default tftpserver may be set
within the pancho configuration, however you will still
be able to specify:
--server 172.16.254.16
in case you would like to push/pull your config to an
alternate server. please read through the accompanying
README file to learn how to set up pancho defaults.
pancho can be set up to have a default group of nodes
that it will affect when ran. this list can be altered
by specifying the --host flag to indicate a single node
or the --list flag which will let you direct pancho to
read the group to be effected from a plain text file.
another method which allows pancho to further granulize
the group of devices touched is the --regex option. this
feature is very powerful in the hands of someone with
a fair amount of knowledge concerning regular expressions
and nodes grouped with logical naming conventions.
--regex ^core.*
would indicate that within the default list of nodes, or
within the list obtained from an external text file, only
those with a name beginning in "core" would be affected.
the final optional flag is --filename. if unspecified,
this value defaults to the hostname of the device being
touched with an extension of ".cfg". the --filename flag
argument should always be used when a single configuration
file will be uploaded to a group of devices.
pancho's only mandatory flag is one of two options,
--upload or --download. this specifies whether or not
pancho will push a configuration to the router or pull
the remote device's config down to the local tftp server.
pancho lives remotely from the router and therefore views
the world from that perspective. --upload signifies that
a file will be uploaded TO the router. conversely,
--download indicates that the config will be brought down
FROM the router.
the final option of --commit is used to perform a remote
"write memory" or "copy run start". this option can be
used either individually, or in conjunction with --upload
essentially committing to memory the changes as they are
being made.
EXAMPLES
in order to utilize pancho's full capacity for router
configuration, one needs to be familiar with cisco's
'copy tftp run' or 'config net' syntax. in depth
discussion on the procedure can be found on cisco's
website at http://www.cisco.com.
a summary of the process is as follows. a remote
router will tftp a configuration file consisting of
standard ios commands into its running-config. the
router will merge the current running-config and the
command options received from the text file and then
apply the whole to its new running configuration.
an example may better state the process.
on the tftp server, we create a plain text file to
update the access-list 5 on a group of remote routers.
the plain text file, is as follows:
!
no access-list 5
access-list 5 permit 10.6.21.64 0.0.0.31
access-list 5 permit 10.12.71.0 0.0.0.255
!
end
since we plan on completely rewriting access-list 5
on the remote routers with this new acl, our first
statement is 'no access-list 5' which allows us to
start a new acl listing. the following acl statements
will then build the new access-list.
since cisco's 'copy tftp run' process first merges the
current running-config and our plain text commands before
it applies the newly created configuration, there will
be no interruption in traffic being inspected by access-
list 5. very different than just copying and pasting the
same commands into the cisco command prompt which applies
each statement with the hit of the carriage return
allowing for the possibility of serious consequences.
with knowledge of cisco's ios syntax, the possibilities for
remote configuration are endless, and with pancho's
capability for customization, an entire network may be
updated or archived from a single point of management.
the following a just a few of pancho's command line options
in running syntax:
update all routers with changes held in a flat file
pancho -u -f acl_update.txt
archive all router configurations locally
pancho -d
or to a remote tftp server
pancho -d --server 10.219.0.25
update all border routers with a new motd using an
alternate snmp community
pancho -u -f motd.txt --regex border --string f00B\@
+r
CAVEATS
pancho's power does come with some caveats that should not
be considered lightly. pancho depends upon remote routers
having a read-write(rw) snmp community string configured.
since read-write strings offer full snmp control to a machine
the potential for exploit could be high.
it is HIGHLY recommended, if not considered mandatory by this
author that all routers using rw snmp strings should have an
acl configured to limit what machines can gain such access to
the device. again, full documentation can be found on cisco's
website, however a short synopsis is as follows:
! access-list specifying nodes that will be capable
! of using snmp access to routers
access-list 10 permit host 10.10.220.78
access-list 10 permit 192.168.96.4 0.0.0.3
!
! apply access-list to snmp community
snmp-server community 9Eck#0-A rw 10
!
pancho also relies on the tftp protocol and server. files held
within the tftproot and its subdirectories are generally world
readable. moreover the tftp protocol does not inherently provi
+de
any method for user authentication.
because of this, it is generally good measure to try to limit
the nodes which have access to the tftp mechanism. this can be
achieved through a local firewall specifying remote nodes or
subnets that can push/pull to and from the tftpserver. with re
+mote
routers all belonging to different subnets, this would at firs
+t
seem tedious to set up and even worse to maintain. a common
convention to combat this is to use loopback addresses from an
aggregate on all remote devices. it is then possible to specif
+y
ip tftp source-interface Loopback 100
and ensure that all tftp requests coming in from remote device
+s
will have a predictable source address, that can be grouped in
+to
the aggregate. using this mechanism, a large group of routers
numbered with Loopback addresses having /32 masks can be conso
+lidated
into a larger aggregate with a shorter mask allowing for less
configuration within the firewall rules.
COMMENTS
Please send all comments regarding pancho to:
pancho\@lunarmedia.net
Check for new releases of pancho at:
http://pancho.lunarmedia.net/
BUGS
AUTHOR
Charles J. Menzes <charles\@lunarmedia.net>
Pancho Copyright(C) 2001
USAGE
}