summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTar Committer <tar@ocjtech.us>2000-09-20 17:23:33 +0000
committerTar Committer <tar@ocjtech.us>2000-09-20 17:23:33 +0000
commit3861ba4cf180eb01fd98a16f4502702ab217e56f (patch)
treef24461455175b1fcd98eeb429d03410523e4d592
parenta505626101e262be2cd5a8c74c44d3616c299519 (diff)
downloadrancid-3861ba4cf180eb01fd98a16f4502702ab217e56f.tar.gz
rancid-3861ba4cf180eb01fd98a16f4502702ab217e56f.tar.xz
rancid-3861ba4cf180eb01fd98a16f4502702ab217e56f.zip
Imported from rancid-1.6.tar.gz.rancid-1.6
-rw-r--r--CHANGES15
-rw-r--r--README23
-rw-r--r--Todo1
-rwxr-xr-xbin/cat5rancid127
-rwxr-xr-xbin/elogin449
-rw-r--r--bin/env3
-rwxr-xr-xbin/erancid296
-rwxr-xr-xbin/jrancid7
-rwxr-xr-xbin/rancid92
-rwxr-xr-xbin/rancid-fe2
10 files changed, 951 insertions, 64 deletions
diff --git a/CHANGES b/CHANGES
index 9721d52..677a161 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,18 @@
+1.7
+
+1.6
+ Add "dir nvram:" to rancid.
+
+ Add support for ADC EZ T3 mux. adapted from tkenndedy@verio.net's
+ contrib.
+
+ strip (try to) snmp community strings from cisco and juniper configs
+ if environment variable NOCOMMSTR is set.
+
+ merge tkennedy@verio.net's support for cisco 2900xl into rancid
+
+ Ignore "fan spinning at" noise on junipers.
+
1.5
sync command-line option between clogin / jlogin. jlogin modified:
-x passphrase -> -r passphrase
diff --git a/README b/README
index d273776..5125ebe 100644
--- a/README
+++ b/README
@@ -12,12 +12,15 @@ control_rancid - Builds router list, calls rancid on each router and
handles cvs routines.
rancid-fe - chooses between rancid/francid/jrancid/rrancid/cat5rancid.
rancid - Runs commands on cisco routers and processes the output - the meat.
+erancid - Runs commands on ADC EZ-T3 muxes and processes the output.
francid - Runs commands on foundry switches and processes the output.
jrancid - Runs commands on juniper routers and processes the output.
rrancid - Runs commands on redback routers and processes the output.
cat5rancid -Runs commands on cisco cat5 switches and processes the output.
clogin - Expect script that logs into routers either interactively,
runs a set of commands or runs another expect script.
+elogin - Expect script that logs into ADC EZ-T3 muxes either interactively,
+ runs a set of commands or runs another expect script.
flogin - Expect script that logs into foundry switches. once foundry
cleans up their bloody UI, clogin should do the job.
jlogin - Expect script that logs into juniper routers similarly to
@@ -42,7 +45,7 @@ tcl - required by expect.
Bill Fenner has a cgi script for interacting with CVS repositories via
a web interface. This provides a great way to view rancid diffs and
full configs, especially for those unfamiliar with cvs. The package is
-not included here, but can be found here:
+not included, but can be found here:
http://www.freebsd.org/~fenner/cvsweb/cvsweb-1.0.tar.gz
@@ -56,9 +59,9 @@ Quick Installation Guide (an example):
3) Put the contents of rancid/bin in <basedir>/bin.
Modify the location of perl and expect in each of cat5rancid,
- clogin, flogin, francid, jlogin, jrancid, par, rancid, rancid-fe,
- rename, and rrancid if necessary. There are also 3 calls to
- perl in control_rancid and one in do-diffs.
+ clogin, elogin, erancid, flogin, francid, jlogin, jrancid, par,
+ rancid, rancid-fe, rename, and rrancid if necessary. There are
+ also 3 calls to perl in control_rancid and one in do-diffs.
Make sure that you are using perl version 5 and not perl version 4.
@@ -97,9 +100,17 @@ Quick Installation Guide (an example):
9) For each "group", modify the router.db file in the group directory.
The file is of the form "router:mfg:state" where "router" is
the name (we use FQDN) of the router, mfg is the manufacturer
- from the set of (cisco|foundry|juniper|redback|cat5), and "state"
+ from the set of (cisco|ezt3|foundry|juniper|redback|cat5), and "state"
is either up or down. Each router listed as "up" will have the
- configuration grabbed.
+ configuration grabbed. Note: manufacturer cat5 is intended only for
+ catalyst switches running catalyst (not IOS) code.
+
+ eg <basedir>/<group>/router.db:
+ cisco-router.domain.com:cisco:up
+ adc-mux.domain.com:ezt3:up
+ foundry-switch-router.domain.com:foundry:up
+ juniper-router.domain.com:juniper:up
+ redback-dsl-router.domain.com:redback:down
10) Put do-diffs in cron to be called however often you want it to run
for each group (do-diffs [<GROUP>]). eg:
diff --git a/Todo b/Todo
index 4afb294..be38291 100644
--- a/Todo
+++ b/Todo
@@ -1,3 +1,4 @@
+- need to strip community strings from foundry, redback
- detect 'same' vty configs
- ignoring length/width/passwd is a start, but need more
- add .cloginrc var to say to use ssh or telnet
diff --git a/bin/cat5rancid b/bin/cat5rancid
index 0055cc8..8073448 100755
--- a/bin/cat5rancid
+++ b/bin/cat5rancid
@@ -681,6 +681,36 @@ sub ShowDiag {
return(0);
}
+# This routine parses "show module"
+sub ShowModule {
+ print STDERR " In ShowModule: $_" if ($debug);
+
+# # eat the header lines
+# $junk = <INPUT>;
+# $junk = <INPUT>;
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if(/^$prompt/);
+# last if(/^$/);
+# $junk = $_;
+# $slot = substr($junk, 0, 2) + 0;
+# $port = substr($junk, 24, 3) + 0;
+# $plu = "";
+# $plu = "s" if $port > 1;
+# $type = substr($junk, 30, 21);
+# $type =~ s/^\s+//;
+# $type =~ s/\s+$//;
+# $board = substr($junk, 52, 9);
+# $board =~ s/ //;
+# $serial = substr($junk, 62,9) + 0;
+# ProcessHistory("SLOT","","","!Slot $slot/$board: $type, $port port$plu, serial $serial\n");
+ ProcessHistory("SLOT","","","! $_");
+ }
+ # The "write term" code gives us one of these, so skip it here
+ # ProcessHistory("SLOT","","","!\n");
+}
+
# This routine parses "show c7200" for the 7200
# This will create arrarys for hw info.
sub ShowC7200 {
@@ -721,7 +751,8 @@ sub WriteTerm {
while (<INPUT>) {
tr/\015//d;
- last if(/^$prompt/);
+ last if (/^$prompt/);
+#heas next if (/^\.+$/);
/Non-Volatile memory is in use/ && return(-1); # NvRAM is locked
# skip the crap
if (/^(\.\.+$|##+$|Building configuration...)/i) {
@@ -810,26 +841,40 @@ sub WriteTerm {
/^access-list\s+(\d\d\d)\s+(\S+)\s+ip\s+any/ &&
ProcessHistory("EACL $1 $2","ipsort","0.0.0.0","$_") && next;
# order arp lists
- /^arp\s+(\d+\.\d+\.\d+\.\d+)\s+/ &&
+ /^set arp\s+(\d+\.\d+\.\d+\.\d+)\s+/ &&
ProcessHistory("ARP","ipsort","$1","$_") && next;
/^ip prefix-list\s+(\S+)\s+seq\s+(\d+)\s+(permit|deny)\s+(\d\S+)(\/.*)$/ &&
ProcessHistory("PACL $1 $3","ipsort","$4","ip prefix-list $1 $3 $4$5\n")
&& next;
# order logging statements
- /^logging (\d+\.\d+\.\d+\.\d+)/ &&
+ /^set logging server (\d+\.\d+\.\d+\.\d+)/ &&
ProcessHistory("LOGGING","ipsort","$1","$_") && next;
# order name-server statements
- /^ip name-server (\d+\.\d+\.\d+\.\d+)/ &&
+ /^set ip dns server (\d+\.\d+\.\d+\.\d+)/ &&
ProcessHistory("NAMESERVER","ipsort","$1","$_") && next;
- # order snmp-server host statements
- /^snmp-server host (\d+\.\d+\.\d+\.\d+)/ &&
- ProcessHistory("SNMPSERVERHOST","ipsort","$1","$_") && next;
- /^snmp-server community / &&
- ProcessHistory("SNMPSERVERCOMM","keysort","$_","$_") && next;
+ # order/prune snmp-server host statements
+ # we only prune lines of the form
+ # snmp-server host a.b.c.d <community>
+ if (/^set snmp trap (\d+\.\d+\.\d+\.\d+) /) {
+ if (defined($ENV{'NOCOMMSTR'})) {
+ ProcessHistory("SNMPSERVERHOST","ipsort","$1","# set snmp trap $1 <removed>\n");
+ } else {
+ ProcessHistory("SNMPSERVERHOST","ipsort","$1","$_");
+ }
+ next;
+ }
+ if (/^(set snmp community) (\S+) (\S+)/) {
+ if (defined($ENV{'NOCOMMSTR'})) {
+ ProcessHistory("SNMPSERVERCOMM","keysort","$_","#$1 $2 <removed>\n");
+ } else {
+ ProcessHistory("SNMPSERVERCOMM","keysort","$_","$_")
+ }
+ next;
+ }
# order tacacs server statements
- /^(tacacs-server key )/ &&
- ProcessHistory("","","","!$1<removed>\n") && next;
- /^tacacs-server host (\d+\.\d+\.\d+\.\d+)/ &&
+ /^set (tacacs) key / &&
+ ProcessHistory("","","","! set $1 key <removed>\n") && next;
+ /^set tacacs server (\d+\.\d+\.\d+\.\d+)/ &&
ProcessHistory("TAC","ipsort","$1","$_") && next;
# order clns host statements
/^clns host \S+ (\S+)/ &&
@@ -873,44 +918,46 @@ sub DoNothing {print STDOUT;}
# Main
%commands=(
'show version' => "ShowVersion",
- 'show install active' => "ShowInstallActive",
- 'show env all' => "ShowEnv",
- 'show gsr chassis' => "ShowGSR",
+# 'show install active' => "ShowInstallActive",
+# 'show env all' => "ShowEnv",
+# 'show gsr chassis' => "ShowGSR",
'show boot' => "ShowBoot",
- 'show bootvar' => "ShowBoot",
+# 'show bootvar' => "ShowBoot",
'show flash' => "ShowFlash",
- 'dir /all bootflash:' => "DirSlotN",
- 'dir /all slot0:' => "DirSlotN",
- 'dir /all disk0:' => "DirSlotN",
- 'dir /all slot1:' => "DirSlotN",
- 'dir /all disk1:' => "DirSlotN",
- 'show controllers' => "ShowContAll",
- 'show controllers cbus' => "ShowContCbus",
- 'show diagbus' => "ShowDiagbus",
- 'show diag' => "ShowDiag",
- 'show c7200' => "ShowC7200",
+ 'dir bootflash:' => "DirSlotN",
+ 'dir slot0:' => "DirSlotN",
+# 'dir /all disk0:' => "DirSlotN",
+ 'dir slot1:' => "DirSlotN",
+# 'dir /all disk1:' => "DirSlotN",
+# 'show controllers' => "ShowContAll",
+# 'show controllers cbus' => "ShowContCbus",
+# 'show diagbus' => "ShowDiagbus",
+# 'show diag' => "ShowDiag",
+ 'show module' => "ShowModule",
+# 'show c7200' => "ShowC7200",
'write term' => "WriteTerm"
);
# keys() doesnt return things in the order entered and the order of the
# cmds is important (show version first and write term last). pita
@commands=(
"show version",
- "show install active",
- "show env all",
- "show gsr chassis",
+# "show install active",
+# "show env all",
+# "show gsr chassis",
"show boot",
- "show bootvar",
+# "show bootvar",
"show flash",
- "dir /all bootflash:",
- "dir /all slot0:",
- "dir /all disk0:",
- "dir /all slot1:",
- "dir /all disk1:",
- "show controllers",
- "show controllers cbus",
- "show diagbus",
- "show diag",
- "show c7200",
+ "dir bootflash:",
+ "dir slot0:",
+# "dir /all disk0:",
+ "dir slot1:",
+# "dir /all disk1:",
+# "show controllers",
+# "show controllers cbus",
+# "show diagbus",
+# "show diag",
+ "show module",
+# "show c7200",
"write term"
);
$cisco_cmds=join(";",@commands);
diff --git a/bin/elogin b/bin/elogin
new file mode 100755
index 0000000..ebf126e
--- /dev/null
+++ b/bin/elogin
@@ -0,0 +1,449 @@
+#!/usr/local/bin/expect --
+##
+##
+## Copyright (C) 1997 by Henry Kilmer, Erik Sherk and Pete Whiting.
+## All rights reserved.
+##
+## This software may be freely copied, modified and redistributed without
+## fee for non-commerical purposes provided that this copyright notice is
+## preserved intact on all copies and modified copies.
+##
+## There is no warranty or other guarantee of fitness of this software.
+## It is provided solely "as is". The author(s) disclaim(s) all
+## responsibility and liability with respect to this software's usage
+## or its effect upon hardware, computer systems, other software, or
+## anything else.
+##
+##
+#
+# elogin - ADC EZT3 login
+#
+# Most options are intuitive for logging into an ADC EZT3 mux.
+#
+
+# Usage line
+set usage "Usage: $argv0 \[-noenable\] \[-c command\] \
+\[-f cloginrc-file\] \[-p user-password\] \
+\[-s script-file\] \[-t timeout\] \[-u username\] \
+\[-v vty-password\] \[-w enable-username\] \[-x command-file\] \
+\[-y ssh_cypher_type\] router \[router...\]\n"
+
+# env(CLOGIN) may contain:
+# x == do not set xterm banner or name
+
+# Password file
+set password_file $env(HOME)/.cloginrc
+# Default is to login to the router
+set do_command 0
+set do_script 0
+# The default is to automatically enable
+set enable 1
+# The default is that you login non-enabled (tacacs can have you login already enabled)
+set autoenable 0
+# The default is to look in the password file to find the passwords. This
+# tracks if we receive them on the command line.
+set do_passwd 1
+
+# Find the user in the ENV, or use the unix userid.
+if {[ info exists env(CISCO_USER) ] } {
+ set default_user $env(CISCO_USER)
+} else {
+ # This uses "id" which I think is portable. At least it has existed
+ # (without options) on all machines/OSes I've been on recently -
+ # unlike whoami or id -nu.
+ regexp {\(([^)]*)} [exec id] junk default_user
+}
+
+# Sometimes routers take awhile to answer (the default is 10 sec)
+set timeout 45
+
+# Process the command line
+for {set i 0} {$i < $argc} {incr i} {
+ set arg [lindex $argv $i]
+
+ switch -glob -- $arg {
+ # Username
+ -u* -
+ -U* {
+ if {! [ regexp .\[uU\](.+) $arg ignore user]} {
+ incr i
+ set username [ lindex $argv $i ]
+ }
+ # VTY Password
+ } -p* -
+ -P* {
+ if {! [ regexp .\[pP\](.+) $arg ignore userpasswd]} {
+ incr i
+ set userpasswd [ lindex $argv $i ]
+ }
+ set do_passwd 0
+ # VTY Password
+ } -v* -
+ -v* {
+ if {! [ regexp .\[vV\](.+) $arg ignore passwd]} {
+ incr i
+ set passwd [ lindex $argv $i ]
+ }
+ set do_passwd 0
+ # Enable Username
+ } -w* -
+ -W* {
+ # ignore -w
+ # Enable Password
+ } -e* -
+ -E* {
+ # ignore -e
+ # Command to run.
+ } -c* -
+ -C* {
+ if {! [ regexp .\[cC\](.+) $arg ignore command]} {
+ incr i
+ set command [ lindex $argv $i ]
+ }
+ set do_command 1
+ # Expect script to run.
+ } -s* -
+ -S* {
+ if {! [ regexp .\[sS\](.+) $arg ignore sfile]} {
+ incr i
+ set sfile [ lindex $argv $i ]
+ }
+ if { ! [ file readable $sfile ] } {
+ send_user "Error: Can't read $sfile\n"
+ exit 1
+ }
+ set do_script 1
+ # 'ssh -c' cypher type
+ } -y* -
+ -Y* {
+ if {! [ regexp .\[eE\](.+) $arg ignore cypher]} {
+ incr i
+ set cypher [ lindex $argv $i ]
+ }
+ # alternate cloginrc file
+ } -f* -
+ -F* {
+ if {! [ regexp .\[fF\](.+) $arg ignore password_file]} {
+ incr i
+ set password_file [ lindex $argv $i ]
+ }
+ # Timeout
+ } -t* -
+ -T* {
+ if {! [ regexp .\[tT\](.+) $arg ignore timeout]} {
+ incr i
+ set timeout [ lindex $argv $i ]
+ }
+ # Command file
+ } -x* -
+ -X {
+ if {! [ regexp .\[xX\](.+) $arg ignore cmd_file]} {
+ incr i
+ set cmd_file [ lindex $argv $i ]
+ }
+ set cmd_fd [open $cmd_file r]
+ set cmd_text [read $cmd_fd]
+ close $cmd_fd
+ set command [join [split $cmd_text \n] \;]
+ set do_command 1
+ # Do we enable?
+ } -noenable {
+ # ignore -noenable
+ # Does tacacs automatically enable us?
+ } -autoenable {
+ # ignore -autoenable
+ } -* {
+ send_user "Error: Unknown argument! $arg\n"
+ send_user $usage
+ exit 1
+ } default {
+ break
+ }
+ }
+}
+# Process routers...no routers listed is an error.
+if { $i == $argc } {
+ send_user "Error: $usage"
+}
+
+# Only be quiet if we are running a script (it can log its output
+# on its own)
+if { $do_script } {
+ log_user 0
+} else {
+ log_user 1
+}
+
+#
+# Done configuration/variable setting. Now run with it...
+#
+
+# Sets Xterm title if interactive...if its an xterm and the user cares
+proc label { host } {
+ global env
+ # if CLOGIN has an 'x' in it, don't set the xterm name/banner
+ if [info exists env(CLOGIN)] {
+ if {[string first "x" $env(CLOGIN)] != -1} { return }
+ }
+ # take host from ENV(TERM)
+ if [info exists env(TERM)] {
+ if [regexp \^(xterm|vs) $env(TERM) ignore ] {
+ send_user "\033]1;[lindex [split $host "."] 0]\a"
+ send_user "\033]2;$host\a"
+ }
+ }
+}
+
+# This is a helper function to make the password file easier to
+# maintain. Using this the password file has the form:
+# add password sl* pete cow
+# add password at* steve
+# add password * hanky-pie
+proc add {var args} { global $var ;lappend $var $args}
+proc find {var router} {
+ source_password_file
+ upvar $var list
+ if { [info exists list] } {
+ foreach line $list {
+ if { [string match [lindex $line 0] $router ] } {
+ return [lrange $line 1 end]
+ }
+ }
+ }
+ return {}
+}
+
+# Loads the password file. Note that as this file is tcl, and that
+# it is sourced, the user better know what to put in there, as it
+# could install more than just password info... I will assume however,
+# that a "bad guy" could just as easy put such code in the clogin
+# script, so I will leave .cloginrc as just an extention of that script
+proc source_password_file { } {
+ global env password_file read_password_file
+ if { [info exists read_password_file] } { return }
+ if { [info exists password_file] == 0 } {
+ set password_file $env(HOME)/.cloginrc
+ }
+ if { ! [file exists $password_file] } {
+ send_user "Error: password file ($password_file) does not exist\n"
+ exit 1
+ }
+ set read_password_file 1
+ file stat $password_file fileinfo
+ if { [expr ($fileinfo(mode) & 007)] != 0000 } {
+ send_user "Error: $password_file must not be world readable/writable\n"
+ exit 1
+ }
+ source $password_file
+}
+
+# Log into the router.
+proc login { router user userpswd passwd prompt cyphertype } {
+ global spawn_id in_proc do_command do_script
+ global u_prompt p_prompt
+ set in_proc 1
+ set tryssh 1
+
+ # Telnet to the router & try to login.
+ if [ catch {spawn telnet $router} reason ] {
+ send_user "Error: failed to telnet: $reason\n"
+ exit 1
+ }
+ sleep 0.3
+
+ # This helps cleanup each expect clause.
+ expect_after {
+ timeout {
+ send_user "\nError: TIMEOUT reached\n"
+ catch {close}; wait
+ if { $in_proc} {
+ return 1
+ } else {
+ continue
+ }
+ } eof {
+ send_user "\nError: EOF received\n"
+ catch {close}; wait
+ if { $in_proc} {
+ return 1
+ } else {
+ continue
+ }
+ }
+ }
+
+ expect {
+ "Connection refused" {
+ close; wait
+ sleep 0.3
+ expect eof
+ send_user "Error: Connection Refused\n"; wait; return 1
+ } eof { send_user "Error: Couldn't login\n"; wait; return 1
+ } "Unknown host\r\n" {
+ expect eof
+ send_user "Error: Unknown host\n"; wait; return 1
+ } "Host is unreachable" {
+ expect eof
+ send_user "Error: Host Unreachable!\n"; wait; return 1
+ } "No address associated with name" {
+ expect eof
+ send_user "Error: Unknown host\n"; wait; return 1
+ }
+ -re "$u_prompt" { send "$user\r"
+ expect {
+ "Login incorrect" { send_user "Error: Couldn't login\n";
+ catch {close}; wait; return 1 }
+ eof { send_user "Error: Couldn't login\n"; wait; return 1 }
+ -re "$p_prompt" { send "$userpswd\r" }
+ "$prompt" { set in_proc 0; return 0 }
+ }
+ exp_continue
+ }
+ -re "$p_prompt" { send "$passwd\r"
+ expect {
+ "Password incorrect" { send_user "Error: Couldn't login\n";
+ catch {close}; wait; return 1 }
+ eof { send_user "Error: Couldn't login\n"; wait; return 1 }
+ "$prompt" { set in_proc 0; return 0 }
+ }
+ exp_continue
+ }
+ "Password incorrect" { send_user "Error: Check your password for $router\n";
+ catch {close}; wait; return 1 }
+ "$prompt" { }
+ denied { send_user "Error: Check your passwd for $router\n"
+ if { $do_command || $do_script } {
+ send "exit\r"
+ wait
+ return 1
+ } else {
+ return 1
+ }
+ }
+ "\r\n" { exp_continue; }
+ }
+ set in_proc 0
+ return 0
+}
+
+# Run commands given on the command line.
+proc run_commands { prompt command } {
+ global in_proc
+ set in_proc 1
+
+ send "screen 0\r"
+ expect $prompt {}
+
+ regsub -all "\[)(]" $prompt {\\&} reprompt
+
+ # Is this a multi-command?
+ if [ string match "*\;*" "$command" ] {
+ set commands [split $command \;]
+ set num_commands [llength $commands]
+
+ for {set i 0} {$i < $num_commands} { incr i} {
+ send "[subst -nocommands [lindex $commands $i]]\r"
+ expect {
+ -re "^\[^\n\r]*$reprompt." { exp_continue }
+ -re "^\[^\n\r *]*$reprompt" {}
+ -re "\[\n\r]" { exp_continue }
+ }
+ }
+ } else {
+ send "[subst -nocommands $command]\r"
+ expect {
+ -re "^\[^\n\r]*$reprompt." { exp_continue }
+ -re "^\[^\n\r *]*$reprompt" {}
+ -re "\[\n\r]" { exp_continue }
+ }
+ }
+ send "exit\r"
+ expect {
+ "\n" { exp_continue }
+ timeout { return 0 }
+ eof { return 0 }
+ }
+ set in_proc 0
+}
+
+#
+# For each router... (this is main loop)
+#
+set in_proc 0
+foreach router [lrange $argv $i end] {
+ set router [string tolower $router]
+ send_user "$router\n"
+
+ # Figure out prompt.
+ set prompt "Active) > "
+ set autoenable 1
+ set enable 0
+
+ # Figure out passwords
+ if { $do_passwd } {
+ set pswd [find password $router]
+ if { [llength $pswd] == 0 } {
+ send_user "Error - no password for $router in $password_file.\n"
+ continue
+ }
+ set passwd [lindex $pswd 0]
+ }
+
+ # Figure out username
+ if {[info exists username]} {
+ # command line username
+ set ruser $username
+ } else {
+ set ruser [find user $router]
+ if { "$ruser" == "" } { set ruser $default_user }
+ }
+
+ # Figure out username's password (if different from the vty password)
+ if {[info exists userpasswd]} {
+ # command line username
+ set userpswd $userpasswd
+ } else {
+ set userpswd [find userpassword $router]
+ if { "$userpswd" == "" } { set userpswd $passwd }
+ }
+
+ # Figure out prompts
+ set u_prompt [find userprompt $router]
+ if { "$u_prompt" == "" } { set u_prompt "(Username|login| Login):" }
+ set p_prompt [find passprompt $router]
+ if { "$p_prompt" == "" } { set p_prompt "\[Pp]assword:" }
+
+ # Figure out cypher type
+ if {[info exists cypher]} {
+ # command line cypher type
+ set cyphertype $cypher
+ } else {
+ set cyphertype [find cyphertype $router]
+ if { "$cyphertype" == "" } { set cyphertype "3des" }
+ }
+
+ # Login to the router
+ if {[login $router $ruser $userpswd $passwd $prompt $cyphertype]} {
+ continue
+ }
+
+ if { $do_command } {
+ if {[run_commands $prompt $command]} {
+ continue
+ }
+ } elseif { $do_script } {
+ send "screen 0\r"
+ expect $prompt {}
+ source $sfile
+ close
+ } else {
+ label $router
+ log_user 1
+ interact
+ }
+
+ # End of for each router
+ wait
+ sleep 0.3
+}
+exit 0
diff --git a/bin/env b/bin/env
index 85aa309..7a18204 100644
--- a/bin/env
+++ b/bin/env
@@ -21,6 +21,9 @@ CVSROOT=$BASEDIR/CVS; export CVSROOT
# collection from the router(s).
#NOPIPE=YES; export NOPIPE
#
+# if NOCOMMSTR is set, snmp community strings will be stripped from the configs
+#NOCOMMSTR=YES; export NOCOMMSTR
+#
# How many hours to go by before complaining about routers that
# can not be reached.
OLDTIME=4; export OLDTIME
diff --git a/bin/erancid b/bin/erancid
new file mode 100755
index 0000000..2adba78
--- /dev/null
+++ b/bin/erancid
@@ -0,0 +1,296 @@
+#!/usr/local/bin/perl
+##
+## Hacked version of rancid for ADC EZT3 series muxes. Only tested
+## with switch software 1.50 so far - terry@tmk.com
+##
+##
+## Copyright (C) 1997 by Henry Kilmer.
+## All rights reserved.
+##
+## This software may be freely copied, modified and redistributed without
+## fee for non-commerical purposes provided that this copyright notice is
+## preserved intact on all copies and modified copies.
+##
+## There is no warranty or other guarantee of fitness of this software.
+## It is provided solely "as is". The author(s) disclaim(s) all
+## responsibility and liability with respect to this software's usage
+## or its effect upon hardware, computer systems, other software, or
+## anything else.
+##
+##
+#
+# RANCID - Really Awesome New Cisco confIg Differ
+#
+# usage: rancid [-d] [-l] [-f filename | $host]
+#
+use Getopt::Std;
+getopts('dflm');
+$log = $opt_l;
+$debug = $opt_d;
+$file = $opt_f;
+$host = $ARGV[0];
+$clean_run = 0;
+$found_end = 0;
+$timeo = 90; # clogin timeout in seconds
+
+# This routine is used to print out the router configuration
+sub ProcessHistory {
+ my($new_hist_tag,$new_command,$command_string,@string)=(@_);
+ if((($new_hist_tag ne $hist_tag) || ($new_command ne $command))
+ && defined %history) {
+ print eval "$command \%history";
+ undef %history;
+ }
+ if (($new_hist_tag) && ($new_command) && ($command_string)) {
+ if ($history{$command_string}) {
+ $history{$command_string} = "$history{$command_string}@string";
+ } else {
+ $history{$command_string} = "@string";
+ }
+ } elsif (($new_hist_tag) && ($new_command)) {
+ $history{++$#history} = "@string";
+ } else {
+ print "@string";
+ }
+ $hist_tag = $new_hist_tag;
+ $command = $new_command;
+ 1;
+}
+
+sub numerically { $a <=> $b; }
+
+# This is a sort routing that will sort numerically on the
+# keys of a hash as if it were a normal array.
+sub keynsort {
+ local(%lines)=@_;
+ local($i) = 0;
+ local(@sorted_lines);
+ foreach $key (sort numerically keys(%lines)) {
+ $sorted_lines[$i] = $lines{$key};
+ $i++;
+ }
+ @sorted_lines;
+}
+
+# This is a sort routing that will sort on the
+# keys of a hash as if it were a normal array.
+sub keysort {
+ local(%lines)=@_;
+ local($i) = 0;
+ local(@sorted_lines);
+ foreach $key (sort keys(%lines)) {
+ $sorted_lines[$i] = $lines{$key};
+ $i++;
+ }
+ @sorted_lines;
+}
+
+# This is a sort routing that will sort on the
+# values of a hash as if it were a normal array.
+sub valsort{
+ local(%lines)=@_;
+ local($i) = 0;
+ local(@sorted_lines);
+ foreach $key (sort values %lines) {
+ $sorted_lines[$i] = $key;
+ $i++;
+ }
+ @sorted_lines;
+}
+
+# This is a numerical sort routing (ascending).
+sub numsort {
+ local(%lines)=@_;
+ local($i) = 0;
+ local(@sorted_lines);
+ foreach $num (sort {$a <=> $b} keys %lines) {
+ $sorted_lines[$i] = $lines{$num};
+ $i++;
+ }
+ @sorted_lines;
+}
+
+# This is a sort routine that will sort on the
+# ip address when the ip address is anywhere in
+# the strings.
+sub ipsort {
+ local(%lines)=@_;
+ local($i) = 0;
+ local(@sorted_lines);
+ foreach $addr (sort sortbyipaddr keys %lines) {
+ $sorted_lines[$i] = $lines{$addr};
+ $i++;
+ }
+ @sorted_lines;
+}
+
+# These two routines will sort based upon IP addresses
+sub ipaddrval {
+ my(@a) = ($_[0] =~ m#^(\d+)\.(\d+)\.(\d+)\.(\d+)$#);
+ $a[3]+256*($a[2]+256*($a[1]+256*$a[0]));
+}
+sub sortbyipaddr {
+ &ipaddrval($a) <=> &ipaddrval($b);
+}
+
+# This routine parses "show version"
+sub ShowVersion {
+ print STDERR " In ShowVersion: $_" if ($debug);
+
+ ProcessHistory("COMMENTS","keysort","A1",
+ "- Chassis type:EZT3 - an ADC EZT3 M13 multiplexor\n");
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if(/Active\) >/);
+ next if(/^(\s*|\s*$cmd\s*)$/);
+
+ /Boot Version (\S*)/ &&
+ ProcessHistory("COMMENTS","keysort","G1",
+ "- ROM Bootstrap: $1\n") && next;
+ /Software Version (\S*)/ &&
+ ProcessHistory("COMMENTS","keysort","F1",
+ "- Software: $1\n") && next;
+ }
+ return(0);
+}
+
+# This routine parses "show module"
+sub ShowModule {
+ print STDERR " In ShowModule: $_" if ($debug);
+
+ # eat the header line
+ $junk = <INPUT>;
+
+ ProcessHistory("SLOT","","","-\n");
+
+ # now just copy it verbatim to the history file
+ while (<INPUT>) {
+ tr/\015//d;
+ last if(/Active\) >/);
+ last if(/^$/);
+ chop;
+ ProcessHistory("SLOT","","","-$_\n");
+ }
+ ProcessHistory("SLOT","","","-\n");
+}
+
+# This routine processes a "write term"
+sub WriteTerm {
+ print STDERR " In WriteTerm: $_" if ($debug);
+
+ # eat the header line
+ $junk = <INPUT>;
+
+ # now just copy it verbatim to the history file
+ while (<INPUT>) {
+ tr/\015//d;
+ last if(/Active\) >/);
+ chop;
+ if (/^\s*snmp/ && defined($ENV{'NOCOMMSTR'})) {
+ /snmp (getcomm|setcomm|trapcomm)(\s+)(\S*)/ &&
+ ProcessHistory("","","","- snmp $1$2\"<removed>\"\n") && next;
+ }
+ # believe it or not, "-" is the "whole line is comment" command
+ ProcessHistory("","","","$_\n");
+ }
+ $found_end = 1;
+ return(1);
+}
+
+# dummy function
+sub DoNothing {print STDOUT;}
+
+# Main
+%commands=(
+ 'version' => "ShowVersion",
+ 'equipment' => "ShowModule",
+ 'config' => "WriteTerm",
+);
+# keys() doesnt return things in the order entered and the order of the
+# cmds is important (show version first and write term last). pita
+@commands=(
+ "version",
+ "equipment",
+ "config",
+);
+$cisco_cmds=join(";",@commands);
+$cmds_regexp=join("|",@commands);
+
+open(OUTPUT,">$host.new") || die "Can't open $host.new for writing: $!\n";
+select(OUTPUT);
+# make OUTPUT unbuffered if debugging
+if ($debug) { $| = 1; }
+
+if ($file) {
+ print STDERR "opening file $host\n" if ($debug);
+ print STDOUT "opening file $host\n" if ($log);
+ open(INPUT,"<$host") || die "open failed for $host: $!\n";
+} else {
+ print STDERR "executing elogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($debug);
+ print STDOUT "executing elogin -t $timeo -c\"$cisco_cmds\" $host\n" if ($log);
+ if (defined($ENV{NOPIPE})) {
+ system "elogin -t $timeo -c \"$cisco_cmds\" $host </dev/null > $host.raw 2>&1" || die "elogin failed for $host: $!\n";
+ open(INPUT, "< $host.raw") || die "elogin failed for $host: $!\n";
+ } else {
+ open(INPUT,"elogin -t $timeo -c \"$cisco_cmds\" $host </dev/null |") || die "elogin failed for $host: $!\n";
+ }
+}
+
+ProcessHistory("COMMENTS","keysort","B0","-\n");
+ProcessHistory("COMMENTS","keysort","F0","-\n");
+ProcessHistory("COMMENTS","keysort","G0","-\n");
+while(<INPUT>) {
+ tr/\015//d;
+ if (/Logging out$/) {
+ $clean_run=1;
+ last;
+ }
+ if (/Error:/) {
+ s/^.*Error:/Error:/;
+ print STDOUT ("$host elogin error: $_");
+ print STDERR ("$host elogin error: $_") if ($debug);
+ $clean_run=0;
+ last;
+ }
+ while (/Active\) >\s*($cmds_regexp)\s*$/) {
+ $cmd = $1;
+ if (!defined($prompt)) {$prompt = ($_ =~ /^([^#]+#)/)[0]; }
+ print STDERR ("HIT COMMAND:$_") if ($debug);
+ if (! defined($commands{$cmd})) {
+ print STDERR "found unexpected command - \"$cmd\"\n";
+ $clean_run = 0;
+ last;
+ }
+ $rval = &{$commands{$cmd}};
+ delete($commands{$cmd});
+ if ($rval == -1) {
+ $clean_run = 0;
+ last;
+ }
+ }
+}
+print STDOUT "Done $logincmd: $_\n" if ($log);
+# Flush History
+ProcessHistory("","","","");
+# Cleanup
+close(INPUT);
+close(OUTPUT);
+
+if (defined($ENV{NOPIPE})) {
+ unlink("$host.raw") if (! $debug);
+}
+
+# check for completeness
+if (scalar(%commands) || !$clean_run || !$found_end) {
+ if (scalar(%commands)) {
+ printf(STDOUT "missed cmd(s): %s\n", join(',', keys(%commands)));
+ printf(STDERR "missed cmd(s): %s\n", join(',', keys(%commands))) if ($debug);
+ }
+ if (!$clean_run || !$found_end) {
+ print STDOUT "End of run not found\n";
+ print STDERR "End of run not found\n" if ($debug);
+ system("/usr/bin/tail -1 $host.new");
+ }
+ unlink "$host.new" if (! $debug);
+}
diff --git a/bin/jrancid b/bin/jrancid
index efc8465..ea158bf 100755
--- a/bin/jrancid
+++ b/bin/jrancid
@@ -177,6 +177,8 @@ sub ShowChassisEnvironment {
ProcessHistory("","","","# $1\n") && next;
/(\s*.+) +\d+ degrees C.*$/ &&
ProcessHistory("","","","# $1\n") && next;
+ /(^.*\S)\s+ Spinning at .*$/ &&
+ ProcessHistory("","","","# $1\n") && next;
ProcessHistory("","","","# $_");
}
return;
@@ -358,6 +360,11 @@ sub ShowConfiguration {
/^database header mismatch: / && return(-1);
/^version .*;\d+$/ && return(-1);
+ if (/^(\s*)(community |trap-group )[^ ;]+(\s?[;{])$/) {
+ if (defined($ENV{'NOCOMMSTR'})) {
+ $_ = "$1$2\"<removed>\"$3\n";
+ }
+ }
s/(\s*authentication-key ).*$/#$1<removed>;/;
s/^(.*\ssecret \")\$9\$.*(\".*)$/#$1<removed>$2/;
s/ # SECRET-DATA$//;
diff --git a/bin/rancid b/bin/rancid
index f283c7f..4bdde6c 100755
--- a/bin/rancid
+++ b/bin/rancid
@@ -173,6 +173,7 @@ sub ShowVersion {
my($proc) = $1;
my($cpu) = $2;
my($mem) = $3;
+ my($deivce) = "router";
if ( $1 eq "CSC") {
$type = "AGS";
} elsif ( $1 eq "CSC4") {
@@ -191,14 +192,17 @@ sub ShowVersion {
$type = "7000";
} elsif ( $1 =~ /720[246]/) {
$type = "7200";
- } elsif ($1 =~ /1200[48]\/GRP/ || $1 =~ /1201[26]\/GRP/) {
+ } elsif ( $1 =~ /1200[48]\/GRP/ || $1 =~ /1201[26]\/GRP/) {
$type = "12000";
+ } elsif ( $1 =~ /WS-C29/) {
+ $type = "2900XL";
+ $device = "switch";
} else {
$type = $1;
}
print STDERR "TYPE = $type\n" if ($debug);
ProcessHistory("COMMENTS","keysort","A1",
- "!Chassis type:$slave $proc - a $type router\n");
+ "!Chassis type:$slave $proc - a $type $device\n");
ProcessHistory("COMMENTS","keysort","B1",
"!Memory:$slave main $mem\n");
ProcessHistory("COMMENTS","keysort","A3","!CPU:$slave $cpu\n");
@@ -379,7 +383,7 @@ sub ShowFlash {
return;
}
-# This routine parses "dir /all ((disk|slot)N|bootflash):"
+# This routine parses "dir /all ((disk|slot)N|bootflash|nvram):"
sub DirSlotN {
# Skip if this is not a 3600, 7000, 7200, 7500, or 12000.
print STDERR " In DirSlotN: $_" if ($debug);
@@ -713,6 +717,20 @@ sub ShowC7200 {
return(0);
}
+# This routine parses "show vtp status"
+sub ShowVTP {
+ print STDERR " In ShowVTP: $_" if ($debug);
+
+ while (<INPUT>) {
+ tr/\015//d;
+ last if (/^$prompt/);
+ next if (/^(\s*|\s*$cmd\s*)$/);
+ return(1) if ($type !~ /^2900XL$/);
+ ProcessHistory("COMMENTS","keysort","I0","!VTP: $_");
+ }
+ ProcessHistory("COMMENTS","keysort","I0","!\n");
+}
+
# This routine processes a "write term"
sub WriteTerm {
print STDERR " In WriteTerm: $_" if ($debug);
@@ -743,17 +761,17 @@ sub WriteTerm {
/^ width / && next; # kill width on serial lines
/^ clockrate / && next; # kill clockrate on serial interfaces
/^enable password / &&
- ProcessHistory("ENABLE","","","!enable password <removed>\n") &&
+ ProcessHistory("ENABLE","","","! enable password <removed>\n") &&
next;
- /^(username .*) password /&&
- ProcessHistory("USER","","","!$1 password <removed>\n") && next;
+ /^username (\S+) password /&&
+ ProcessHistory("USER","keysort","$1","! username $1 password <removed>\n") && next;
/^\s*password / &&
ProcessHistory("LINE-PASS","","","! password <removed>\n") && next;
/^\s*neighbor (\S*) password / &&
ProcessHistory("","","","! neighbor $1 password <removed>\n") &&
next;
/^(ip ftp password) / &&
- ProcessHistory("","","","!$1 <removed>\n") && next;
+ ProcessHistory("","","","! $1 <removed>\n") && next;
/^( ip ospf authentication-key) / &&
ProcessHistory("","","","!$1 <removed>\n") && next;
/^( ip ospf message-digest-key \d+ md5) / &&
@@ -818,16 +836,41 @@ sub WriteTerm {
# order name-server statements
/^ip name-server (\d+\.\d+\.\d+\.\d+)/ &&
ProcessHistory("NAMESERVER","ipsort","$1","$_") && next;
- # order snmp-server host statements
- /^snmp-server host (\d+\.\d+\.\d+\.\d+)/ &&
- ProcessHistory("SNMPSERVERHOST","ipsort","$1","$_") && next;
- /^snmp-server community / &&
- ProcessHistory("SNMPSERVERCOMM","keysort","$_","$_") && next;
- # order tacacs server statements
- /^(tacacs-server key )/ &&
- ProcessHistory("","","","!$1<removed>\n") && next;
- /^tacacs-server host (\d+\.\d+\.\d+\.\d+)/ &&
- ProcessHistory("TAC","ipsort","$1","$_") && next;
+ # order/prune snmp-server host statements
+ # we only prune lines of the form
+ # snmp-server host a.b.c.d <community>
+ if (/^snmp-server host (\d+\.\d+\.\d+\.\d+) /) {
+ if (defined($ENV{'NOCOMMSTR'})) {
+ my($ip) = $1;
+ my($line) = "snmp-server host $ip";
+ my(@tokens) = split(' ', $');
+ my($token);
+ while ($token = shift(@tokens)) {
+ if ($token eq 'version') {
+ $line .= " " . join(' ', ($token, shift(@tokens)));
+ } elsif ($token =~ /^(informs?|traps?|(no)?auth)$/) {
+ $line .= " " . $token;
+ } else {
+ $line = "! $line " . join(' ', ("<removed>", join(' ',@tokens)));
+ last;
+ }
+ }
+ ProcessHistory("SNMPSERVERHOST","ipsort","$ip","$line\n");
+ } else {
+ ProcessHistory("SNMPSERVERHOST","ipsort","$1","$_");
+ }
+ next;
+ }
+ if (/^(snmp-server community) (\S+)/) {
+ if (defined($ENV{'NOCOMMSTR'})) {
+ ProcessHistory("SNMPSERVERCOMM","keysort","$_","! $1 <removed>$'") && next;
+ } else {
+ ProcessHistory("SNMPSERVERCOMM","keysort","$_","$_") && next;
+ }
+ }
+ # order/prune tacacs/radius server statements
+ /^(tacacs-server|radius-server) key / &&
+ ProcessHistory("","","","! $1 key <removed>\n") && next;
# order clns host statements
/^clns host \S+ (\S+)/ &&
ProcessHistory("CLNS","keysort","$1","$_") && next;
@@ -835,7 +878,7 @@ sub WriteTerm {
/^alias / && ProcessHistory("ALIAS","keysort","$_","$_") && next;
# delete ntp auth password
/^(ntp authentication-key \d+ md5) / &&
- ProcessHistory("","","","!$1 <removed>\n") && next;
+ ProcessHistory("","","","! $1 <removed>\n") && next;
# order ntp peers/servers
if (/^ntp (server|peer) (\d+)\.(\d+)\.(\d+)\.(\d+)/) {
$sortkey = sprintf("$1 %03d%03d%03d%03d",$2,$3,$4,$5);
@@ -854,6 +897,15 @@ sub WriteTerm {
# order ip rcmd lines
/^ip rcmd/ && ProcessHistory("RCMD","keysort","$_","$_") && next;
+ # system controller
+ /^syscon address (\S*) (\S*)/ &&
+ ProcessHistory("","","","! syscon address $1 <removed>\n") &&
+ next;
+ /^syscon password (\S*)/ &&
+ ProcessHistory("","","","! syscon password <removed>\n") &&
+ next;
+
+ # catch anything that wasnt match above.
ProcessHistory("","","","$_");
# end of config
if (/^end$/) {
@@ -876,6 +928,7 @@ sub DoNothing {print STDOUT;}
'show boot' => "ShowBoot",
'show bootvar' => "ShowBoot",
'show flash' => "ShowFlash",
+ 'dir /all nvram:' => "DirSlotN",
'dir /all bootflash:' => "DirSlotN",
'dir /all slot0:' => "DirSlotN",
'dir /all disk0:' => "DirSlotN",
@@ -886,6 +939,7 @@ sub DoNothing {print STDOUT;}
'show diagbus' => "ShowDiagbus",
'show diag' => "ShowDiag",
'show c7200' => "ShowC7200",
+ 'show vtp status' => "ShowVTP",
'write term' => "WriteTerm"
);
# keys() doesnt return things in the order entered and the order of the
@@ -898,6 +952,7 @@ sub DoNothing {print STDOUT;}
"show boot",
"show bootvar",
"show flash",
+ "dir /all nvram:",
"dir /all bootflash:",
"dir /all slot0:",
"dir /all disk0:",
@@ -908,6 +963,7 @@ sub DoNothing {print STDOUT;}
"show diagbus",
"show diag",
"show c7200",
+ "show vtp status",
"write term"
);
$cisco_cmds=join(";",@commands);
diff --git a/bin/rancid-fe b/bin/rancid-fe
index f85d235..e3fa735 100755
--- a/bin/rancid-fe
+++ b/bin/rancid-fe
@@ -29,6 +29,8 @@ if ($vendor =~ /^cisco$/i) {
exec('rancid', $router);
} elsif ($vendor =~ /^cat5$/i) {
exec('cat5rancid', $router);
+} elsif ($vendor =~ /^ezt3$/i) {
+ exec('erancid', $router);
} elsif ($vendor =~ /^juniper$/i) {
exec('jrancid', $router);
} elsif ($vendor =~ /^foundry$/i) {